-/*\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
+