From 888e65734886674d4d533b85af5518367a65c19e Mon Sep 17 00:00:00 2001 From: dcone Date: Tue, 5 May 1998 14:47:16 +0000 Subject: [PATCH] Composition Work 24 bit complete git-svn-id: svn://10.0.0.236/trunk@1131 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/gfx/src/nsIImage.h | 13 ++ mozilla/gfx/src/windows/nsImageWin.cpp | 166 +++++++++++++++++++++++-- mozilla/gfx/src/windows/nsImageWin.h | 39 ++++-- mozilla/gfx/tests/btest/BitTest.cpp | 143 +++++++++++++++------ mozilla/gfx/tests/btest/image.rc | 4 +- mozilla/gfx/tests/btest/resources.h | 2 + 6 files changed, 305 insertions(+), 62 deletions(-) diff --git a/mozilla/gfx/src/nsIImage.h b/mozilla/gfx/src/nsIImage.h index 6b1aae7b135..6aa185d9fc1 100644 --- a/mozilla/gfx/src/nsIImage.h +++ b/mozilla/gfx/src/nsIImage.h @@ -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 diff --git a/mozilla/gfx/src/windows/nsImageWin.cpp b/mozilla/gfx/src/windows/nsImageWin.cpp index eeeef4bb1a4..f85796a3c36 100644 --- a/mozilla/gfx/src/windows/nsImageWin.cpp +++ b/mozilla/gfx/src/windows/nsImageWin.cpp @@ -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;ybiBitCount) / 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; diff --git a/mozilla/gfx/src/windows/nsImageWin.h b/mozilla/gfx/src/windows/nsImageWin.h index aa34badc5f6..c24c088b96b 100644 --- a/mozilla/gfx/src/windows/nsImageWin.h +++ b/mozilla/gfx/src/windows/nsImageWin.h @@ -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 diff --git a/mozilla/gfx/tests/btest/BitTest.cpp b/mozilla/gfx/tests/btest/BitTest.cpp index bfdccd61961..3179edc2f38 100644 --- a/mozilla/gfx/tests/btest/BitTest.cpp +++ b/mozilla/gfx/tests/btest/BitTest.cpp @@ -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); } diff --git a/mozilla/gfx/tests/btest/image.rc b/mozilla/gfx/tests/btest/image.rc index a38f865d4bf..c940c1bef28 100644 --- a/mozilla/gfx/tests/btest/image.rc +++ b/mozilla/gfx/tests/btest/image.rc @@ -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 diff --git a/mozilla/gfx/tests/btest/resources.h b/mozilla/gfx/tests/btest/resources.h index 07f0650c6f6..615dac88f53 100644 --- a/mozilla/gfx/tests/btest/resources.h +++ b/mozilla/gfx/tests/btest/resources.h @@ -28,5 +28,7 @@ #define FILLTEST 40015 #define ARCTEST 40016 #define COMPTST 40017 +#define COMPTSTSPEED 40018 +#define RDMSK 40019 #endif /* resources_h___ */