Created
November 20, 2015 23:44
-
-
Save martincohen/62e23219a5940d812112 to your computer and use it in GitHub Desktop.
Tiny PCX reader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PCX_H | |
#define PCX_H | |
#include <assert.h> | |
#include "common.h" | |
typedef struct PCXHeader | |
{ | |
u8 id; | |
u8 version; | |
u8 encoding; | |
u8 bits_per_px; | |
s16 x_min; | |
s16 y_min; | |
s16 x_max; | |
s16 y_max; | |
s16 x_res; | |
s16 y_res; | |
u8 pal[48]; | |
u8 __reserved_1; | |
u8 planes; | |
s16 bytes_per_line; | |
s16 palette_type; | |
s16 x_screen_size; | |
s16 y_screen_size; | |
u8 __reserved_2[54]; /* Reserved (Always 0) */ | |
} PCXHeader; | |
typedef struct PCXColor | |
{ | |
u8 r; | |
u8 g; | |
u8 b; | |
} PCXColor; | |
typedef PCXColor PCXPalette[256]; | |
typedef struct PCX | |
{ | |
PCXHeader *header; | |
u8 *data_begin; | |
PCXPalette *palette; | |
u32 size; | |
u16 w; | |
u16 pitch; | |
u16 h; | |
u16 bpp; | |
} PCX; | |
PCX | |
pcx_open(u8 *buffer, u32 size) | |
{ | |
assert(size >= sizeof(PCXHeader)); | |
PCX pcx = {0}; | |
pcx.header = (PCXHeader*)buffer; | |
// PCX header control byte 0x0a. | |
assert(pcx.header->id == 0x0a); | |
// Encoding must be RLE. | |
assert(pcx.header->encoding == 1); | |
// Only 8-bit format is supported. | |
assert(pcx.header->bits_per_px == 8); | |
assert(pcx.header->x_max > pcx.header->x_min); | |
assert(pcx.header->y_max > pcx.header->y_min); | |
pcx.w = pcx.header->x_max - pcx.header->x_min + 1; | |
pcx.h = pcx.header->y_max - pcx.header->y_min + 1; | |
pcx.bpp = 8 / pcx.header->bits_per_px; | |
pcx.pitch = pcx.header->bytes_per_line * pcx.header->planes * pcx.bpp; | |
// No padding allowed. | |
assert((pcx.pitch - pcx.w) == 0); | |
pcx.size = pcx.w * pcx.h * pcx.bpp; | |
pcx.data_begin = (u8*)(pcx.header + 1); | |
u8 *palette = buffer + size - sizeof(PCXPalette) - 1; | |
// Control byte 0xC before the palette. | |
assert(*palette == 0xC); | |
pcx.palette = (PCXPalette*)(palette + 1); | |
return pcx; | |
} | |
void | |
pcx_decode(PCX *pcx, u8 *buffer) | |
{ | |
u8 *wit = buffer; | |
u8 *rit = pcx->data_begin; | |
u8 rc; | |
while ((wit - buffer) < (s32)pcx->size) | |
{ | |
if ((*rit & 0xC0) == 0xC0) | |
{ | |
rc = *rit & 0x3F; | |
rit++; | |
assert(rit != (u8*)pcx->palette); | |
do { | |
*wit++ = *rit; | |
} while (--rc); | |
rit++; | |
} | |
else | |
{ | |
*wit++ = *rit++; | |
} | |
} | |
assert((wit - buffer) == (s32)pcx->size); | |
} | |
#endif // PCX_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment