📄 ximapal.cpp
字号:
// xImaPal.cpp : Palette and Pixel functions/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 */#include "ximage.h"/////////////////////////////////////////////////////////////////////////////////** * returns the palette dimension in byte */DWORD CxImage::GetPaletteSize(){ return (head.biClrUsed * sizeof(RGBQUAD));}////////////////////////////////////////////////////////////////////////////////void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha){ if ((pDib)&&(head.biClrUsed)){ BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); if (idx<head.biClrUsed){ long ldx=idx*sizeof(RGBQUAD); iDst[ldx++] = (BYTE) b; iDst[ldx++] = (BYTE) g; iDst[ldx++] = (BYTE) r; iDst[ldx] = (BYTE) alpha; info.last_c_isvalid = false; } }}////////////////////////////////////////////////////////////////////////////////void CxImage::SetPaletteColor(BYTE idx, RGBQUAD c){ if ((pDib)&&(head.biClrUsed)){ BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); if (idx<head.biClrUsed){ long ldx=idx*sizeof(RGBQUAD); iDst[ldx++] = (BYTE) c.rgbBlue; iDst[ldx++] = (BYTE) c.rgbGreen; iDst[ldx++] = (BYTE) c.rgbRed; iDst[ldx] = (BYTE) c.rgbReserved; info.last_c_isvalid = false; } }}////////////////////////////////////////////////////////////////////////////////void CxImage::SetPaletteColor(BYTE idx, COLORREF cr){ if ((pDib)&&(head.biClrUsed)){ BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); if (idx<head.biClrUsed){ long ldx=idx*sizeof(RGBQUAD); iDst[ldx++] = (BYTE) GetBValue(cr); iDst[ldx++] = (BYTE) GetGValue(cr); iDst[ldx++] = (BYTE) GetRValue(cr); iDst[ldx] = (BYTE) 0; info.last_c_isvalid = false; } }}/////////////////////////////////////////////////////////////////////////////////** * returns the pointer to the first palette index */RGBQUAD* CxImage::GetPalette() const{ if ((pDib)&&(head.biClrUsed)) return (RGBQUAD*)((BYTE*)pDib + sizeof(BITMAPINFOHEADER)); return NULL;}/////////////////////////////////////////////////////////////////////////////////** * Returns the color of the specified index. */RGBQUAD CxImage::GetPaletteColor(BYTE idx){ RGBQUAD rgb = {0,0,0,0}; if ((pDib)&&(head.biClrUsed)){ BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); if (idx<head.biClrUsed){ long ldx=idx*sizeof(RGBQUAD); rgb.rgbBlue = iDst[ldx++]; rgb.rgbGreen=iDst[ldx++]; rgb.rgbRed =iDst[ldx++]; rgb.rgbReserved = iDst[ldx]; if ( IsTransparent() ) rgb.rgbReserved = (idx==GetTransIndex()) ? 0 : 255; } } return rgb;}/////////////////////////////////////////////////////////////////////////////////** * Returns the palette index of the specified pixel. */BYTE CxImage::GetPixelIndex(long x,long y){ if ((pDib==NULL)||(head.biClrUsed==0)) return 0; if ((x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) { if (info.nBkgndIndex != -1) return (BYTE)info.nBkgndIndex; else return *info.pImage; } if (head.biBitCount==8){ return info.pImage[y*info.dwEffWidth + x]; } else { BYTE pos; BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)]; if (head.biBitCount==4){ pos = (BYTE)(4*(1-x%2)); iDst &= (0x0F<<pos); return (BYTE)(iDst >> pos); } else if (head.biBitCount==1){ pos = (BYTE)(7-x%8); iDst &= (0x01<<pos); return (BYTE)(iDst >> pos); } } return 0;}////////////////////////////////////////////////////////////////////////////////BYTE CxImage::BlindGetPixelIndex(const long x,const long y){#ifdef _DEBUG if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y)) throw 0;#endif if (head.biBitCount==8){ return info.pImage[y*info.dwEffWidth + x]; } else { BYTE pos; BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)]; if (head.biBitCount==4){ pos = (BYTE)(4*(1-x%2)); iDst &= (0x0F<<pos); return (BYTE)(iDst >> pos); } else if (head.biBitCount==1){ pos = (BYTE)(7-x%8); iDst &= (0x01<<pos); return (BYTE)(iDst >> pos); } } return 0;}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::GetPixelColor(long x,long y, bool bGetAlpha){// RGBQUAD rgb={0,0,0,0}; RGBQUAD rgb=info.nBkgndColor; //<mpwolski> if ((pDib==NULL)||(x<0)||(y<0)|| (x>=head.biWidth)||(y>=head.biHeight)){ if (info.nBkgndIndex != -1){ if (head.biBitCount<24) return GetPaletteColor((BYTE)info.nBkgndIndex); else return info.nBkgndColor; } else if (pDib) return GetPixelColor(0,0); return rgb; } if (head.biClrUsed){ rgb = GetPaletteColor(GetPixelIndex(x,y)); } else { BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; rgb.rgbBlue = *iDst++; rgb.rgbGreen= *iDst++; rgb.rgbRed = *iDst; }#if CXIMAGE_SUPPORT_ALPHA if (pAlpha && bGetAlpha) rgb.rgbReserved = AlphaGet(x,y);#else rgb.rgbReserved = 0;#endif //CXIMAGE_SUPPORT_ALPHA return rgb;}/////////////////////////////////////////////////////////////////////////////////** * This is (a bit) faster version of GetPixelColor. * It tests bounds only in debug mode (_DEBUG defined). * * It is an error to request out-of-borders pixel with this method. * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode. * \author ***bd*** 2.2004 */RGBQUAD CxImage::BlindGetPixelColor(const long x,const long y){ RGBQUAD rgb;#ifdef _DEBUG if ((pDib==NULL) || !IsInside(x,y)) throw 0;#endif if (head.biClrUsed){ return GetPaletteColor(BlindGetPixelIndex(x,y)); } BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; rgb.rgbBlue = *iDst++; rgb.rgbGreen= *iDst++; rgb.rgbRed = *iDst;#if CXIMAGE_SUPPORT_ALPHA if (pAlpha) rgb.rgbReserved = pAlpha[x+y*head.biWidth]; else rgb.rgbReserved = 0;#else rgb.rgbReserved = 0;#endif //CXIMAGE_SUPPORT_ALPHA return rgb;}////////////////////////////////////////////////////////////////////////////////BYTE CxImage::GetPixelGray(long x, long y){ RGBQUAD color = GetPixelColor(x,y); return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);}////////////////////////////////////////////////////////////////////////////////void CxImage::SetPixelIndex(long x,long y,BYTE i){ if ((pDib==NULL)||(head.biClrUsed==0)|| (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ; if (head.biBitCount==8){ info.pImage[y*info.dwEffWidth + x]=i; return; } else { BYTE pos; BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3); if (head.biBitCount==4){ pos = (BYTE)(4*(1-x%2)); *iDst &= ~(0x0F<<pos); *iDst |= ((i & 0x0F)<<pos); return; } else if (head.biBitCount==1){ pos = (BYTE)(7-x%8); *iDst &= ~(0x01<<pos); *iDst |= ((i & 0x01)<<pos); return; } }}////////////////////////////////////////////////////////////////////////////////void CxImage::SetPixelColor(long x,long y,COLORREF cr){ SetPixelColor(x,y,RGBtoRGBQUAD(cr));}////////////////////////////////////////////////////////////////////////////////void CxImage::SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha){ if ((pDib==NULL)||(x<0)||(y<0)|| (x>=head.biWidth)||(y>=head.biHeight)) return; if (head.biClrUsed) SetPixelIndex(x,y,GetNearestIndex(c)); else { BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; *iDst++ = c.rgbBlue; *iDst++ = c.rgbGreen; *iDst = c.rgbRed;#if CXIMAGE_SUPPORT_ALPHA if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);#endif //CXIMAGE_SUPPORT_ALPHA }}/////////////////////////////////////////////////////////////////////////////////** * Blends the current pixel color with a new color. * \param x,y = pixel * \param c = new color * \param blend = can be from 0 (no effect) to 1 (full effect). * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved */void CxImage::BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha){ if ((pDib==NULL)||(x<0)||(y<0)|| (x>=head.biWidth)||(y>=head.biHeight)) return; int a0 = (int)(256*blend); int a1 = 256 - a0; RGBQUAD c0 = BlindGetPixelColor(x,y); c.rgbRed = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8); c.rgbBlue = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8); c.rgbGreen = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8); if (head.biClrUsed) SetPixelIndex(x,y,GetNearestIndex(c)); else { BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; *iDst++ = c.rgbBlue; *iDst++ = c.rgbGreen; *iDst = c.rgbRed;#if CXIMAGE_SUPPORT_ALPHA if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);#endif //CXIMAGE_SUPPORT_ALPHA }}/////////////////////////////////////////////////////////////////////////////////** * Returns the best palette index that matches a specified color. */BYTE CxImage::GetNearestIndex(RGBQUAD c){ if ((pDib==NULL)||(head.biClrUsed==0)) return 0; // <RJ> check matching with the previous result if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index; info.last_c = c; info.last_c_isvalid = true; BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); long distance=200000; int i,j = 0; long k,l; int m = (int)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant); for(i=0,l=0;i<m;i++,l+=sizeof(RGBQUAD)){ k = (iDst[l]-c.rgbBlue)*(iDst[l]-c.rgbBlue)+ (iDst[l+1]-c.rgbGreen)*(iDst[l+1]-c.rgbGreen)+ (iDst[l+2]-c.rgbRed)*(iDst[l+2]-c.rgbRed);// k = abs(iDst[l]-c.rgbBlue)+abs(iDst[l+1]-c.rgbGreen)+abs(iDst[l+2]-c.rgbRed); if (k==0){ j=i; break; } if (k<distance){ distance=k; j=i; } } info.last_c_index = j; return (BYTE)j;}/////////////////////////////////////////////////////////////////////////////////** * swaps the blue and red components (for RGB images) * \param buffer : pointer to the pixels * \param length : number of bytes to swap. lenght may not exceed the scan line. */void CxImage::RGBtoBGR(BYTE *buffer, int length){ if (buffer && (head.biClrUsed==0)){ BYTE temp; length = min(length,(int)info.dwEffWidth); for (int i=0;i<length;i+=3){ temp = buffer[i]; buffer[i] = buffer[i+2]; buffer[i+2] = temp; } }}////////////////////////////////////////////////////////////////////////////////RGBQUAD CxImage::RGBtoRGBQUAD(COLORREF cr){ RGBQUAD c; c.rgbRed = GetRValue(cr); /* get R, G, and B out of DWORD */ c.rgbGreen = GetGValue(cr); c.rgbBlue = GetBValue(cr); c.rgbReserved=0; return c;}////////////////////////////////////////////////////////////////////////////////COLORREF CxImage::RGBQUADtoRGB (RGBQUAD c){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -