]> Creatis software - clitk.git/blobdiff - utilities/CxImage/ximatga.cpp
cosmetic
[clitk.git] / utilities / CxImage / ximatga.cpp
index b137126c4d1d7c154206651278c09083ab7e08ce..d0842548813cd87b51cd2b4d864f835a0a2a08e4 100644 (file)
-/*\r
- * File:       ximatga.cpp\r
- * Purpose:    Platform Independent TGA Image Class Loader and Writer\r
- * 05/Jan/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximatga.h"\r
-\r
-#if CXIMAGE_SUPPORT_TGA\r
-\r
-#include "ximaiter.h"\r
-\r
-// Definitions for image types.\r
-#define TGA_Null 0\r
-#define TGA_Map 1\r
-#define TGA_RGB 2\r
-#define TGA_Mono 3\r
-#define TGA_RLEMap 9\r
-#define TGA_RLERGB 10\r
-#define TGA_RLEMono 11\r
-#define TGA_CompMap 32\r
-#define TGA_CompMap4 33\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTGA::Decode(CxFile *hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       TGAHEADER tgaHead;\r
-\r
-  cx_try\r
-  {\r
-       if (hFile->Read(&tgaHead,sizeof(tgaHead),1)==0)\r
-               cx_throw("Not a TGA");\r
-\r
-       tga_toh(&tgaHead);\r
-\r
-       bool bCompressed;\r
-       switch (tgaHead.ImageType){\r
-       case TGA_Map:\r
-       case TGA_RGB:\r
-       case TGA_Mono:\r
-               bCompressed = false;\r
-               break;\r
-       case TGA_RLEMap:\r
-       case TGA_RLERGB:\r
-       case TGA_RLEMono:\r
-               bCompressed = true;\r
-               break;\r
-       default:\r
-               cx_throw("Unknown TGA image type");\r
-       }\r
-\r
-       if (tgaHead.ImageWidth==0 || tgaHead.ImageHeight==0 || tgaHead.PixelDepth==0 || tgaHead.CmapLength>256)\r
-               cx_throw("bad TGA header");\r
-\r
-       if (tgaHead.PixelDepth!=8 && tgaHead.PixelDepth!=15 && tgaHead.PixelDepth!=16 && tgaHead.PixelDepth!=24 && tgaHead.PixelDepth!=32)\r
-               cx_throw("bad TGA header");\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = tgaHead.ImageWidth ;\r
-               head.biHeight= tgaHead.ImageHeight;\r
-               info.dwType = CXIMAGE_FORMAT_TGA;\r
-               return true;\r
-       }\r
-\r
-       if (tgaHead.IdLength>0) hFile->Seek(tgaHead.IdLength,SEEK_CUR); //skip descriptor\r
-\r
-       Create(tgaHead.ImageWidth, tgaHead.ImageHeight, tgaHead.PixelDepth, CXIMAGE_FORMAT_TGA);\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-       if (tgaHead.PixelDepth==32) AlphaCreate(); // Image has alpha channel\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       if (!IsValid()) cx_throw("TGA Create failed");\r
-       \r
-       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-       if (tgaHead.CmapType != 0){ // read the palette\r
-               rgb_color pal[256];\r
-               hFile->Read(pal,tgaHead.CmapLength*sizeof(rgb_color), 1);\r
-               for (int i=0;i<tgaHead.CmapLength; i++) SetPaletteColor((BYTE)i,pal[i].b,pal[i].g,pal[i].r);\r
-       }\r
-\r
-       if (tgaHead.ImageType == TGA_Mono || tgaHead.ImageType == TGA_RLEMono)\r
-               SetGrayPalette();\r
-\r
-       // Bits 4 & 5 of the Image Descriptor byte control the ordering of the pixels.\r
-       bool bXReversed = ((tgaHead.ImagDesc & 16) == 16);\r
-       bool bYReversed = ((tgaHead.ImagDesc & 32) == 32);\r
-\r
-    CImageIterator iter(this);\r
-       BYTE rleLeftover = 255; //for images with illegal packet boundary \r
-       BYTE* pDest;\r
-    for (int y=0; y < tgaHead.ImageHeight; y++){\r
-\r
-               if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-               if (hFile == NULL || hFile->Eof()) cx_throw("corrupted TGA");\r
-\r
-               if (bYReversed) pDest = iter.GetRow(tgaHead.ImageHeight-y-1);\r
-               else pDest = iter.GetRow(y);\r
-\r
-               if (bCompressed) rleLeftover = ExpandCompressedLine(pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,rleLeftover);\r
-               else ExpandUncompressedLine  (pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,0);\r
-    }\r
-\r
-       if (bXReversed) Mirror();\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bYReversed && tgaHead.PixelDepth==32) AlphaFlip(); //<lioucr>\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       return false;\r
-  }\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTGA::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       if (head.biBitCount<8){\r
-               strcpy(info.szLastError,"Bit depth must be 8 or 24");\r
-               return false;\r
-       }\r
-\r
-       TGAHEADER tgaHead;\r
-\r
-    tgaHead.IdLength = 0;                              // Image ID Field Length\r
-    tgaHead.CmapType = GetPalette()!=0; // Color Map Type\r
-    tgaHead.ImageType = (head.biBitCount == 8) ? (BYTE)TGA_Map : (BYTE)TGA_RGB; // Image Type\r
-\r
-    tgaHead.CmapIndex=0;                               // First Entry Index\r
-    tgaHead.CmapLength=(head.biBitCount == 8) ? 256 : 0;   // Color Map Length\r
-    tgaHead.CmapEntrySize=(head.biBitCount == 8) ? (BYTE)24 : (BYTE)0; // Color Map Entry Size\r
-\r
-    tgaHead.X_Origin=0;                                        // X-origin of Image\r
-    tgaHead.Y_Origin=0;                                        // Y-origin of Image\r
-    tgaHead.ImageWidth=(WORD)head.biWidth;             // Image Width\r
-    tgaHead.ImageHeight=(WORD)head.biHeight;   // Image Height\r
-    tgaHead.PixelDepth=(BYTE)head.biBitCount;  // Pixel Depth\r
-    tgaHead.ImagDesc=0;                                        // Image Descriptor\r
-\r
-       if (pAlpha && head.biBitCount==24) tgaHead.PixelDepth=32; \r
-\r
-       tga_toh(&tgaHead);\r
-       hFile->Write(&tgaHead,sizeof(TGAHEADER),1);\r
-       tga_toh(&tgaHead);\r
-\r
-       if (head.biBitCount==8){\r
-               rgb_color pal[256];\r
-               RGBQUAD* ppal = GetPalette();\r
-               for (int i=0;i<256; i++){\r
-                       pal[i].r = ppal[i].rgbBlue;\r
-                       pal[i].g = ppal[i].rgbGreen;\r
-                       pal[i].b = ppal[i].rgbRed;\r
-               }\r
-               hFile->Write(&pal,256*sizeof(rgb_color),1);\r
-       }\r
-       \r
-       CImageIterator iter(this);\r
-       BYTE* pDest;\r
-       if (pAlpha==0 || head.biBitCount==8){\r
-               for (int y=0; y < tgaHead.ImageHeight; y++){\r
-                       pDest = iter.GetRow(y);\r
-                       hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1);\r
-               }\r
-       } else {\r
-               pDest = (BYTE*)malloc(4*tgaHead.ImageWidth);\r
-               RGBQUAD c;\r
-               for (int y=0; y < tgaHead.ImageHeight; y++){\r
-                       for(int x=0, x4=0;x<tgaHead.ImageWidth;x++, x4+=4){\r
-                               c = BlindGetPixelColor(x,y);\r
-                               pDest[x4+0]=c.rgbBlue;\r
-                               pDest[x4+1]=c.rgbGreen;\r
-                               pDest[x4+2]=c.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                               pDest[x4+3]=AlphaGet(x,y);\r
-#else\r
-                               pDest[x4+3]=0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-                       hFile->Write(pDest,4*tgaHead.ImageWidth,1);\r
-               }\r
-               free(pDest);\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-BYTE CxImageTGA::ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover)\r
-{\r
-       BYTE rle;\r
-       long filePos=0;\r
-       for (int x=0; x<width; ){\r
-               if (rleLeftover != 255){\r
-            rle = rleLeftover;\r
-            rleLeftover = 255;\r
-        } else {\r
-                       hFile->Read(&rle,1,1);\r
-               }\r
-               if (rle & 128) { // RLE-Encoded packet\r
-                       rle -= 127; // Calculate real repeat count.\r
-                       if ((x+rle)>width){\r
-                               rleLeftover = (BYTE)(128 + (rle - (width - x) - 1));\r
-                filePos = hFile->Tell();\r
-                               rle = (BYTE)(width - x);\r
-                       }\r
-                       switch (ptgaHead->PixelDepth)\r
-                       {\r
-                       case 32: {\r
-                               RGBQUAD color;\r
-                               hFile->Read(&color,4,1);\r
-                               for (int ix = 0; ix < rle; ix++){\r
-                                       memcpy(&pDest[3*ix],&color,3);\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                                       AlphaSet(ix+x,y,color.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                               }\r
-                               break;\r
-                                        } \r
-                       case 24: {\r
-                               rgb_color triple;\r
-                               hFile->Read(&triple,3,1);\r
-                               for (int ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3);\r
-                               break;\r
-                                        }\r
-                       case 15:\r
-                       case 16: {\r
-                               WORD pixel;\r
-                               hFile->Read(&pixel,2,1);\r
-                               rgb_color triple;\r
-                               triple.r = (BYTE)(( pixel & 0x1F ) * 8);     // red\r
-                               triple.g = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green\r
-                               triple.b = (BYTE)(( pixel >> 7 ) & 0x0F8);   // blue\r
-                               for (int ix = 0; ix < rle; ix++){\r
-                                       memcpy(&pDest[3*ix],&triple,3);\r
-                               }\r
-                               break;\r
-                                        }\r
-                       case 8: {\r
-                               BYTE pixel;\r
-                               hFile->Read(&pixel,1,1);\r
-                               for (int ix = 0; ix < rle; ix++) pDest[ix] = pixel;\r
-                                       }\r
-                       }\r
-                       if (rleLeftover!=255) hFile->Seek(filePos, SEEK_SET);\r
-               } else { // Raw packet\r
-                       rle += 1; // Calculate real repeat count.\r
-                       if ((x+rle)>width){\r
-                rleLeftover = (BYTE)(rle - (width - x) - 1);\r
-                               rle = (BYTE)(width - x);\r
-                       }\r
-                       ExpandUncompressedLine(pDest,ptgaHead,hFile,rle,y,x);\r
-               }\r
-               if (head.biBitCount == 24)      pDest += rle*3; else pDest += rle;\r
-               x += rle;\r
-       }\r
-       return rleLeftover;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTGA::ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset)\r
-{\r
-       switch (ptgaHead->PixelDepth){\r
-       case 8:\r
-               hFile->Read(pDest,width,1);\r
-               break;\r
-       case 15:\r
-       case 16:{\r
-               BYTE* dst=pDest;\r
-               WORD pixel;\r
-               for (int x=0; x<width; x++){\r
-                       hFile->Read(&pixel,2,1);\r
-                       *dst++ = (BYTE)(( pixel & 0x1F ) * 8);     // blue\r
-                       *dst++ = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green\r
-                       *dst++ = (BYTE)(( pixel >> 7 ) & 0x0F8);   // red\r
-               }\r
-               break;\r
-                       }\r
-       case 24:\r
-               hFile->Read(pDest,3*width,1);\r
-               break;\r
-       case 32:{\r
-               BYTE* dst=pDest;\r
-               for (int x=0; x<width; x++){\r
-                       RGBQUAD pixel;\r
-                       hFile->Read(&pixel,4,1);\r
-                       *dst++ = pixel.rgbBlue;\r
-                       *dst++ = pixel.rgbGreen;\r
-                       *dst++ = pixel.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                       AlphaSet(x+xoffset,y,pixel.rgbReserved); //alpha\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-               }\r
-               break;\r
-                       }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTGA::tga_toh(TGAHEADER* p)\r
-{\r
-    p->CmapIndex = ntohs(p->CmapIndex);\r
-    p->CmapLength = ntohs(p->CmapLength);\r
-    p->X_Origin = ntohs(p->X_Origin);\r
-    p->Y_Origin = ntohs(p->Y_Origin);\r
-    p->ImageWidth = ntohs(p->ImageWidth);\r
-    p->ImageHeight = ntohs(p->ImageHeight);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif         // CXIMAGE_SUPPORT_TGA\r
-\r
+/*
+ * File:       ximatga.cpp
+ * Purpose:    Platform Independent TGA Image Class Loader and Writer
+ * 05/Jan/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximatga.h"
+
+#if CXIMAGE_SUPPORT_TGA
+
+#include "ximaiter.h"
+
+// Definitions for image types.
+#define TGA_Null 0
+#define TGA_Map 1
+#define TGA_RGB 2
+#define TGA_Mono 3
+#define TGA_RLEMap 9
+#define TGA_RLERGB 10
+#define TGA_RLEMono 11
+#define TGA_CompMap 32
+#define TGA_CompMap4 33
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTGA::Decode(CxFile *hFile)
+{
+       if (hFile == NULL) return false;
+
+       TGAHEADER tgaHead;
+
+  cx_try
+  {
+       if (hFile->Read(&tgaHead,sizeof(tgaHead),1)==0)
+               cx_throw("Not a TGA");
+
+       tga_toh(&tgaHead);
+
+       bool bCompressed;
+       switch (tgaHead.ImageType){
+       case TGA_Map:
+       case TGA_RGB:
+       case TGA_Mono:
+               bCompressed = false;
+               break;
+       case TGA_RLEMap:
+       case TGA_RLERGB:
+       case TGA_RLEMono:
+               bCompressed = true;
+               break;
+       default:
+               cx_throw("Unknown TGA image type");
+       }
+
+       if (tgaHead.ImageWidth==0 || tgaHead.ImageHeight==0 || tgaHead.PixelDepth==0 || tgaHead.CmapLength>256)
+               cx_throw("bad TGA header");
+
+       if (tgaHead.PixelDepth!=8 && tgaHead.PixelDepth!=15 && tgaHead.PixelDepth!=16 && tgaHead.PixelDepth!=24 && tgaHead.PixelDepth!=32)
+               cx_throw("bad TGA header");
+
+       if (info.nEscape == -1){
+               head.biWidth = tgaHead.ImageWidth ;
+               head.biHeight= tgaHead.ImageHeight;
+               info.dwType = CXIMAGE_FORMAT_TGA;
+               return true;
+       }
+
+       if (tgaHead.IdLength>0) hFile->Seek(tgaHead.IdLength,SEEK_CUR); //skip descriptor
+
+       Create(tgaHead.ImageWidth, tgaHead.ImageHeight, tgaHead.PixelDepth, CXIMAGE_FORMAT_TGA);
+#if CXIMAGE_SUPPORT_ALPHA      // <vho>
+       if (tgaHead.PixelDepth==32) AlphaCreate(); // Image has alpha channel
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+       if (!IsValid()) cx_throw("TGA Create failed");
+       
+       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+       if (tgaHead.CmapType != 0){ // read the palette
+               rgb_color pal[256];
+               hFile->Read(pal,tgaHead.CmapLength*sizeof(rgb_color), 1);
+               for (int i=0;i<tgaHead.CmapLength; i++) SetPaletteColor((BYTE)i,pal[i].b,pal[i].g,pal[i].r);
+       }
+
+       if (tgaHead.ImageType == TGA_Mono || tgaHead.ImageType == TGA_RLEMono)
+               SetGrayPalette();
+
+       // Bits 4 & 5 of the Image Descriptor byte control the ordering of the pixels.
+       bool bXReversed = ((tgaHead.ImagDesc & 16) == 16);
+       bool bYReversed = ((tgaHead.ImagDesc & 32) == 32);
+
+    CImageIterator iter(this);
+       BYTE rleLeftover = 255; //for images with illegal packet boundary 
+       BYTE* pDest;
+    for (int y=0; y < tgaHead.ImageHeight; y++){
+
+               if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+               if (hFile == NULL || hFile->Eof()) cx_throw("corrupted TGA");
+
+               if (bYReversed) pDest = iter.GetRow(tgaHead.ImageHeight-y-1);
+               else pDest = iter.GetRow(y);
+
+               if (bCompressed) rleLeftover = ExpandCompressedLine(pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,rleLeftover);
+               else ExpandUncompressedLine  (pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,0);
+    }
+
+       if (bXReversed) Mirror();
+
+#if CXIMAGE_SUPPORT_ALPHA
+       if (bYReversed && tgaHead.PixelDepth==32) AlphaFlip(); //<lioucr>
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+  } cx_catch {
+       if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+       return false;
+  }
+    return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTGA::Encode(CxFile * hFile)
+{
+       if (EncodeSafeCheck(hFile)) return false;
+
+       if (head.biBitCount<8){
+               strcpy(info.szLastError,"Bit depth must be 8 or 24");
+               return false;
+       }
+
+       TGAHEADER tgaHead;
+
+    tgaHead.IdLength = 0;                              // Image ID Field Length
+    tgaHead.CmapType = GetPalette()!=0; // Color Map Type
+    tgaHead.ImageType = (head.biBitCount == 8) ? (BYTE)TGA_Map : (BYTE)TGA_RGB; // Image Type
+
+    tgaHead.CmapIndex=0;                               // First Entry Index
+    tgaHead.CmapLength=(head.biBitCount == 8) ? 256 : 0;   // Color Map Length
+    tgaHead.CmapEntrySize=(head.biBitCount == 8) ? (BYTE)24 : (BYTE)0; // Color Map Entry Size
+
+    tgaHead.X_Origin=0;                                        // X-origin of Image
+    tgaHead.Y_Origin=0;                                        // Y-origin of Image
+    tgaHead.ImageWidth=(WORD)head.biWidth;             // Image Width
+    tgaHead.ImageHeight=(WORD)head.biHeight;   // Image Height
+    tgaHead.PixelDepth=(BYTE)head.biBitCount;  // Pixel Depth
+    tgaHead.ImagDesc=0;                                        // Image Descriptor
+
+       if (pAlpha && head.biBitCount==24) tgaHead.PixelDepth=32; 
+
+       tga_toh(&tgaHead);
+       hFile->Write(&tgaHead,sizeof(TGAHEADER),1);
+       tga_toh(&tgaHead);
+
+       if (head.biBitCount==8){
+               rgb_color pal[256];
+               RGBQUAD* ppal = GetPalette();
+               for (int i=0;i<256; i++){
+                       pal[i].r = ppal[i].rgbBlue;
+                       pal[i].g = ppal[i].rgbGreen;
+                       pal[i].b = ppal[i].rgbRed;
+               }
+               hFile->Write(&pal,256*sizeof(rgb_color),1);
+       }
+       
+       CImageIterator iter(this);
+       BYTE* pDest;
+       if (pAlpha==0 || head.biBitCount==8){
+               for (int y=0; y < tgaHead.ImageHeight; y++){
+                       pDest = iter.GetRow(y);
+                       hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1);
+               }
+       } else {
+               pDest = (BYTE*)malloc(4*tgaHead.ImageWidth);
+               RGBQUAD c;
+               for (int y=0; y < tgaHead.ImageHeight; y++){
+                       for(int x=0, x4=0;x<tgaHead.ImageWidth;x++, x4+=4){
+                               c = BlindGetPixelColor(x,y);
+                               pDest[x4+0]=c.rgbBlue;
+                               pDest[x4+1]=c.rgbGreen;
+                               pDest[x4+2]=c.rgbRed;
+#if CXIMAGE_SUPPORT_ALPHA      // <vho>
+                               pDest[x4+3]=AlphaGet(x,y);
+#else
+                               pDest[x4+3]=0;
+#endif //CXIMAGE_SUPPORT_ALPHA
+                       }
+                       hFile->Write(pDest,4*tgaHead.ImageWidth,1);
+               }
+               free(pDest);
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+BYTE CxImageTGA::ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover)
+{
+       BYTE rle;
+       long filePos=0;
+       for (int x=0; x<width; ){
+               if (rleLeftover != 255){
+            rle = rleLeftover;
+            rleLeftover = 255;
+        } else {
+                       hFile->Read(&rle,1,1);
+               }
+               if (rle & 128) { // RLE-Encoded packet
+                       rle -= 127; // Calculate real repeat count.
+                       if ((x+rle)>width){
+                               rleLeftover = (BYTE)(128 + (rle - (width - x) - 1));
+                filePos = hFile->Tell();
+                               rle = (BYTE)(width - x);
+                       }
+                       switch (ptgaHead->PixelDepth)
+                       {
+                       case 32: {
+                               RGBQUAD color;
+                               hFile->Read(&color,4,1);
+                               for (int ix = 0; ix < rle; ix++){
+                                       memcpy(&pDest[3*ix],&color,3);
+#if CXIMAGE_SUPPORT_ALPHA      // <vho>
+                                       AlphaSet(ix+x,y,color.rgbReserved);
+#endif //CXIMAGE_SUPPORT_ALPHA
+                               }
+                               break;
+                                        } 
+                       case 24: {
+                               rgb_color triple;
+                               hFile->Read(&triple,3,1);
+                               for (int ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3);
+                               break;
+                                        }
+                       case 15:
+                       case 16: {
+                               WORD pixel;
+                               hFile->Read(&pixel,2,1);
+                               rgb_color triple;
+                               triple.r = (BYTE)(( pixel & 0x1F ) * 8);     // red
+                               triple.g = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green
+                               triple.b = (BYTE)(( pixel >> 7 ) & 0x0F8);   // blue
+                               for (int ix = 0; ix < rle; ix++){
+                                       memcpy(&pDest[3*ix],&triple,3);
+                               }
+                               break;
+                                        }
+                       case 8: {
+                               BYTE pixel;
+                               hFile->Read(&pixel,1,1);
+                               for (int ix = 0; ix < rle; ix++) pDest[ix] = pixel;
+                                       }
+                       }
+                       if (rleLeftover!=255) hFile->Seek(filePos, SEEK_SET);
+               } else { // Raw packet
+                       rle += 1; // Calculate real repeat count.
+                       if ((x+rle)>width){
+                rleLeftover = (BYTE)(rle - (width - x) - 1);
+                               rle = (BYTE)(width - x);
+                       }
+                       ExpandUncompressedLine(pDest,ptgaHead,hFile,rle,y,x);
+               }
+               if (head.biBitCount == 24)      pDest += rle*3; else pDest += rle;
+               x += rle;
+       }
+       return rleLeftover;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTGA::ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset)
+{
+       switch (ptgaHead->PixelDepth){
+       case 8:
+               hFile->Read(pDest,width,1);
+               break;
+       case 15:
+       case 16:{
+               BYTE* dst=pDest;
+               WORD pixel;
+               for (int x=0; x<width; x++){
+                       hFile->Read(&pixel,2,1);
+                       *dst++ = (BYTE)(( pixel & 0x1F ) * 8);     // blue
+                       *dst++ = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green
+                       *dst++ = (BYTE)(( pixel >> 7 ) & 0x0F8);   // red
+               }
+               break;
+                       }
+       case 24:
+               hFile->Read(pDest,3*width,1);
+               break;
+       case 32:{
+               BYTE* dst=pDest;
+               for (int x=0; x<width; x++){
+                       RGBQUAD pixel;
+                       hFile->Read(&pixel,4,1);
+                       *dst++ = pixel.rgbBlue;
+                       *dst++ = pixel.rgbGreen;
+                       *dst++ = pixel.rgbRed;
+#if CXIMAGE_SUPPORT_ALPHA      // <vho>
+                       AlphaSet(x+xoffset,y,pixel.rgbReserved); //alpha
+#endif //CXIMAGE_SUPPORT_ALPHA
+               }
+               break;
+                       }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTGA::tga_toh(TGAHEADER* p)
+{
+    p->CmapIndex = ntohs(p->CmapIndex);
+    p->CmapLength = ntohs(p->CmapLength);
+    p->X_Origin = ntohs(p->X_Origin);
+    p->Y_Origin = ntohs(p->Y_Origin);
+    p->ImageWidth = ntohs(p->ImageWidth);
+    p->ImageHeight = ntohs(p->ImageHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif         // CXIMAGE_SUPPORT_TGA
+