From 1d7439f12ae0d8afcb35f4367f3154104dbfe18f Mon Sep 17 00:00:00 2001 From: kervala Date: Mon, 4 Jan 2016 13:54:59 +0100 Subject: [PATCH] Changed: Allow to resample Luminance (grayscale) bitmaps --- code/nel/include/nel/misc/bitmap.h | 28 ++++ code/nel/src/misc/bitmap.cpp | 252 ++++++++++++++++++++++++++++- 2 files changed, 273 insertions(+), 7 deletions(-) diff --git a/code/nel/include/nel/misc/bitmap.h b/code/nel/include/nel/misc/bitmap.h index e572c8de0..8d2bf156f 100644 --- a/code/nel/include/nel/misc/bitmap.h +++ b/code/nel/include/nel/misc/bitmap.h @@ -236,6 +236,34 @@ private : sint32 nDestWidth, sint32 nDestHeight); + /** + * The grayscale resample function + * \param pSrc grayscale 8-bits array + * \param pDest grayscale 8-bits array for storing resampled texture + * \param nSrcWidth original width + * \param nSrcHeight original height + * \param nDestWidth width after resample + * \param nDestHeight height after resample + */ + void resamplePicture8 (const uint8 *pSrc, uint8 *pDest, + sint32 nSrcWidth, sint32 nSrcHeight, + sint32 nDestWidth, sint32 nDestHeight); + + /** + * The FAST resample function : works only when reducing the size by two + * and when the image is square + * \param pSrc grayscale 8-bits array + * \param pDest grayscale 8-bits array for storing resampled texture + * \param nSrcWidth original width + * \param nSrcHeight original height + * \param nDestWidth width after resample + * \param nDestHeight height after resample + */ + void resamplePicture8Fast (const uint8 *pSrc, uint8 *pDest, + sint32 nSrcWidth, sint32 nSrcHeight, + sint32 nDestWidth, sint32 nDestHeight); + + /** * Quadratic interpolator * \return the interpolation in (x,y) of the values (xy**) diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp index eef7386f7..7a90b6282 100644 --- a/code/nel/src/misc/bitmap.cpp +++ b/code/nel/src/misc/bitmap.cpp @@ -1785,7 +1785,7 @@ void CBitmap::releaseMipMaps() \*-------------------------------------------------------------------*/ void CBitmap::resample(sint32 nNewWidth, sint32 nNewHeight) { - nlassert(PixelFormat == RGBA); + nlassert(PixelFormat == RGBA || PixelFormat == Luminance); bool needRebuild = false; // Deleting mipmaps @@ -1804,13 +1804,27 @@ void CBitmap::resample(sint32 nNewWidth, sint32 nNewHeight) //logResample("Resample: 30"); CObjectVector pDestui; - pDestui.resize(nNewWidth*nNewHeight*4); - //logResample("Resample: 40"); - NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0]; - //logResample("Resample: 50"); - resamplePicture32 ((NLMISC::CRGBA*)&_Data[0][0], pDestRgba, _Width, _Height, nNewWidth, nNewHeight); - //logResample("Resample: 60"); + if (PixelFormat == RGBA) + { + pDestui.resize(nNewWidth*nNewHeight*4); + //logResample("Resample: 40"); + NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0]; + //logResample("Resample: 50"); + + resamplePicture32 ((NLMISC::CRGBA*)&_Data[0][0], pDestRgba, _Width, _Height, nNewWidth, nNewHeight); + //logResample("Resample: 60"); + } + else if (PixelFormat == Luminance) + { + pDestui.resize(nNewWidth*nNewHeight); + //logResample("Resample: 40"); + uint8 *pDestGray = &pDestui[0]; + //logResample("Resample: 50"); + + resamplePicture8 (&_Data[0][0], pDestGray, _Width, _Height, nNewWidth, nNewHeight); + //logResample("Resample: 60"); + } NLMISC::contReset(_Data[0]); // free memory //logResample("Resample: 70"); @@ -2126,6 +2140,230 @@ void CBitmap::resamplePicture32Fast (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *p } +/*-------------------------------------------------------------------*\ + resamplePicture32 +\*-------------------------------------------------------------------*/ +void CBitmap::resamplePicture8 (const uint8 *pSrc, uint8 *pDest, + sint32 nSrcWidth, sint32 nSrcHeight, + sint32 nDestWidth, sint32 nDestHeight) +{ + //logResample("RP8: 0 pSrc=%p pDest=%p, Src=%d x %d Dest=%d x %d", pSrc, pDest, nSrcWidth, nSrcHeight, nDestWidth, nDestHeight); + if ((nSrcWidth<=0)||(nSrcHeight<=0)||(nDestHeight<=0)||(nDestHeight<=0)) + return; + + // If we're reducing it by 2, call the fast resample + if (((nSrcHeight / 2) == nDestHeight) && ((nSrcHeight % 2) == 0) && + ((nSrcWidth / 2) == nDestWidth) && ((nSrcWidth % 2) == 0)) + { + resamplePicture8Fast(pSrc, pDest, nSrcWidth, nSrcHeight, nDestWidth, nDestHeight); + return; + } + + bool bXMag=(nDestWidth>=nSrcWidth); + bool bYMag=(nDestHeight>=nSrcHeight); + bool bXEq=(nDestWidth==nSrcWidth); + bool bYEq=(nDestHeight==nSrcHeight); + std::vector pIterm (nDestWidth*nSrcHeight); + + if (bXMag) + { + float fXdelta=(float)(nSrcWidth)/(float)(nDestWidth); + float *pItermPtr=&*pIterm.begin(); + sint32 nY; + for (nY=0; nY=0.f); + float vColor; + if (fVirgule>=0.5f) + { + if (fX<(float)(nSrcWidth-1)) + { + float vColor1 (pSrcLine[(sint32)floor(fX)]); + float vColor2 (pSrcLine[(sint32)floor(fX)+1]); + vColor=vColor1*(1.5f-fVirgule)+vColor2*(fVirgule-0.5f); + } + else + vColor = float(pSrcLine[(sint32)floor(fX)]); + } + else + { + if (fX>=1.f) + { + float vColor1 (pSrcLine[(sint32)floor(fX)]); + float vColor2 (pSrcLine[(sint32)floor(fX)-1]); + vColor = vColor1*(0.5f+fVirgule)+vColor2*(0.5f-fVirgule); + } + else + vColor = float (pSrcLine[(sint32)floor(fX)]); + } + *(pItermPtr++)=vColor; + fX+=fXdelta; + } + pSrc+=nSrcWidth; + } + } + else if (bXEq) + { + float *pItermPtr=&*pIterm.begin(); + for (sint32 nY=0; nY1.f); + float *pItermPtr=&*pIterm.begin(); + sint32 nY; + for (nY=0; nYfFinal) + fNext=fFinal; + vColor+=((float)(fNext-fX))* float (pSrcLine[(sint32)floor(fX)]); + fX=fNext; + } + fX = fFinal; // ensure fX == fFinal + vColor/=(float)fXdelta; + *(pItermPtr++)=vColor; + } + pSrc+=nSrcWidth; + } + } + + if (bYMag) + { + double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight); + sint32 nX; + for (nX=0; nX=0.f); + float vColor; + if (fVirgule>=0.5f) + { + if (fY<(double)(nSrcHeight-1)) + { + float vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX]; + float vColor2=pIterm[(((sint32)floor(fY))+1)*nDestWidth+nX]; + vColor=vColor1*(1.5f-(float)fVirgule)+vColor2*((float)fVirgule-0.5f); + } + else + vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX]; + } + else + { + if (fY>=1.f) + { + float vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX]; + float vColor2=pIterm[(((sint32)floor(fY))-1)*nDestWidth+nX]; + vColor=vColor1*(0.5f+(float)fVirgule)+vColor2*(0.5f-(float)fVirgule); + } + else + vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX]; + } + pDest[nX+nY*nDestWidth]=vColor; + fY+=fYdelta; + } + } + } + else if (bYEq) + { + for (sint32 nX=0; nX1.f); + sint32 nX; + for (nX=0; nXfFinal) + fNext=fFinal; + vColor+=((float)(fNext-fY))*pIterm[((sint32)floor(fY))*nDestWidth+nX]; + fY=fNext; + } + vColor/=(float)fYdelta; + pDest[nX+nY*nDestWidth]=vColor; + } + } + } +} + + +/*-------------------------------------------------------------------*\ + resamplePicture8Fast +\*-------------------------------------------------------------------*/ +void CBitmap::resamplePicture8Fast (const uint8 *pSrc, uint8 *pDest, + sint32 nSrcWidth, sint32 nSrcHeight, + sint32 nDestWidth, sint32 nDestHeight) +{ + // the image is divided by two : 1 pixel in dest = 4 pixels in src + // the resulting pixel in dest is an average of the four pixels in src + + nlassert(nSrcWidth % 2 == 0); + nlassert(nSrcHeight % 2 == 0); + nlassert(nSrcWidth / 2 == nDestWidth); + nlassert(nSrcHeight / 2 == nDestHeight); + + sint32 x, y, twoX, twoSrcWidthByY; + + for (y=0 ; y>2; + } + } +} + + /*-------------------------------------------------------------------*\ readTGA