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