Composition Work 24 bit complete

This commit is contained in:
dcone 1998-05-05 14:47:16 +00:00
parent 519b12bffe
commit 148da3401d
6 changed files with 305 additions and 62 deletions

View File

@ -161,6 +161,19 @@ public:
*/
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation) = 0;
/**
* Build an alpha mask using this image
* @param aTheMaskImage The image to build the mask from
* @return true if the mask was set up.
*/
virtual PRBool SetAlphaMask(nsIImage *aTheMask) = 0;
/**
* Move the alpha mask to this absolute location
* @param the horiztonal location
* @param the vertical location
*/
virtual void MoveAlphaMask(PRInt32 aX, PRInt32 aY) = 0;
//get the color space metrics for this image
//virtual NI_ColorSpec * GetColorSpec() = 0; fix

View File

@ -210,7 +210,142 @@ nsImageWin::CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation)
{
// call the correct sub routine for each blend
if( mNumBytesPixel==3 && ((nsImageWin*)aTheImage)->mNumBytesPixel==3)
this->Comp24to24((nsImageWin*)aTheImage,aULLocation);
}
//------------------------------------------------------------
// lets build an alpha mask from this image
PRBool
nsImageWin::SetAlphaMask(nsIImage *aTheMask)
{
PRInt32 num;
LPBYTE srcbits;
if(aTheMask && ((nsImageWin*)aTheMask)->mNumBytesPixel == 1)
{
mLocation.x = 0;
mLocation.y = 0;
mlphaDepth = 8;
mAlphaWidth = aTheMask->GetWidth();
mAlphaHeight = aTheMask->GetWidth();
num = mAlphaWidth*mAlphaHeight;
mARowBytes = aTheMask->GetLineStride();
mAlphaBits = new unsigned char[mARowBytes * mAlphaHeight];
srcbits = aTheMask->GetBits();
memcpy(mAlphaBits,srcbits,num);
return(PR_TRUE);
}
return(PR_FALSE);
}
//------------------------------------------------------------
// this routine has to flip the y, since the bits are in bottom scan
// line to top.
void
nsImageWin::Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation)
{
nsRect arect,srect,drect,irect;
PRInt32 dlinespan,slinespan,mlinespan,startx,starty,numbytes,numlines,x,y;
LPBYTE d1,d2,s1,s2,m1,m2;
double a1,a2;
if(mAlphaBits)
{
x = mLocation.x;
y = mLocation.y;
arect.SetRect(0,0,this->GetWidth(),this->GetHeight());
srect.SetRect(mLocation.x,mLocation.y,mAlphaWidth,mAlphaHeight);
arect.IntersectRect(arect,srect);
}
else
{
arect.SetRect(0,0,this->GetWidth(),this->GetHeight());
x = y = 0;
}
srect.SetRect(aULLocation->x,aULLocation->y,aTheImage->GetWidth(),aTheImage->GetHeight());
drect = arect;
if(irect.IntersectRect(srect,drect))
{
// calculate destination information
dlinespan = this->GetLineStride();
numbytes = this->CalcBytesSpan(irect.width);
numlines = irect.height;
startx = irect.x;
starty = this->GetHeight()-(irect.y+irect.height);
d1 = mImageBits +(starty*dlinespan)+(3*startx);
// get the intersection relative to the source rectangle
srect.SetRect(0,0,aTheImage->GetWidth(),aTheImage->GetHeight());
drect = irect;
drect.MoveBy(-aULLocation->x,-aULLocation->y);
drect.IntersectRect(drect,srect);
slinespan = aTheImage->GetLineStride();
startx = drect.x;
starty = aTheImage->GetHeight() - (drect.y+drect.height);
s1 = aTheImage->GetBits() + (starty*slinespan)+(3*startx);
if(mAlphaBits)
{
mlinespan = this->GetAlphaLineStride();
m1 = mAlphaBits;
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)/256.0;
a2 = 1.0-a1;
*d2 = (*d2)*a1 + (*s2)*a2;
d2++;
s2++;
*d2 = (*d2)*a1 + (*s2)*a2;
d2++;
s2++;
*d2 = (*d2)*a1 + (*s2)*a2;
d2++;
s2++;
m2++;
}
s1 += slinespan;
d1 += dlinespan;
m1 += mlinespan;
}
}
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)/2;
d2++;
s2++;
}
s1 += slinespan;
d1 += dlinespan;
}
}
}
}
@ -309,23 +444,39 @@ void nsImageWin :: ComputePaletteSize(PRIntn nBitCount)
{
case 8:
mNumPalleteColors = 256;
mNumBytesColor = 1;
mNumBytesPixel = 1;
break;
case 24:
mNumPalleteColors = 0;
mNumBytesColor = 3;
mNumBytesPixel = 3;
break;
default:
mNumPalleteColors = -1;
mNumBytesColor = 0;
mNumBytesPixel = 0;
break;
}
}
//------------------------------------------------------------
PRInt32 nsImageWin :: CalcBytesSpan(PRUint32 aWidth)
{
PRInt32 spanbytes;
spanbytes = (aWidth * mBHead->biBitCount) / 32;
if (((PRUint32)mBHead->biWidth * mBHead->biBitCount) % 32)
spanbytes++;
spanbytes *= 4;
return(spanbytes);
}
//------------------------------------------------------------
void nsImageWin :: ComputeMetrics()
{
@ -333,12 +484,7 @@ void nsImageWin :: ComputeMetrics()
if (mSizeImage == 0)
{
mRowBytes = ((PRUint32) mBHead->biWidth * mBHead->biBitCount) / 32;
if (((PRUint32)mBHead->biWidth * mBHead->biBitCount) % 32)
mRowBytes++;
mRowBytes *= 4;
mRowBytes = CalcBytesSpan(mBHead->biWidth);
mSizeImage = mRowBytes * mBHead->biHeight; // no compression
}
@ -388,7 +534,7 @@ void nsImageWin :: CleanUp(PRBool aCleanUpAll)
mColorTable = nsnull;
mNumPalleteColors = -1;
mNumBytesColor = 0;
mNumBytesPixel = 0;
mSizeImage = 0;
mHPalette = nsnull;
mImageBits = nsnull;

View File

@ -36,7 +36,7 @@ public:
virtual PRInt32 GetHeight() { return mBHead->biHeight; }
virtual PRInt32 GetWidth() { return mBHead->biWidth; }
virtual PRUint8* GetAlphaBits() { return mAlphaBits; }
virtual PRInt32 GetAlphaLineStride(){ return mBHead->biWidth; }
virtual PRInt32 GetAlphaLineStride(){ return mARowBytes; }
virtual PRUint8* GetBits() { return mImageBits; }
virtual PRInt32 GetLineStride() {return mRowBytes; }
virtual PRBool Draw(nsDrawingSurface aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
@ -83,6 +83,18 @@ public:
*/
PRUintn UsePalette(HDC* aHdc, PRBool bBackground = PR_FALSE);
/**
* Calculate the number of bytes spaned for this image for a given width
* @param aWidth is the width to calculate the number of bytes for
* @return the number of bytes in this span
*/
PRInt32 CalcBytesSpan(PRUint32 aWidth);
PRBool SetAlphaMask(nsIImage *aTheMask);
void MoveAlphaMask(PRInt32 aX, PRInt32 aY){mLocation.x=aX;mLocation.y=aY;}
private:
/**
* Clean up the memory used nsImageWin.
@ -94,20 +106,33 @@ private:
* Calculate the amount of memory needed for the palette
* @param aBitCount is the number of bits per pixel
*/
void ComputePaletteSize(PRIntn aBitCount);
/**
* 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
*/
void Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation);
/**
* Calculate the amount of memory needed for the initialization of the pixelmap
*/
void ComputeMetrics();
PRInt8 mNumBytesColor; // number of bytes per color
PRInt8 mNumBytesPixel; // number of bytes per pixel
PRInt16 mNumPalleteColors; // either 8 or 0
PRInt32 mSizeImage; // number of bytes
PRInt32 mRowBytes; // number of bytes per row
PRUint8 *mColorTable; // color table for the bitmap
LPBYTE mImageBits; // starting address of DIB bits
LPBYTE mAlphaBits; // alpha layer if we made one
PRInt8 mlphaDepth; // 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
@ -117,12 +142,4 @@ private:
LPBITMAPINFOHEADER mBHead; // BITMAPINFOHEADER
};
/* TODO
===================================
1.) Share teh offscreen DC between other nsImageWin objects if nessasary
*/
#endif

View File

@ -55,9 +55,11 @@ static HWND gHwnd;
static nsIWidget *gWindow = nsnull;
static nsIImage *gImage = nsnull;
static nsIImage *gBlendImage = nsnull;
static nsIImage *gMaskImage = nsnull;
static PRBool gInstalledColorMap = PR_FALSE;
static PRInt32 gXOff,gYOff,gTestNum;
extern void Compositetest(nsIImage *aTheImage,nsIImage *aBlendImage,nsIRenderingContext *aSurface, PRInt32 aX, PRInt32 aY);
extern void Compositetest(PRInt32 aTestNum,nsIImage *aImage,nsIImage *aBImage,nsIImage *aMImage, PRInt32 aX, PRInt32 aY);
extern PRInt32 speedtest(nsIImage *aTheImage,nsIRenderingContext *aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
extern PRInt32 drawtest(nsIRenderingContext *aSurface);
extern PRInt32 filltest(nsIRenderingContext *aSurface);
@ -66,7 +68,6 @@ extern PRBool IsImageLoaded();
//------------------------------------------------------------
@ -77,7 +78,6 @@ private:
public:
MyBlendObserver(nsIImage **aImage);
//MyBlendObserver();
~MyBlendObserver();
NS_DECL_ISUPPORTS
@ -128,33 +128,12 @@ MyBlendObserver::Notify(nsIImageRequest *aImageRequest,
NS_ADDREF(aImage);
}
//if (gBlendImage == nsnull && aImage)
//{
//gBlendImage = aImage;
//NS_ADDREF(aImage);
//}
if (!gInstalledColorMap && gBlendImage)
if ( gBlendImage && (aNotificationType == nsImageNotification_kImageComplete) )
{
nsColorMap *cmap = (*mImage)->GetColorMap();
if(aNotificationType == nsImageNotification_kImageComplete)
{
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
Compositetest(gImage,gBlendImage,drawCtx,0,0);
}
//if (cmap != nsnull && cmap->NumColors > 0)
//{
//gWindow->SetColorMap(cmap);
//}
//gInstalledColorMap = PR_TRUE;
nsRect *rect = (nsRect *)aParam3;
Compositetest(gTestNum,gImage,gBlendImage,gMaskImage,gXOff,gYOff);
}
//nsRect *rect = (nsRect *)aParam3;
//nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
}
break;
}
@ -187,8 +166,6 @@ public:
};
//------------------------------------------------------------
MyObserver::MyObserver()
@ -267,15 +244,88 @@ MyObserver::NotifyError(nsIImageRequest *aImageRequest,
// This tests the compositing for the image
void
Compositetest(nsIImage *aTheImage,nsIImage *aBlendImage,nsIRenderingContext *aSurface, PRInt32 aX, PRInt32 aY)
Compositetest(PRInt32 aTestNum,nsIImage *aImage,nsIImage *aBImage,nsIImage *aMImage, PRInt32 aX, PRInt32 aY)
{
PRInt32 swidth, sheight,bwidth,bheight;
swidth = aTheImage->GetWidth();
sheight = aTheImage->GetHeight();
nsPoint *location;
PRUint32 min,seconds,milli,i,h,w;
SYSTEMTIME thetime;
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
if(aTestNum == 1)
{
location = new nsPoint(aX,aY);
if(aMImage)
{
aImage->SetAlphaMask(aMImage);
aImage->MoveAlphaMask(rand() % gImage->GetWidth(),rand() % gImage->GetHeight());
}
if(aMImage == nsnull)
{
location->x = rand() % gImage->GetWidth();
location->y = rand() % gImage->GetHeight();
printf("\n Image Location is %d, %d\n", location->x,location->y);
}
aImage->CompositeImage(aBImage,location);
}
if(aTestNum == 2)
{
if(aMImage)
{
aImage->SetAlphaMask(aMImage);
}
printf("\nSTARTING Blending TEST\n");
::GetSystemTime(&thetime);
min = thetime.wMinute;
seconds = thetime.wSecond;
milli = thetime.wMilliseconds;
location = new nsPoint(0,0);
w = gImage->GetWidth();
h = gImage->GetHeight();
if(aMImage)
{
for(i=0;i<200;i++)
{
aImage->MoveAlphaMask(rand()%w,rand()%h);
aImage->CompositeImage(aBImage,location);
drawCtx->DrawImage(gImage, 0, 0, gImage->GetWidth(), gImage->GetHeight());
}
}
else
for(i=0;i<200;i++)
{
aImage->CompositeImage(aBImage,location);
drawCtx->DrawImage(gImage, 0, 0, gImage->GetWidth(), gImage->GetHeight());
}
::GetSystemTime(&thetime);
min = thetime.wMinute-min;
if(min>0)
min = min*60;
seconds = min+thetime.wSecond-seconds;
if(seconds>0)
seconds = (seconds*1000)+thetime.wMilliseconds;
else
seconds = thetime.wMilliseconds;
milli=seconds-milli;
printf("The composite Time was %lu Milliseconds\n",milli);
}
drawCtx->DrawImage(gImage, 0, 0, gImage->GetWidth(), gImage->GetHeight());
// we are finished with this
if (gBlendImage)
{
NS_RELEASE(gBlendImage);
gBlendImage = NULL;
}
bwidth = aBlendImage->GetWidth();
bheight = aBlendImage->GetHeight();
}
@ -639,6 +689,7 @@ long PASCAL
WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam)
{
HMENU hMenu;
char szFile[256];
switch (msg)
{
@ -649,7 +700,6 @@ WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam)
{
case TIMER_OPEN:
{
char szFile[256];
if (!OpenFileDialog(szFile, 256))
return 0L;
@ -660,18 +710,31 @@ WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam)
::DestroyWindow(hWnd);
exit(0);
break;
case RDMSK:
if (gMaskImage!=nsnull)
{
NS_RELEASE(gMaskImage);
gMaskImage = nsnull;
}
if (OpenFileDialog(szFile, 256))
MyLoadImage(szFile,PR_TRUE,&gMaskImage);
break;
case COMPTST:
gTestNum = 1;
case COMPTSTSPEED:
if(LOWORD(param) == COMPTSTSPEED)
gTestNum = 2;
IsImageLoaded();
if(gImage)
{
char szFile[256];
{
if (gBlendImage!=nsnull)
{
NS_RELEASE(gBlendImage);
gBlendImage = nsnull;
}
gXOff = 100;
gYOff = 100;
if (OpenFileDialog(szFile, 256))
MyLoadImage(szFile,PR_TRUE,&gBlendImage);
}

View File

@ -28,7 +28,9 @@ IMAGETEST MENU DISCARDABLE
POPUP "TEST"
{
MENUITEM "Composite Test", COMPTST
MENUITEM "Read Mask", RDMSK
MENUITEM "Composit Test", COMPTST
MENUITEM "Composite Speed", COMPTSTSPEED
MENUITEM "Blit Speed",BSTNOOPT
MENUITEM "Blit Speed, Optimzed.",BSTOPT
MENUITEM "Draw Test",DRAWTEST

View File

@ -28,5 +28,7 @@
#define FILLTEST 40015
#define ARCTEST 40016
#define COMPTST 40017
#define COMPTSTSPEED 40018
#define RDMSK 40019
#endif /* resources_h___ */