X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=utilities%2FCxImage%2Fximatga.cpp;h=d0842548813cd87b51cd2b4d864f835a0a2a08e4;hb=d268b74408bad9a7388c864e01627d8217549bd6;hp=b137126c4d1d7c154206651278c09083ab7e08ce;hpb=3fd15028ab81e6746d3af96695526d7d973a26c8;p=clitk.git diff --git a/utilities/CxImage/ximatga.cpp b/utilities/CxImage/ximatga.cpp index b137126..d084254 100644 --- a/utilities/CxImage/ximatga.cpp +++ b/utilities/CxImage/ximatga.cpp @@ -1,321 +1,321 @@ -/* - * 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 // - 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"); // - 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 - 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(); // -#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 - 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; xRead(&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 // - 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; xRead(&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; xRead(&pixel,4,1); - *dst++ = pixel.rgbBlue; - *dst++ = pixel.rgbGreen; - *dst++ = pixel.rgbRed; -#if CXIMAGE_SUPPORT_ALPHA // - 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 - +/* + * 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 // + 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"); // - 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 - 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(); // +#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 + 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; xRead(&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 // + 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; xRead(&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; xRead(&pixel,4,1); + *dst++ = pixel.rgbBlue; + *dst++ = pixel.rgbGreen; + *dst++ = pixel.rgbRed; +#if CXIMAGE_SUPPORT_ALPHA // + 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 +