1 /*
2 * Copyright(c) 1997-2001 Id Software, Inc.
3 * Copyright(c) 2002 The Quakeforge Project.
4 * Copyright(c) 2006 Quetoo.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or(at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include "pcx.h"
23 #include "video.h"
24
25 /*
26 LoadPCX
27 */
LoadPCX(char * name,byte ** pic,byte ** palette,int * width,int * height)28 void LoadPCX(char *name, byte **pic, byte **palette, int *width, int *height){
29 byte *buffer;
30 pcx_t *pcx;
31 int x, y, length;
32 int data, run_length;
33 byte *out, *pixbuf;
34
35 *pic = NULL;
36 *palette = NULL;
37
38 length = FS_LoadFile(name, (void **)(char *)&buffer);
39
40 if(!buffer){ // unable to open file
41 return;
42 }
43
44 pcx = (pcx_t *)buffer;
45
46 pcx->xmin = LittleShort(pcx->xmin);
47 pcx->ymin = LittleShort(pcx->ymin);
48 pcx->xmax = LittleShort(pcx->xmax);
49 pcx->ymax = LittleShort(pcx->ymax);
50 pcx->hres = LittleShort(pcx->hres);
51 pcx->vres = LittleShort(pcx->vres);
52 pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
53 pcx->palette_type = LittleShort(pcx->palette_type);
54
55 buffer = &pcx->data;
56
57 if(pcx->manufacturer != 0x0a
58 || pcx->version != 5
59 || pcx->encoding != 1
60 || pcx->bits_per_pixel != 8
61 || pcx->xmax >= 640
62 || pcx->ymax >= 480){
63 return;
64 }
65
66 out = malloc((pcx->ymax + 1) *(pcx->xmax + 1));
67
68 *pic = out;
69
70 pixbuf = out;
71
72 if(palette){
73 *palette = malloc(768);
74 memcpy(*palette,(byte *)pcx + length - 768, 768);
75 }
76
77 if(width)
78 *width = pcx->xmax + 1;
79 if(height)
80 *height = pcx->ymax + 1;
81
82 for(y = 0; y <= pcx->ymax; y++, pixbuf += pcx->xmax + 1){
83 for(x = 0; x <= pcx->xmax;){
84 data = *buffer++;
85
86 if((data & 0xC0) == 0xC0){
87 run_length = data & 0x3F;
88 data = *buffer++;
89 } else
90 run_length = 1;
91
92 while(run_length-- > 0)
93 pixbuf[x++] = data;
94 }
95
96 }
97
98 if(buffer - (byte *)pcx > length){
99 free(*pic);
100 *pic = NULL;
101 }
102
103 FS_FreeFile(pcx);
104 }
105
106 /*
107 WritePCX
108 */
WritePCX(char * name,byte * data,int width,int height,int rowbytes,byte * palette)109 void WritePCX(char *name, byte *data, int width, int height, int rowbytes, byte *palette){
110 int i, j, length;
111 pcx_t *pcx;
112 byte *pack;
113 FILE *f;
114
115 pcx = (pcx_t *)malloc(width * height * 2 + 1000);
116 if(!pcx)
117 return;
118
119 pcx->manufacturer = 0x0a; // PCX id
120 pcx->version = 5; // 256 color
121 pcx->encoding = 1; // uncompressed
122 pcx->bits_per_pixel = 8; // 256 color
123 pcx->xmin = 0;
124 pcx->ymin = 0;
125 pcx->xmax = LittleShort((short)(width - 1));
126 pcx->ymax = LittleShort((short)(height - 1));
127 pcx->hres = LittleShort((short)width);
128 pcx->vres = LittleShort((short)height);
129 memset(pcx->palette, 0, sizeof(pcx->palette));
130 pcx->color_planes = 1; // chunky image
131 pcx->bytes_per_line = LittleShort((short)width);
132 pcx->palette_type = LittleShort(2); // not a grey scale
133 memset(pcx->filler, 0, sizeof(pcx->filler));
134
135 // pack the image
136 pack = &pcx->data;
137
138 for(i = 0; i < height; i++){
139 for(j = 0; j < width; j++){
140 if((*data & 0xc0) != 0xc0)
141 *pack++ = *data++;
142 else {
143 *pack++ = 0xc1;
144 *pack++ = *data++;
145 }
146 }
147
148 data += rowbytes - width;
149 }
150
151 // write the palette
152 *pack++ = 0x0c; // palette ID byte
153 for(i = 0; i < 768; i++)
154 *pack++ = *palette++;
155
156 // write output file
157 length = pack - (byte *)pcx;
158 f = fopen(name, "wb");
159 if(!f)
160 Com_Printf( "Failed to open to %s\n", name);
161 else {
162 fwrite((void *)pcx, 1, length, f);
163 fclose(f);
164 }
165
166 free(pcx);
167 }
168