]> Creatis software - clitk.git/blobdiff - utilities/CxImage/ximapal.cpp
cosmetic
[clitk.git] / utilities / CxImage / ximapal.cpp
index f7de9eb73768c654eb50a3bc58f3caad01ede1b5..b3bd3da39a5b7b0c50043d9725246328b2103aba 100644 (file)
-// xImaPal.cpp : Palette and Pixel functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * returns the palette dimension in byte\r
- */\r
-DWORD CxImage::GetPaletteSize()\r
-{\r
-       return (head.biClrUsed * sizeof(RGBQUAD));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha)\r
-{\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       iDst[ldx++] = (BYTE) b;\r
-                       iDst[ldx++] = (BYTE) g;\r
-                       iDst[ldx++] = (BYTE) r;\r
-                       iDst[ldx] = (BYTE) alpha;\r
-                       info.last_c_isvalid = false;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPaletteColor(BYTE idx, RGBQUAD c)\r
-{\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       iDst[ldx++] = (BYTE) c.rgbBlue;\r
-                       iDst[ldx++] = (BYTE) c.rgbGreen;\r
-                       iDst[ldx++] = (BYTE) c.rgbRed;\r
-                       iDst[ldx] = (BYTE) c.rgbReserved;\r
-                       info.last_c_isvalid = false;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPaletteColor(BYTE idx, COLORREF cr)\r
-{\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       iDst[ldx++] = (BYTE) GetBValue(cr);\r
-                       iDst[ldx++] = (BYTE) GetGValue(cr);\r
-                       iDst[ldx++] = (BYTE) GetRValue(cr);\r
-                       iDst[ldx] = (BYTE) 0;\r
-                       info.last_c_isvalid = false;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * returns the pointer to the first palette index\r
- */\r
-RGBQUAD* CxImage::GetPalette() const\r
-{\r
-       if ((pDib)&&(head.biClrUsed))\r
-               return (RGBQUAD*)((BYTE*)pDib + sizeof(BITMAPINFOHEADER));\r
-       return NULL;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the color of the specified index.\r
- */\r
-RGBQUAD CxImage::GetPaletteColor(BYTE idx)\r
-{\r
-       RGBQUAD rgb = {0,0,0,0};\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       rgb.rgbBlue = iDst[ldx++];\r
-                       rgb.rgbGreen=iDst[ldx++];\r
-                       rgb.rgbRed =iDst[ldx++];\r
-                       rgb.rgbReserved = iDst[ldx];\r
-               }\r
-       }\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the palette index of the specified pixel.\r
- */\r
-BYTE CxImage::GetPixelIndex(long x,long y)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return 0;\r
-\r
-       if ((x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) {\r
-               if (info.nBkgndIndex >= 0)      return (BYTE)info.nBkgndIndex;\r
-               else return *info.pImage;\r
-       }\r
-       if (head.biBitCount==8){\r
-               return info.pImage[y*info.dwEffWidth + x];\r
-       } else {\r
-               BYTE pos;\r
-               BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       iDst &= (0x0F<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       iDst &= (0x01<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-BYTE CxImage::BlindGetPixelIndex(const long x,const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-\r
-       if (head.biBitCount==8){\r
-               return info.pImage[y*info.dwEffWidth + x];\r
-       } else {\r
-               BYTE pos;\r
-               BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       iDst &= (0x0F<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       iDst &= (0x01<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::GetPixelColor(long x,long y, bool bGetAlpha)\r
-{\r
-//     RGBQUAD rgb={0,0,0,0};\r
-       RGBQUAD rgb=info.nBkgndColor; //<mpwolski>\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight)){\r
-               if (info.nBkgndIndex >= 0){\r
-                       if (head.biBitCount<24) return GetPaletteColor((BYTE)info.nBkgndIndex);\r
-                       else return info.nBkgndColor;\r
-               } else if (pDib) return GetPixelColor(0,0);\r
-               return rgb;\r
-       }\r
-\r
-       if (head.biClrUsed){\r
-               rgb = GetPaletteColor(BlindGetPixelIndex(x,y));\r
-       } else {\r
-               BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3;\r
-               rgb.rgbBlue = *iDst++;\r
-               rgb.rgbGreen= *iDst++;\r
-               rgb.rgbRed  = *iDst;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);\r
-#else\r
-       rgb.rgbReserved = 0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * This is (a bit) faster version of GetPixelColor. \r
- * It tests bounds only in debug mode (_DEBUG defined).\r
- * \r
- * It is an error to request out-of-borders pixel with this method. \r
- * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode. \r
- * \author ***bd*** 2.2004\r
- */\r
-RGBQUAD CxImage::BlindGetPixelColor(const long x,const long y, bool bGetAlpha)\r
-{\r
-  RGBQUAD rgb;\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL) || !IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               {rgb.rgbReserved = 0; return rgb;}\r
-  #endif\r
-#endif\r
-\r
-       if (head.biClrUsed){\r
-               rgb = GetPaletteColor(BlindGetPixelIndex(x,y));\r
-       } else {\r
-               BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3;\r
-               rgb.rgbBlue = *iDst++;\r
-               rgb.rgbGreen= *iDst++;\r
-               rgb.rgbRed  = *iDst;\r
-               rgb.rgbReserved = 0; //needed for images without alpha layer\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);\r
-#else\r
-       rgb.rgbReserved = 0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-BYTE CxImage::GetPixelGray(long x, long y)\r
-{\r
-       RGBQUAD color = GetPixelColor(x,y);\r
-       return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::BlindSetPixelIndex(long x,long y,BYTE i)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL)||(head.biClrUsed==0)||\r
-               (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return;\r
-  #endif\r
-#endif\r
-\r
-       if (head.biBitCount==8){\r
-               info.pImage[y*info.dwEffWidth + x]=i;\r
-               return;\r
-       } else {\r
-               BYTE pos;\r
-               BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       *iDst &= ~(0x0F<<pos);\r
-                       *iDst |= ((i & 0x0F)<<pos);\r
-                       return;\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       *iDst &= ~(0x01<<pos);\r
-                       *iDst |= ((i & 0x01)<<pos);\r
-                       return;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPixelIndex(long x,long y,BYTE i)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)||\r
-               (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ;\r
-\r
-       if (head.biBitCount==8){\r
-               info.pImage[y*info.dwEffWidth + x]=i;\r
-               return;\r
-       } else {\r
-               BYTE pos;\r
-               BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       *iDst &= ~(0x0F<<pos);\r
-                       *iDst |= ((i & 0x0F)<<pos);\r
-                       return;\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       *iDst &= ~(0x01<<pos);\r
-                       *iDst |= ((i & 0x01)<<pos);\r
-                       return;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPixelColor(long x,long y,COLORREF cr)\r
-{\r
-       SetPixelColor(x,y,RGBtoRGBQUAD(cr));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::BlindSetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return;\r
-  #endif\r
-#endif\r
-       if (head.biClrUsed)\r
-               BlindSetPixelIndex(x,y,GetNearestIndex(c));\r
-       else {\r
-               BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;\r
-               *iDst++ = c.rgbBlue;\r
-               *iDst++ = c.rgbGreen;\r
-               *iDst   = c.rgbRed;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)\r
-{\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight)) return;\r
-       if (head.biClrUsed)\r
-               BlindSetPixelIndex(x,y,GetNearestIndex(c));\r
-       else {\r
-               BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;\r
-               *iDst++ = c.rgbBlue;\r
-               *iDst++ = c.rgbGreen;\r
-               *iDst   = c.rgbRed;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Blends the current pixel color with a new color.\r
- * \param x,y = pixel\r
- * \param c = new color\r
- * \param blend = can be from 0 (no effect) to 1 (full effect).\r
- * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved\r
- */\r
-void CxImage::BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha)\r
-{\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight)) return;\r
-\r
-       int a0 = (int)(256*blend);\r
-       int a1 = 256 - a0;\r
-\r
-       RGBQUAD c0 = BlindGetPixelColor(x,y);\r
-       c.rgbRed  = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8);\r
-       c.rgbBlue  = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8);\r
-       c.rgbGreen  = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8);\r
-\r
-       if (head.biClrUsed)\r
-               BlindSetPixelIndex(x,y,GetNearestIndex(c));\r
-       else {\r
-               BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;\r
-               *iDst++ = c.rgbBlue;\r
-               *iDst++ = c.rgbGreen;\r
-               *iDst   = c.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the best palette index that matches a specified color.\r
- */\r
-BYTE CxImage::GetNearestIndex(RGBQUAD c)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return 0;\r
-\r
-       // <RJ> check matching with the previous result\r
-       if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index;\r
-       info.last_c = c;\r
-       info.last_c_isvalid = true;\r
-\r
-       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-       long distance=200000;\r
-       int i,j = 0;\r
-       long k,l;\r
-       int m = (int)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant);\r
-       for(i=0,l=0;i<m;i++,l+=sizeof(RGBQUAD)){\r
-               k = (iDst[l]-c.rgbBlue)*(iDst[l]-c.rgbBlue)+\r
-                       (iDst[l+1]-c.rgbGreen)*(iDst[l+1]-c.rgbGreen)+\r
-                       (iDst[l+2]-c.rgbRed)*(iDst[l+2]-c.rgbRed);\r
-//             k = abs(iDst[l]-c.rgbBlue)+abs(iDst[l+1]-c.rgbGreen)+abs(iDst[l+2]-c.rgbRed);\r
-               if (k==0){\r
-                       j=i;\r
-                       break;\r
-               }\r
-               if (k<distance){\r
-                       distance=k;\r
-                       j=i;\r
-               }\r
-       }\r
-       info.last_c_index = (BYTE)j;\r
-       return (BYTE)j;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * swaps the blue and red components (for RGB images)\r
- * \param buffer : pointer to the pixels\r
- * \param length : number of bytes to swap. lenght may not exceed the scan line.\r
- */\r
-void CxImage::RGBtoBGR(BYTE *buffer, int length)\r
-{\r
-       if (buffer && (head.biClrUsed==0)){\r
-               BYTE temp;\r
-               length = min(length,(int)info.dwEffWidth);\r
-               length = min(length,(int)(3*head.biWidth));\r
-               for (int i=0;i<length;i+=3){\r
-                       temp = buffer[i]; buffer[i] = buffer[i+2]; buffer[i+2] = temp;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::RGBtoRGBQUAD(COLORREF cr)\r
-{\r
-       RGBQUAD c;\r
-       c.rgbRed = GetRValue(cr);       /* get R, G, and B out of DWORD */\r
-       c.rgbGreen = GetGValue(cr);\r
-       c.rgbBlue = GetBValue(cr);\r
-       c.rgbReserved=0;\r
-       return c;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-COLORREF CxImage::RGBQUADtoRGB (RGBQUAD c)\r
-{\r
-       return RGB(c.rgbRed,c.rgbGreen,c.rgbBlue);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the color of the specified index.\r
- * \param i = palette index\r
- * \param r, g, b = output color channels\r
- */\r
-bool CxImage::GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b)\r
-{\r
-       RGBQUAD* ppal=GetPalette();\r
-       if (ppal) {\r
-               *r = ppal[i].rgbRed;\r
-               *g = ppal[i].rgbGreen;\r
-               *b = ppal[i].rgbBlue; \r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b)\r
-{\r
-       if ((!r)||(pDib==NULL)||(head.biClrUsed==0)) return;\r
-       if (!g) g = r;\r
-       if (!b) b = g;\r
-       RGBQUAD* ppal=GetPalette();\r
-       DWORD m=min(n,head.biClrUsed);\r
-       for (DWORD i=0; i<m;i++){\r
-               ppal[i].rgbRed=r[i];\r
-               ppal[i].rgbGreen=g[i];\r
-               ppal[i].rgbBlue=b[i];\r
-       }\r
-       info.last_c_isvalid = false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPalette(rgb_color *rgb,DWORD nColors)\r
-{\r
-       if ((!rgb)||(pDib==NULL)||(head.biClrUsed==0)) return;\r
-       RGBQUAD* ppal=GetPalette();\r
-       DWORD m=min(nColors,head.biClrUsed);\r
-       for (DWORD i=0; i<m;i++){\r
-               ppal[i].rgbRed=rgb[i].r;\r
-               ppal[i].rgbGreen=rgb[i].g;\r
-               ppal[i].rgbBlue=rgb[i].b;\r
-       }\r
-       info.last_c_isvalid = false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPalette(RGBQUAD* pPal,DWORD nColors)\r
-{\r
-       if ((pPal==NULL)||(pDib==NULL)||(head.biClrUsed==0)) return;\r
-       memcpy(GetPalette(),pPal,min(GetPaletteSize(),nColors*sizeof(RGBQUAD)));\r
-       info.last_c_isvalid = false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets (or replaces) the palette to gray scale palette.\r
- * The function doesn't change the pixels; for standard\r
- * gray scale conversion use GrayScale().\r
- */\r
-void CxImage::SetGrayPalette()\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return;\r
-       RGBQUAD* pal=GetPalette();\r
-       for (DWORD ni=0;ni<head.biClrUsed;ni++)\r
-               pal[ni].rgbBlue=pal[ni].rgbGreen = pal[ni].rgbRed = (BYTE)(ni*(255/(head.biClrUsed-1)));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Colorize the palette.\r
- * \sa Colorize\r
- */\r
-void CxImage::BlendPalette(COLORREF cr,long perc)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return;\r
-       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-       DWORD i,r,g,b;\r
-       RGBQUAD* pPal=(RGBQUAD*)iDst;\r
-       r = GetRValue(cr);\r
-       g = GetGValue(cr);\r
-       b = GetBValue(cr);\r
-       if (perc>100) perc=100;\r
-       for(i=0;i<head.biClrUsed;i++){\r
-               pPal[i].rgbBlue=(BYTE)((pPal[i].rgbBlue*(100-perc)+b*perc)/100);\r
-               pPal[i].rgbGreen =(BYTE)((pPal[i].rgbGreen*(100-perc)+g*perc)/100);\r
-               pPal[i].rgbRed =(BYTE)((pPal[i].rgbRed*(100-perc)+r*perc)/100);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns true if the image has 256 colors and a linear grey scale palette.\r
- */\r
-bool CxImage::IsGrayScale()\r
-{\r
-       RGBQUAD* ppal=GetPalette();\r
-       if(!(pDib && ppal && head.biClrUsed)) return false;\r
-       for(DWORD i=0;i<head.biClrUsed;i++){\r
-               if (ppal[i].rgbBlue!=i || ppal[i].rgbGreen!=i || ppal[i].rgbRed!=i) return false;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * swap two indexes in the image and their colors in the palette\r
- */\r
-void CxImage::SwapIndex(BYTE idx1, BYTE idx2)\r
-{\r
-       RGBQUAD* ppal=GetPalette();\r
-       if(!(pDib && ppal)) return;\r
-       //swap the colors\r
-       RGBQUAD tempRGB=GetPaletteColor(idx1);\r
-       SetPaletteColor(idx1,GetPaletteColor(idx2));\r
-       SetPaletteColor(idx2,tempRGB);\r
-       //swap the pixels\r
-       BYTE idx;\r
-       for(long y=0; y < head.biHeight; y++){\r
-               for(long x=0; x < head.biWidth; x++){\r
-                       idx=BlindGetPixelIndex(x,y);\r
-                       if (idx==idx1) BlindSetPixelIndex(x,y,idx2);\r
-                       if (idx==idx2) BlindSetPixelIndex(x,y,idx1);\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * swap Red and Blue colors\r
- */\r
-void CxImage::SwapRGB2BGR()\r
-{\r
-       if (!pDib) return;\r
-\r
-       if (head.biClrUsed){\r
-               RGBQUAD* ppal=GetPalette();\r
-               BYTE b;\r
-               if(!ppal) return;\r
-               for(WORD a=0;a<head.biClrUsed;a++){\r
-                       b=ppal[a].rgbBlue; ppal[a].rgbBlue=ppal[a].rgbRed; ppal[a].rgbRed=b;\r
-               }\r
-       } else {\r
-               for(long y=0;y<head.biHeight;y++){\r
-                       RGBtoBGR(GetBits(y),3*head.biWidth);\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::IsTransparent(long x, long y)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       if (info.nBkgndIndex>=0){\r
-               if (head.biClrUsed){\r
-                       if (GetPixelIndex(x,y) == info.nBkgndIndex) return true;\r
-               } else {\r
-                       RGBQUAD ct = info.nBkgndColor;\r
-                       RGBQUAD c = GetPixelColor(x,y,false);\r
-                       if (*(long*)&c==*(long*)&ct) return true;\r
-               }\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha) return AlphaGet(x,y)==0;\r
-#endif\r
-\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::GetTransparentMask(CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       CxImage tmp;\r
-       tmp.Create(head.biWidth, head.biHeight, 1, GetType());\r
-       tmp.SetStdPalette();\r
-       tmp.Clear(0);\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       if (IsTransparent(x,y)){\r
-                               tmp.BlindSetPixelIndex(x,y,1);\r
-                       }\r
-               }\r
-       }\r
-\r
-       if (iDst) iDst->Transfer(tmp);\r
-       else Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if image has the same palette, if any.\r
- * \param img = image to compare.\r
- * \param bCheckAlpha = check also the rgbReserved field.\r
- */\r
-bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha)\r
-{\r
-       if (head.biClrUsed != img.head.biClrUsed)\r
-               return false;\r
-       if (head.biClrUsed == 0)\r
-               return false;\r
-\r
-       RGBQUAD c1,c2;\r
-       for (DWORD n=0; n<head.biClrUsed; n++){\r
-               c1 = GetPaletteColor((BYTE)n);\r
-               c2 = img.GetPaletteColor((BYTE)n);\r
-               if (c1.rgbRed != c2.rgbRed) return false;\r
-               if (c1.rgbBlue != c2.rgbBlue) return false;\r
-               if (c1.rgbGreen != c2.rgbGreen) return false;\r
-               if (bCheckAlpha && (c1.rgbReserved != c2.rgbReserved)) return false;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetClrImportant\r
- */\r
-DWORD CxImage::GetClrImportant() const\r
-{\r
-       return head.biClrImportant;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * sets the maximum number of colors that some functions like\r
- * DecreaseBpp() or GetNearestIndex() will use on indexed images\r
- * \param ncolors should be less than 2^bpp,\r
- * or 0 if all the colors are important.\r
- */\r
-void CxImage::SetClrImportant(DWORD ncolors)\r
-{\r
-       if (ncolors==0 || ncolors>256) {\r
-               head.biClrImportant = 0;\r
-               return;\r
-       }\r
-\r
-       switch(head.biBitCount){\r
-       case 1:\r
-               head.biClrImportant = min(ncolors,2);\r
-               break;\r
-       case 4:\r
-               head.biClrImportant = min(ncolors,16);\r
-               break;\r
-       case 8:\r
-               head.biClrImportant = ncolors;\r
-               break;\r
-       }\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns pointer to pixel. Currently implemented only for truecolor images.\r
- *  \r
- * \param  x,y - coordinates\r
- *\r
- * \return pointer to first byte of pixel data\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-void* CxImage::BlindGetPixelPointer(const long x, const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL) || !IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-  if (!IsIndexed())\r
-    return info.pImage + y*info.dwEffWidth + x*3;\r
-  else\r
-    return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr)\r
-{\r
-       DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha)\r
-{\r
-       if (!pDib) return;\r
-       //////////////////////////////////////////////////////\r
-       // Draws a line using the Bresenham line algorithm\r
-       // Thanks to Jordan DeLozier <JDL>\r
-       //////////////////////////////////////////////////////\r
-       int x1 = StartX;\r
-       int y1 = StartY;\r
-       int x = x1;                       // Start x off at the first pixel\r
-       int y = y1;                       // Start y off at the first pixel\r
-       int x2 = EndX;\r
-       int y2 = EndY;\r
-\r
-       int xinc1,xinc2,yinc1,yinc2;      // Increasing values\r
-       int den, num, numadd,numpixels;   \r
-       int deltax = abs(x2 - x1);        // The difference between the x's\r
-       int deltay = abs(y2 - y1);        // The difference between the y's\r
-\r
-       // Get Increasing Values\r
-       if (x2 >= x1) {                // The x-values are increasing\r
-               xinc1 = 1;\r
-               xinc2 = 1;\r
-       } else {                         // The x-values are decreasing\r
-               xinc1 = -1;\r
-               xinc2 = -1;\r
-       }\r
-\r
-       if (y2 >= y1) {                // The y-values are increasing\r
-               yinc1 = 1;\r
-               yinc2 = 1;\r
-       } else {                         // The y-values are decreasing\r
-               yinc1 = -1;\r
-               yinc2 = -1;\r
-       }\r
-\r
-       // Actually draw the line\r
-       if (deltax >= deltay)         // There is at least one x-value for every y-value\r
-       {\r
-               xinc1 = 0;                  // Don't change the x when numerator >= denominator\r
-               yinc2 = 0;                  // Don't change the y for every iteration\r
-               den = deltax;\r
-               num = deltax / 2;\r
-               numadd = deltay;\r
-               numpixels = deltax;         // There are more x-values than y-values\r
-       }\r
-       else                          // There is at least one y-value for every x-value\r
-       {\r
-               xinc2 = 0;                  // Don't change the x for every iteration\r
-               yinc1 = 0;                  // Don't change the y when numerator >= denominator\r
-               den = deltay;\r
-               num = deltay / 2;\r
-               numadd = deltax;\r
-               numpixels = deltay;         // There are more y-values than x-values\r
-       }\r
-       \r
-       for (int curpixel = 0; curpixel <= numpixels; curpixel++)\r
-       {\r
-               // Draw the current pixel\r
-               SetPixelColor(x,y,color,bSetAlpha);\r
-               \r
-               num += numadd;              // Increase the numerator by the top of the fraction\r
-               if (num >= den)             // Check if numerator >= denominator\r
-               {\r
-                       num -= den;               // Calculate the new numerator value\r
-                       x += xinc1;               // Change the x as appropriate\r
-                       y += yinc1;               // Change the y as appropriate\r
-               }\r
-               x += xinc2;                 // Change the x as appropriate\r
-               y += yinc2;                 // Change the y as appropriate\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets a palette with standard colors for 1, 4 and 8 bpp images.\r
- */\r
-void CxImage::SetStdPalette()\r
-{\r
-       if (!pDib) return;\r
-       switch (head.biBitCount){\r
-       case 8:\r
-               {\r
-                       const BYTE pal256[1024] = {0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,\r
-                       192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0,\r
-                       72,184,255,0,37,170,255,0,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,\r
-                       50,80,0,212,227,255,0,177,199,255,0,142,171,255,0,107,143,255,0,72,115,255,0,37,87,255,0,0,\r
-                       85,255,0,0,73,220,0,0,61,185,0,0,49,150,0,0,37,115,0,0,25,80,0,212,212,255,0,177,177,255,0,\r
-                       142,142,255,0,107,107,255,0,72,72,255,0,37,37,255,0,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,\r
-                       0,0,115,0,0,0,80,0,227,212,255,0,199,177,255,0,171,142,255,0,143,107,255,0,115,72,255,0,\r
-                       87,37,255,0,85,0,255,0,73,0,220,0,61,0,185,0,49,0,150,0,37,0,115,0,25,0,80,0,240,212,255,0,\r
-                       226,177,255,0,212,142,255,0,198,107,255,0,184,72,255,0,170,37,255,0,170,0,255,0,146,0,220,0,\r
-                       122,0,185,0,98,0,150,0,74,0,115,0,50,0,80,0,255,212,255,0,255,177,255,0,255,142,255,0,255,107,255,0,\r
-                       255,72,255,0,255,37,255,0,254,0,254,0,220,0,220,0,185,0,185,0,150,0,150,0,115,0,115,0,80,0,80,0,\r
-                       255,212,240,0,255,177,226,0,255,142,212,0,255,107,198,0,255,72,184,0,255,37,170,0,255,0,170,0,\r
-                       220,0,146,0,185,0,122,0,150,0,98,0,115,0,74,0,80,0,50,0,255,212,227,0,255,177,199,0,255,142,171,0,\r
-                       255,107,143,0,255,72,115,0,255,37,87,0,255,0,85,0,220,0,73,0,185,0,61,0,150,0,49,0,115,0,37,0,\r
-                       80,0,25,0,255,212,212,0,255,177,177,0,255,142,142,0,255,107,107,0,255,72,72,0,255,37,37,0,254,0,\r
-                       0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,0,255,227,212,0,255,199,177,0,255,171,142,0,\r
-                       255,143,107,0,255,115,72,0,255,87,37,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,115,37,0,\r
-                       0,80,25,0,0,255,240,212,0,255,226,177,0,255,212,142,0,255,198,107,0,255,184,72,0,255,170,37,0,\r
-                       255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,0,255,255,212,0,255,255,177,0,\r
-                       255,255,142,0,255,255,107,0,255,255,72,0,255,255,37,0,254,254,0,0,220,220,0,0,185,185,0,0,150,150,0,\r
-                       0,115,115,0,0,80,80,0,0,240,255,212,0,226,255,177,0,212,255,142,0,198,255,107,0,184,255,72,0,\r
-                       170,255,37,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,50,80,0,0,227,255,212,0,\r
-                       199,255,177,0,171,255,142,0,143,255,107,0,115,255,72,0,87,255,37,0,85,255,0,0,73,220,0,0,61,185,0,\r
-                       0,49,150,0,0,37,115,0,0,25,80,0,0,212,255,212,0,177,255,177,0,142,255,142,0,107,255,107,0,72,255,72,0,\r
-                       37,255,37,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,212,255,227,0,177,255,199,0,\r
-                       142,255,171,0,107,255,143,0,72,255,115,0,37,255,87,0,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,\r
-                       115,37,0,0,80,25,0,212,255,240,0,177,255,226,0,142,255,212,0,107,255,198,0,72,255,184,0,37,255,170,0,\r
-                       0,255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,212,255,255,0,177,255,255,0,\r
-                       142,255,255,0,107,255,255,0,72,255,255,0,37,255,255,0,0,254,254,0,0,220,220,0,0,185,185,0,0,\r
-                       150,150,0,0,115,115,0,0,80,80,0,242,242,242,0,230,230,230,0,218,218,218,0,206,206,206,0,194,194,194,0,\r
-                       182,182,182,0,170,170,170,0,158,158,158,0,146,146,146,0,134,134,134,0,122,122,122,0,110,110,110,0,\r
-                       98,98,98,0,86,86,86,0,74,74,74,0,62,62,62,0,50,50,50,0,38,38,38,0,26,26,26,0,14,14,14,0,240,251,255,0,\r
-                       164,160,160,0,128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};\r
-                       memcpy(GetPalette(),pal256,1024);\r
-                       break;\r
-               }\r
-       case 4:\r
-               {\r
-                       const BYTE pal16[64]={0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,\r
-                                                               128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};\r
-                       memcpy(GetPalette(),pal16,64);\r
-                       break;\r
-               }\r
-       case 1:\r
-               {\r
-                       const BYTE pal2[8]={0,0,0,0,255,255,255,0};\r
-                       memcpy(GetPalette(),pal2,8);\r
-                       break;\r
-               }\r
-       }\r
-       info.last_c_isvalid = false;\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
+// xImaPal.cpp : Palette and Pixel functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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];
+               }
+       }
+       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 >= 0)      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))
+  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+               throw 0;
+  #else
+               return 0;
+  #endif
+#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 >= 0){
+                       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(BlindGetPixelIndex(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 = BlindAlphaGet(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, bool bGetAlpha)
+{
+  RGBQUAD rgb;
+#ifdef _DEBUG
+       if ((pDib==NULL) || !IsInside(x,y))
+  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+               throw 0;
+  #else
+               {rgb.rgbReserved = 0; return rgb;}
+  #endif
+#endif
+
+       if (head.biClrUsed){
+               rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
+       } else {
+               BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3;
+               rgb.rgbBlue = *iDst++;
+               rgb.rgbGreen= *iDst++;
+               rgb.rgbRed  = *iDst;
+               rgb.rgbReserved = 0; //needed for images without alpha layer
+       }
+#if CXIMAGE_SUPPORT_ALPHA
+       if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);
+#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::BlindSetPixelIndex(long x,long y,BYTE i)
+{
+#ifdef _DEBUG
+       if ((pDib==NULL)||(head.biClrUsed==0)||
+               (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight))
+  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+               throw 0;
+  #else
+               return;
+  #endif
+#endif
+
+       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::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::BlindSetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)
+{
+#ifdef _DEBUG
+       if ((pDib==NULL)||(x<0)||(y<0)||
+               (x>=head.biWidth)||(y>=head.biHeight))
+  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+               throw 0;
+  #else
+               return;
+  #endif
+#endif
+       if (head.biClrUsed)
+               BlindSetPixelIndex(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
+}
+////////////////////////////////////////////////////////////////////////////////
+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)
+               BlindSetPixelIndex(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)
+               BlindSetPixelIndex(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 = (BYTE)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);
+               length = min(length,(int)(3*head.biWidth));
+               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)
+{
+       return RGB(c.rgbRed,c.rgbGreen,c.rgbBlue);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the color of the specified index.
+ * \param i = palette index
+ * \param r, g, b = output color channels
+ */
+bool CxImage::GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b)
+{
+       RGBQUAD* ppal=GetPalette();
+       if (ppal) {
+               *r = ppal[i].rgbRed;
+               *g = ppal[i].rgbGreen;
+               *b = ppal[i].rgbBlue; 
+               return true;
+       }
+       return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b)
+{
+       if ((!r)||(pDib==NULL)||(head.biClrUsed==0)) return;
+       if (!g) g = r;
+       if (!b) b = g;
+       RGBQUAD* ppal=GetPalette();
+       DWORD m=min(n,head.biClrUsed);
+       for (DWORD i=0; i<m;i++){
+               ppal[i].rgbRed=r[i];
+               ppal[i].rgbGreen=g[i];
+               ppal[i].rgbBlue=b[i];
+       }
+       info.last_c_isvalid = false;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPalette(rgb_color *rgb,DWORD nColors)
+{
+       if ((!rgb)||(pDib==NULL)||(head.biClrUsed==0)) return;
+       RGBQUAD* ppal=GetPalette();
+       DWORD m=min(nColors,head.biClrUsed);
+       for (DWORD i=0; i<m;i++){
+               ppal[i].rgbRed=rgb[i].r;
+               ppal[i].rgbGreen=rgb[i].g;
+               ppal[i].rgbBlue=rgb[i].b;
+       }
+       info.last_c_isvalid = false;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPalette(RGBQUAD* pPal,DWORD nColors)
+{
+       if ((pPal==NULL)||(pDib==NULL)||(head.biClrUsed==0)) return;
+       memcpy(GetPalette(),pPal,min(GetPaletteSize(),nColors*sizeof(RGBQUAD)));
+       info.last_c_isvalid = false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets (or replaces) the palette to gray scale palette.
+ * The function doesn't change the pixels; for standard
+ * gray scale conversion use GrayScale().
+ */
+void CxImage::SetGrayPalette()
+{
+       if ((pDib==NULL)||(head.biClrUsed==0)) return;
+       RGBQUAD* pal=GetPalette();
+       for (DWORD ni=0;ni<head.biClrUsed;ni++)
+               pal[ni].rgbBlue=pal[ni].rgbGreen = pal[ni].rgbRed = (BYTE)(ni*(255/(head.biClrUsed-1)));
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Colorize the palette.
+ * \sa Colorize
+ */
+void CxImage::BlendPalette(COLORREF cr,long perc)
+{
+       if ((pDib==NULL)||(head.biClrUsed==0)) return;
+       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+       DWORD i,r,g,b;
+       RGBQUAD* pPal=(RGBQUAD*)iDst;
+       r = GetRValue(cr);
+       g = GetGValue(cr);
+       b = GetBValue(cr);
+       if (perc>100) perc=100;
+       for(i=0;i<head.biClrUsed;i++){
+               pPal[i].rgbBlue=(BYTE)((pPal[i].rgbBlue*(100-perc)+b*perc)/100);
+               pPal[i].rgbGreen =(BYTE)((pPal[i].rgbGreen*(100-perc)+g*perc)/100);
+               pPal[i].rgbRed =(BYTE)((pPal[i].rgbRed*(100-perc)+r*perc)/100);
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the image has 256 colors and a linear grey scale palette.
+ */
+bool CxImage::IsGrayScale()
+{
+       RGBQUAD* ppal=GetPalette();
+       if(!(pDib && ppal && head.biClrUsed)) return false;
+       for(DWORD i=0;i<head.biClrUsed;i++){
+               if (ppal[i].rgbBlue!=i || ppal[i].rgbGreen!=i || ppal[i].rgbRed!=i) return false;
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * swap two indexes in the image and their colors in the palette
+ */
+void CxImage::SwapIndex(BYTE idx1, BYTE idx2)
+{
+       RGBQUAD* ppal=GetPalette();
+       if(!(pDib && ppal)) return;
+       //swap the colors
+       RGBQUAD tempRGB=GetPaletteColor(idx1);
+       SetPaletteColor(idx1,GetPaletteColor(idx2));
+       SetPaletteColor(idx2,tempRGB);
+       //swap the pixels
+       BYTE idx;
+       for(long y=0; y < head.biHeight; y++){
+               for(long x=0; x < head.biWidth; x++){
+                       idx=BlindGetPixelIndex(x,y);
+                       if (idx==idx1) BlindSetPixelIndex(x,y,idx2);
+                       if (idx==idx2) BlindSetPixelIndex(x,y,idx1);
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * swap Red and Blue colors
+ */
+void CxImage::SwapRGB2BGR()
+{
+       if (!pDib) return;
+
+       if (head.biClrUsed){
+               RGBQUAD* ppal=GetPalette();
+               BYTE b;
+               if(!ppal) return;
+               for(WORD a=0;a<head.biClrUsed;a++){
+                       b=ppal[a].rgbBlue; ppal[a].rgbBlue=ppal[a].rgbRed; ppal[a].rgbRed=b;
+               }
+       } else {
+               for(long y=0;y<head.biHeight;y++){
+                       RGBtoBGR(GetBits(y),3*head.biWidth);
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::IsTransparent(long x, long y)
+{
+       if (!pDib) return false;
+
+       if (info.nBkgndIndex>=0){
+               if (head.biClrUsed){
+                       if (GetPixelIndex(x,y) == info.nBkgndIndex) return true;
+               } else {
+                       RGBQUAD ct = info.nBkgndColor;
+                       RGBQUAD c = GetPixelColor(x,y,false);
+                       if (*(long*)&c==*(long*)&ct) return true;
+               }
+       }
+
+#if CXIMAGE_SUPPORT_ALPHA
+       if (pAlpha) return AlphaGet(x,y)==0;
+#endif
+
+       return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::GetTransparentMask(CxImage* iDst)
+{
+       if (!pDib) return false;
+
+       CxImage tmp;
+       tmp.Create(head.biWidth, head.biHeight, 1, GetType());
+       tmp.SetStdPalette();
+       tmp.Clear(0);
+
+       for(long y=0; y<head.biHeight; y++){
+               for(long x=0; x<head.biWidth; x++){
+                       if (IsTransparent(x,y)){
+                               tmp.BlindSetPixelIndex(x,y,1);
+                       }
+               }
+       }
+
+       if (iDst) iDst->Transfer(tmp);
+       else Transfer(tmp);
+
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if image has the same palette, if any.
+ * \param img = image to compare.
+ * \param bCheckAlpha = check also the rgbReserved field.
+ */
+bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha)
+{
+       if (head.biClrUsed != img.head.biClrUsed)
+               return false;
+       if (head.biClrUsed == 0)
+               return false;
+
+       RGBQUAD c1,c2;
+       for (DWORD n=0; n<head.biClrUsed; n++){
+               c1 = GetPaletteColor((BYTE)n);
+               c2 = img.GetPaletteColor((BYTE)n);
+               if (c1.rgbRed != c2.rgbRed) return false;
+               if (c1.rgbBlue != c2.rgbBlue) return false;
+               if (c1.rgbGreen != c2.rgbGreen) return false;
+               if (bCheckAlpha && (c1.rgbReserved != c2.rgbReserved)) return false;
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetClrImportant
+ */
+DWORD CxImage::GetClrImportant() const
+{
+       return head.biClrImportant;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * sets the maximum number of colors that some functions like
+ * DecreaseBpp() or GetNearestIndex() will use on indexed images
+ * \param ncolors should be less than 2^bpp,
+ * or 0 if all the colors are important.
+ */
+void CxImage::SetClrImportant(DWORD ncolors)
+{
+       if (ncolors==0 || ncolors>256) {
+               head.biClrImportant = 0;
+               return;
+       }
+
+       switch(head.biBitCount){
+       case 1:
+               head.biClrImportant = min(ncolors,2);
+               break;
+       case 4:
+               head.biClrImportant = min(ncolors,16);
+               break;
+       case 8:
+               head.biClrImportant = ncolors;
+               break;
+       }
+       return;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns pointer to pixel. Currently implemented only for truecolor images.
+ *  
+ * \param  x,y - coordinates
+ *
+ * \return pointer to first byte of pixel data
+ *
+ * \author ***bd*** 2.2004
+ */
+void* CxImage::BlindGetPixelPointer(const long x, const long y)
+{
+#ifdef _DEBUG
+       if ((pDib==NULL) || !IsInside(x,y))
+  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+               throw 0;
+  #else
+               return 0;
+  #endif
+#endif
+  if (!IsIndexed())
+    return info.pImage + y*info.dwEffWidth + x*3;
+  else
+    return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr)
+{
+       DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha)
+{
+       if (!pDib) return;
+       //////////////////////////////////////////////////////
+       // Draws a line using the Bresenham line algorithm
+       // Thanks to Jordan DeLozier <JDL>
+       //////////////////////////////////////////////////////
+       int x1 = StartX;
+       int y1 = StartY;
+       int x = x1;                       // Start x off at the first pixel
+       int y = y1;                       // Start y off at the first pixel
+       int x2 = EndX;
+       int y2 = EndY;
+
+       int xinc1,xinc2,yinc1,yinc2;      // Increasing values
+       int den, num, numadd,numpixels;   
+       int deltax = abs(x2 - x1);        // The difference between the x's
+       int deltay = abs(y2 - y1);        // The difference between the y's
+
+       // Get Increasing Values
+       if (x2 >= x1) {                // The x-values are increasing
+               xinc1 = 1;
+               xinc2 = 1;
+       } else {                         // The x-values are decreasing
+               xinc1 = -1;
+               xinc2 = -1;
+       }
+
+       if (y2 >= y1) {                // The y-values are increasing
+               yinc1 = 1;
+               yinc2 = 1;
+       } else {                         // The y-values are decreasing
+               yinc1 = -1;
+               yinc2 = -1;
+       }
+
+       // Actually draw the line
+       if (deltax >= deltay)         // There is at least one x-value for every y-value
+       {
+               xinc1 = 0;                  // Don't change the x when numerator >= denominator
+               yinc2 = 0;                  // Don't change the y for every iteration
+               den = deltax;
+               num = deltax / 2;
+               numadd = deltay;
+               numpixels = deltax;         // There are more x-values than y-values
+       }
+       else                          // There is at least one y-value for every x-value
+       {
+               xinc2 = 0;                  // Don't change the x for every iteration
+               yinc1 = 0;                  // Don't change the y when numerator >= denominator
+               den = deltay;
+               num = deltay / 2;
+               numadd = deltax;
+               numpixels = deltay;         // There are more y-values than x-values
+       }
+       
+       for (int curpixel = 0; curpixel <= numpixels; curpixel++)
+       {
+               // Draw the current pixel
+               SetPixelColor(x,y,color,bSetAlpha);
+               
+               num += numadd;              // Increase the numerator by the top of the fraction
+               if (num >= den)             // Check if numerator >= denominator
+               {
+                       num -= den;               // Calculate the new numerator value
+                       x += xinc1;               // Change the x as appropriate
+                       y += yinc1;               // Change the y as appropriate
+               }
+               x += xinc2;                 // Change the x as appropriate
+               y += yinc2;                 // Change the y as appropriate
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets a palette with standard colors for 1, 4 and 8 bpp images.
+ */
+void CxImage::SetStdPalette()
+{
+       if (!pDib) return;
+       switch (head.biBitCount){
+       case 8:
+               {
+                       const BYTE pal256[1024] = {0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,
+                       192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0,
+                       72,184,255,0,37,170,255,0,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,
+                       50,80,0,212,227,255,0,177,199,255,0,142,171,255,0,107,143,255,0,72,115,255,0,37,87,255,0,0,
+                       85,255,0,0,73,220,0,0,61,185,0,0,49,150,0,0,37,115,0,0,25,80,0,212,212,255,0,177,177,255,0,
+                       142,142,255,0,107,107,255,0,72,72,255,0,37,37,255,0,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,
+                       0,0,115,0,0,0,80,0,227,212,255,0,199,177,255,0,171,142,255,0,143,107,255,0,115,72,255,0,
+                       87,37,255,0,85,0,255,0,73,0,220,0,61,0,185,0,49,0,150,0,37,0,115,0,25,0,80,0,240,212,255,0,
+                       226,177,255,0,212,142,255,0,198,107,255,0,184,72,255,0,170,37,255,0,170,0,255,0,146,0,220,0,
+                       122,0,185,0,98,0,150,0,74,0,115,0,50,0,80,0,255,212,255,0,255,177,255,0,255,142,255,0,255,107,255,0,
+                       255,72,255,0,255,37,255,0,254,0,254,0,220,0,220,0,185,0,185,0,150,0,150,0,115,0,115,0,80,0,80,0,
+                       255,212,240,0,255,177,226,0,255,142,212,0,255,107,198,0,255,72,184,0,255,37,170,0,255,0,170,0,
+                       220,0,146,0,185,0,122,0,150,0,98,0,115,0,74,0,80,0,50,0,255,212,227,0,255,177,199,0,255,142,171,0,
+                       255,107,143,0,255,72,115,0,255,37,87,0,255,0,85,0,220,0,73,0,185,0,61,0,150,0,49,0,115,0,37,0,
+                       80,0,25,0,255,212,212,0,255,177,177,0,255,142,142,0,255,107,107,0,255,72,72,0,255,37,37,0,254,0,
+                       0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,0,255,227,212,0,255,199,177,0,255,171,142,0,
+                       255,143,107,0,255,115,72,0,255,87,37,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,115,37,0,
+                       0,80,25,0,0,255,240,212,0,255,226,177,0,255,212,142,0,255,198,107,0,255,184,72,0,255,170,37,0,
+                       255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,0,255,255,212,0,255,255,177,0,
+                       255,255,142,0,255,255,107,0,255,255,72,0,255,255,37,0,254,254,0,0,220,220,0,0,185,185,0,0,150,150,0,
+                       0,115,115,0,0,80,80,0,0,240,255,212,0,226,255,177,0,212,255,142,0,198,255,107,0,184,255,72,0,
+                       170,255,37,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,50,80,0,0,227,255,212,0,
+                       199,255,177,0,171,255,142,0,143,255,107,0,115,255,72,0,87,255,37,0,85,255,0,0,73,220,0,0,61,185,0,
+                       0,49,150,0,0,37,115,0,0,25,80,0,0,212,255,212,0,177,255,177,0,142,255,142,0,107,255,107,0,72,255,72,0,
+                       37,255,37,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,212,255,227,0,177,255,199,0,
+                       142,255,171,0,107,255,143,0,72,255,115,0,37,255,87,0,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,
+                       115,37,0,0,80,25,0,212,255,240,0,177,255,226,0,142,255,212,0,107,255,198,0,72,255,184,0,37,255,170,0,
+                       0,255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,212,255,255,0,177,255,255,0,
+                       142,255,255,0,107,255,255,0,72,255,255,0,37,255,255,0,0,254,254,0,0,220,220,0,0,185,185,0,0,
+                       150,150,0,0,115,115,0,0,80,80,0,242,242,242,0,230,230,230,0,218,218,218,0,206,206,206,0,194,194,194,0,
+                       182,182,182,0,170,170,170,0,158,158,158,0,146,146,146,0,134,134,134,0,122,122,122,0,110,110,110,0,
+                       98,98,98,0,86,86,86,0,74,74,74,0,62,62,62,0,50,50,50,0,38,38,38,0,26,26,26,0,14,14,14,0,240,251,255,0,
+                       164,160,160,0,128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};
+                       memcpy(GetPalette(),pal256,1024);
+                       break;
+               }
+       case 4:
+               {
+                       const BYTE pal16[64]={0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,
+                                                               128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};
+                       memcpy(GetPalette(),pal16,64);
+                       break;
+               }
+       case 1:
+               {
+                       const BYTE pal2[8]={0,0,0,0,255,255,255,0};
+                       memcpy(GetPalette(),pal2,8);
+                       break;
+               }
+       }
+       info.last_c_isvalid = false;
+       return;
+}
+////////////////////////////////////////////////////////////////////////////////