1 /***********************************************************************
3 * Description: GfxDecode -- functions for reading Diablo's GFX files
4 * Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
5 * Created at: Son Jan 27 15:20:43 CET 2002
6 * Computer: hangloose.flachland-chemnitz.de
7 * System: Linux 2.4.16 on i686
9 * Copyright (c) 2002 BMX-Chemnitz.DE All rights reserved.
11 * ---------------------------------------------------------------------
12 * included are functions for getting:
13 * - the framecount of .CEL-files -> celGetFrameCount()
14 * - single frames of .CEL-files -> celGetFrameData()
15 * - the framecount of .CL2-files -> cl2GetFrameCount()
16 * - single directions of .CL2-files (all frames) -> cl2GetDirData()
17 * - single .PCX-files (256 color; v2, v5) -> pcxGetData()
18 ***********************************************************************/
31 /****** RAMP stuff *****************************************************
32 * for a more detailed description/explanation see below
33 ***********************************************************************/
34 // two variations: one/two ramp(s)
35 static const uint16_t c_2RampSize
= 544; // the frame size
36 static const uint16_t c_1RampSize
= 800; // the frame size
38 // ramps (both variations) can be either left or right
39 static const uint16_t c_RampOffsetLeft
[17] = {
41 8, // + 8 note that this __--
42 24, // + 16 "drawing" is __--
43 48, // + 24 upside down! __-- this area
44 80, // + 32 __-- is always
45 120, // + 40 __-- colored
47 224, // + 56 __-- lower ramp ends here (+30 == 254)
48 288, // + 64 --__ upper ramp might be missing
50 400, // + 52 | --__ this area
51 444, // + 44 | --__ is always
52 480, // + 36 | --__ colored
53 508, // + 28 | either trans- --__
54 528, // + 20 | parent or colored --__
55 540, // + 12 | --__ +2 Pixels = 544
56 542 // + 2 | this last one doesn't exist, it's those^ 2 pixels
59 static const uint16_t c_RampOffsetRight
[17] = {
60 2, // __ before this, there are 2 Pixels
61 14, // + 12 --__ 4^2 - 2
62 34, // + 20 --__ 6^2 - 2
63 62, // + 28 this area --__ 8^2 - 2
64 98, // + 36 is always --__ 10^2 - 2 pattern anyone? ;)
65 142, // + 44 colored --__
67 254, // + 60 lower ramp ends here --__ (-30 == 224)
68 318, // + 64 upper ramp might be missing __--
70 422, // + 48 this area __-- | note that this
71 462, // + 40 is always __-- | "drawing"
72 494, // + 32 colored __-- eiter trans- | is upside down!
73 518, // + 24 __-- parent or colored |
75 542, // + 8 __-- +2 Startpixels = 544 |
76 542 // + 0 this last one doesn't exist, it | would be EOF
79 /****** FrameBuffer class **********************************************
80 * holds buffers and size information of the actual target image
81 * purpose: buffer management and avoidance of ugly globals
82 **********************************************************************/
86 vector
<uint8_t *> vecData
;
100 uint8_t *pPal
=NULL
, uint16_t frame
=0, uint16_t xsize
=0,
101 uint16_t *pysize
=NULL
, uint16_t *pmaxx
=NULL
, uint16_t maxblock
=0)
103 pCurrRow
= new uint8_t[4*xsize
];
109 uMaxBlock
= maxblock
;
118 for (vector
<uint8_t *>::iterator vi
=vecData
.begin(); vi
!=vecData
.end(); vi
++)
126 vecData
.push_back(pCurrRow
);
127 pCurrRow
= new uint8_t[4*uXSize
];
129 void addPixel(uint16_t uColorNum
)
131 if (uColorNum
> TRANS_COL
) {
132 cerr
<< "\n*** there seemed to be an error, illegal color index " << uColorNum
;
133 cerr
<< "\n +++ at (" << uCols
<< "," << uRows
<< "), see for yourself *** \n\n";
134 uColorNum
= TRANS_COL
; // sane setting to avoid segfaults
137 memcpy(pCurrRow
+ 4*uCols
, pPalette
+ 4*uColorNum
, 4*sizeof(uint8_t));
138 if (++uCols
== uXSize
)
140 else if ((uColorNum
!= TRANS_COL
) && (upMaxX
!= NULL
) && (uCols
> *upMaxX
))
143 // used to return the actual image data
147 vector
<uint8_t *>::reverse_iterator vri
;
148 // allocate a buffer to hold the actual image size
149 uint8_t *tmp
= new uint8_t[4*uXSize
*uRows
];
151 // the lines are upside down inside the vector, use reverse iterator
152 for (i
=0, vri
=vecData
.rbegin(); vri
!=vecData
.rend(); vri
++, i
++)
153 memcpy(tmp
+4*uXSize
*i
, *vri
, 4*uXSize
*sizeof(uint8_t));
155 *upYSize
= uRows
; // set height
158 cerr
<< "\n*** there seemed to be an error (last line does not match boundary, " << uCols
<< " pixels left)";
159 cerr
<< "\n +++ this is often caused by specifying an invalid width, see for yourself *** \n\n";
166 uint16_t WINAPI
celGetFrameCount(uint8_t *pFileBuf
)
169 memcpy(&tmp
, pFileBuf
, sizeof(uint32_t));
170 return (uint16_t)tmp
;
173 /***** Block Decoder ***************************************************
174 * one of three possible decoding techniques necessary for .cel
175 * possible block contents are either colored (in that case the
176 * appropriate number of pixels are read) or transparent pixels
177 * there are neither ramps nor plain pixels allowed here
178 ***********************************************************************/
179 uint8_t *celDecodeBlocks(uint8_t *pFileBuf
, FrameBuf
*pFrame
, uint32_t *framestart
)
181 uint32_t uFilePos
=framestart
[pFrame
->uFrameNum
];
182 uint8_t cRead
=0, i
=0;
184 if (!pFrame
->bHasBlocks
) // sanity check
187 while (uFilePos
< framestart
[pFrame
->uFrameNum
+1]) {
188 cRead
= pFileBuf
[uFilePos
++];
190 if ((uFilePos
== framestart
[pFrame
->uFrameNum
]+1))
191 // TODO: what is this 0x0A 0x00 stuff all about?
192 if ((cRead
== 0x0A) && (pFileBuf
[uFilePos
] == 0x00)) {
194 cRead
= pFileBuf
[uFilePos
++];
198 // transparent block (complement, 256-val)
199 for (i
=0; i
<256-cRead
; i
++)
200 pFrame
->addPixel(TRANS_COL
);
201 else if (cRead
< pFrame
->uMaxBlock
+ 1)
202 // pixel block (block size pixels to be read!)
203 for (i
=0; i
<cRead
; i
++)
204 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
206 cerr
<< "\n*** block mode: illegal block (> max_size) ***\n\n";
208 return pFrame
->getData();
211 /***** Ramp Decoder ****************************************************
212 * the second of three possible decoding techniques necessary for .cel
213 * each block save the first/last is enclosed by two 0x00 pairs
214 * those blocks affect _TWO_ rows with one being 2 colored pixels shorter
215 * the first/last "block" affects only one row
216 ***********************************************************************/
217 uint8_t *celDecodeRamps(uint8_t *pFileBuf
, FrameBuf
*pFrame
, uint32_t *framestart
, bool bLeft
)
219 uint32_t uFrameLen
= framestart
[pFrame
->uFrameNum
+1]-framestart
[pFrame
->uFrameNum
];
221 uint16_t uBlockLen
=0, i
=0, j
=0;
222 bool bFirstLonger
=false;
224 if (!pFrame
->bHasRamps
) // sanity check
227 if (pFrame
->uXSize
!= 32) // only used in that case
230 if (!bLeft
) { // get first two pixels for right side ramps
231 pFrame
->addPixel(pFileBuf
[framestart
[pFrame
->uFrameNum
]]);
232 pFrame
->addPixel(pFileBuf
[framestart
[pFrame
->uFrameNum
]+1]);
235 // do all the ramp blocks
236 for (i
=0; i
<(uFrameLen
== c_2RampSize
? 15 : 7); i
++) {
237 uBlockLen
= (bLeft
? (c_RampOffsetLeft
[i
+1] - c_RampOffsetLeft
[i
]) : (c_RampOffsetRight
[i
+1] - c_RampOffsetRight
[i
]));
238 uFilePos
= framestart
[pFrame
->uFrameNum
] + (bLeft
? c_RampOffsetLeft
[i
] : c_RampOffsetRight
[i
]) + 2;
239 bFirstLonger
= (i
>(bLeft
? 7 : 6));
241 // OK, first line, starting with transparency
242 for (j
=0; j
<pFrame
->uXSize
- uBlockLen
/2 + (bFirstLonger
? 0 : 2); j
++)
243 pFrame
->addPixel(TRANS_COL
);
244 // fill it up with the pixel block
245 for (j
=0; j
<uBlockLen
/2 - (bFirstLonger
? 0 : 2); j
++)
246 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
247 // second line, starting again with transparency
248 for (j
=0; j
<pFrame
->uXSize
- uBlockLen
/2 + (bFirstLonger
? 2 : 0); j
++)
249 pFrame
->addPixel(TRANS_COL
);
250 // fill the second line with the remaining pixels
251 for (j
=0; j
<uBlockLen
/2 - (bFirstLonger
? 2 : 0); j
++)
252 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
254 if (pFrame
->uCols
!= 0) // fill current line with trans (if not empty)
255 for (j
=pFrame
->uXSize
- pFrame
->uCols
; j
>0; j
--)
256 pFrame
->addPixel(TRANS_COL
);
257 // OK, insert the first pixels into a new line
258 for (j
=0; j
<uBlockLen
/2 - (bFirstLonger
? 0 : 2); j
++)
259 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
260 // fill the line with transparency
261 for (j
=0; j
<pFrame
->uXSize
- uBlockLen
/2 + (bFirstLonger
? 0 : 2); j
++)
262 pFrame
->addPixel(TRANS_COL
);
263 // start a second line with the remaining pixels
264 for (j
=0; j
<uBlockLen
/2 - (bFirstLonger
? 2 : 0); j
++)
265 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
269 // now read the last 0x00 pair and fill up
270 uBlockLen
= (uFrameLen
== c_2RampSize
? 30 : 2); // one or two ramps?
271 uFilePos
= framestart
[pFrame
->uFrameNum
] + (bLeft
? c_RampOffsetLeft
[i
] : c_RampOffsetRight
[i
]) + 2;
272 // the transparency for the last (single) 0x00 pair
273 for (j
=0; j
<uBlockLen
; j
++)
274 pFrame
->addPixel(TRANS_COL
);
275 if (bLeft
) { // left side only: the remaining line
276 for (j
=0; j
<pFrame
->uXSize
- uBlockLen
; j
++)
277 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
280 // now the rest of the file (plain)
281 while (uFilePos
< framestart
[pFrame
->uFrameNum
+1])
282 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
284 // the uppermost line is emtpy when 2 ramps are used
285 if (uFrameLen
== c_2RampSize
)
286 for (j
=0; j
<pFrame
->uXSize
; j
++)
287 pFrame
->addPixel(TRANS_COL
);
289 return pFrame
->getData();
292 /***** celGetFrameData *************************************************
293 * decode .cel data for given frame and xsize
295 * *vpFileBuf the buffer containing the filecontent
296 * *palette the palette (4 bytes for each of the 257 entries)
297 * 256 colors are needed + 1 for alpha
298 * uXSize this information must be given
299 * uFrameNume the frame to get
300 * *uYSize the actual value is returned therein
301 * *uMaxX this can be used (if != NULL) to get the column
302 * of the rightmost nontransparent pixel (useable
305 * Returns: an array containing 4 Bytes (RGBA) for each pixel
307 * ---------------------------------------------------------------
308 * Comments: dirty hack, started from scratch @ 2000-10-11
309 * cleanly rewritten during incorporation into ladiks StormLib
310 * status: structured hack ;)
312 * It took me approx. 6 days to understand the format basics (hex viewer)
313 * For this I had a little help from a dos tool ("ddecode", from
314 * www.cowlevel.com, binary only, no sources) which, however, gave
315 * me the general idea what the pictures are actually supposed to look like.
317 * The fine adjustments, however, took quite some time and a little luck.
318 * After I had written to various people (mickyk and ladik), which could
319 * not help me, but wished best luck (thanks, btw, it helped ;)), I tried
320 * some reverse engineering which was not succesful in the end.
322 * I then had incidentally a new idea of what could be going on @ 2002-01-23.
323 * It just came to my mind that I could retry some actual painting in
324 * reverse order (had done that before to no avail) and when looking closer
325 * at it I realized the "ramp" stuff. This really is the trickiest part and
326 * it took me some eight days to implement it without breaking the other
327 * parts of the code. Very odd format indeed.
329 * TODO: learn what 0x0A 0x00 means
330 **********************************************************************/
331 uint8_t * WINAPI
celGetFrameData(uint8_t *pFileBuf
, uint8_t *palette
, uint16_t uXSize
, uint16_t uFrameNum
, uint16_t *uYSize
, uint16_t *uMaxX
)
334 uint32_t *framestart
=NULL
, frames
=0, uFilePos
=0;
335 uint16_t i
, tmpWord
=0;
336 uint8_t cRead
=0, *data
;
338 memcpy(&frames
, pFileBuf
, sizeof(uint32_t));
339 uFilePos
+= sizeof(uint32_t);
341 if (pFileBuf
== NULL
) {
342 SetLastError(ERROR_INVALID_PARAMETER
);
346 if (palette
== NULL
) {
347 SetLastError(ERROR_INVALID_PARAMETER
);
351 if (uFrameNum
> frames
-1) {
352 SetLastError(ERROR_INVALID_PARAMETER
);
356 if (uYSize
== NULL
) {
357 SetLastError(ERROR_INVALID_PARAMETER
);
361 // in case we want to know the rightmost pixels column (usable eg. for fonts)
365 // get the frame offsets
366 framestart
= new uint32_t[frames
+1];
367 for (i
=0; i
<frames
+1; i
++) {
368 memcpy(&framestart
[i
], pFileBuf
+uFilePos
, sizeof(uint32_t));
369 uFilePos
+= sizeof(uint32_t);
372 /****** block size *************************************************
373 * depends on the image width
374 ******************************/
376 double erg
= rint(sqrt(pow(2, rint(log((double)(framestart
[uFrameNum
+1] - framestart
[uFrameNum
])) / log(2.0)))));
377 pFrame
= new FrameBuf(palette
, uFrameNum
, uXSize
, uYSize
, uMaxX
, max((uint16_t)min((int)erg
, 0x7F), uXSize
));
379 /****** ramp detection -- AFAIK only needed for 32x32 tiles ********
380 * here I use hard coded constants because this is the only simple
381 * way to get the detection done; plus this stuff is only to be
382 * found in such 32x32 (tile) files and so wont hurt anyone ;)
383 ******************************************************************/
385 uint32_t uFrameLen
= framestart
[uFrameNum
+1] - framestart
[uFrameNum
];
386 if ((uXSize
== 32) && ((uFrameLen
== c_2RampSize
) || (uFrameLen
== c_1RampSize
))) {
388 // use the static arrays for the check
389 for (i
=0; i
<(uFrameLen
== c_2RampSize
? 16 : 8); i
++) {
390 memcpy(&tmpWord
, pFileBuf
+framestart
[uFrameNum
]+c_RampOffsetLeft
[i
], sizeof(uint16_t));
394 bool bRampsLeft
= pFrame
->bHasRamps
= (i
==(uFrameLen
== c_2RampSize
? 16 : 8));
395 if (!pFrame
->bHasRamps
) { // only one can apply
396 for (i
=0; i
<(uFrameLen
== c_2RampSize
? 16 : 8); i
++) {
397 memcpy(&tmpWord
, pFileBuf
+framestart
[uFrameNum
]+c_RampOffsetRight
[i
], sizeof(uint16_t));
401 pFrame
->bHasRamps
= (i
==(uFrameLen
== c_2RampSize
? 16 : 8)); // bRampsLeft stays false in this case
404 if (pFrame
->bHasRamps
) { // decode ramps and be off (if appropriate)
405 data
= celDecodeRamps(pFileBuf
, pFrame
, framestart
, bRampsLeft
);
412 /*********** block detection ***************************************
413 * 0x0A as start byte seems to be sufficient (though I still dunno
414 * what the trailing 10 bytes mean); in any other case we act as if
415 * blocks were to be used and check afterwards if the image looks
416 * OK (that is, the last line has no pixels in it)
417 ******************************************************************/
419 cRead
= pFileBuf
[framestart
[uFrameNum
]];
420 if (cRead
== 0x0A) // sufficient
421 pFrame
->bHasBlocks
= true;
422 // if width == 32 && framelen == 32*32, assume plain
423 else if ((uXSize
!= 32) || (uFrameLen
!= 32*32)) { // check needed
424 uFilePos
=framestart
[uFrameNum
];
426 // rush through the frame
427 while (uFilePos
< framestart
[uFrameNum
+1]) {
428 cRead
= pFileBuf
[uFilePos
++];
430 // transparency blocks
431 while (cRead
> 0x7F) {
434 if (uFilePos
< framestart
[uFrameNum
+1])
435 cRead
= pFileBuf
[uFilePos
++];
440 // colored pixel block
441 if (uFilePos
< framestart
[uFrameNum
+1]) {
442 if (cRead
< pFrame
->uMaxBlock
+ 1) {
447 // when the value is out of valid blockrange
448 i
=1; // trigger error (1%uXSize != 0)
453 if (i
%uXSize
== 0) // looks as if we got it right
454 pFrame
->bHasBlocks
=true;
457 if (pFrame
->bHasBlocks
) { // use block decoder if appropriate
458 data
= celDecodeBlocks(pFileBuf
, pFrame
, framestart
);
464 // plain mode (#3), read each color index and write the pixel
465 uFilePos
=framestart
[uFrameNum
];
466 while (uFilePos
< framestart
[uFrameNum
+1])
467 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
469 // cleanup, return image data and height
470 data
= pFrame
->getData();
476 uint16_t WINAPI
cl2GetFrameCount(uint8_t *pFileBuf
)
479 memcpy(&tmp
, pFileBuf
, sizeof(uint32_t));
480 memcpy(&tmp
, pFileBuf
+tmp
, sizeof(uint32_t));
481 return (uint16_t)tmp
;
484 /***** cl2GetDirData ***************************************************
485 * decodes all frames of a .cl2 for given direction and xsize
487 * *pFileBuf the buffer containing the filecontent
488 * *palette the palette (4 bytes for each of the 257 entries)
489 * 256 colors are needed + 1 for alpha
490 * uXSize this information must be given
491 * uDirNum the direction to get the frames from
492 * *uYSize the actual height is returned herein
494 * Returns: <frames> arrays containing 4 Bytes (RGBA) for each pixel
495 * where <frames> is read at runtime and handed back via *uFrames
497 * ---------------------------------------------------------------
498 * Comments: dirty hack, started from scratch @ 2000-10-12
500 * The format basics are similar to .cel, with the main difference
501 * that the values read have reverse interpretation. In .cel a value
502 * greater than 0x7F means transparency, while in .cl2 this means
503 * color and vice-versa. .cl2 has the additional understanding
504 * of blocks of the same color (0x80 .. 0xBF) where the one color is
505 * written multiple times.
507 * .cl2 only uses the block scheme, so there is no detection
508 * necessary in order to get it right. The only thing still unknown
509 * is that 0x0A 0x00 stuff...
511 * TODO: learn what 0x0A 0x00 means
512 ***********************************************************************/
513 BYTE
** WINAPI
cl2GetDirData(BYTE
*pFileBuf
, BYTE
*palette
, WORD uXSize
, WORD uDirNum
, WORD
*uYSize
)
516 uint32_t frames
=0, *framestart
=NULL
, uFilePos
=0;
518 uint8_t cRead
=0, **data
=NULL
;
520 if (pFileBuf
== NULL
) {
521 SetLastError(ERROR_INVALID_PARAMETER
);
525 if (palette
== NULL
) {
526 SetLastError(ERROR_INVALID_PARAMETER
);
531 SetLastError(ERROR_INVALID_PARAMETER
);
535 if (uYSize
== NULL
) {
536 SetLastError(ERROR_INVALID_PARAMETER
);
540 // get direction offsets
541 uint32_t dirstart
[8];
542 for (i
=0; i
<8; i
++) {
543 memcpy(&dirstart
[i
], pFileBuf
+uFilePos
, sizeof(uint32_t));
544 uFilePos
+= sizeof(uint32_t);
547 uFilePos
= dirstart
[uDirNum
];
549 memcpy(&frames
, pFileBuf
+uFilePos
, sizeof(uint32_t));
550 uFilePos
+= sizeof(uint32_t);
552 data
= new uint8_t*[frames
];
555 framestart
= new uint32_t[frames
+1];
556 for (i
=0; i
<frames
+1; i
++) {
557 memcpy(&framestart
[i
], pFileBuf
+uFilePos
, sizeof(uint32_t));
558 uFilePos
+= sizeof(uint32_t);
562 for (fc
=0; fc
<frames
; fc
++) {
563 pFrame
= new FrameBuf(palette
, 0, uXSize
, uYSize
, NULL
, 0);
565 uFilePos
= dirstart
[uDirNum
] + framestart
[fc
];
566 while (uFilePos
< dirstart
[uDirNum
] + framestart
[fc
+1]) {
568 cRead
= pFileBuf
[uFilePos
++];
569 if (cRead
< 0x80) { // transparency
570 // TODO: what is this 0x0A 0x00 stuff all about?
571 if ((cRead
== 0x0A) && (pFileBuf
[uFilePos
] == 0) && (uFilePos
== dirstart
[uDirNum
] + framestart
[fc
] + 1))
572 uFilePos
+= 9; // ignore the 9 bytes after 0x0A 0x00 at the framestart
574 for (i
=0; i
<cRead
; i
++)
575 pFrame
->addPixel(TRANS_COL
);
576 } else if (cRead
< 0xC0) {
577 // read the next byte and write it <0xBF - cRead> times
578 for (i
=0; i
<0xBF - cRead
; i
++)
579 pFrame
->addPixel(pFileBuf
[uFilePos
]);
581 } else // cRead > 0xBF
582 // read a block of the given size and write it
583 for (i
=0; i
< 256-cRead
; i
++)
584 pFrame
->addPixel(pFileBuf
[uFilePos
++]);
587 // got the frame data, save it
588 data
[fc
] = pFrame
->getData();
596 /****** pcxGetData *****************************************************
597 * decodes pcx files (256 color, as in diablo mpq)
599 * *pFileBuf the buffer containing the filecontent
600 * uFileSize the size of the file buffer
601 * uTransColor the palette entry to be transparent
602 * *uXSize the actual width is returned herein
603 * *uYSize the actual height is returned herein
605 * Returns: an array containing 4 Bytes (RGBA) for each pixel
607 * ---------------------------------------------------------------
608 * Comments: format info and pseudocode taken from:
609 * Klaus Holtorf, "Das Handbuch der Grafikformate"
611 ***********************************************************************/
612 BYTE
* WINAPI
pcxGetData(BYTE
*pFileBuf
, DWORD uFileSize
, BYTE uTransColor
, WORD
*uXSize
, WORD
*uYSize
)
615 uint32_t uDataRead
=0; // potentially big! (logo.pcx: 550 * 216 * 15 = 1,782,000)
617 uint8_t *data
, *palette
;
618 uint8_t uColorNum
=0, uCount
=0;
620 struct pcx_header_t
{
639 if (pFileBuf
== NULL
) {
640 SetLastError(ERROR_INVALID_PARAMETER
);
644 if (uXSize
== NULL
) {
645 SetLastError(ERROR_INVALID_PARAMETER
);
649 if (uYSize
== NULL
) {
650 SetLastError(ERROR_INVALID_PARAMETER
);
654 // get image information
655 memcpy(&pcxHeader
, pFileBuf
, sizeof(struct pcx_header_t
));
656 *uXSize
= (pcxHeader
.x1
- pcxHeader
.x0
+ 1);
657 *uYSize
= (pcxHeader
.y1
- pcxHeader
.y0
+ 1);
659 if ((pcxHeader
.version
!= 2) && (pcxHeader
.version
!= 5)) {
660 cerr
<< "cannot handle pcx v" << pcxHeader
.version
<< "\n";
665 palette
= new uint8_t[256*4];
666 if (pFileBuf
[uFileSize
- 768 - 1] != 0x0C) {
667 cerr
<< "palette error at " << uFileSize
- 768 - 1 << "\n";
670 for (i
=0; i
<256; i
++) {
671 memcpy(palette
+i
*4, pFileBuf
+uFileSize
-768+i
*3, 3*sizeof(uint8_t));
672 palette
[i
*4+3] = 0xFF;
674 memset(palette
+uTransColor
*4, 0, 4*sizeof(uint8_t)); // transparent black
676 // start right after the header
677 uFilePos
= sizeof(struct pcx_header_t
);
678 data
= new uint8_t[*uXSize
* *uYSize
* 4];
679 while (uDataRead
< (uint32_t)(*uXSize
* *uYSize
)) {
681 uColorNum
= pFileBuf
[uFilePos
++];
682 if ((pcxHeader
.compressed
) && (uColorNum
> 0xBF)) {
683 uCount
= (uColorNum
& 0x3F);
684 uColorNum
= pFileBuf
[uFilePos
++];
688 // draw count pixels with color val
689 for (i
=0; i
<uCount
; i
++)
690 memcpy(data
+(uDataRead
++)*4, palette
+uColorNum
*4, 4*sizeof(uint8_t));