#51179 blending calculations were incorrect (dividing by 256 instead of 255).

r=brendan, sr=roc
This commit is contained in:
tor%cs.brown.edu 2001-01-02 23:41:07 +00:00
Родитель e99a242b69
Коммит 30513bad4f
5 изменённых файлов: 83 добавлений и 75 удалений

Просмотреть файл

@ -47,6 +47,24 @@ typedef PRUint32 nscolor;
#define NS_GET_B(_rgba) ((PRUint8) (((_rgba) >> 16) & 0xff))
#define NS_GET_A(_rgba) ((PRUint8) (((_rgba) >> 24) & 0xff))
// Fast approximate division by 255. It has the property that
// for all 0 <= n <= 255*255, FAST_DIVIDE_BY_255(n) == n/255.
// But it only uses two adds and two shifts instead of an
// integer division (which is expensive on many processors).
//
// equivalent to target=v/255
#define FAST_DIVIDE_BY_255(target,v) \
PR_BEGIN_MACRO \
unsigned tmp_ = v; \
target = ((tmp_ << 8) + tmp_ + 255) >> 16; \
PR_END_MACRO
// Blending macro
//
// equivalent to target=(bg*(255-alpha)+fg*alpha)/255
#define MOZ_BLEND(target, bg, fg, alpha) \
FAST_DIVIDE_BY_255(target, (bg)*(255-(alpha)) + (fg)*(alpha))
// Translate a hex string to a color. Return true if it parses ok,
// otherwise return false.
// This accepts only 3, 6 or 9 digits

Просмотреть файл

@ -379,8 +379,6 @@ findIndex24(unsigned mask)
}
}
// blending macro
#define MOZ_BLEND(bg, fg, alpha) (((bg)*(255-(alpha)) + (fg)*(alpha))/255)
// 32-bit (888) truecolor convert/composite function
void
@ -414,9 +412,9 @@ nsImageGTK::DrawComposited32(PRBool isLSB, PRBool flipBytes,
for (unsigned i=0; i<width;
i++, baseRow+=4, targetRow+=3, imageRow+=3, alphaRow++) {
unsigned alpha = *alphaRow;
targetRow[0] = MOZ_BLEND(baseRow[redIndex], imageRow[0], alpha);
targetRow[1] = MOZ_BLEND(baseRow[greenIndex], imageRow[1], alpha);
targetRow[2] = MOZ_BLEND(baseRow[blueIndex], imageRow[2], alpha);
MOZ_BLEND(targetRow[0], baseRow[redIndex], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], baseRow[greenIndex], imageRow[1], alpha);
MOZ_BLEND(targetRow[2], baseRow[blueIndex], imageRow[2], alpha);
}
}
}
@ -449,9 +447,9 @@ nsImageGTK::DrawComposited24(PRBool isLSB, PRBool flipBytes,
for (unsigned i=0; i<width;
i++, baseRow+=3, targetRow+=3, imageRow+=3, alphaRow++) {
unsigned alpha = *alphaRow;
targetRow[0] = MOZ_BLEND(baseRow[redIndex], imageRow[0], alpha);
targetRow[1] = MOZ_BLEND(baseRow[greenIndex], imageRow[1], alpha);
targetRow[2] = MOZ_BLEND(baseRow[blueIndex], imageRow[2], alpha);
MOZ_BLEND(targetRow[0], baseRow[redIndex], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], baseRow[greenIndex], imageRow[1], alpha);
MOZ_BLEND(targetRow[2], baseRow[blueIndex], imageRow[2], alpha);
}
}
}
@ -499,15 +497,15 @@ nsImageGTK::DrawComposited16(PRBool isLSB, PRBool flipBytes,
} else
pix = *((short *)baseRow);
unsigned alpha = *alphaRow;
targetRow[0] =
MOZ_BLEND(redScale[(pix&visual->red_mask)>>visual->red_shift],
imageRow[0], alpha);
targetRow[1] =
MOZ_BLEND(greenScale[(pix&visual->green_mask)>>visual->green_shift],
imageRow[1], alpha);
targetRow[2] =
MOZ_BLEND(blueScale[(pix&visual->blue_mask)>>visual->blue_shift],
imageRow[2], alpha);
MOZ_BLEND(targetRow[0],
redScale[(pix&visual->red_mask)>>visual->red_shift],
imageRow[0], alpha);
MOZ_BLEND(targetRow[1],
greenScale[(pix&visual->green_mask)>>visual->green_shift],
imageRow[1], alpha);
MOZ_BLEND(targetRow[2],
blueScale[(pix&visual->blue_mask)>>visual->blue_shift],
imageRow[2], alpha);
}
}
}
@ -649,9 +647,9 @@ nsImageGTK::DrawCompositedGeneral(PRBool isLSB, PRBool flipBytes,
for (unsigned i=0; i<width; i++) {
unsigned alpha = alphaRow[i];
targetRow[3*i] = MOZ_BLEND(targetRow[3*i], imageRow[3*i], alpha);
targetRow[3*i+1] = MOZ_BLEND(targetRow[3*i+1], imageRow[3*i+1], alpha);
targetRow[3*i+2] = MOZ_BLEND(targetRow[3*i+2], imageRow[3*i+2], alpha);
MOZ_BLEND(targetRow[3*i], targetRow[3*i], imageRow[3*i], alpha);
MOZ_BLEND(targetRow[3*i+1], targetRow[3*i+1], imageRow[3*i+1], alpha);
MOZ_BLEND(targetRow[3*i+2], targetRow[3*i+2], imageRow[3*i+2], alpha);
}
}
}

Просмотреть файл

@ -290,7 +290,7 @@ PRUint32 pixSColor,pixSSColor;
s2 = s1;
d2 = d1;
for(x = 0; x < aNumbytes; x++){
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
FAST_DIVIDE_BY_255(temp1,((*d2)*val1)+((*s2)*val2));
if(temp1>255){
temp1 = 255;
}
@ -316,7 +316,7 @@ PRUint32 pixSColor,pixSSColor;
if((pixSColor!=srccolor) || (pixSSColor!=secsrccolor)) {
for(i=0;i<4;i++){
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
FAST_DIVIDE_BY_255(temp1,((*d2)*val1)+((*s2)*val2));
if(temp1>255){
temp1 = 255;
}
@ -377,7 +377,7 @@ PRUint32 pixSColor,pixSSColor;
s2 = s1;
d2 = d1;
for(x = 0; x < aNumbytes; x++){
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
FAST_DIVIDE_BY_255(temp1,((*d2)*val1)+((*s2)*val2));
if(temp1>255){
temp1 = 255;
}
@ -403,7 +403,7 @@ PRUint32 pixSColor,pixSSColor;
if((pixSColor!=srccolor) || (pixSSColor!=secsrccolor)) {
for(i=0;i<3;i++){
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
FAST_DIVIDE_BY_255(temp1,((*d2)*val1)+((*s2)*val2));
if(temp1>255){
temp1 = 255;
}
@ -487,17 +487,17 @@ PRInt16 dspan,sspan,span;
if ((stemp != srccolor) || (sstemp != secsrccolor)) {
dtemp = *d2;
red = (RED16(dtemp) * val1 + RED16(stemp) * val2) >> 8;
FAST_DIVIDE_BY_255(red, RED16(dtemp) * val1 + RED16(stemp) * val2);
if (red > 255)
red = 255;
green = (GREEN16(dtemp) * val1 + GREEN16(stemp) * val2) >> 8;
FAST_DIVIDE_BY_255(green, GREEN16(dtemp) * val1 + GREEN16(stemp) * val2);
if (green > 255)
green = 255;
blue = (BLUE16(dtemp) * val1 + BLUE16(stemp) * val2) >> 8;
FAST_DIVIDE_BY_255(blue, BLUE16(dtemp) * val1 + BLUE16(stemp) * val2);
if (blue > 255)
blue = 255;
@ -523,17 +523,17 @@ PRInt16 dspan,sspan,span;
stemp = *s2;
dtemp = *d2;
red = (RED16(dtemp) * val1 + RED16(stemp) * val2) >> 8;
FAST_DIVIDE_BY_255(red, RED16(dtemp) * val1 + RED16(stemp) * val2);
if (red > 255)
red = 255;
green = (GREEN16(dtemp) * val1 + GREEN16(stemp) * val2) >> 8;
FAST_DIVIDE_BY_255(green, GREEN16(dtemp) * val1 + GREEN16(stemp) * val2);
if (green > 255)
green = 255;
blue = (BLUE16(dtemp) * val1 + BLUE16(stemp) * val2) >> 8;
FAST_DIVIDE_BY_255(blue, BLUE16(dtemp) * val1 + BLUE16(stemp) * val2);
if (blue > 255)
blue = 255;

Просмотреть файл

@ -362,9 +362,12 @@ void nsImageWin::CreateImageWithAlphaBits(HDC TheHDC)
for (int x = 0; x < mBHead->biWidth;
x++, imageWithAlphaRow += 4, imageRow++, alphaRow++) {
imageWithAlphaRow[0] = (mColorMap->Index[3 * (*imageRow)] * *alphaRow) >> 8;
imageWithAlphaRow[1] = (mColorMap->Index[3 * (*imageRow) + 1] * *alphaRow) >> 8;
imageWithAlphaRow[2] = (mColorMap->Index[3 * (*imageRow) + 2] * *alphaRow) >> 8;
FAST_DIVIDE_BY_255(imageWithAlphaRow[0],
mColorMap->Index[3 * (*imageRow)] * *alphaRow);
FAST_DIVIDE_BY_255(imageWithAlphaRow[1],
mColorMap->Index[3 * (*imageRow) + 1] * *alphaRow);
FAST_DIVIDE_BY_255(imageWithAlphaRow[2],
mColorMap->Index[3 * (*imageRow) + 2] * *alphaRow);
imageWithAlphaRow[3] = *alphaRow;
}
}
@ -376,9 +379,9 @@ void nsImageWin::CreateImageWithAlphaBits(HDC TheHDC)
for (int x = 0; x < mBHead->biWidth;
x++, imageWithAlphaRow += 4, imageRow += 3, alphaRow++) {
imageWithAlphaRow[0] = (imageRow[0] * *alphaRow) >> 8;
imageWithAlphaRow[1] = (imageRow[1] * *alphaRow) >> 8;
imageWithAlphaRow[2] = (imageRow[2] * *alphaRow) >> 8;
FAST_DIVIDE_BY_255(imageWithAlphaRow[0], imageRow[0] * *alphaRow);
FAST_DIVIDE_BY_255(imageWithAlphaRow[1], imageRow[1] * *alphaRow);
FAST_DIVIDE_BY_255(imageWithAlphaRow[2], imageRow[2] * *alphaRow);
imageWithAlphaRow[3] = *alphaRow;
}
}
@ -557,12 +560,10 @@ void nsImageWin::DrawComposited24(unsigned char *aBits, int aX, int aY, int aWid
for (int x = 0; x < aWidth;
x++, targetRow += 3, imageRow += 3, alphaRow++) {
targetRow[0] =
(targetRow[0] * (255 - *alphaRow) + imageRow[0] * *alphaRow) >> 8;
targetRow[1] =
(targetRow[1] * (255 - *alphaRow) + imageRow[1] * *alphaRow) >> 8;
targetRow[2] =
(targetRow[2] * (255 - *alphaRow) + imageRow[2] * *alphaRow) >> 8;
unsigned alpha = *alphaRow;
MOZ_BLEND(targetRow[0], targetRow[0], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], targetRow[1], imageRow[1], alpha);
MOZ_BLEND(targetRow[2], targetRow[2], imageRow[2], alpha);
}
}
}

Просмотреть файл

@ -329,6 +329,7 @@ findIndex24(unsigned mask)
}
}
// 32-bit (888) truecolor convert/composite function
void nsImageXlib::DrawComposited32(PRBool isLSB, PRBool flipBytes,
unsigned offsetX, unsigned offsetY,
@ -358,12 +359,10 @@ void nsImageXlib::DrawComposited32(PRBool isLSB, PRBool flipBytes,
for (unsigned i=0; i<width;
i++, baseRow+=4, targetRow+=3, imageRow+=3, alphaRow++)
{
targetRow[0] = (unsigned(baseRow[redIndex]) * (255-*alphaRow) +
unsigned(imageRow[0]) * *alphaRow) >> 8;
targetRow[1] = (unsigned(baseRow[greenIndex]) * (255-*alphaRow) +
unsigned(imageRow[1]) * *alphaRow) >> 8;
targetRow[2] = (unsigned(baseRow[blueIndex]) * (255-*alphaRow) +
unsigned(imageRow[2]) * *alphaRow) >> 8;
unsigned alpha = *alphaRow;
MOZ_BLEND(targetRow[0], baseRow[redIndex], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], baseRow[greenIndex], imageRow[1], alpha);
MOZ_BLEND(targetRow[2], baseRow[blueIndex], imageRow[2], alpha);
}
}
}
@ -395,15 +394,10 @@ nsImageXlib::DrawComposited24(PRBool isLSB, PRBool flipBytes,
for (unsigned i=0; i<width;
i++, baseRow+=3, targetRow+=3, imageRow+=3, alphaRow++) {
targetRow[0] =
(unsigned(baseRow[redIndex]) * (255-*alphaRow) +
unsigned(imageRow[0]) * *alphaRow) >> 8;
targetRow[1] =
(unsigned(baseRow[greenIndex]) * (255-*alphaRow) +
unsigned(imageRow[1]) * *alphaRow) >> 8;
targetRow[2] =
(unsigned(baseRow[blueIndex]) * (255-*alphaRow) +
unsigned(imageRow[2]) * *alphaRow) >> 8;
unsigned alpha = *alphaRow;
MOZ_BLEND(targetRow[0], baseRow[redIndex], imageRow[0], alpha);
MOZ_BLEND(targetRow[1], baseRow[greenIndex], imageRow[1], alpha);
MOZ_BLEND(targetRow[2], baseRow[blueIndex], imageRow[2], alpha);
}
}
}
@ -452,21 +446,20 @@ nsImageXlib::DrawComposited16(PRBool isLSB, PRBool flipBytes,
pix = *((short *)tmp);
} else
pix = *((short *)baseRow);
targetRow[0] =
(redScale[(pix&visual->red_mask) >>
xlib_get_shift_from_mask(visual->red_mask)] *
(255-*alphaRow) + unsigned(imageRow[0]) * *alphaRow) >> 8;
targetRow[1] =
(greenScale[(pix&visual->green_mask) >>
xlib_get_shift_from_mask(visual->green_mask)] *
(255-*alphaRow) + unsigned(imageRow[1]) * *alphaRow) >> 8;
targetRow[2] =
(blueScale[(pix&visual->blue_mask) >>
xlib_get_shift_from_mask(visual->blue_mask)] *
(255-*alphaRow) + unsigned(imageRow[2]) * *alphaRow) >> 8;
unsigned alpha = *alphaRow;
MOZ_BLEND(targetRow[0],
redScale[(pix&visual->red_mask)>>visual->red_shift],
imageRow[0], alpha);
MOZ_BLEND(targetRow[1],
greenScale[(pix&visual->green_mask)>>visual->green_shift],
imageRow[1], alpha);
MOZ_BLEND(targetRow[2],
blueScale[(pix&visual->blue_mask)>>visual->blue_shift],
imageRow[2], alpha);
}
}
}
// Generic convert/composite function
void
nsImageXlib::DrawCompositedGeneral(PRBool isLSB, PRBool flipBytes,
@ -584,12 +577,10 @@ nsImageXlib::DrawCompositedGeneral(PRBool isLSB, PRBool flipBytes,
unsigned char *imageRow = mImageBits +(y+offsetY)*mRowBytes+3*offsetX;
unsigned char *alphaRow = mAlphaBits +(y+offsetY)*mAlphaRowBytes+offsetX;
for (unsigned i=0; i<width; i++) {
targetRow[3*i] = (unsigned(targetRow[3*i])*(255-alphaRow[i]) +
unsigned(imageRow[3*i])*alphaRow[i])>>8;
targetRow[3*i+1] = (unsigned(targetRow[3*i+1])*(255-alphaRow[i]) +
unsigned(imageRow[3*i+1])*alphaRow[i])>>8;
targetRow[3*i+2] = (unsigned(targetRow[3*i+2])*(255-alphaRow[i]) +
unsigned(imageRow[3*i+2])*alphaRow[i])>>8;
unsigned alpha = alphaRow[i];
MOZ_BLEND(targetRow[3*i], targetRow[3*i], imageRow[3*i], alpha);
MOZ_BLEND(targetRow[3*i+1], targetRow[3*i+1], imageRow[3*i+1], alpha);
MOZ_BLEND(targetRow[3*i+2], targetRow[3*i+2], imageRow[3*i+2], alpha);
}
}
}