~ubuntu-branches/ubuntu/gutsy/amsn/gutsy

« back to all changes in this revision

Viewing changes to utils/TkCximage/src/CxImage/ximatga.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Karkoulis
  • Date: 2006-01-04 15:26:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104152602-ipe1yg00rl3nlklv
Tags: 0.95-1
New Upstream Release (closes: #345052, #278575).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * File:        ximatga.cpp
 
3
 * Purpose:     Platform Independent TGA Image Class Loader and Writer
 
4
 * 05/Jan/2001 Davide Pizzolato - www.xdp.it
 
5
 * CxImage version 5.99c 17/Oct/2004
 
6
 */
 
7
 
 
8
#include "ximatga.h"
 
9
 
 
10
#if CXIMAGE_SUPPORT_TGA
 
11
 
 
12
#include "ximaiter.h"
 
13
 
 
14
// Definitions for image types.
 
15
#define TGA_Null 0
 
16
#define TGA_Map 1
 
17
#define TGA_RGB 2
 
18
#define TGA_Mono 3
 
19
#define TGA_RLEMap 9
 
20
#define TGA_RLERGB 10
 
21
#define TGA_RLEMono 11
 
22
#define TGA_CompMap 32
 
23
#define TGA_CompMap4 33
 
24
 
 
25
////////////////////////////////////////////////////////////////////////////////
 
26
bool CxImageTGA::Decode(CxFile *hFile)
 
27
{
 
28
        if (hFile == NULL) return false;
 
29
 
 
30
        TGAHEADER tgaHead;
 
31
 
 
32
  try
 
33
  {
 
34
        if (hFile->Read(&tgaHead,sizeof(tgaHead),1)==0)
 
35
                throw "Not a TGA";
 
36
 
 
37
        bool bCompressed;
 
38
        switch (tgaHead.ImageType){
 
39
        case TGA_Map:
 
40
        case TGA_RGB:
 
41
        case TGA_Mono:
 
42
                bCompressed = false;
 
43
                break;
 
44
        case TGA_RLEMap:
 
45
        case TGA_RLERGB:
 
46
        case TGA_RLEMono:
 
47
                bCompressed = true;
 
48
                break;
 
49
        default:
 
50
                throw "Unknown TGA image type";
 
51
        }
 
52
 
 
53
        if (tgaHead.ImageWidth==0 || tgaHead.ImageHeight==0 || tgaHead.PixelDepth==0 || tgaHead.CmapLength>256)
 
54
                throw "bad TGA header";
 
55
 
 
56
        if (tgaHead.PixelDepth!=8 && tgaHead.PixelDepth!=15 && tgaHead.PixelDepth!=16 && tgaHead.PixelDepth!=24 && tgaHead.PixelDepth!=32)
 
57
                throw "bad TGA header";
 
58
 
 
59
        if (tgaHead.IdLength>0) hFile->Seek(tgaHead.IdLength,SEEK_CUR); //skip descriptor
 
60
 
 
61
        Create(tgaHead.ImageWidth, tgaHead.ImageHeight, tgaHead.PixelDepth, CXIMAGE_FORMAT_TGA);
 
62
#if CXIMAGE_SUPPORT_ALPHA       // <vho>
 
63
        if (tgaHead.PixelDepth==32) AlphaCreate(); // Image has alpha channel
 
64
#endif //CXIMAGE_SUPPORT_ALPHA
 
65
 
 
66
        if (!IsValid()) throw "TGA Create failed";
 
67
        
 
68
        if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding
 
69
 
 
70
        if (tgaHead.CmapType != 0){ // read the palette
 
71
                rgb_color pal[256];
 
72
                hFile->Read(pal,tgaHead.CmapLength*sizeof(rgb_color), 1);
 
73
                for (int i=0;i<tgaHead.CmapLength; i++) SetPaletteColor((BYTE)i,pal[i].b,pal[i].g,pal[i].r);
 
74
        }
 
75
 
 
76
        if (tgaHead.ImageType == TGA_Mono || tgaHead.ImageType == TGA_RLEMono)
 
77
                SetGrayPalette();
 
78
 
 
79
        // Bits 4 & 5 of the Image Descriptor byte control the ordering of the pixels.
 
80
        bool bXReversed = ((tgaHead.ImagDesc & 16) == 16);
 
81
        bool bYReversed = ((tgaHead.ImagDesc & 32) == 32);
 
82
 
 
83
    CImageIterator iter(this);
 
84
        BYTE rleLeftover = 255; //for images with illegal packet boundary 
 
85
        BYTE* pDest;
 
86
    for (int y=0; y < tgaHead.ImageHeight; y++){
 
87
 
 
88
                if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding
 
89
 
 
90
                if (hFile == NULL || hFile->Eof()) throw "corrupted TGA";
 
91
 
 
92
                if (bYReversed) pDest = iter.GetRow(tgaHead.ImageHeight-y-1);
 
93
                else pDest = iter.GetRow(y);
 
94
 
 
95
                if (bCompressed) rleLeftover = ExpandCompressedLine(pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,rleLeftover);
 
96
                else ExpandUncompressedLine  (pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,0);
 
97
    }
 
98
 
 
99
        if (bXReversed) Mirror();
 
100
 
 
101
#if CXIMAGE_SUPPORT_ALPHA
 
102
        if (bYReversed && tgaHead.PixelDepth==32) AlphaFlip(); //<lioucr>
 
103
#endif //CXIMAGE_SUPPORT_ALPHA
 
104
 
 
105
  } catch (const char *message) {
 
106
        strncpy(info.szLastError,message,255);
 
107
        return FALSE;
 
108
  }
 
109
    return true;
 
110
}
 
111
////////////////////////////////////////////////////////////////////////////////
 
112
#if CXIMAGE_SUPPORT_ENCODE
 
113
////////////////////////////////////////////////////////////////////////////////
 
114
bool CxImageTGA::Encode(CxFile * hFile)
 
115
{
 
116
        if (EncodeSafeCheck(hFile)) return false;
 
117
 
 
118
        if (head.biBitCount<8){
 
119
                strcpy(info.szLastError,"Bit depth must be 8 or 24");
 
120
                return false;
 
121
        }
 
122
 
 
123
        TGAHEADER tgaHead;
 
124
 
 
125
    tgaHead.IdLength = 0;                               // Image ID Field Length
 
126
    tgaHead.CmapType = GetPalette()!=0; // Color Map Type
 
127
    tgaHead.ImageType = (head.biBitCount == 8) ? (BYTE)TGA_Map : (BYTE)TGA_RGB; // Image Type
 
128
 
 
129
    tgaHead.CmapIndex=0;                                // First Entry Index
 
130
    tgaHead.CmapLength=(head.biBitCount == 8) ? 256 : 0;   // Color Map Length
 
131
    tgaHead.CmapEntrySize=(head.biBitCount == 8) ? (BYTE)24 : (BYTE)0; // Color Map Entry Size
 
132
 
 
133
    tgaHead.X_Origin=0;                                 // X-origin of Image
 
134
    tgaHead.Y_Origin=0;                                 // Y-origin of Image
 
135
    tgaHead.ImageWidth=(WORD)head.biWidth;              // Image Width
 
136
    tgaHead.ImageHeight=(WORD)head.biHeight;    // Image Height
 
137
    tgaHead.PixelDepth=(BYTE)head.biBitCount;   // Pixel Depth
 
138
    tgaHead.ImagDesc=0;                                 // Image Descriptor
 
139
 
 
140
        if (pAlpha && head.biBitCount==24) tgaHead.PixelDepth=32; 
 
141
 
 
142
        hFile->Write(&tgaHead,sizeof(TGAHEADER),1);
 
143
 
 
144
        if (head.biBitCount==8){
 
145
                rgb_color pal[256];
 
146
                RGBQUAD* ppal = GetPalette();
 
147
                for (int i=0;i<256; i++){
 
148
                        pal[i].r = ppal[i].rgbBlue;
 
149
                        pal[i].g = ppal[i].rgbGreen;
 
150
                        pal[i].b = ppal[i].rgbRed;
 
151
                }
 
152
                hFile->Write(&pal,256*sizeof(rgb_color),1);
 
153
        }
 
154
        
 
155
        CImageIterator iter(this);
 
156
        BYTE* pDest;
 
157
        if (pAlpha==0 || head.biBitCount==8){
 
158
                for (int y=0; y < tgaHead.ImageHeight; y++){
 
159
                        pDest = iter.GetRow(y);
 
160
                        hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1);
 
161
                }
 
162
        } else {
 
163
                pDest = (BYTE*)malloc(4*tgaHead.ImageWidth);
 
164
                RGBQUAD c;
 
165
                for (int y=0; y < tgaHead.ImageHeight; y++){
 
166
                        for(int x=0, x4=0;x<tgaHead.ImageWidth;x++, x4+=4){
 
167
                                c=GetPixelColor(x,y);
 
168
                                pDest[x4+0]=c.rgbBlue;
 
169
                                pDest[x4+1]=c.rgbGreen;
 
170
                                pDest[x4+2]=c.rgbRed;
 
171
#if CXIMAGE_SUPPORT_ALPHA       // <vho>
 
172
                                pDest[x4+3]=(BYTE)((AlphaGet(x,y)*info.nAlphaMax)/255);
 
173
#else
 
174
                                pDest[x4+3]=0;
 
175
#endif //CXIMAGE_SUPPORT_ALPHA
 
176
                        }
 
177
                        hFile->Write(pDest,4*tgaHead.ImageWidth,1);
 
178
                }
 
179
                free(pDest);
 
180
        }
 
181
        return true;
 
182
}
 
183
////////////////////////////////////////////////////////////////////////////////
 
184
#endif // CXIMAGE_SUPPORT_ENCODE
 
185
////////////////////////////////////////////////////////////////////////////////
 
186
BYTE CxImageTGA::ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover)
 
187
{
 
188
        try{
 
189
        BYTE rle;
 
190
        long filePos;
 
191
        for (int x=0; x<width; ){
 
192
                if (rleLeftover != 255){
 
193
            rle = rleLeftover;
 
194
            rleLeftover = 255;
 
195
        } else {
 
196
                        hFile->Read(&rle,1,1);
 
197
                }
 
198
                if (rle & 128) { // RLE-Encoded packet
 
199
                        rle -= 127; // Calculate real repeat count.
 
200
                        if ((x+rle)>width){
 
201
                                rleLeftover = 128 + (rle - (width - x) - 1);
 
202
                filePos = hFile->Tell();
 
203
                                rle=width-x;
 
204
                        }
 
205
                        switch (ptgaHead->PixelDepth)
 
206
                        {
 
207
                        case 32: {
 
208
                                RGBQUAD color;
 
209
                                hFile->Read(&color,4,1);
 
210
                                for (int ix = 0; ix < rle; ix++){
 
211
                                        memcpy(&pDest[3*ix],&color,3);
 
212
#if CXIMAGE_SUPPORT_ALPHA       // <vho>
 
213
                                        AlphaSet(ix+x,y,color.rgbReserved);
 
214
#endif //CXIMAGE_SUPPORT_ALPHA
 
215
                                }
 
216
                                break;
 
217
                                         } 
 
218
                        case 24: {
 
219
                                rgb_color triple;
 
220
                                hFile->Read(&triple,3,1);
 
221
                                for (int ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3);
 
222
                                break;
 
223
                                         }
 
224
                        case 15:
 
225
                        case 16: {
 
226
                                WORD pixel;
 
227
                                hFile->Read(&pixel,2,1);
 
228
                                rgb_color triple;
 
229
                                triple.r = (BYTE)(( pixel & 0x1F ) * 8);     // red
 
230
                                triple.g = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green
 
231
                                triple.b = (BYTE)(( pixel >> 7 ) & 0x0F8);   // blue
 
232
                                for (int ix = 0; ix < rle; ix++){
 
233
                                        memcpy(&pDest[3*ix],&triple,3);
 
234
                                }
 
235
                                break;
 
236
                                         }
 
237
                        case 8: {
 
238
                                BYTE pixel;
 
239
                                hFile->Read(&pixel,1,1);
 
240
                                for (int ix = 0; ix < rle; ix++) pDest[ix] = pixel;
 
241
                                        }
 
242
                        }
 
243
                        if (rleLeftover!=255) hFile->Seek(filePos, SEEK_SET);
 
244
                } else { // Raw packet
 
245
                        rle += 1; // Calculate real repeat count.
 
246
                        if ((x+rle)>width){
 
247
                rleLeftover = rle - (width - x) - 1;
 
248
                                rle=width-x;
 
249
                        }
 
250
                        ExpandUncompressedLine(pDest,ptgaHead,hFile,rle,y,x);
 
251
                }
 
252
                if (head.biBitCount == 24)      pDest += rle*3; else pDest += rle;
 
253
                x += rle;
 
254
        }
 
255
        } catch(...){   }
 
256
        return rleLeftover;
 
257
}
 
258
////////////////////////////////////////////////////////////////////////////////
 
259
void CxImageTGA::ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset)
 
260
{
 
261
        try{
 
262
        switch (ptgaHead->PixelDepth){
 
263
        case 8:
 
264
                hFile->Read(pDest,width,1);
 
265
                break;
 
266
        case 15:
 
267
        case 16:{
 
268
                BYTE* dst=pDest;
 
269
                WORD pixel;
 
270
                for (int x=0; x<width; x++){
 
271
                        hFile->Read(&pixel,2,1);
 
272
                        *dst++ = (BYTE)(( pixel & 0x1F ) * 8);     // blue
 
273
                        *dst++ = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green
 
274
                        *dst++ = (BYTE)(( pixel >> 7 ) & 0x0F8);   // red
 
275
                }
 
276
                break;
 
277
                        }
 
278
        case 24:
 
279
                hFile->Read(pDest,3*width,1);
 
280
                break;
 
281
        case 32:{
 
282
                BYTE* dst=pDest;
 
283
                for (int x=0; x<width; x++){
 
284
                        RGBQUAD pixel;
 
285
                        hFile->Read(&pixel,4,1);
 
286
                        *dst++ = pixel.rgbBlue;
 
287
                        *dst++ = pixel.rgbGreen;
 
288
                        *dst++ = pixel.rgbRed;
 
289
#if CXIMAGE_SUPPORT_ALPHA       // <vho>
 
290
                        AlphaSet(x+xoffset,y,pixel.rgbReserved); //alpha
 
291
#endif //CXIMAGE_SUPPORT_ALPHA
 
292
                }
 
293
                break;
 
294
                        }
 
295
        }
 
296
        } catch(...){   }
 
297
}
 
298
////////////////////////////////////////////////////////////////////////////////
 
299
#endif  // CXIMAGE_SUPPORT_TGA
 
300