47 #if defined(_MSC_VER) && _MSC_VER < 1600
77 typedef size_t (*
drpcx_read_proc)(
void* userData,
void* bufferOut,
size_t bytesToRead);
87 #ifndef DR_PCX_NO_STDIO
108 #ifdef DR_PCX_IMPLEMENTATION
113 #ifndef DR_PCX_NO_STDIO
116 static size_t drpcx__on_read_stdio(
void* pUserData,
void* bufferOut,
size_t bytesToRead)
118 return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
125 if (fopen_s(&pFile, filename,
"rb") != 0) {
129 pFile = fopen(filename,
"rb");
135 drpcx_uint8* pImageData =
drpcx_load(drpcx__on_read_stdio, pFile, flipped, x, y, internalComponents, desiredComponents);
140 #endif // DR_PCX_NO_STDIO
146 const unsigned char* data;
148 size_t currentReadPos;
151 static size_t drpcx__on_read_memory(
void* pUserData,
void* bufferOut,
size_t bytesToRead)
153 drpcx_memory* memory = (drpcx_memory*)pUserData;
154 assert(memory !=
NULL);
155 assert(memory->dataSize >= memory->currentReadPos);
157 size_t bytesRemaining = memory->dataSize - memory->currentReadPos;
158 if (bytesToRead > bytesRemaining) {
159 bytesToRead = bytesRemaining;
162 if (bytesToRead > 0) {
163 memcpy(bufferOut, memory->data + memory->currentReadPos, bytesToRead);
164 memory->currentReadPos += bytesToRead;
173 memory.data = (
const unsigned char*)data;
174 memory.dataSize = dataSize;
175 memory.currentReadPos = 0;
176 return drpcx_load(drpcx__on_read_memory, &memory, flipped, x, y, internalComponents, desiredComponents);
219 pPCX->onRead(pPCX->pUserData, &
byte, 1);
230 pRow += (pPCX->height - row - 1) * stride;
232 pRow += row * stride;
243 rleValue = drpcx__read_byte(pPCX);
244 if ((rleValue & 0xC0) == 0xC0) {
245 rleCount = rleValue & 0x3F;
246 rleValue = drpcx__read_byte(pPCX);
252 *pRLEValueOut = rleValue;
262 switch (pPCX->header.bitPlanes)
268 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
270 rleCount = drpcx__rle(pPCX, &rleValue);
274 for (
int bit = 0; (bit < 8) && ((x*8 + bit) < pPCX->width); ++bit) {
276 drpcx_uint8 paletteIndex = (rleValue & mask) >> (7 - bit);
278 pRow[0] = paletteIndex * 255;
279 pRow[1] = paletteIndex * 255;
280 pRow[2] = paletteIndex * 255;
295 for (
drpcx_uint32 c = 0; c < pPCX->header.bitPlanes; ++c) {
297 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
299 rleCount = drpcx__rle(pPCX, &rleValue);
303 for (
int bit = 0; (bit < 8) && ((x*8 + bit) < pPCX->width); ++bit) {
305 drpcx_uint8 paletteIndex = (rleValue & mask) >> (7 - bit);
307 pRow[0] |= ((paletteIndex & 0x01) << c);
308 pRow += pPCX->components;
318 pRow[c] = pPCX->header.palette16[paletteIndex*3 + c];
321 pRow += pPCX->components;
337 switch (pPCX->header.bitPlanes)
342 paletteCGA[ 0] = 0x00; paletteCGA[ 1] = 0x00; paletteCGA[ 2] = 0x00;
343 paletteCGA[ 3] = 0x00; paletteCGA[ 4] = 0x00; paletteCGA[ 5] = 0xAA;
344 paletteCGA[ 6] = 0x00; paletteCGA[ 7] = 0xAA; paletteCGA[ 8] = 0x00;
345 paletteCGA[ 9] = 0x00; paletteCGA[10] = 0xAA; paletteCGA[11] = 0xAA;
346 paletteCGA[12] = 0xAA; paletteCGA[13] = 0x00; paletteCGA[14] = 0x00;
347 paletteCGA[15] = 0xAA; paletteCGA[16] = 0x00; paletteCGA[17] = 0xAA;
348 paletteCGA[18] = 0xAA; paletteCGA[19] = 0x55; paletteCGA[20] = 0x00;
349 paletteCGA[21] = 0xAA; paletteCGA[22] = 0xAA; paletteCGA[23] = 0xAA;
350 paletteCGA[24] = 0x55; paletteCGA[25] = 0x55; paletteCGA[26] = 0x55;
351 paletteCGA[27] = 0x55; paletteCGA[28] = 0x55; paletteCGA[29] = 0xFF;
352 paletteCGA[30] = 0x55; paletteCGA[31] = 0xFF; paletteCGA[32] = 0x55;
353 paletteCGA[33] = 0x55; paletteCGA[34] = 0xFF; paletteCGA[35] = 0xFF;
354 paletteCGA[36] = 0xFF; paletteCGA[37] = 0x55; paletteCGA[38] = 0x55;
355 paletteCGA[39] = 0xFF; paletteCGA[40] = 0x55; paletteCGA[41] = 0xFF;
356 paletteCGA[42] = 0xFF; paletteCGA[43] = 0xFF; paletteCGA[44] = 0x55;
357 paletteCGA[45] = 0xFF; paletteCGA[46] = 0xFF; paletteCGA[47] = 0xFF;
359 drpcx_uint8 cgaBGColor = pPCX->header.palette16[0] >> 4;
360 drpcx_uint8 i = (pPCX->header.palette16[3] & 0x20) >> 5;
361 drpcx_uint8 p = (pPCX->header.palette16[3] & 0x40) >> 6;
366 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
368 rleCount = drpcx__rle(pPCX, &rleValue);
372 for (
int bit = 0; bit < 4; ++bit) {
373 if (x*4 + bit < pPCX->width) {
375 drpcx_uint8 paletteIndex = (rleValue & mask) >> ((3 - bit) * 2);
378 if (paletteIndex == 0) {
379 cgaIndex = cgaBGColor;
381 cgaIndex = (((paletteIndex << 1) + p) + (i << 3));
384 pRow[0] = paletteCGA[cgaIndex*3 + 0];
385 pRow[1] = paletteCGA[cgaIndex*3 + 1];
386 pRow[2] = paletteCGA[cgaIndex*3 + 2];
396 if (pPCX->header.version == 5) {
397 drpcx_uint8 paletteMarker = drpcx__read_byte(pPCX);
398 if (paletteMarker == 0x0C) {
412 for (
drpcx_uint32 c = 0; c < pPCX->header.bitPlanes; ++c) {
414 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
416 rleCount = drpcx__rle(pPCX, &rleValue);
420 for (
int bitpair = 0; (bitpair < 4) && ((x*4 + bitpair) < pPCX->width); ++bitpair) {
422 drpcx_uint8 paletteIndex = (rleValue & mask) >> (3 - bitpair);
424 pRow[0] |= ((paletteIndex & 0x03) << (c*2));
425 pRow += pPCX->components;
434 for (
drpcx_uint32 c = 0; c < pPCX->header.bitPlanes; ++c) {
435 pRow[c] = pPCX->header.palette16[paletteIndex*3 + c];
438 pRow += pPCX->components;
454 if (pPCX->header.bitPlanes > 1) {
462 for (
drpcx_uint32 c = 0; c < pPCX->header.bitPlanes; ++c) {
464 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
466 rleCount = drpcx__rle(pPCX, &rleValue);
470 for (
int nibble = 0; (nibble < 2) && ((x*2 + nibble) < pPCX->width); ++nibble)
473 drpcx_uint8 paletteIndex = (rleValue & mask) >> (1 - nibble);
475 pRow[0] |= ((paletteIndex & 0x0F) << (c*4));
476 pRow += pPCX->components;
486 pRow[c] = pPCX->header.palette16[paletteIndex*3 + c];
489 pRow += pPCX->components;
502 switch (pPCX->header.bitPlanes)
508 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
510 rleCount = drpcx__rle(pPCX, &rleValue);
514 if (x < pPCX->width) {
525 drpcx_uint8 paletteMarker = drpcx__read_byte(pPCX);
526 if (paletteMarker == 0x0C) {
529 if (pPCX->onRead(pPCX->pUserData, palette256,
sizeof(palette256)) !=
sizeof(palette256)) {
534 drpcx_uint8* pRow = pPCX->pImageData + (y * stride);
537 pRow[0] = palette256[index*3 + 0];
538 pRow[1] = palette256[index*3 + 1];
539 pRow[2] = palette256[index*3 + 2];
554 for (
drpcx_uint32 x = 0; x < pPCX->header.bytesPerLine; ++x) {
556 rleCount = drpcx__rle(pPCX, &rleValue);
560 if (x < pPCX->width) {
562 pRow += pPCX->components;
578 if (desiredComponents > 4)
return NULL;
582 pcx.pUserData = pUserData;
583 pcx.flipped = flipped;
584 if (onRead(pUserData, &pcx.header,
sizeof(pcx.header)) !=
sizeof(pcx.header)) {
588 if (pcx.header.header != 10) {
592 if (pcx.header.encoding != 1) {
596 if (pcx.header.bpp != 1 && pcx.header.bpp != 2 && pcx.header.bpp != 4 && pcx.header.bpp != 8) {
601 if (pcx.header.left > pcx.header.right) {
603 pcx.header.left = pcx.header.right;
604 pcx.header.right = temp;
606 if (pcx.header.top > pcx.header.bottom) {
608 pcx.header.top = pcx.header.bottom;
609 pcx.header.bottom = temp;
612 pcx.width = pcx.header.right - pcx.header.left + 1;
613 pcx.height = pcx.header.bottom - pcx.header.top + 1;
614 pcx.components = (pcx.header.bpp == 8 && pcx.header.bitPlanes == 4) ? 4 : 3;
616 size_t dataSize = pcx.width * pcx.height * pcx.components;
617 pcx.pImageData = (
drpcx_uint8*)calloc(1, dataSize);
618 if (pcx.pImageData ==
NULL) {
623 switch (pcx.header.bpp)
627 result = drpcx__decode_1bit(&pcx);
632 result = drpcx__decode_2bit(&pcx);
637 result = drpcx__decode_4bit(&pcx);
642 result = drpcx__decode_8bit(&pcx);
647 free(pcx.pImageData);
653 if (desiredComponents == 0) desiredComponents = pcx.components;
654 if (desiredComponents != (
int)pcx.components) {
656 if (pNewImageData ==
NULL) {
657 free(pcx.pImageData);
663 if (desiredComponents < (
int)pcx.components) {
665 for (
drpcx_uint32 i = 0; i < pcx.width*pcx.height; ++i) {
666 for (
int c = 0; c < desiredComponents; ++c) {
667 pDstData[c] = pSrcData[c];
670 pSrcData += pcx.components;
671 pDstData += desiredComponents;
675 if (pcx.components == 1) {
676 for (
drpcx_uint32 i = 0; i < pcx.width*pcx.height; ++i) {
677 for (
int c = 0; c < desiredComponents; ++c) {
678 pDstData[c] = pSrcData[0];
681 pSrcData += pcx.components;
682 pDstData += desiredComponents;
684 }
else if (pcx.components == 2) {
685 for (
drpcx_uint32 i = 0; i < pcx.width*pcx.height; ++i) {
686 pDstData[0] = pSrcData[0];
687 pDstData[1] = pSrcData[1];
689 if (desiredComponents == 4) pDstData[3] = 0xFF;
691 pSrcData += pcx.components;
692 pDstData += desiredComponents;
695 assert(pcx.components == 3);
696 assert(desiredComponents == 4);
697 for (
drpcx_uint32 i = 0; i < pcx.width*pcx.height; ++i) {
698 pDstData[0] = pSrcData[0];
699 pDstData[1] = pSrcData[1];
700 pDstData[2] = pSrcData[2];
703 pSrcData += pcx.components;
704 pDstData += desiredComponents;
709 free(pcx.pImageData);
710 pcx.pImageData = pNewImageData;
713 if (x) *x = pcx.width;
714 if (y) *y = pcx.height;
715 if (internalComponents) *internalComponents = pcx.components;
716 return pcx.pImageData;
721 free(pReturnValueFromLoad);
724 #endif // DR_PCX_IMPLEMENTATION