-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcx.c
118 lines (99 loc) · 3.04 KB
/
pcx.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* KallistiOS ##version##
pcx.c
(c)2000-2001 Dan Potter
PCX image loader
*/
#include <kos.h>
#include <assert.h>
#include "pcx.h"
typedef struct {
char mfg; /* manufacturer, always 0xa0 */
char ver; /* encoder version number (5) */
char enc; /* encoding code, always 1 */
char bpp; /* bits per pixel, 8 in mode 0x13 */
uint16 xmin,ymin; /* image origin, usually 0,0 */
uint16 xmax,ymax; /* image dimensions */
uint16 hres; /* horizontal resolution value */
uint16 vres; /* vertical resolution value */
char pal[48]; /* palette (not in mode 0x13) */
char reserved; /* who knows? */
char clrplanes; /* number of planes, 1 in mode 0x13 */
uint16 bpl; /* bytes per line, 80 in mode 0x13 */
uint16 pltype; /* Grey or Color palette flag */
char filler[58]; /* Zsoft wanted a 128 byte header */
} pcx_hdr;
/* Loads a PCX file into a kos_img_t struct */
int pcx_to_img(const char *fn, kos_img_t *rv) {
pcx_hdr pcxh;
uint32 fd;
int bytes = 0; /* counts unpacked bytes */
uint8 c; /* byte being processed */
int runlen, i; /* length of packet */
int num_bytes;
uint8 *pcxpal;
uint8 *image;
int r, g, b, v;
uint16 *pxls;
assert( rv != NULL );
/* Open the file */
fd = fs_open(fn, O_RDONLY);
if (fd < 0) {
printf("pcx_load(%s): Couldn't open file\r\n", fn);
return -1;
}
/* Load the PCX header */
fs_read(fd, &pcxh, sizeof(pcxh));
if (pcxh.bpp != 8) {
printf("pcx_load(%s): PCX data is not 8bpp\r\n", fn);
fs_close(fd);
return -2;
}
/* Setup the output structure */
rv->w = pcxh.xmax + 1;
rv->h = pcxh.ymax + 1;
num_bytes = rv->w * rv->h;
/* printf("pcx_load(%s): image %08x is %dx%d (%d bytes)\r\n", fn, rv, rv->width, rv->height, num_bytes); */
pxls = (uint16 *)malloc(num_bytes * 2);
rv->data = (void *)pxls;
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_RGB565, 0);
rv->byte_count = 2 * rv->w * rv->h;
/* Do the RLE decoding (allocate a temp buffer + palette) */
image = malloc(num_bytes + 768);
if (image == NULL) {
printf("pcx_load(%s): Can't allocate temp space of %d bytes\r\n", fn, num_bytes);
fs_close(fd);
free(rv->data);
return -3;
}
/* printf(" decoding into buffer at %08x\r\n", image); */
do {
fs_read(fd, &c, 1); /* Read one byte */
if ((c & 0xc0) == 0xc0) { /* high 2 bits set is packet */
runlen = (c & 0x3f); /* AND off the high bits */
fs_read(fd, &c, 1);
while(runlen--)
image[bytes++] = c;
}
else
image[bytes++] = c;
} while (bytes < num_bytes);
/* Load the palette */
fs_read(fd, &c, 1); /* This is a marker before the palette */
pcxpal = image + num_bytes;
fs_read(fd, pcxpal, 768);
fs_close(fd);
/* Decode the image into RGB565 */
for (i=0; i<num_bytes; i++) {
v = image[i];
r = pcxpal[v*3+0];
g = pcxpal[v*3+1];
b = pcxpal[v*3+2];
v = (((r >> 3) & 0x1f) << 11)
| (((g >> 2) & 0x3f) << 5)
| (((b >> 3) & 0x1f) << 0);
pxls[i] = v;
}
/* Free temp buffers */
free(image);
return 0;
}