1 | /*
|
---|
2 |
|
---|
3 | gbmkps.c - IBM KIPS support
|
---|
4 |
|
---|
5 | Reads array as 8 bit palettised colour.
|
---|
6 | Writes 8 bit palettised colour.
|
---|
7 | Input options: pal,kpl (default: pal)
|
---|
8 | Output options: pal,kpl (default: pal)
|
---|
9 |
|
---|
10 | */
|
---|
11 |
|
---|
12 | /*...sincludes:0:*/
|
---|
13 | #include <stdio.h>
|
---|
14 | #include <ctype.h>
|
---|
15 | #include <stddef.h>
|
---|
16 | #include <stdlib.h>
|
---|
17 | #include <string.h>
|
---|
18 | #include "gbm.h"
|
---|
19 | #include "gbmhelp.h"
|
---|
20 |
|
---|
21 | /*...vgbm\46\h:0:*/
|
---|
22 | /*...vgbmhelp\46\h:0:*/
|
---|
23 |
|
---|
24 | /* Handle case for UNIX machines where O_BINARY has no meaning */
|
---|
25 |
|
---|
26 | #ifndef O_BINARY
|
---|
27 | #define O_BINARY 0
|
---|
28 | #endif
|
---|
29 | /*...e*/
|
---|
30 |
|
---|
31 | /*...suseful:0:*/
|
---|
32 | #define low_byte(w) ((byte) ( (w)&0x00ffU) )
|
---|
33 | #define high_byte(w) ((byte) (((unsigned)(w)&0xff00U)>>8))
|
---|
34 | #define make_word(a,b) (((word)a) + (((word)b) << 8))
|
---|
35 | /*...e*/
|
---|
36 | /*...sextension:0:*/
|
---|
37 | static char *extension(char *fn)
|
---|
38 | {
|
---|
39 | char *dot, *slash;
|
---|
40 |
|
---|
41 | if ( (dot = strrchr(fn, '.')) == NULL )
|
---|
42 | return NULL;
|
---|
43 |
|
---|
44 | if ( (slash = strpbrk(fn, "/\\")) == NULL )
|
---|
45 | return dot + 1;
|
---|
46 |
|
---|
47 | return ( slash < dot ) ? dot + 1 : NULL;
|
---|
48 | }
|
---|
49 | /*...e*/
|
---|
50 |
|
---|
51 | static GBMFT kps_gbmft =
|
---|
52 | {
|
---|
53 | "KIPS",
|
---|
54 | "IBM KIPS",
|
---|
55 | "KPS",
|
---|
56 | GBM_FT_R8|
|
---|
57 | GBM_FT_W8,
|
---|
58 | };
|
---|
59 |
|
---|
60 | #define GBM_ERR_KPS_OPEN ((GBM_ERR) 500)
|
---|
61 | #define GBM_ERR_KPS_CREATE ((GBM_ERR) 501)
|
---|
62 |
|
---|
63 | /*...skps file header definition:0:*/
|
---|
64 | /*
|
---|
65 | This defines the 32 byte header found on .KPS and .KPL files.
|
---|
66 | */
|
---|
67 |
|
---|
68 | #define KPS_SIGNITURE "DFIMAG00"
|
---|
69 |
|
---|
70 | typedef struct
|
---|
71 | {
|
---|
72 | byte signiture[8]; /* Usually "DFIMAG00" */
|
---|
73 | byte height_low;
|
---|
74 | byte height_high; /* Image height in pixels */
|
---|
75 | byte width_low;
|
---|
76 | byte width_high; /* Image width in pixels */
|
---|
77 | byte unknown[20]; /* 20 unknown bytes */
|
---|
78 | } KPS_HEADER;
|
---|
79 | /*...e*/
|
---|
80 |
|
---|
81 | typedef struct
|
---|
82 | {
|
---|
83 | char fn[600+1];
|
---|
84 | BOOLEAN kpl;
|
---|
85 | } KPS_PRIV;
|
---|
86 |
|
---|
87 | /*...skps_qft:0:*/
|
---|
88 | GBM_ERR kps_qft(GBMFT *gbmft)
|
---|
89 | {
|
---|
90 | *gbmft = kps_gbmft;
|
---|
91 | return GBM_ERR_OK;
|
---|
92 | }
|
---|
93 | /*...e*/
|
---|
94 | /*...skps_rhdr:0:*/
|
---|
95 | GBM_ERR kps_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
|
---|
96 | {
|
---|
97 | BOOLEAN pal = ( gbm_find_word(opt, "pal") != NULL );
|
---|
98 | BOOLEAN kpl = ( gbm_find_word(opt, "kpl") != NULL );
|
---|
99 | KPS_HEADER kps_header;
|
---|
100 | KPS_PRIV *priv = (KPS_PRIV *) gbm->priv;
|
---|
101 | int w, h;
|
---|
102 |
|
---|
103 | if ( kpl && pal )
|
---|
104 | return GBM_ERR_BAD_OPTION;
|
---|
105 |
|
---|
106 | gbm_file_read(fd, (char *) &kps_header, sizeof(KPS_HEADER));
|
---|
107 |
|
---|
108 | if ( memcmp(kps_header.signiture, KPS_SIGNITURE, strlen(KPS_SIGNITURE)) )
|
---|
109 | return GBM_ERR_BAD_MAGIC;
|
---|
110 |
|
---|
111 | w = make_word(kps_header.width_low , kps_header.width_high );
|
---|
112 | h = make_word(kps_header.height_low, kps_header.height_high);
|
---|
113 |
|
---|
114 | if ( w <= 0 || h <= 0 )
|
---|
115 | return GBM_ERR_BAD_SIZE;
|
---|
116 |
|
---|
117 | gbm->w = w;
|
---|
118 | gbm->h = h;
|
---|
119 | gbm->bpp = 8;
|
---|
120 |
|
---|
121 | /* Keep these for a later kps_rpal() call */
|
---|
122 |
|
---|
123 | strcpy(priv->fn, fn);
|
---|
124 | priv->kpl = kpl;
|
---|
125 |
|
---|
126 | return GBM_ERR_OK;
|
---|
127 | }
|
---|
128 | /*...e*/
|
---|
129 | /*...skps_rpal:0:*/
|
---|
130 | GBM_ERR kps_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
|
---|
131 | {
|
---|
132 | KPS_PRIV *priv = (KPS_PRIV *) gbm->priv;
|
---|
133 | char fn2[600+1], *ext;
|
---|
134 |
|
---|
135 | fd=fd; /* Suppress 'unref arg' compiler warning */
|
---|
136 |
|
---|
137 | strcpy(fn2, priv->fn);
|
---|
138 | ext = extension(fn2);
|
---|
139 | if ( priv->kpl )
|
---|
140 | /*...sread a \46\kpl palette file:16:*/
|
---|
141 | {
|
---|
142 | int fd2, i, w, h;
|
---|
143 | byte p[3][0x100];
|
---|
144 | KPS_HEADER kps_header;
|
---|
145 |
|
---|
146 | if ( ext != NULL )
|
---|
147 | strcpy(ext, "kpl");
|
---|
148 | else
|
---|
149 | strcat(fn2, ".kpl");
|
---|
150 |
|
---|
151 | if ( (fd2 = gbm_file_open(fn2, O_RDONLY|O_BINARY)) == -1 )
|
---|
152 | return GBM_ERR_KPS_OPEN;
|
---|
153 |
|
---|
154 | gbm_file_read(fd2, (char *) &kps_header, sizeof(KPS_HEADER));
|
---|
155 | if ( memcmp(kps_header.signiture, KPS_SIGNITURE, strlen(KPS_SIGNITURE)) )
|
---|
156 | return GBM_ERR_BAD_MAGIC;
|
---|
157 |
|
---|
158 | w = make_word(kps_header.width_low , kps_header.width_high );
|
---|
159 | h = make_word(kps_header.height_low, kps_header.height_high);
|
---|
160 |
|
---|
161 | if ( w != 0x100 || h != 3 )
|
---|
162 | return GBM_ERR_BAD_SIZE;
|
---|
163 |
|
---|
164 | gbm_file_read(fd2, &(p[0][0]), 0x300);
|
---|
165 | gbm_file_close(fd2);
|
---|
166 |
|
---|
167 | for ( i = 0; i < 0x100; i++ )
|
---|
168 | {
|
---|
169 | gbmrgb[i].r = p[0][i];
|
---|
170 | gbmrgb[i].b = p[1][i];
|
---|
171 | gbmrgb[i].g = p[2][i];
|
---|
172 | }
|
---|
173 | }
|
---|
174 | /*...e*/
|
---|
175 | else
|
---|
176 | /*...sread a \46\pal palette file:16:*/
|
---|
177 | {
|
---|
178 | int fd2, i;
|
---|
179 | byte b[4];
|
---|
180 |
|
---|
181 | if ( ext != NULL )
|
---|
182 | strcpy(ext, "pal");
|
---|
183 | else
|
---|
184 | strcat(fn2, ".pal");
|
---|
185 |
|
---|
186 | if ( (fd2 = gbm_file_open(fn2, O_RDONLY|O_BINARY)) == -1 )
|
---|
187 | return GBM_ERR_KPS_OPEN;
|
---|
188 |
|
---|
189 | for ( i = 0; i < 0x100; i++ )
|
---|
190 | {
|
---|
191 | gbm_file_read(fd2, (char *) b, 4);
|
---|
192 | gbmrgb[i].r = b[0];
|
---|
193 | gbmrgb[i].b = b[1];
|
---|
194 | gbmrgb[i].g = b[2];
|
---|
195 | }
|
---|
196 | gbm_file_close(fd2);
|
---|
197 | }
|
---|
198 | /*...e*/
|
---|
199 |
|
---|
200 | return GBM_ERR_OK;
|
---|
201 | }
|
---|
202 | /*...e*/
|
---|
203 | /*...skps_rdata:0:*/
|
---|
204 | GBM_ERR kps_rdata(int fd, GBM *gbm, byte *data)
|
---|
205 | {
|
---|
206 | int i, stride;
|
---|
207 | byte *p;
|
---|
208 |
|
---|
209 | stride = ((gbm->w + 3) & ~3);
|
---|
210 | p = data + ((gbm->h - 1) * stride);
|
---|
211 | for ( i = gbm->h - 1; i >= 0; i-- )
|
---|
212 | {
|
---|
213 | gbm_file_read(fd, p, gbm->w);
|
---|
214 | p -= stride;
|
---|
215 | }
|
---|
216 |
|
---|
217 | return GBM_ERR_OK;
|
---|
218 | }
|
---|
219 | /*...e*/
|
---|
220 | /*...skps_w:0:*/
|
---|
221 | GBM_ERR kps_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
|
---|
222 | {
|
---|
223 | KPS_HEADER kps_header;
|
---|
224 | int i, stride;
|
---|
225 | const byte *p;
|
---|
226 | char fn2[600+1], *ext;
|
---|
227 | BOOLEAN pal = ( gbm_find_word(opt, "pal") != NULL );
|
---|
228 | BOOLEAN kpl = ( gbm_find_word(opt, "kpl") != NULL );
|
---|
229 |
|
---|
230 | if ( gbm->bpp != 8 )
|
---|
231 | return GBM_ERR_NOT_SUPP;
|
---|
232 |
|
---|
233 | if ( pal && kpl )
|
---|
234 | return GBM_ERR_BAD_OPTION;
|
---|
235 |
|
---|
236 | memcpy(kps_header.signiture, KPS_SIGNITURE, strlen(KPS_SIGNITURE));
|
---|
237 | kps_header.width_low = low_byte(gbm->w);
|
---|
238 | kps_header.width_high = high_byte(gbm->w);
|
---|
239 | kps_header.height_low = low_byte(gbm->h);
|
---|
240 | kps_header.height_high = high_byte(gbm->h);
|
---|
241 | kps_header.unknown[0] = 1;
|
---|
242 | memset(&kps_header.unknown[1], 0, 19);
|
---|
243 | gbm_file_write(fd, (char *) &kps_header, sizeof(KPS_HEADER));
|
---|
244 |
|
---|
245 | stride = ((gbm->w + 3) & ~3);
|
---|
246 | p = data + ((gbm->h - 1) * stride);
|
---|
247 | for ( i = gbm->h - 1; i >= 0; i-- )
|
---|
248 | {
|
---|
249 | gbm_file_write(fd, p, gbm->w);
|
---|
250 | p -= stride;
|
---|
251 | }
|
---|
252 |
|
---|
253 | strcpy(fn2, fn);
|
---|
254 | ext = extension(fn2);
|
---|
255 | if ( kpl )
|
---|
256 | /*...swrite a \46\kpl palette file:16:*/
|
---|
257 | {
|
---|
258 | int fd2, j;
|
---|
259 | byte palette[3][0x100];
|
---|
260 |
|
---|
261 | if ( ext != NULL )
|
---|
262 | strcpy(ext, "kpl");
|
---|
263 | else
|
---|
264 | strcat(fn2, ".kpl");
|
---|
265 |
|
---|
266 | if ( (fd2 = gbm_file_create(fn2, O_WRONLY|O_BINARY)) == -1 )
|
---|
267 | return GBM_ERR_KPS_CREATE;
|
---|
268 |
|
---|
269 | kps_header.width_low = low_byte(0x100);
|
---|
270 | kps_header.width_high = high_byte(0x100);
|
---|
271 | kps_header.height_low = low_byte(3);
|
---|
272 | kps_header.height_high = high_byte(3);
|
---|
273 | gbm_file_write(fd2, (char *) &kps_header, sizeof(KPS_HEADER));
|
---|
274 |
|
---|
275 | for ( j = 0; j < 0x100; j++ )
|
---|
276 | {
|
---|
277 | palette[0][j] = gbmrgb[j].r;
|
---|
278 | palette[1][j] = gbmrgb[j].b;
|
---|
279 | palette[2][j] = gbmrgb[j].g;
|
---|
280 | }
|
---|
281 |
|
---|
282 | gbm_file_write(fd2, &(palette[0][0]), 0x300);
|
---|
283 | gbm_file_close(fd2);
|
---|
284 | }
|
---|
285 | /*...e*/
|
---|
286 | else
|
---|
287 | /*...swrite a \46\pal palette file:16:*/
|
---|
288 | {
|
---|
289 | int fd2;
|
---|
290 | byte b[4];
|
---|
291 |
|
---|
292 | if ( ext != NULL )
|
---|
293 | strcpy(ext, "pal");
|
---|
294 | else
|
---|
295 | strcat(fn2, ".pal");
|
---|
296 |
|
---|
297 | if ( (fd2 = gbm_file_create(fn2, O_WRONLY|O_BINARY)) == -1 )
|
---|
298 | return GBM_ERR_KPS_CREATE;
|
---|
299 |
|
---|
300 | b[3] = 0;
|
---|
301 | for ( i = 0; i < 0x100; i++ )
|
---|
302 | {
|
---|
303 | b[0] = gbmrgb[i].r;
|
---|
304 | b[1] = gbmrgb[i].b;
|
---|
305 | b[2] = gbmrgb[i].g;
|
---|
306 | gbm_file_write(fd2, (char *) b, 4);
|
---|
307 | }
|
---|
308 | gbm_file_close(fd2);
|
---|
309 | }
|
---|
310 | /*...e*/
|
---|
311 |
|
---|
312 | return GBM_ERR_OK;
|
---|
313 | }
|
---|
314 | /*...e*/
|
---|
315 | /*...skps_err:0:*/
|
---|
316 | const char *kps_err(GBM_ERR rc)
|
---|
317 | {
|
---|
318 | switch ( (int) rc )
|
---|
319 | {
|
---|
320 | case GBM_ERR_KPS_OPEN:
|
---|
321 | return "can't open complementary palette file";
|
---|
322 | case GBM_ERR_KPS_CREATE:
|
---|
323 | return "can't create complementary palette file";
|
---|
324 | }
|
---|
325 | return NULL;
|
---|
326 | }
|
---|
327 | /*...e*/
|
---|