Intermediate 16 bit blending

git-svn-id: svn://10.0.0.236/trunk@5141 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dcone
1998-07-08 14:31:31 +00:00
parent 1301adda9f
commit eb99bfd773
4 changed files with 262 additions and 57 deletions

View File

@@ -62,8 +62,7 @@ public:
* @param aSrcOpacity 0.0f -> 1.0f opacity value of source area. 1.0f indicates
* complete opacity.
*/
virtual void Blend(nsDrawingSurface aSrc,
PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
virtual nsresult Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsDrawingSurface aDest, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea) = 0;
/**

View File

@@ -119,10 +119,11 @@ nsBlenderWin::CleanUp()
//------------------------------------------------------------
void
nsBlenderWin::Blend(nsDrawingSurface aSrc,PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsresult
nsBlenderWin::Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsDrawingSurface aDst, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea)
{
nsresult result = NS_ERROR_FAILURE;
HDC dstdc,tb1;
HBITMAP dstbits;
nsPoint srcloc,maskloc;
@@ -146,7 +147,7 @@ nsColorMap *colormap;
oldsize = mSaveLS*mSaveNumLines;
// allocate some memory
mSaveLS = CalcBytesSpan(numbytes,mDstInfo.bmBitsPixel);
mSaveLS = numbytes;
mSaveNumLines = numlines;
size = mSaveLS * numlines;
mSaveNumBytes = numbytes;
@@ -171,13 +172,14 @@ nsColorMap *colormap;
{
if(mask)
{
numbytes/=3; // since the mask is only 8 bits, this routine wants number of pixels
this->Do24BlendWithMask(numlines,numbytes,s1,d1,m1,slinespan,dlinespan,mlinespan,nsHighQual,aSaveBlendArea);
result = NS_OK;
}
else
{
level = (PRInt32)(aSrcOpacity*100);
this->Do24Blend(level,numlines,numbytes,s1,d1,slinespan,dlinespan,nsHighQual,aSaveBlendArea);
result = NS_OK;
}
}
else
@@ -186,11 +188,24 @@ nsColorMap *colormap;
if(mask)
{
this->Do8BlendWithMask(numlines,numbytes,s1,d1,m1,slinespan,dlinespan,mlinespan,nsHighQual,aSaveBlendArea);
result = NS_OK;
}
else
{
level = (PRInt32)(aSrcOpacity*100);
this->Do8Blend(level,numlines,numbytes,s1,d1,slinespan,dlinespan,colormap,nsHighQual,aSaveBlendArea);
result = NS_OK;
}
}
else
{
if ((mSrcInfo.bmBitsPixel==16) && (mDstInfo.bmBitsPixel==16))
{
if(!mask)
{
this->Do16Blend(level,numlines,numbytes,s1,d1,slinespan,dlinespan,nsHighQual,aSaveBlendArea);
result = NS_OK;
}
}
}
@@ -201,6 +216,7 @@ nsColorMap *colormap;
::DeleteObject(tb1);
}
return result;
}
//------------------------------------------------------------
@@ -340,14 +356,21 @@ nsBlenderWin :: BuildDIB(LPBITMAPINFOHEADER *aBHead,unsigned char **aBits,PRInt
{
PRInt32 numpalletcolors,imagesize,spanbytes;
PRUint8 *colortable;
DWORD bicomp;
switch (aDepth)
{
case 8:
numpalletcolors = 256;
bicomp = BI_RGB;
break;
case 16:
numpalletcolors = 0;
bicomp = BI_RGB;
break;
case 24:
numpalletcolors = 0;
bicomp = BI_RGB;
break;
default:
numpalletcolors = -1;
@@ -363,7 +386,7 @@ PRUint8 *colortable;
(*aBHead)->biHeight = aHeight;
(*aBHead)->biPlanes = 1;
(*aBHead)->biBitCount = (unsigned short) aDepth;
(*aBHead)->biCompression = BI_RGB;
(*aBHead)->biCompression = bicomp;
(*aBHead)->biSizeImage = 0; // not compressed, so we dont need this to be set
(*aBHead)->biXPelsPerMeter = 0;
(*aBHead)->biYPelsPerMeter = 0;
@@ -539,6 +562,109 @@ PRUint8 *saveptr,*sv2;
//------------------------------------------------------------
#define RED16(x) ((x)&0x7C00)>>7
#define GREEN16(x) ((x)&0x3E0)>>2
#define BLUE16(x) ((x)&0x1F)<<3
// This routine can not be fast enough
void
nsBlenderWin::Do16Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea)
{
PRUint16 *d1,*d2,*s1,*s2;
PRUint32 val1,val2,red,green,blue;
PRInt32 x,y,numlines,xinc,yinc;
PRUint16 *saveptr,*sv2;
PRInt16 dspan,sspan,span,savesp;
// since we are using 16 bit pointers, the num bytes need to be cut by 2
saveptr = (PRUint16*)mSaveBytes;
aBlendVal = (aBlendVal*255)/100;
val2 = aBlendVal;
val1 = 255-val2;
// now go thru the image and blend (remember, its bottom upwards)
s1 = (PRUint16*)aSImage;
d1 = (PRUint16*)aDImage;
dspan = aDLSpan/2;
sspan = aSLSpan/2;
span = aNumbytes/2;
savesp = mSaveLS/2;
numlines = aNumlines;
xinc = 1;
yinc = 1;
if(aSaveBlendArea)
{
for(y = 0; y < aNumlines; y++)
{
s2 = s1;
d2 = d1;
sv2 = saveptr;
for(x=0;x<span;x++)
{
red = ((PRUint32)(RED16(*d2))*val1+(PRUint32)(RED16(*s2)*val2))>>8;
if(red>255)
red = 255;
green = ((PRUint32)(GREEN16(*d2))*val1+(PRUint32)(GREEN16(*s2)*val2))>>8;
if(green>255)
green = 255;
blue = ((PRUint32)(BLUE16(*d2))*val1+(PRUint32)(BLUE16(*s2)*val2))>>8;
if(blue>255)
blue = 255;
*sv2 = *d2;
*d2 = ((red&0xF8)<<7) | ((green&0xF8)<<2) | (blue&0xF8)>>3;
sv2++;
d2++;
s2++;
}
s1 += sspan;
d1 += dspan;
saveptr += savesp;
}
}
else
{
for(y = 0; y < aNumlines; y++)
{
s2 = s1;
d2 = d1;
for(x = 0; x < aNumbytes; x++)
{
red = RED16(*d2)*val1+RED16(*s2)*val2;
if(red>255)
red = 255;
green = GREEN16(*d2)*val1+GREEN16(*s2)*val2;
if(green>255)
green = 255;
blue = BLUE16(*d2)*val1+BLUE16(*s2)*val2;
if(blue>255)
blue = 255;
*d2 = ((red&0xf8)<<7) | ((green&0xf8)<<2) | ((blue&0xf8)>>3);
d2++;
s2++;
}
s1 += aSLSpan;
d1 += aDLSpan;
}
}
}
//------------------------------------------------------------
// This routine can not be fast enough
void
nsBlenderWin::Do8BlendWithMask(PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRUint8 *aMImage,PRInt32 aSLSpan,PRInt32 aDLSpan,PRInt32 aMLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea)

View File

@@ -40,9 +40,8 @@ public:
virtual nsresult Init(nsDrawingSurface aSrc,nsDrawingSurface aDst);
virtual void CleanUp();
virtual void Blend(nsDrawingSurface aSrc,
PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsDrawingSurface aDest, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea);
virtual nsresult Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsDrawingSurface aDest, PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,PRBool aSaveBlendArea);
nsDrawingSurface GetSrcDS() {return(mSrcDC);}
nsDrawingSurface GetDstDS() {return(mDstDC);}
@@ -105,10 +104,27 @@ public:
* @param aBlendQuality The quality of this blend, this is for tweening if neccesary
* @param aSaveBlendArea informs routine if the area affected area will be save first
*/
void Do24Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,
PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea);
/**
* Blend two 16 bit image arrays using a passed in blend value
* @param aNumlines Number of lines to blend
* @param aNumberBytes Number of bytes per line to blend
* @param aSImage Pointer to beginning of the source bytes
* @param aDImage Pointer to beginning of the destination bytes
* @param aMImage Pointer to beginning of the mask bytes
* @param aSLSpan number of bytes per line for the source bytes
* @param aDLSpan number of bytes per line for the destination bytes
* @param aMLSpan number of bytes per line for the Mask bytes
* @param aBlendQuality The quality of this blend, this is for tweening if neccesary
* @param aSaveBlendArea informs routine if the area affected area will be save first
*/
void Do16Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,
PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality,PRBool aSaveBlendArea);
/**
* Blend two 8 bit image arrays using an 8 bit alpha mask
* @param aNumlines Number of lines to blend

View File

@@ -72,7 +72,7 @@ static PRBool gCanBlend = PR_FALSE;
static HBITMAP gDobits,gSobits,gSrcbits,gDestbits;
static HDC gDestdc,gSrcdc,gScreendc;
extern void Compositetest(nsIBlender *aBlender,nsIImage *aImage,
extern nsresult Compositetest(nsIBlender *aBlender,nsIImage *aImage,
PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth,PRInt32 aHeight,
PRInt32 aDX,PRInt32 aDY,
float aBlendAmount,PRBool aBuff);
@@ -88,6 +88,9 @@ extern nsresult BuildDIB(LPBITMAPINFOHEADER *aBHead,unsigned char **aBits,PRInt
extern PRInt32 CalcBytesSpan(PRUint32 aWidth,PRUint32 aBitsPixel);
#define RED16(x) ((x)&0x7C00)>>7
#define GREEN16(x) ((x)&0x3E0)>>2
#define BLUE16(x) ((x)&0x1F)<<3
//------------------------------------------------------------
@@ -288,9 +291,7 @@ nsresult rv;
rv = NSRepository::CreateInstance(kBlenderCID, nsnull, kBlenderIID, (void **)&gImageblender);
gImageblender->Init(gSrcdc,gDestdc);
}
}
//------------------------------------------------------------
@@ -315,6 +316,7 @@ void
Restore(nsIBlender *aBlender,nsIImage *aImage)
{
PRUint8 *thebytes,*curbyte,*srcbytes,*cursourcebytes;
PRUint16 *cur16;
PRInt32 w,h,ls,x,y,numbytes,sls;
HDC dstdc;
HBITMAP srcbits,tb1;
@@ -343,22 +345,45 @@ nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
w = aImage->GetWidth();
ls = aImage->GetLineStride();
sls = CalcBytesSpan(srcinfo.bmWidth,srcinfo.bmBitsPixel);
for(y=0;y<h;y++)
if(srcinfo.bmBitsPixel==24)
{
curbyte = thebytes + (y*ls);
cursourcebytes = srcbytes + (y*sls);
for(x=0;x<ls;x++)
for(y=0;y<h;y++)
{
*curbyte = *cursourcebytes;
curbyte++;
cursourcebytes++;
curbyte = thebytes + (y*ls);
cursourcebytes = srcbytes + (y*sls);
for(x=0;x<ls;x++)
{
*curbyte = *cursourcebytes;
curbyte++;
cursourcebytes++;
}
}
}
else
if(srcinfo.bmBitsPixel==16) // 16 bit going into a 24 bit
{
for(y=0;y<h;y++)
{
curbyte = thebytes + (y*ls);
cur16 = (PRUint16*)(srcbytes + (y*sls));
for(x=0;x<w;x++)
{
*curbyte = BLUE16(*cur16);
curbyte++;
*curbyte = GREEN16(*cur16);
curbyte++;
*curbyte = RED16(*cur16);
curbyte++;
cur16++;
}
}
}
delete [] srcbytes;
delete srcbinfo;
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
//drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
}
//------------------------------------------------------------
@@ -366,6 +391,7 @@ nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
void
InterActiveBlend(nsIBlender *aBlender,nsIImage *aImage)
{
nsresult result;
float blendamount;
nsString str;
PRInt32 numerror,i,height,width;
@@ -392,27 +418,35 @@ MSG msg;
width = gBlendImage->GetWidth();
height = gBlendImage->GetHeight();
Compositetest(aBlender,aImage,cpos.x,cpos.y,width,height,0,0,blendamount,PR_TRUE);
Restore(aBlender,aImage);
result = Compositetest(aBlender,aImage,cpos.x,cpos.y,width,height,0,0,blendamount,PR_TRUE);
if(GetMessage(&msg,NULL,0,0))
if(result == NS_OK)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
Restore(aBlender,aImage);
if(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
break;
}
}
}
//------------------------------------------------------------
void
nsresult
Compositetest(nsIBlender *aBlender,nsIImage *aImage,
PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth,PRInt32 aHeight,
PRInt32 aDX, PRInt32 aDY,
float aBlendAmount,PRBool aBuff)
{
nsresult result = NS_ERROR_FAILURE;
PRUint8 *thebytes,*curbyte,*srcbytes,*cursourcebytes;
PRUint16 *cur16;
PRInt32 w,h,ls,x,y,numbytes,sls;
HDC srcdc,dstdc;
HBITMAP srcbits,tb1;
@@ -424,42 +458,71 @@ nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
srcdc = aBlender->GetSrcDS();
dstdc = aBlender->GetDstDS();
aBlender->Blend(srcdc,aSX,aSY,aWidth,aHeight,dstdc,0, 0,aBlendAmount,aBuff);
result = aBlender->Blend(aSX,aSY,aWidth,aHeight,dstdc,0, 0,aBlendAmount,aBuff);
// this takes the Destination DC and copies the information into aImage
tb1 = CreateCompatibleBitmap(dstdc,3,3);
srcbits = ::SelectObject(dstdc, tb1);
numbytes = ::GetObject(srcbits,sizeof(BITMAP),&srcinfo);
// put into a DIB
BuildDIB(&srcbinfo,&srcbytes,srcinfo.bmWidth,srcinfo.bmHeight,srcinfo.bmBitsPixel);
numbytes = ::GetDIBits(dstdc,srcbits,0,srcinfo.bmHeight,srcbytes,(LPBITMAPINFO)srcbinfo,DIB_RGB_COLORS);
::SelectObject(dstdc,srcbits);
DeleteObject(tb1);
// copy the information back into the source
thebytes = aImage->GetBits();
h = aImage->GetHeight();
w = aImage->GetWidth();
ls = aImage->GetLineStride();
sls = CalcBytesSpan(srcinfo.bmWidth,srcinfo.bmBitsPixel);
for(y=0;y<h;y++)
if(result == NS_OK)
{
curbyte = thebytes + (y*ls);
cursourcebytes = srcbytes + (y*sls);
for(x=0;x<ls;x++)
// this takes the Destination DC and copies the information into aImage
tb1 = CreateCompatibleBitmap(dstdc,3,3);
srcbits = ::SelectObject(dstdc, tb1);
numbytes = ::GetObject(srcbits,sizeof(BITMAP),&srcinfo);
// put into a DIB
BuildDIB(&srcbinfo,&srcbytes,srcinfo.bmWidth,srcinfo.bmHeight,srcinfo.bmBitsPixel);
numbytes = ::GetDIBits(dstdc,srcbits,0,srcinfo.bmHeight,srcbytes,(LPBITMAPINFO)srcbinfo,DIB_RGB_COLORS);
::SelectObject(dstdc,srcbits);
DeleteObject(tb1);
// copy the information back into the source
thebytes = aImage->GetBits();
h = aImage->GetHeight();
w = aImage->GetWidth();
ls = aImage->GetLineStride();
sls = CalcBytesSpan(srcinfo.bmWidth,srcinfo.bmBitsPixel);
// put the bitmap back into the image
if(srcinfo.bmBitsPixel==24)
{
*curbyte = *cursourcebytes;
curbyte++;
cursourcebytes++;
for(y=0;y<h;y++)
{
curbyte = thebytes + (y*ls);
cursourcebytes = srcbytes + (y*sls);
for(x=0;x<ls;x++)
{
*curbyte = *cursourcebytes;
curbyte++;
cursourcebytes++;
}
}
}
}
else
if(srcinfo.bmBitsPixel==16) // 16 bit going into a 24 bit
{
for(y=0;y<h;y++)
{
curbyte = thebytes + (y*ls);
cur16 = (PRUint16*)(srcbytes + (y*sls));
for(x=0;x<w;x++)
{
*curbyte = BLUE16(*cur16);
curbyte++;
*curbyte = GREEN16(*cur16);
curbyte++;
*curbyte = RED16(*cur16);
curbyte++;
cur16++;
}
}
}
delete [] srcbytes;
delete srcbinfo;
delete [] srcbytes;
delete srcbinfo;
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
}
return(result);
}
//------------------------------------------------------------
@@ -1091,6 +1154,7 @@ PRUint8 *colortable;
case 8:
numpalletcolors = 256;
break;
case 16:
case 24:
numpalletcolors = 0;
break;