]> Creatis software - clitk.git/blobdiff - utilities/CxImage/ximalpha.cpp
cosmetic
[clitk.git] / utilities / CxImage / ximalpha.cpp
index 8233dcbd58418738663f85b61d9fda505b55c174..823c3cef22c2beb99f8bb29361c760f7fbc1e838 100644 (file)
-// xImalpha.cpp : Alpha channel 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
-#if CXIMAGE_SUPPORT_ALPHA\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa AlphaSetMax\r
- */\r
-BYTE CxImage::AlphaGetMax() const\r
-{\r
-       return info.nAlphaMax;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets global Alpha (opacity) value applied to the whole image,\r
- * valid only for painting functions.\r
- * \param nAlphaMax: can be from 0 to 255\r
- */\r
-void CxImage::AlphaSetMax(BYTE nAlphaMax)\r
-{\r
-       info.nAlphaMax=nAlphaMax;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the image has a valid alpha channel.\r
- */\r
-bool CxImage::AlphaIsValid()\r
-{\r
-       return pAlpha!=0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enables the alpha palette, so the Draw() function changes its behavior.\r
- */\r
-void CxImage::AlphaPaletteEnable(bool enable)\r
-{\r
-       info.bAlphaPaletteEnabled=enable;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * True if the alpha palette is enabled for painting.\r
- */\r
-bool CxImage::AlphaPaletteIsEnabled()\r
-{\r
-       return info.bAlphaPaletteEnabled;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the alpha channel to full transparent. AlphaSet(0) has the same effect\r
- */\r
-void CxImage::AlphaClear()\r
-{\r
-       if (pAlpha)     memset(pAlpha,0,head.biWidth * head.biHeight);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the alpha level for the whole image.\r
- * \param level : from 0 (transparent) to 255 (opaque)\r
- */\r
-void CxImage::AlphaSet(BYTE level)\r
-{\r
-       if (pAlpha)     memset(pAlpha,level,head.biWidth * head.biHeight);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Allocates an empty (opaque) alpha channel.\r
- */\r
-bool CxImage::AlphaCreate()\r
-{\r
-       if (pAlpha==NULL) {\r
-               pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-               if (pAlpha) memset(pAlpha,255,head.biWidth * head.biHeight);\r
-       }\r
-       return (pAlpha!=0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::AlphaDelete()\r
-{\r
-       if (pAlpha) { free(pAlpha); pAlpha=0; }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::AlphaInvert()\r
-{\r
-       if (pAlpha) {\r
-               BYTE *iSrc=pAlpha;\r
-               long n=head.biHeight*head.biWidth;\r
-               for(long i=0; i < n; i++){\r
-                       *iSrc=(BYTE)~(*(iSrc));\r
-                       iSrc++;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Imports an existing alpa channel from another image with the same width and height.\r
- */\r
-bool CxImage::AlphaCopy(CxImage &from)\r
-{\r
-       if (from.pAlpha == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;\r
-       if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       if (pAlpha==NULL) return false;\r
-       memcpy(pAlpha,from.pAlpha,head.biWidth * head.biHeight);\r
-       info.nAlphaMax=from.info.nAlphaMax;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Creates the alpha channel from a gray scale image.\r
- */\r
-bool CxImage::AlphaSet(CxImage &from)\r
-{\r
-       if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;\r
-       if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       BYTE* src = from.info.pImage;\r
-       BYTE* dst = pAlpha;\r
-       if (src==NULL || dst==NULL) return false;\r
-       for (long y=0; y<head.biHeight; y++){\r
-               memcpy(dst,src,head.biWidth);\r
-               dst += head.biWidth;\r
-               src += from.info.dwEffWidth;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the alpha level for a single pixel \r
- */\r
-void CxImage::AlphaSet(const long x,const long y,const BYTE level)\r
-{\r
-       if (pAlpha && IsInside(x,y)) pAlpha[x+y*head.biWidth]=level;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the alpha level for a single pixel \r
- */\r
-BYTE CxImage::AlphaGet(const long x,const long y)\r
-{\r
-       if (pAlpha && IsInside(x,y)) return pAlpha[x+y*head.biWidth];\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns pointer to alpha data for pixel (x,y).\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-BYTE* CxImage::AlphaGetPointer(const long x,const long y)\r
-{\r
-       if (pAlpha && IsInside(x,y)) return pAlpha+x+y*head.biWidth;\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Get alpha value without boundscheck (a bit faster). Pixel must be inside the image.\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-BYTE CxImage::BlindAlphaGet(const long x,const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if (!IsInside(x,y) || (pAlpha==0))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-       return pAlpha[x+y*head.biWidth];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Resets the alpha palette \r
- */\r
-void CxImage::AlphaPaletteClear()\r
-{\r
-       RGBQUAD c;\r
-       for(WORD ip=0; ip<head.biClrUsed;ip++){\r
-               c=GetPaletteColor((BYTE)ip);\r
-               c.rgbReserved=0;\r
-               SetPaletteColor((BYTE)ip,c);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the image has a valid alpha palette. \r
- */\r
-bool CxImage::AlphaPaletteIsValid()\r
-{\r
-       RGBQUAD c;\r
-       for(WORD ip=0; ip<head.biClrUsed;ip++){\r
-               c=GetPaletteColor((BYTE)ip);\r
-               if (c.rgbReserved != 0) return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Blends the alpha channel and the alpha palette with the pixels. The result is a 24 bit image.\r
- * The background color can be selected using SetTransColor().\r
- */\r
-void CxImage::AlphaStrip()\r
-{\r
-       bool bAlphaPaletteIsValid = AlphaPaletteIsValid();\r
-       bool bAlphaIsValid = AlphaIsValid();\r
-       if (!(bAlphaIsValid || bAlphaPaletteIsValid)) return;\r
-       RGBQUAD c;\r
-       long a, a1;\r
-       if (head.biBitCount==24){\r
-               for(long y=0; y<head.biHeight; y++){\r
-                       for(long x=0; x<head.biWidth; x++){\r
-                               c = BlindGetPixelColor(x,y);\r
-                               if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;\r
-                               a1 = 256-a;\r
-                               c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);\r
-                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);\r
-                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);\r
-                               BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-               AlphaDelete();\r
-       } else {\r
-               CxImage tmp(head.biWidth,head.biHeight,24);\r
-               if (!tmp.IsValid()){\r
-                       strcpy(info.szLastError,tmp.GetLastError());\r
-                       return;\r
-               }\r
-\r
-               for(long y=0; y<head.biHeight; y++){\r
-                       for(long x=0; x<head.biWidth; x++){\r
-                               c = BlindGetPixelColor(x,y);\r
-                               if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;\r
-                               if (bAlphaPaletteIsValid) a=(c.rgbReserved*a)/255;\r
-                               a1 = 256-a;\r
-                               c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);\r
-                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);\r
-                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);\r
-                               tmp.BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-               Transfer(tmp);\r
-       }\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::AlphaFlip()\r
-{\r
-       if (!pAlpha) return false;\r
-\r
-       BYTE *buff = (BYTE*)malloc(head.biWidth);\r
-       if (!buff) return false;\r
-\r
-       BYTE *iSrc,*iDst;\r
-       iSrc = pAlpha + (head.biHeight-1)*head.biWidth;\r
-       iDst = pAlpha;\r
-       for (long i=0; i<(head.biHeight/2); ++i)\r
-       {\r
-               memcpy(buff, iSrc, head.biWidth);\r
-               memcpy(iSrc, iDst, head.biWidth);\r
-               memcpy(iDst, buff, head.biWidth);\r
-               iSrc-=head.biWidth;\r
-               iDst+=head.biWidth;\r
-       }\r
-\r
-       free(buff);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::AlphaMirror()\r
-{\r
-       if (!pAlpha) return false;\r
-       BYTE* pAlpha2 = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       if (!pAlpha2) return false;\r
-       BYTE *iSrc,*iDst;\r
-       long wdt=head.biWidth-1;\r
-       iSrc=pAlpha + wdt;\r
-       iDst=pAlpha2;\r
-       for(long y=0; y < head.biHeight; y++){\r
-               for(long x=0; x <= wdt; x++)\r
-                       *(iDst+x)=*(iSrc-x);\r
-               iSrc+=head.biWidth;\r
-               iDst+=head.biWidth;\r
-       }\r
-       free(pAlpha);\r
-       pAlpha=pAlpha2;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Exports the alpha channel in a 8bpp grayscale image. \r
- */\r
-bool CxImage::AlphaSplit(CxImage *dest)\r
-{\r
-       if (!pAlpha || !dest) return false;\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,8);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       tmp.BlindSetPixelIndex(x,y,pAlpha[x+y*head.biWidth]);\r
-               }\r
-       }\r
-\r
-       tmp.SetGrayPalette();\r
-       dest->Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Exports the alpha palette channel in a 8bpp grayscale image. \r
- */\r
-bool CxImage::AlphaPaletteSplit(CxImage *dest)\r
-{\r
-       if (!AlphaPaletteIsValid() || !dest) return false;\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,8);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       tmp.BlindSetPixelIndex(x,y,BlindGetPixelColor(x,y).rgbReserved);\r
-               }\r
-       }\r
-\r
-       tmp.SetGrayPalette();\r
-       dest->Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Merge in the alpha layer the transparent color mask\r
- * (previously set with SetTransColor or SetTransIndex) \r
- */\r
-bool CxImage::AlphaFromTransparency()\r
-{\r
-       if (!IsValid() || !IsTransparent())\r
-               return false;\r
-\r
-       AlphaCreate();\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
-                               AlphaSet(x,y,0);\r
-                       }\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
+// xImalpha.cpp : Alpha channel functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_ALPHA
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa AlphaSetMax
+ */
+BYTE CxImage::AlphaGetMax() const
+{
+       return info.nAlphaMax;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets global Alpha (opacity) value applied to the whole image,
+ * valid only for painting functions.
+ * \param nAlphaMax: can be from 0 to 255
+ */
+void CxImage::AlphaSetMax(BYTE nAlphaMax)
+{
+       info.nAlphaMax=nAlphaMax;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid alpha channel.
+ */
+bool CxImage::AlphaIsValid()
+{
+       return pAlpha!=0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enables the alpha palette, so the Draw() function changes its behavior.
+ */
+void CxImage::AlphaPaletteEnable(bool enable)
+{
+       info.bAlphaPaletteEnabled=enable;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * True if the alpha palette is enabled for painting.
+ */
+bool CxImage::AlphaPaletteIsEnabled()
+{
+       return info.bAlphaPaletteEnabled;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the alpha channel to full transparent. AlphaSet(0) has the same effect
+ */
+void CxImage::AlphaClear()
+{
+       if (pAlpha)     memset(pAlpha,0,head.biWidth * head.biHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the alpha level for the whole image.
+ * \param level : from 0 (transparent) to 255 (opaque)
+ */
+void CxImage::AlphaSet(BYTE level)
+{
+       if (pAlpha)     memset(pAlpha,level,head.biWidth * head.biHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Allocates an empty (opaque) alpha channel.
+ */
+bool CxImage::AlphaCreate()
+{
+       if (pAlpha==NULL) {
+               pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);
+               if (pAlpha) memset(pAlpha,255,head.biWidth * head.biHeight);
+       }
+       return (pAlpha!=0);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::AlphaDelete()
+{
+       if (pAlpha) { free(pAlpha); pAlpha=0; }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::AlphaInvert()
+{
+       if (pAlpha) {
+               BYTE *iSrc=pAlpha;
+               long n=head.biHeight*head.biWidth;
+               for(long i=0; i < n; i++){
+                       *iSrc=(BYTE)~(*(iSrc));
+                       iSrc++;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Imports an existing alpa channel from another image with the same width and height.
+ */
+bool CxImage::AlphaCopy(CxImage &from)
+{
+       if (from.pAlpha == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
+       if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);
+       if (pAlpha==NULL) return false;
+       memcpy(pAlpha,from.pAlpha,head.biWidth * head.biHeight);
+       info.nAlphaMax=from.info.nAlphaMax;
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Creates the alpha channel from a gray scale image.
+ */
+bool CxImage::AlphaSet(CxImage &from)
+{
+       if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
+       if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);
+       BYTE* src = from.info.pImage;
+       BYTE* dst = pAlpha;
+       if (src==NULL || dst==NULL) return false;
+       for (long y=0; y<head.biHeight; y++){
+               memcpy(dst,src,head.biWidth);
+               dst += head.biWidth;
+               src += from.info.dwEffWidth;
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the alpha level for a single pixel 
+ */
+void CxImage::AlphaSet(const long x,const long y,const BYTE level)
+{
+       if (pAlpha && IsInside(x,y)) pAlpha[x+y*head.biWidth]=level;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the alpha level for a single pixel 
+ */
+BYTE CxImage::AlphaGet(const long x,const long y)
+{
+       if (pAlpha && IsInside(x,y)) return pAlpha[x+y*head.biWidth];
+       return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns pointer to alpha data for pixel (x,y).
+ *
+ * \author ***bd*** 2.2004
+ */
+BYTE* CxImage::AlphaGetPointer(const long x,const long y)
+{
+       if (pAlpha && IsInside(x,y)) return pAlpha+x+y*head.biWidth;
+       return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Get alpha value without boundscheck (a bit faster). Pixel must be inside the image.
+ *
+ * \author ***bd*** 2.2004
+ */
+BYTE CxImage::BlindAlphaGet(const long x,const long y)
+{
+#ifdef _DEBUG
+       if (!IsInside(x,y) || (pAlpha==0))
+  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+               throw 0;
+  #else
+               return 0;
+  #endif
+#endif
+       return pAlpha[x+y*head.biWidth];
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Resets the alpha palette 
+ */
+void CxImage::AlphaPaletteClear()
+{
+       RGBQUAD c;
+       for(WORD ip=0; ip<head.biClrUsed;ip++){
+               c=GetPaletteColor((BYTE)ip);
+               c.rgbReserved=0;
+               SetPaletteColor((BYTE)ip,c);
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid alpha palette. 
+ */
+bool CxImage::AlphaPaletteIsValid()
+{
+       RGBQUAD c;
+       for(WORD ip=0; ip<head.biClrUsed;ip++){
+               c=GetPaletteColor((BYTE)ip);
+               if (c.rgbReserved != 0) return true;
+       }
+       return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Blends the alpha channel and the alpha palette with the pixels. The result is a 24 bit image.
+ * The background color can be selected using SetTransColor().
+ */
+void CxImage::AlphaStrip()
+{
+       bool bAlphaPaletteIsValid = AlphaPaletteIsValid();
+       bool bAlphaIsValid = AlphaIsValid();
+       if (!(bAlphaIsValid || bAlphaPaletteIsValid)) return;
+       RGBQUAD c;
+       long a, a1;
+       if (head.biBitCount==24){
+               for(long y=0; y<head.biHeight; y++){
+                       for(long x=0; x<head.biWidth; x++){
+                               c = BlindGetPixelColor(x,y);
+                               if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;
+                               a1 = 256-a;
+                               c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
+                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
+                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
+                               BlindSetPixelColor(x,y,c);
+                       }
+               }
+               AlphaDelete();
+       } else {
+               CxImage tmp(head.biWidth,head.biHeight,24);
+               if (!tmp.IsValid()){
+                       strcpy(info.szLastError,tmp.GetLastError());
+                       return;
+               }
+
+               for(long y=0; y<head.biHeight; y++){
+                       for(long x=0; x<head.biWidth; x++){
+                               c = BlindGetPixelColor(x,y);
+                               if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;
+                               if (bAlphaPaletteIsValid) a=(c.rgbReserved*a)/255;
+                               a1 = 256-a;
+                               c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
+                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
+                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
+                               tmp.BlindSetPixelColor(x,y,c);
+                       }
+               }
+               Transfer(tmp);
+       }
+       return;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::AlphaFlip()
+{
+       if (!pAlpha) return false;
+
+       BYTE *buff = (BYTE*)malloc(head.biWidth);
+       if (!buff) return false;
+
+       BYTE *iSrc,*iDst;
+       iSrc = pAlpha + (head.biHeight-1)*head.biWidth;
+       iDst = pAlpha;
+       for (long i=0; i<(head.biHeight/2); ++i)
+       {
+               memcpy(buff, iSrc, head.biWidth);
+               memcpy(iSrc, iDst, head.biWidth);
+               memcpy(iDst, buff, head.biWidth);
+               iSrc-=head.biWidth;
+               iDst+=head.biWidth;
+       }
+
+       free(buff);
+
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::AlphaMirror()
+{
+       if (!pAlpha) return false;
+       BYTE* pAlpha2 = (BYTE*)malloc(head.biWidth * head.biHeight);
+       if (!pAlpha2) return false;
+       BYTE *iSrc,*iDst;
+       long wdt=head.biWidth-1;
+       iSrc=pAlpha + wdt;
+       iDst=pAlpha2;
+       for(long y=0; y < head.biHeight; y++){
+               for(long x=0; x <= wdt; x++)
+                       *(iDst+x)=*(iSrc-x);
+               iSrc+=head.biWidth;
+               iDst+=head.biWidth;
+       }
+       free(pAlpha);
+       pAlpha=pAlpha2;
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Exports the alpha channel in a 8bpp grayscale image. 
+ */
+bool CxImage::AlphaSplit(CxImage *dest)
+{
+       if (!pAlpha || !dest) return false;
+
+       CxImage tmp(head.biWidth,head.biHeight,8);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       for(long y=0; y<head.biHeight; y++){
+               for(long x=0; x<head.biWidth; x++){
+                       tmp.BlindSetPixelIndex(x,y,pAlpha[x+y*head.biWidth]);
+               }
+       }
+
+       tmp.SetGrayPalette();
+       dest->Transfer(tmp);
+
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Exports the alpha palette channel in a 8bpp grayscale image. 
+ */
+bool CxImage::AlphaPaletteSplit(CxImage *dest)
+{
+       if (!AlphaPaletteIsValid() || !dest) return false;
+
+       CxImage tmp(head.biWidth,head.biHeight,8);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       for(long y=0; y<head.biHeight; y++){
+               for(long x=0; x<head.biWidth; x++){
+                       tmp.BlindSetPixelIndex(x,y,BlindGetPixelColor(x,y).rgbReserved);
+               }
+       }
+
+       tmp.SetGrayPalette();
+       dest->Transfer(tmp);
+
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Merge in the alpha layer the transparent color mask
+ * (previously set with SetTransColor or SetTransIndex) 
+ */
+bool CxImage::AlphaFromTransparency()
+{
+       if (!IsValid() || !IsTransparent())
+               return false;
+
+       AlphaCreate();
+
+       for(long y=0; y<head.biHeight; y++){
+               for(long x=0; x<head.biWidth; x++){
+                       if (IsTransparent(x,y)){
+                               AlphaSet(x,y,0);
+                       }
+               }
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ALPHA