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