speed up of alpha, some small fixes, inter checkin

This commit is contained in:
dcone 1998-05-13 14:28:16 +00:00
parent f604d0bdd4
commit 0e94d920e1
6 changed files with 303 additions and 108 deletions

View File

@ -42,6 +42,12 @@ typedef enum {
nsMaskRequirements_kNeeds8Bit
} nsMaskRequirements;
typedef enum{
nsHighQual,
nsMedQual,
nsLowQual
}nsBlendQuality;
#define nsImageUpdateFlags_kColorMapChanged 0x1
#define nsImageUpdateFlags_kBitsChanged 0x2
@ -54,7 +60,9 @@ typedef enum {
// Interface to Images
class nsIImage : public nsISupports
{
public:
/**
* Build and initialize the pixelmap
* @param aWidth The width in pixels of the desired pixelmap
@ -183,7 +191,7 @@ public:
* @param aTheImage The image to blend into this image
* @param aULLocation The upper left coordinate to place the passed in image
*/
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation) = 0;
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation,nsBlendQuality aQuality) = 0;
/**
* Build an alpha mask using this image

View File

@ -236,12 +236,12 @@ PRBool nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurfa
//------------------------------------------------------------
void nsImageWin::CompositeImage(nsIImage *aTheImage, nsPoint *aULLocation)
void nsImageWin::CompositeImage(nsIImage *aTheImage, nsPoint *aULLocation,nsBlendQuality aBlendQuality)
{
// call the correct sub routine for each blend
if ((mNumBytesPixel == 3) && (((nsImageWin *)aTheImage)->mNumBytesPixel == 3))
this->Comp24to24((nsImageWin*)aTheImage, aULLocation);
this->Comp24to24((nsImageWin*)aTheImage, aULLocation,aBlendQuality);
}
@ -275,18 +275,17 @@ PRUint8 *srcbits;
//------------------------------------------------------------
// this routine has to flip the y, since the bits are in bottom scan
// line to top.
void nsImageWin::Comp24to24(nsImageWin *aTheImage, nsPoint *aULLocation)
PRBool nsImageWin::CalcAlphaMetrics(nsIImage *aTheImage,nsPoint *aULLocation,PRInt32 *aNumlines,
PRInt32 *aNumbytes,PRUint8 **aSImage,PRUint8 **aDImage,
PRUint8 **aMImage,PRInt32 *aSLSpan,PRInt32 *aDLSpan,PRInt32 *aMLSpan)
{
PRBool doalpha = PR_FALSE;
nsRect arect,srect,drect,irect;
PRInt32 dlinespan,slinespan,mlinespan,startx,starty,numbytes,numlines,x,y;
PRInt16 temp;
PRUint8 *alphabits, *d1,*d2,*s1,*s2,*m1,*m2;
double a1,a2;
PRInt32 startx,starty,x,y;
PRUint8 *alphabits;
if( IsOptimized() )
return;
return doalpha;
alphabits = aTheImage->GetAlphaBits();
if(alphabits)
@ -307,12 +306,12 @@ double a1,a2;
if (irect.IntersectRect(srect, drect))
{
// calculate destination information
dlinespan = this->GetLineStride();
numbytes = this->CalcBytesSpan(irect.width);
numlines = irect.height;
*aDLSpan = this->GetLineStride();
*aNumbytes = this->CalcBytesSpan(irect.width);
*aNumlines = irect.height;
startx = irect.x;
starty = this->GetHeight() - (irect.y + irect.height);
d1 = mImageBits + (starty * dlinespan) + (3 * startx);
*aDImage = mImageBits + (starty * (*aDLSpan)) + (3 * startx);
// get the intersection relative to the source rectangle
srect.SetRect(0, 0, aTheImage->GetWidth(), aTheImage->GetHeight());
@ -320,77 +319,150 @@ double a1,a2;
drect.MoveBy(-aULLocation->x, -aULLocation->y);
drect.IntersectRect(drect,srect);
slinespan = aTheImage->GetLineStride();
*aSLSpan = aTheImage->GetLineStride();
startx = drect.x;
starty = aTheImage->GetHeight() - (drect.y + drect.height);
s1 = aTheImage->GetBits() + (starty * slinespan) + (3 * startx);
*aSImage = aTheImage->GetBits() + (starty * (*aSLSpan)) + (3 * startx);
// 24 bit
*aNumbytes/=3;
doalpha = PR_TRUE;
if(alphabits)
{
mlinespan = aTheImage->GetAlphaLineStride();
m1 = alphabits;
numbytes/=3;
// now go thru the image and blend (remember, its bottom upwards)
for (y = 0; y < numlines; y++)
{
s2 = s1;
d2 = d1;
m2 = m1;
for(x=0;x<numbytes;x++)
{
a1 = (*m2) * (1.0 / 256.0);
a2 = 1.0-a1;
temp = (PRUint16)((*d2)*a1 + (*s2)*a2);
if(temp>255)
temp = 255;
*d2 = (PRUint8)temp;
d2++;
s2++;
temp = (PRUint16)((*d2)*a1 + (*s2)*a2);
if(temp>255)
temp = 255;
*d2 = (PRUint8)temp;
d2++;
s2++;
temp = (PRUint16)((*d2)*a1 + (*s2)*a2);
if(temp>255)
temp = 255;
*d2 = (PRUint8)temp;
d2++;
s2++;
m2++;
}
s1 += slinespan;
d1 += dlinespan;
m1 += mlinespan;
*aMLSpan = aTheImage->GetAlphaLineStride();
*aMImage = alphabits;
}
}
else
{
// now go thru the image and blend (remember, its bottom upwards)
for(y = 0; y < numlines; y++)
{
s2 = s1;
d2 = d1;
for(x = 0; x < numbytes; x++)
{
*d2 = (*d2 + *s2) >> 1;
d2++;
s2++;
}
s1 += slinespan;
d1 += dlinespan;
}
aMLSpan = 0;
*aMImage = nsnull;
}
}
return doalpha;
}
//------------------------------------------------------------
// this routine has to flip the y, since the bits are in bottom scan
// line to top.
void nsImageWin::Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation,nsBlendQuality aBlendQuality)
{
nsRect arect,srect,drect,irect;
PRInt32 dlinespan,slinespan,mlinespan,numbytes,numlines;
PRUint8 *alphabits,*s1,*d1,*m1;
if( IsOptimized() )
return;
if(CalcAlphaMetrics(aTheImage,aULLocation,&numlines,&numbytes,&s1,&d1,&m1,&slinespan,&dlinespan,&mlinespan))
{
if(alphabits)
{
Do24BlendWithMask(numlines,numbytes,s1,d1,m1,slinespan,dlinespan,mlinespan,aBlendQuality);
}
else
{
Do24Blend(50,numlines,numbytes,s1,d1,slinespan,dlinespan,aBlendQuality);
}
}
}
//------------------------------------------------------------
// This routine can not be fast enough
void
nsImageWin::Do24BlendWithMask(PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRUint8 *aMImage,PRInt32 aSLSpan,PRInt32 aDLSpan,PRInt32 aMLSpan,nsBlendQuality aBlendQuality)
{
PRUint8 *d1,*d2,*s1,*s2,*m1,*m2;
PRInt32 x,y,val1,val2,temp1,inc;
PRInt32 sspan,dspan,mspan;
if(aBlendQuality == nsHighQual )
inc = 1;
else
inc = 2;
sspan = aSLSpan*inc;
dspan = aDLSpan*inc;
mspan = aMLSpan*inc;
// now go thru the image and blend (remember, its bottom upwards)
s1 = aSImage;
d1 = aDImage;
m1 = aMImage;
printf("increment = %d\n",inc);
for (y = 0; y < aNumlines; y+=inc)
{
s2 = s1;
d2 = d1;
m2 = m1;
for(x=0;x<aNumbytes;x++)
{
val1 = (*m2);
val2 = 255-val1;
temp1 = (((*d2)*val1)/255)+(((*s2)*val2)/255);
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
temp1 = (((*d2)*val1)/255)+(((*s2)*val2)/255);
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
temp1 = (((*d2)*val1)/255)+(((*s2)*val2)/255);
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
m2++;
}
s1 += sspan;
d1 += dspan;
m1 += mspan;
}
}
//------------------------------------------------------------
// This routine can not be fast enough
void
nsImageWin::Do24Blend(PRInt8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality)
{
PRInt32 x,y;
PRUint8 *d1,*d2,*s1,*s2;
// now go thru the image and blend (remember, its bottom upwards)
s1 = aSImage;
d1 = aDImage;
for(y = 0; y < aNumlines; y++)
{
s2 = s1;
d2 = d1;
for(x = 0; x < aNumbytes; x++)
{
*d2 = (*d2 + *s2) >> 1;
d2++;
s2++;
}
s1 += aSLSpan;
d1 += aDLSpan;
}
}
//------------------------------------------------------------
@ -400,24 +472,23 @@ nsImageWin::DuplicateImage()
{
PRInt32 num,i;
nsImageWin *theimage;
PRUint8 *cpointer;
if( IsOptimized() )
return nsnull;
theimage = new nsImageWin();
NS_ADDREF(theimage);
// get the header and copy it
theimage->mBHead = (LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * theimage->mNumPalleteColors];
//*(theimage->mBHead) = *(this->mBHead);
num = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * theimage->mNumPalleteColors;
memcpy(theimage->mBHead,this->mBHead,num);
// set in compute metrics
theimage->mSizeImage = this->mSizeImage;
theimage->mRowBytes = this->mRowBytes;
theimage->mColorTable = (PRUint8 *)this->mBHead + sizeof(BITMAPINFOHEADER);
theimage->mColorTable = (PRUint8 *)theimage->mBHead + sizeof(BITMAPINFOHEADER);
theimage->mNumBytesPixel = this->mNumBytesPixel;
theimage->mNumPalleteColors = this->mNumPalleteColors;
theimage->mAlphaDepth = this->mAlphaDepth;
@ -428,7 +499,9 @@ PRUint8 *cpointer;
theimage->mIsOptimized = this->mIsOptimized;
// set up the memory
memset(mColorTable, 0, sizeof(RGBQUAD) * mNumPalleteColors);
num = sizeof(RGBQUAD) * mNumPalleteColors;
if(num>0)
memcpy(mColorTable,this->mColorTable,sizeof(RGBQUAD) * mNumPalleteColors);
// the bits of the image
if(theimage->mSizeImage>0)
@ -458,17 +531,11 @@ PRUint8 *cpointer;
memset(theimage->mColorMap->Index, 0, sizeof(PRUint8) * (3 * theimage->mNumPalleteColors));
}
cpointer = theimage->mColorTable;
for(i = 0; i < theimage->mColorMap->NumColors; i++)
{
theimage->mColorMap->Index[(3 * i) + 2] = this->mColorMap->Index[(3 * i) + 2];
theimage->mColorMap->Index[(3 * i) + 1] = this->mColorMap->Index[(3 * i) + 1];
theimage->mColorMap->Index[(3 * i)] = this->mColorMap->Index[(3 * i)];
*cpointer++ = theimage->mColorMap->Index[(3 * i) + 2];
*cpointer++ = theimage->mColorMap->Index[(3 * i) + 1];
*cpointer++ = theimage->mColorMap->Index[(3 * i)];
*cpointer++ = 0;
}
theimage->MakePalette();
@ -548,6 +615,7 @@ PRBool nsImageWin :: SetSystemPalette(HDC* aHdc)
// creates an optimized bitmap, or HBITMAP
nsresult nsImageWin :: Optimize(nsDrawingSurface aSurface)
{
return NS_OK; // TAKE THIS OUT
HDC the_hdc = (HDC)aSurface;

View File

@ -51,8 +51,7 @@ public:
virtual PRInt32 GetAlphaXLoc() {return mLocation.x;}
virtual PRInt32 GetAlphaYLoc() {return mLocation.y;}
virtual PRInt32 GetAlphaLineStride(){ return mARowBytes; }
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation);
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation,nsBlendQuality aQuality);
virtual nsIImage* DuplicateImage();
/**
@ -102,6 +101,54 @@ public:
void MoveAlphaMask(PRInt32 aX, PRInt32 aY){mLocation.x=aX;mLocation.y=aY;}
private:
/**
* Blend two 24 bit image arrays using an 8 bit alpha mask
* @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
*/
void Do24BlendWithMask(PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,
PRUint8 *aMImage,PRInt32 aSLSpan,PRInt32 aDLSpan,PRInt32 aMLSpan,nsBlendQuality aBlendQuality);
/**
* Blend two 24 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
*/
void Do24Blend(PRInt8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,
PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality);
/**
* Calculate the information we need to do a blend
* @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
*/
PRBool CalcAlphaMetrics(nsIImage *aTheImage,nsPoint *aULLocation,PRInt32 *aNumlines,
PRInt32 *aNumbytes,PRUint8 **aSImage,PRUint8 **aDImage,
PRUint8 **aMImage,PRInt32 *SLSpan,PRInt32 *aDLSpan,PRInt32 *aMLSpan);
/**
* Clean up the memory used nsImageWin.
* @param aCleanUpAll if True, all the memory used will be released otherwise just clean up the DIB memory
@ -118,8 +165,9 @@ private:
* Composite a 24 bit image into another 24 bit image
* @param aTheImage The image to blend into this image
* @param aULLocation The upper left coordinate to place the passed in image
* @param aBlendQuality The quality of this blend, this is for tweening if neccesary
*/
void Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation);
void Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation,nsBlendQuality aBlendQuality);
/**
@ -133,15 +181,20 @@ private:
PRInt32 mRowBytes; // number of bytes per row
PRUint8 *mColorTable; // color table for the bitmap
PRUint8 *mImageBits; // starting address of DIB bits
PRBool mIsOptimized; // Have we turned our DIB into a GDI?
nsColorMap *mColorMap; // Redundant with mColorTable, but necessary
// alpha layer members
PRUint8 *mAlphaBits; // alpha layer if we made one
PRInt8 mAlphaDepth; // alpha layer depth
PRInt16 mARowBytes;
PRInt16 mAlphaWidth; // alpha layer width
PRInt16 mAlphaHeight; // alpha layer height
nsPoint mLocation; // alpha mask location
PRBool mIsOptimized; // Have we turned our DIB into a GDI?
nsColorMap *mColorMap; // Redundant with mColorTable, but necessary
// for Set/GetColorMap
PRInt8 mImageCache; // place to save off the old image for fast animation
// for Set/GetColorMap
HPALETTE mHPalette;
HBITMAP mHBitmap; // the GDI bitmap
LPBITMAPINFOHEADER mBHead; // BITMAPINFOHEADER

View File

@ -38,6 +38,8 @@
#include "nsGfxCIID.h"
#include "nsFont.h"
#include <windows.h>
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID);
@ -247,11 +249,12 @@ MyObserver::NotifyError(nsIImageRequest *aImageRequest,
void
Compositetest(PRInt32 aTestNum,nsIImage *aImage,nsIImage *aBImage,nsIImage *aMImage, PRInt32 aX, PRInt32 aY)
{
nsPoint *location;
PRUint32 min,seconds,milli,i,h,w;
SYSTEMTIME thetime;
nsPoint *location;
PRUint32 min,seconds,milli,i,h,w;
nsBlendQuality quality=nsMedQual;
SYSTEMTIME thetime;
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
nsIImage *theimage;
nsIImage *theimage;
if(aTestNum == 1)
@ -270,17 +273,11 @@ nsIImage *theimage;
printf("\n Image Location is %d, %d\n", location->x,location->y);
}
aImage->CompositeImage(aBImage,location);
aImage->CompositeImage(aBImage,location,quality);
}
if(aTestNum == 2)
{
if(aMImage)
{
aBImage->SetAlphaMask(aMImage);
}
printf("\nSTARTING Blending TEST\n");
::GetSystemTime(&thetime);
min = thetime.wMinute;
@ -292,20 +289,26 @@ nsIImage *theimage;
if(aMImage)
{
aBImage->SetAlphaMask(aMImage);
for(i=0;i<200;i++)
{
aBImage->MoveAlphaMask(rand()%w,rand()%h);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location);
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
}
}
else
for(i=0;i<200;i++)
{
aImage->CompositeImage(aBImage,location);
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
aBImage->MoveAlphaMask(rand()%w,rand()%h);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
}
::GetSystemTime(&thetime);
@ -321,7 +324,51 @@ nsIImage *theimage;
printf("The composite Time was %lu Milliseconds\n",milli);
}
if(aTestNum == 3)
{
location = new nsPoint(aX,aY);
if(aMImage)
{
aBImage->SetAlphaMask(aMImage);
for(i=0;i<200;i++)
{
DWORD pos = ::GetMessagePos();
POINT cpos;
cpos.x = LOWORD(pos);
cpos.y = HIWORD(pos);
::ScreenToClient(gHwnd, &cpos);
aBImage->MoveAlphaMask(cpos.x,cpos.y);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
MSG msg;
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
else
for(i=0;i<200;i++)
{
aBImage->MoveAlphaMask(rand()%w,rand()%h);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
}
}
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
// we are finished with this
@ -724,8 +771,11 @@ WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam)
if (OpenFileDialog(szFile, 256))
MyLoadImage(szFile,PR_TRUE,&gMaskImage);
break;
case COMPINT:
gTestNum = 3;
case COMPTST:
gTestNum = 1;
if(LOWORD(param) == COMPTST)
gTestNum = 1;
case COMPTSTSPEED:
if(LOWORD(param) == COMPTSTSPEED)
gTestNum = 2;
@ -794,6 +844,20 @@ WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam)
gImageManager->SetCacheSize(1024*1024);
break;
/*case WM_MOUSEMOVE:
{
DWORD pos = ::GetMessagePos();
POINT cpos;
cpos.x = LOWORD(pos);
cpos.y = HIWORD(pos);
::ScreenToClient(hWnd, &cpos);
// Dothing(cpos.x, cpos.y);
}
break;*/
case WM_DESTROY:
MyInterrupt();
MyReleaseImages();
@ -890,7 +954,7 @@ WinMain(HANDLE instance, HANDLE prevInstance, LPSTR cmdParam, int nCmdShow)
}
// Create our first top level window
HWND gHwnd = CreateTopLevel(class1Name, "Graphics tester", 620, 400);
gHwnd = CreateTopLevel(class1Name, "Graphics tester", 620, 400);
// Process messages
MSG msg;

View File

@ -29,6 +29,7 @@ IMAGETEST MENU DISCARDABLE
POPUP "TEST"
{
MENUITEM "Read Mask", RDMSK
MENUITEM "Composit Interactive",COMPINT
MENUITEM "Composit Test", COMPTST
MENUITEM "Composite Speed", COMPTSTSPEED
MENUITEM "Blit Speed",BSTNOOPT

View File

@ -30,5 +30,6 @@
#define COMPTST 40017
#define COMPTSTSPEED 40018
#define RDMSK 40019
#define COMPINT 40020
#endif /* resources_h___ */