1 /* $Header: /home/yav/xpx/RCS/magtoppm.c,v 1.22 1996/04/23 10:58:05 yav Exp $
2 * MAG to portable pixmap convert routine
3 * written by yav (UHD98984@pcvan.or.jp)
4 */
5
6 #ifndef MAGTOPPM_STANDALONE
7 # include <X11/Xlib.h>
8 # include "headers.h"
9 # include "xpx.h"
10 # include "work.h"
11 # define PUBLIC_MAGTOPPM_C
12 # include "extern.h"
13 #else
14 # include <stdio.h>
15 # ifdef __MSDOS__
16 # include <stdlib.h>
17 # include <fcntl.h>
18 # endif
19 #endif
20
21 #define DECODE_ALL 0
22 #define DECODE_COLOR 1
23 #define DECODE_PIXEL 2
24 #define DECODE_XPX 3
25
26 typedef struct {
27 unsigned char top;
28 unsigned char machine_code;
29 unsigned char machine_flag;
30 unsigned char screen_mode;
31 unsigned short topx;
32 unsigned short topy;
33 unsigned short endx;
34 unsigned short endy;
35 long flaga_offset;
36 long flagb_offset;
37 long flagb_size;
38 long pixel_offset;
39 long pixel_size;
40 } MAGHEADER;
41
42 #define ScreenModeAspectMask (1<<0)
43 #define ScreenModeColor8Mask (1<<1)
44 #define ScreenModeDigitalMask (1<<2)
45 #define ScreenModeColor256Mask (1<<7)
46
47 #ifndef MAX_FILE_X
48 #define MAX_FILE_X 4096
49 #endif
50 #ifndef MAX_FILE_Y
51 #define MAX_FILE_Y 4096
52 #endif
53
54 char rcsid_magtoppm[] = "$Id: magtoppm.c,v 1.22 1996/04/23 10:58:05 yav Exp $";
55 static char rcsrev[] = "$Revision: 1.22 $";
56 static char *my_name = "magtoppm";
57 static char mag_magic_number[] = "MAKI02 ";
58 static struct {int x,y;} magpostbl[16]={
59 {0,0},{1,0},{2,0},{4,0},{0,1},{1,1},{0,2},{1,2},
60 {2,2},{0,4},{1,4},{2,4},{0,8},{1,8},{2,8},{0,16}};
61 static char pnm_comment_id[] = "#Converted by %s %s\n";
62 static char pnm_comment_file[] = "# file: %s\n";
63 static char pnm_comment_position[] = "# position: %4d %4d %4d %4d\n";
64 static char pnm_comment_memo[] = "# memo:";
65 static char pnm_comment_color[] = "# color:%3d %3d %3d %3d\n";
66 #ifdef MAGTOPPM_STANDALONE
67 static int debug_mode = 0;
68 static int decode_mode = DECODE_ALL;
69 #else
70 static int decode_mode = DECODE_XPX;
71 #endif
72 static int palcount;
73 static long flaga_size;
74 static long datafpos;
75 static int dataw, datah;
76 static int pixel_direct;
77 static int binary_mode = 1;
78 static MAGHEADER hdr;
79 static unsigned short *pix_buffer;
80 static int pixbuf_xsize;
81 static unsigned char *flag_a;
82 static unsigned char *flag_b;
83 static unsigned char palbuf[3*256];
84 #ifdef MAGTOPPM_STANDALONE
85 static char *error_message[] = {
86 "???\n",
87 "abort.\n",
88 "more core!\n",
89 "write error!\n",
90 "``%s'' not found!\n",
91 "``%s'' read error!\n",
92 "``%s'' header read error!\n",
93 "``%s'' is not MAG file!\n",
94 "``%s'' is too large!\n",
95 "``%s'' flag-A seek error!\n",
96 "``%s'' flag-B seek error!\n",
97 "``%s'' pixel seek error!\n",
98 NULL
99 };
100 #endif
101
102 #define ERR_None 0
103 #define ERR_ABORT 1
104 #define ERR_MORECORE 2
105 #define ERR_WRITE 3
106 #define ERR_NOTFOUND 4
107 #define ERR_READ 5
108 #define ERR_READHEADER 6
109 #define ERR_MAGICNUMBER 7
110 #define ERR_TOOLARGE 8
111 #define ERR_OFFSETA 9
112 #define ERR_OFFSETB 10
113 #define ERR_OFFSETP 11
114
115 #ifdef MAGTOPPM_STANDALONE
usage()116 void usage()
117 {
118 fprintf(stderr, "* %s %s *\n", my_name, rcsrev);
119 fprintf(stderr, "written by yav (UHD98984@pcvan.or.jp)\n");
120 fprintf(stderr, "usage : %s [options] filename\n", my_name);
121 fprintf(stderr, "option :\n");
122 fprintf(stderr, " -b : binary mode\n");
123 fprintf(stderr, " -t : text mode\n");
124 fprintf(stderr, " -c : output color data as ppmfile\n");
125 fprintf(stderr, " -p : output pixel data as pgmfile\n");
126 exit(ERR_ABORT);
127 }
128 #endif /* MAGTOPPM_STANDALONE */
129
readbyte(fp)130 int readbyte(fp)
131 FILE *fp;
132 {
133 return fgetc(fp);
134 }
135
readleshort(fp)136 int readleshort(fp)
137 FILE *fp;
138 {
139 unsigned char buf[2];
140
141 fread(buf, sizeof(buf), 1, fp);
142 return buf[0] + (((signed char *)buf)[1] << 8);
143 }
144
readlelong(fp)145 long readlelong(fp)
146 FILE *fp;
147 {
148 unsigned char buf[4];
149
150 fread(buf, sizeof(buf), 1, fp);
151 return buf[0] + (buf[1] << 8) + (((long)buf[2]) << 16) +
152 (((long)((signed char *)buf)[3]) << 24);
153 }
154
read_mag_header(fp,p)155 int read_mag_header(fp, p)
156 FILE *fp;
157 MAGHEADER *p;
158 {
159 p->top = readbyte(fp);
160 p->machine_code = readbyte(fp);
161 p->machine_flag = readbyte(fp);
162 p->screen_mode = readbyte(fp);
163 p->topx = readleshort(fp);
164 p->topy = readleshort(fp);
165 p->endx = readleshort(fp);
166 p->endy = readleshort(fp);
167 p->flaga_offset = readlelong(fp);
168 p->flagb_offset = readlelong(fp);
169 p->flagb_size = readlelong(fp);
170 p->pixel_offset = readlelong(fp);
171 p->pixel_size = readlelong(fp);
172 return ferror(fp);
173 }
174
color_decode()175 int color_decode()
176 {
177 int i;
178 unsigned char *p;
179 char buf[80];
180
181 p = palbuf;
182 for (i = 0; i < palcount; i++) {
183 if (binary_mode) {
184 if (fputc(*(p+1), stdout) == EOF ||
185 fputc(*p, stdout) == EOF ||
186 fputc(*(p+2), stdout) == EOF)
187 return ERR_WRITE;
188 } else {
189 sprintf(buf, "%3d %3d %3d\n", *(p+1), *p, *(p+2));
190 if (fputs(buf, stdout) == EOF)
191 return ERR_WRITE;
192 }
193 p += 3;
194 }
195 return 0;
196 }
197
readpixel(fp,px)198 int readpixel(fp, px)
199 FILE *fp;
200 unsigned short *px;
201 {
202 int c;
203
204 if ((c = getc(fp)) == EOF)
205 return ERR_READ;
206 *px = c << 8;
207 if ((c = getc(fp)) == EOF)
208 return ERR_READ;
209 *px |= c & 0xff;
210 return 0;
211 }
212
DecodePixGroup(fp,pbuf,y,x2,f)213 int DecodePixGroup(fp, pbuf, y, x2, f)
214 FILE *fp;
215 unsigned char *pbuf;
216 int y;
217 int x2;
218 int f;
219 {
220 unsigned short px;
221
222 if (f)
223 px = pix_buffer[((y-magpostbl[f].y)&15)*pixbuf_xsize + x2-magpostbl[f].x];
224 else
225 if (readpixel(fp, &px))
226 return ERR_READ; /* decode error */
227 pix_buffer[(y&15)*pixbuf_xsize + x2] = px;
228 if (palcount == 256) {
229 pbuf[0] = (px>>8)&0xff;
230 pbuf[1] = px&0xff;
231 } else {
232 pbuf[0] = (px>>12)&0xf;
233 pbuf[1] = (px>>8)&0xf;
234 pbuf[2] = (px>>4)&0xf;
235 pbuf[3] = px&0xf;
236 }
237 return 0;
238 }
239
240 #ifndef MAGTOPPM_STANDALONE
241 static int outline_cnt;
242 #endif
243
outline(pix,n)244 int outline(pix, n)
245 unsigned char *pix;
246 int n;
247 {
248 int i;
249
250 #ifndef MAGTOPPM_STANDALONE
251 if (decode_mode == DECODE_XPX) {
252 if (outline_cnt < imgmaxh) {
253 if (n > imgmaxw)
254 n = imgmaxw;
255 memcpy(imgdata+outline_cnt*imgmaxw, pix, n);
256 outline_cnt++;
257 }
258 return 0;
259 }
260 #endif
261 if (binary_mode) {
262 for (i = 0; i < n; i++) {
263 if (pixel_direct) {
264 if (fputc(*pix, stdout) == EOF)
265 return ERR_WRITE;
266 } else {
267 if (fputc(palbuf[*pix*3+1], stdout) == EOF||
268 fputc(palbuf[*pix*3+0], stdout) == EOF||
269 fputc(palbuf[*pix*3+2], stdout) == EOF)
270 return ERR_WRITE;
271 }
272 pix++;
273 }
274 } else {
275 char *p, buf[80];
276 p = buf;
277 for (i = 0; i < n; i++) {
278 if (pixel_direct)
279 sprintf(p, "%d ", *pix);
280 else
281 sprintf(p, "%d %d %d ",
282 palbuf[*pix*3+1], palbuf[*pix*3+0], palbuf[*pix*3+2]);
283 pix++;
284 p += strlen(p);
285 if (strlen(buf) >= (70-4*3)) {
286 *--p = '\n';
287 if (fputs(buf, stdout) == EOF)
288 return ERR_WRITE;
289 p = buf;
290 *p = '\0';
291 }
292 }
293 if (strlen(buf)) {
294 *--p = '\n';
295 if (fputs(buf, stdout) == EOF)
296 return ERR_WRITE;
297 }
298 }
299 return 0;
300 }
301
pixel_decode_sub(fp)302 int pixel_decode_sub(fp)
303 FILE *fp;
304 {
305 int x, y, x2, aspf, dx, r;
306 unsigned char a_bit, *pf, *pa, *pb;
307 unsigned char pbuf[MAX_FILE_X+4];
308 unsigned char flag_buffer[(MAX_FILE_X+3)/4];
309
310 #ifndef MAGTOPPM_STANDALONE
311 outline_cnt = 0;
312 #endif
313 /* pixel data decode */
314 memset(flag_buffer, 0, sizeof(flag_buffer));
315 pa = flag_a;
316 pb = flag_b;
317 a_bit=0x80;
318 aspf = hdr.screen_mode & ScreenModeAspectMask;
319 dx = (palcount == 256) ? 2 : 4;
320 for (y = 0; y < datah; y++) {
321 pf = flag_buffer;
322 for (x = x2 = 0; x < dataw; pf++) {
323 if (*pa & a_bit)
324 *pf ^= *pb++;
325 if (!(a_bit >>= 1)) {
326 a_bit = 0x80;
327 pa++;
328 }
329 /* left */
330 r = DecodePixGroup(fp, pbuf+x, y, x2++, *pf >> 4);
331 if (r)
332 return r;
333 x += dx;
334 /* right */
335 r = DecodePixGroup(fp, pbuf+x, y, x2++, *pf & 0xf);
336 if (r)
337 return r;
338 x += dx;
339 }
340 r = outline(pbuf, dataw);
341 if (r)
342 return r;
343 if (aspf) {
344 r = outline(pbuf, dataw);
345 if (r)
346 return r;
347 }
348 }
349 return 0;
350 }
351
dataseek(fp,pos)352 int dataseek(fp, pos)
353 FILE *fp;
354 long pos;
355 {
356 if (datafpos == pos)
357 return 0;
358 if (datafpos > pos)
359 return 1;
360 while (datafpos < pos) {
361 if (getc(fp) == EOF)
362 return 1;
363 datafpos++;
364 }
365 return 0;
366 }
367
pixel_decode(fp)368 int pixel_decode(fp)
369 FILE *fp;
370 {
371 int r;
372
373 if (debug_mode) {
374 fprintf(stderr, "flagA offset %ld size %ld\n",
375 hdr.flaga_offset, flaga_size);
376 fprintf(stderr, "flagB offset %ld size %ld\n",
377 hdr.flagb_offset, hdr.flagb_size);
378 fprintf(stderr, "pixel offset %ld size %ld\n",
379 hdr.pixel_offset, hdr.pixel_size);
380 }
381 pix_buffer = (unsigned short*)malloc(sizeof(unsigned short)*16*pixbuf_xsize);
382 flag_a = (unsigned char *)malloc(flaga_size);
383 flag_b = (unsigned char *)malloc(hdr.flagb_size);
384 if (pix_buffer == NULL || flag_a == NULL || flag_b == NULL)
385 return ERR_MORECORE;
386 if (dataseek(fp, hdr.flaga_offset))
387 return ERR_OFFSETA;
388 if (fread(flag_a, 1, flaga_size, fp) != flaga_size)
389 return ERR_READ;
390 datafpos += flaga_size;
391 if (dataseek(fp, hdr.flagb_offset))
392 return ERR_OFFSETB;
393 if (fread(flag_b, 1, hdr.flagb_size, fp) != hdr.flagb_size)
394 return ERR_READ;
395 datafpos += hdr.flagb_size;
396 if (dataseek(fp, hdr.pixel_offset))
397 return ERR_OFFSETP;
398 r = pixel_decode_sub(fp);
399 free(flag_b);
400 free(flag_a);
401 free(pix_buffer);
402 return r;
403 }
404
decode_mag(fp,filename)405 int decode_mag(fp, filename)
406 FILE *fp;
407 char *filename;
408 {
409 int c, i;
410 int comment_lf;
411 char buf[256];
412
413 /* check magic number */
414 i = strlen(mag_magic_number);
415 if (!fread(buf, i, 1, fp))
416 return ERR_READ;
417 buf[i] = '\0';
418 if (strcmp(buf, mag_magic_number))
419 return ERR_MAGICNUMBER;
420 if (decode_mode != DECODE_XPX) {
421 printf("%s\n", (decode_mode == DECODE_PIXEL) ? (binary_mode ? "P5" : "P2") :
422 (binary_mode ? "P6" : "P3"));
423 printf(pnm_comment_id, my_name, rcsrev);
424 printf(pnm_comment_file, filename);
425 }
426 /* skip comment */
427 comment_lf = 1;
428 while ((c = fgetc(fp)) != 0x1a) {
429 if (c == EOF)
430 return ERR_READ;
431 if (decode_mode != DECODE_XPX) {
432 if (comment_lf)
433 printf(pnm_comment_memo);
434 if (putchar(c) == EOF)
435 return ERR_WRITE;
436 }
437 comment_lf = c == '\n';
438 }
439 if (!comment_lf && decode_mode != DECODE_XPX)
440 if (putchar('\n') == EOF)
441 return ERR_WRITE;
442 if (read_mag_header(fp, &hdr))
443 return ERR_READHEADER;
444 datafpos = 32;
445 if (decode_mode != DECODE_XPX)
446 printf(pnm_comment_position, hdr.topx, hdr.topy, hdr.endx, hdr.endy);
447 flaga_size = hdr.flagb_offset - hdr.flaga_offset;
448 if (hdr.screen_mode & ScreenModeColor256Mask) {
449 #ifndef MAGTOPPM_STANDALONE
450 imgfiledepth = 8;
451 #endif
452 palcount = 256;
453 pixbuf_xsize = MAX_FILE_X/2;
454 } else {
455 #ifndef MAGTOPPM_STANDALONE
456 imgfiledepth = 4;
457 #endif
458 palcount = 16;
459 pixbuf_xsize = MAX_FILE_X/4;
460 }
461 dataw = ((hdr.endx+8)/8)*8 - (hdr.topx/8)*8;
462 datah = hdr.endy - hdr.topy + 1;
463 if (dataw > MAX_FILE_X || datah > MAX_FILE_Y)
464 return ERR_TOOLARGE;
465 if (!fread(palbuf, palcount*3, 1, fp))
466 return ERR_READ;
467 datafpos += palcount*3;
468 switch (decode_mode) {
469 case DECODE_COLOR:
470 sprintf(buf, "1 %d\n255\n", palcount);
471 if (fputs(buf, stdout) == EOF)
472 return ERR_WRITE;
473 return color_decode();
474 case DECODE_PIXEL:
475 for (i = 0; i < palcount; i++)
476 printf(pnm_comment_color, i, palbuf[3*i+1], palbuf[3*i], palbuf[3*i+2]);
477 pixel_direct = 1;
478 sprintf(buf, "%d %d\n%d\n", dataw, datah, palcount-1);
479 if (fputs(buf, stdout) == EOF)
480 return ERR_WRITE;
481 break;
482 #ifndef MAGTOPPM_STANDALONE
483 case DECODE_XPX:
484 for (i = 0; i < palcount; i++) {
485 color_buf[i].rgb.red = palbuf[3*i+1];
486 color_buf[i].rgb.green = palbuf[3*i];
487 color_buf[i].rgb.blue = palbuf[3*i+2];
488 }
489 mag_palcnt = palcount;
490 mag_dataw = dataw;
491 mag_datah = datah;
492 imgposx = hdr.topx;
493 imgposy = hdr.topy;
494 break;
495 #endif
496 default:
497 for (i = 0; i < palcount; i++)
498 printf(pnm_comment_color, i, palbuf[3*i+1], palbuf[3*i], palbuf[3*i+2]);
499 pixel_direct = 0;
500 sprintf(buf, "%d %d\n255\n", dataw, datah);
501 if (fputs(buf, stdout) == EOF)
502 return ERR_WRITE;
503 }
504 return pixel_decode(fp);
505 }
506
507 #ifdef MAGTOPPM_STANDALONE
508
get_filename(str)509 char *get_filename(str)
510 char *str;
511 {
512 char *p, *p1;
513
514 p = strrchr(str, '/');
515 if (p == NULL)
516 p = str;
517 else
518 p++;
519 #ifdef __MSDOS__
520 p1 = p;
521 p = strrchr(p1, '\\');
522 if (p == NULL)
523 p = p1;
524 else
525 p++;
526 p1 = strrchr(p, '.');
527 if (p1 != NULL)
528 *p1 = '\0';
529 #endif
530 return p;
531 }
532
main(argc,argv)533 main(argc, argv)
534 char **argv;
535 {
536 int i;
537 FILE *fp;
538 char *inputfile;
539
540 my_name = get_filename(*argv);
541 while (--argc && **++argv == '-') {
542 switch(*++*argv) {
543 case 'd':
544 debug_mode = 1;
545 break;
546 case 'c':
547 decode_mode = DECODE_COLOR;
548 break;
549 case 'p':
550 decode_mode = DECODE_PIXEL;
551 break;
552 case 'b':
553 binary_mode = 1;
554 break;
555 case 't':
556 binary_mode = 0;
557 break;
558 case 'h':
559 case '?':
560 default:
561 usage();
562 }
563 }
564 i = 0;
565 if (argc) {
566 --argc;
567 inputfile = *argv++;
568 fp = fopen(inputfile, "r");
569 if (fp == NULL)
570 i = ERR_NOTFOUND;
571 } else {
572 inputfile = "<stdin>";
573 fp = stdin;
574 }
575 #ifdef __MSDOS__
576 setmode(fileno(fp), O_BINARY);
577 if (binary_mode)
578 setmode(fileno(stdout), O_BINARY);
579 #endif
580 if (!i)
581 i = decode_mag(fp, get_filename(inputfile));
582 if (i) {
583 fprintf(stderr, " %s: ", my_name);
584 fprintf(stderr, error_message[i], inputfile);
585 }
586 if (fp != NULL)
587 fclose(fp);
588 return i;
589 }
590
591 #endif /* MAGTOPPM_STANDALONE */
592
593 /* End of file */
594