/* $Header: /home/yav/xpx/RCS/magtoppm.c,v 1.22 1996/04/23 10:58:05 yav Exp $ * MAG to portable pixmap convert routine * written by yav (UHD98984@pcvan.or.jp) */ #ifndef MAGTOPPM_STANDALONE # include # include "headers.h" # include "xpx.h" # include "work.h" # define PUBLIC_MAGTOPPM_C # include "extern.h" #else # include # ifdef __MSDOS__ # include # include # endif #endif #define DECODE_ALL 0 #define DECODE_COLOR 1 #define DECODE_PIXEL 2 #define DECODE_XPX 3 typedef struct { unsigned char top; unsigned char machine_code; unsigned char machine_flag; unsigned char screen_mode; unsigned short topx; unsigned short topy; unsigned short endx; unsigned short endy; long flaga_offset; long flagb_offset; long flagb_size; long pixel_offset; long pixel_size; } MAGHEADER; #define ScreenModeAspectMask (1<<0) #define ScreenModeColor8Mask (1<<1) #define ScreenModeDigitalMask (1<<2) #define ScreenModeColor256Mask (1<<7) #ifndef MAX_FILE_X #define MAX_FILE_X 4096 #endif #ifndef MAX_FILE_Y #define MAX_FILE_Y 4096 #endif char rcsid_magtoppm[] = "$Id: magtoppm.c,v 1.22 1996/04/23 10:58:05 yav Exp $"; static char rcsrev[] = "$Revision: 1.22 $"; static char *my_name = "magtoppm"; static char mag_magic_number[] = "MAKI02 "; static struct {int x,y;} magpostbl[16]={ {0,0},{1,0},{2,0},{4,0},{0,1},{1,1},{0,2},{1,2}, {2,2},{0,4},{1,4},{2,4},{0,8},{1,8},{2,8},{0,16}}; static char pnm_comment_id[] = "#Converted by %s %s\n"; static char pnm_comment_file[] = "# file: %s\n"; static char pnm_comment_position[] = "# position: %4d %4d %4d %4d\n"; static char pnm_comment_memo[] = "# memo:"; static char pnm_comment_color[] = "# color:%3d %3d %3d %3d\n"; #ifdef MAGTOPPM_STANDALONE static int debug_mode = 0; static int decode_mode = DECODE_ALL; #else static int decode_mode = DECODE_XPX; #endif static int palcount; static long flaga_size; static long datafpos; static int dataw, datah; static int pixel_direct; static int binary_mode = 1; static MAGHEADER hdr; static unsigned short *pix_buffer; static int pixbuf_xsize; static unsigned char *flag_a; static unsigned char *flag_b; static unsigned char palbuf[3*256]; #ifdef MAGTOPPM_STANDALONE static char *error_message[] = { "???\n", "abort.\n", "more core!\n", "write error!\n", "``%s'' not found!\n", "``%s'' read error!\n", "``%s'' header read error!\n", "``%s'' is not MAG file!\n", "``%s'' is too large!\n", "``%s'' flag-A seek error!\n", "``%s'' flag-B seek error!\n", "``%s'' pixel seek error!\n", NULL }; #endif #define ERR_None 0 #define ERR_ABORT 1 #define ERR_MORECORE 2 #define ERR_WRITE 3 #define ERR_NOTFOUND 4 #define ERR_READ 5 #define ERR_READHEADER 6 #define ERR_MAGICNUMBER 7 #define ERR_TOOLARGE 8 #define ERR_OFFSETA 9 #define ERR_OFFSETB 10 #define ERR_OFFSETP 11 #ifdef MAGTOPPM_STANDALONE void usage() { fprintf(stderr, "* %s %s *\n", my_name, rcsrev); fprintf(stderr, "written by yav (UHD98984@pcvan.or.jp)\n"); fprintf(stderr, "usage : %s [options] filename\n", my_name); fprintf(stderr, "option :\n"); fprintf(stderr, " -b : binary mode\n"); fprintf(stderr, " -t : text mode\n"); fprintf(stderr, " -c : output color data as ppmfile\n"); fprintf(stderr, " -p : output pixel data as pgmfile\n"); exit(ERR_ABORT); } #endif /* MAGTOPPM_STANDALONE */ int readbyte(fp) FILE *fp; { return fgetc(fp); } int readleshort(fp) FILE *fp; { unsigned char buf[2]; fread(buf, sizeof(buf), 1, fp); return buf[0] + (((signed char *)buf)[1] << 8); } long readlelong(fp) FILE *fp; { unsigned char buf[4]; fread(buf, sizeof(buf), 1, fp); return buf[0] + (buf[1] << 8) + (((long)buf[2]) << 16) + (((long)((signed char *)buf)[3]) << 24); } int read_mag_header(fp, p) FILE *fp; MAGHEADER *p; { p->top = readbyte(fp); p->machine_code = readbyte(fp); p->machine_flag = readbyte(fp); p->screen_mode = readbyte(fp); p->topx = readleshort(fp); p->topy = readleshort(fp); p->endx = readleshort(fp); p->endy = readleshort(fp); p->flaga_offset = readlelong(fp); p->flagb_offset = readlelong(fp); p->flagb_size = readlelong(fp); p->pixel_offset = readlelong(fp); p->pixel_size = readlelong(fp); return ferror(fp); } int color_decode() { int i; unsigned char *p; char buf[80]; p = palbuf; for (i = 0; i < palcount; i++) { if (binary_mode) { if (fputc(*(p+1), stdout) == EOF || fputc(*p, stdout) == EOF || fputc(*(p+2), stdout) == EOF) return ERR_WRITE; } else { sprintf(buf, "%3d %3d %3d\n", *(p+1), *p, *(p+2)); if (fputs(buf, stdout) == EOF) return ERR_WRITE; } p += 3; } return 0; } int readpixel(fp, px) FILE *fp; unsigned short *px; { int c; if ((c = getc(fp)) == EOF) return ERR_READ; *px = c << 8; if ((c = getc(fp)) == EOF) return ERR_READ; *px |= c & 0xff; return 0; } int DecodePixGroup(fp, pbuf, y, x2, f) FILE *fp; unsigned char *pbuf; int y; int x2; int f; { unsigned short px; if (f) px = pix_buffer[((y-magpostbl[f].y)&15)*pixbuf_xsize + x2-magpostbl[f].x]; else if (readpixel(fp, &px)) return ERR_READ; /* decode error */ pix_buffer[(y&15)*pixbuf_xsize + x2] = px; if (palcount == 256) { pbuf[0] = (px>>8)&0xff; pbuf[1] = px&0xff; } else { pbuf[0] = (px>>12)&0xf; pbuf[1] = (px>>8)&0xf; pbuf[2] = (px>>4)&0xf; pbuf[3] = px&0xf; } return 0; } #ifndef MAGTOPPM_STANDALONE static int outline_cnt; #endif int outline(pix, n) unsigned char *pix; int n; { int i; #ifndef MAGTOPPM_STANDALONE if (decode_mode == DECODE_XPX) { if (outline_cnt < imgmaxh) { if (n > imgmaxw) n = imgmaxw; memcpy(imgdata+outline_cnt*imgmaxw, pix, n); outline_cnt++; } return 0; } #endif if (binary_mode) { for (i = 0; i < n; i++) { if (pixel_direct) { if (fputc(*pix, stdout) == EOF) return ERR_WRITE; } else { if (fputc(palbuf[*pix*3+1], stdout) == EOF|| fputc(palbuf[*pix*3+0], stdout) == EOF|| fputc(palbuf[*pix*3+2], stdout) == EOF) return ERR_WRITE; } pix++; } } else { char *p, buf[80]; p = buf; for (i = 0; i < n; i++) { if (pixel_direct) sprintf(p, "%d ", *pix); else sprintf(p, "%d %d %d ", palbuf[*pix*3+1], palbuf[*pix*3+0], palbuf[*pix*3+2]); pix++; p += strlen(p); if (strlen(buf) >= (70-4*3)) { *--p = '\n'; if (fputs(buf, stdout) == EOF) return ERR_WRITE; p = buf; *p = '\0'; } } if (strlen(buf)) { *--p = '\n'; if (fputs(buf, stdout) == EOF) return ERR_WRITE; } } return 0; } int pixel_decode_sub(fp) FILE *fp; { int x, y, x2, aspf, dx, r; unsigned char a_bit, *pf, *pa, *pb; unsigned char pbuf[MAX_FILE_X+4]; unsigned char flag_buffer[(MAX_FILE_X+3)/4]; #ifndef MAGTOPPM_STANDALONE outline_cnt = 0; #endif /* pixel data decode */ memset(flag_buffer, 0, sizeof(flag_buffer)); pa = flag_a; pb = flag_b; a_bit=0x80; aspf = hdr.screen_mode & ScreenModeAspectMask; dx = (palcount == 256) ? 2 : 4; for (y = 0; y < datah; y++) { pf = flag_buffer; for (x = x2 = 0; x < dataw; pf++) { if (*pa & a_bit) *pf ^= *pb++; if (!(a_bit >>= 1)) { a_bit = 0x80; pa++; } /* left */ r = DecodePixGroup(fp, pbuf+x, y, x2++, *pf >> 4); if (r) return r; x += dx; /* right */ r = DecodePixGroup(fp, pbuf+x, y, x2++, *pf & 0xf); if (r) return r; x += dx; } r = outline(pbuf, dataw); if (r) return r; if (aspf) { r = outline(pbuf, dataw); if (r) return r; } } return 0; } int dataseek(fp, pos) FILE *fp; long pos; { if (datafpos == pos) return 0; if (datafpos > pos) return 1; while (datafpos < pos) { if (getc(fp) == EOF) return 1; datafpos++; } return 0; } int pixel_decode(fp) FILE *fp; { int r; if (debug_mode) { fprintf(stderr, "flagA offset %ld size %ld\n", hdr.flaga_offset, flaga_size); fprintf(stderr, "flagB offset %ld size %ld\n", hdr.flagb_offset, hdr.flagb_size); fprintf(stderr, "pixel offset %ld size %ld\n", hdr.pixel_offset, hdr.pixel_size); } pix_buffer = (unsigned short*)malloc(sizeof(unsigned short)*16*pixbuf_xsize); flag_a = (unsigned char *)malloc(flaga_size); flag_b = (unsigned char *)malloc(hdr.flagb_size); if (pix_buffer == NULL || flag_a == NULL || flag_b == NULL) return ERR_MORECORE; if (dataseek(fp, hdr.flaga_offset)) return ERR_OFFSETA; if (fread(flag_a, 1, flaga_size, fp) != flaga_size) return ERR_READ; datafpos += flaga_size; if (dataseek(fp, hdr.flagb_offset)) return ERR_OFFSETB; if (fread(flag_b, 1, hdr.flagb_size, fp) != hdr.flagb_size) return ERR_READ; datafpos += hdr.flagb_size; if (dataseek(fp, hdr.pixel_offset)) return ERR_OFFSETP; r = pixel_decode_sub(fp); free(flag_b); free(flag_a); free(pix_buffer); return r; } int decode_mag(fp, filename) FILE *fp; char *filename; { int c, i; int comment_lf; char buf[256]; /* check magic number */ i = strlen(mag_magic_number); if (!fread(buf, i, 1, fp)) return ERR_READ; buf[i] = '\0'; if (strcmp(buf, mag_magic_number)) return ERR_MAGICNUMBER; if (decode_mode != DECODE_XPX) { printf("%s\n", (decode_mode == DECODE_PIXEL) ? (binary_mode ? "P5" : "P2") : (binary_mode ? "P6" : "P3")); printf(pnm_comment_id, my_name, rcsrev); printf(pnm_comment_file, filename); } /* skip comment */ comment_lf = 1; while ((c = fgetc(fp)) != 0x1a) { if (c == EOF) return ERR_READ; if (decode_mode != DECODE_XPX) { if (comment_lf) printf(pnm_comment_memo); if (putchar(c) == EOF) return ERR_WRITE; } comment_lf = c == '\n'; } if (!comment_lf && decode_mode != DECODE_XPX) if (putchar('\n') == EOF) return ERR_WRITE; if (read_mag_header(fp, &hdr)) return ERR_READHEADER; datafpos = 32; if (decode_mode != DECODE_XPX) printf(pnm_comment_position, hdr.topx, hdr.topy, hdr.endx, hdr.endy); flaga_size = hdr.flagb_offset - hdr.flaga_offset; if (hdr.screen_mode & ScreenModeColor256Mask) { #ifndef MAGTOPPM_STANDALONE imgfiledepth = 8; #endif palcount = 256; pixbuf_xsize = MAX_FILE_X/2; } else { #ifndef MAGTOPPM_STANDALONE imgfiledepth = 4; #endif palcount = 16; pixbuf_xsize = MAX_FILE_X/4; } dataw = ((hdr.endx+8)/8)*8 - (hdr.topx/8)*8; datah = hdr.endy - hdr.topy + 1; if (dataw > MAX_FILE_X || datah > MAX_FILE_Y) return ERR_TOOLARGE; if (!fread(palbuf, palcount*3, 1, fp)) return ERR_READ; datafpos += palcount*3; switch (decode_mode) { case DECODE_COLOR: sprintf(buf, "1 %d\n255\n", palcount); if (fputs(buf, stdout) == EOF) return ERR_WRITE; return color_decode(); case DECODE_PIXEL: for (i = 0; i < palcount; i++) printf(pnm_comment_color, i, palbuf[3*i+1], palbuf[3*i], palbuf[3*i+2]); pixel_direct = 1; sprintf(buf, "%d %d\n%d\n", dataw, datah, palcount-1); if (fputs(buf, stdout) == EOF) return ERR_WRITE; break; #ifndef MAGTOPPM_STANDALONE case DECODE_XPX: for (i = 0; i < palcount; i++) { color_buf[i].rgb.red = palbuf[3*i+1]; color_buf[i].rgb.green = palbuf[3*i]; color_buf[i].rgb.blue = palbuf[3*i+2]; } mag_palcnt = palcount; mag_dataw = dataw; mag_datah = datah; imgposx = hdr.topx; imgposy = hdr.topy; break; #endif default: for (i = 0; i < palcount; i++) printf(pnm_comment_color, i, palbuf[3*i+1], palbuf[3*i], palbuf[3*i+2]); pixel_direct = 0; sprintf(buf, "%d %d\n255\n", dataw, datah); if (fputs(buf, stdout) == EOF) return ERR_WRITE; } return pixel_decode(fp); } #ifdef MAGTOPPM_STANDALONE char *get_filename(str) char *str; { char *p, *p1; p = strrchr(str, '/'); if (p == NULL) p = str; else p++; #ifdef __MSDOS__ p1 = p; p = strrchr(p1, '\\'); if (p == NULL) p = p1; else p++; p1 = strrchr(p, '.'); if (p1 != NULL) *p1 = '\0'; #endif return p; } main(argc, argv) char **argv; { int i; FILE *fp; char *inputfile; my_name = get_filename(*argv); while (--argc && **++argv == '-') { switch(*++*argv) { case 'd': debug_mode = 1; break; case 'c': decode_mode = DECODE_COLOR; break; case 'p': decode_mode = DECODE_PIXEL; break; case 'b': binary_mode = 1; break; case 't': binary_mode = 0; break; case 'h': case '?': default: usage(); } } i = 0; if (argc) { --argc; inputfile = *argv++; fp = fopen(inputfile, "r"); if (fp == NULL) i = ERR_NOTFOUND; } else { inputfile = ""; fp = stdin; } #ifdef __MSDOS__ setmode(fileno(fp), O_BINARY); if (binary_mode) setmode(fileno(stdout), O_BINARY); #endif if (!i) i = decode_mag(fp, get_filename(inputfile)); if (i) { fprintf(stderr, " %s: ", my_name); fprintf(stderr, error_message[i], inputfile); } if (fp != NULL) fclose(fp); return i; } #endif /* MAGTOPPM_STANDALONE */ /* End of file */