home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / pbm.c < prev    next >
C/C++ Source or Header  |  1993-10-28  |  14KB  |  572 lines

  1. /* pbm.c:
  2.  *
  3.  * portable bit map (pbm) format images
  4.  *
  5.  * jim frost 09.27.89
  6.  *
  7.  * patched by W. David Higgins (wdh@mkt.csd.harris.com) to support
  8.  * raw-format PBM files.
  9.  *
  10.  * patched by Ian MacPhedran (macphed@dvinci.usask.ca) to support
  11.  * PGM and PPM files (03-July-1990)
  12.  */
  13.  
  14. #include "image.h"
  15. #include "pbm.h"
  16.  
  17. /* SUPPRESS 558 */
  18.  
  19. static int          IntTable[256];
  20. static unsigned int Initialized= 0;
  21.  
  22. #define NOTINT  -1
  23. #define COMMENT -2
  24. #define SPACE   -3
  25. #define NEWLINE -4
  26.  
  27. #define BADREAD    0 /* read error */
  28. #define NOTPBM     1 /* not a pbm file */
  29. #define PBMNORMAL  2 /* pbm normal type file */
  30. #define PBMCOMPACT 3 /* pbm compacty type file */
  31. #define PBMRAWBITS 4 /* pbm raw bits type file */
  32. #define PGMNORMAL  5 /* pgm normal type file */
  33. #define PGMRAWBITS 6 /* pgm raw bytes type file */
  34. #define PPMNORMAL  7 /* ppm normal type file */
  35. #define PPMRAWBITS 8 /* ppm raw bytes type file */
  36.  
  37. static void initializeTable()
  38. { unsigned int a;
  39.  
  40.   for (a= 0; a < 256; a++)
  41.     IntTable[a]= NOTINT;
  42.   IntTable['#']= COMMENT;
  43.   IntTable['\n']= NEWLINE;
  44.   IntTable['\r']= IntTable['\t']= IntTable[' ']= SPACE;
  45.   IntTable['0']= 0;
  46.   IntTable['1']= 1;
  47.   IntTable['2']= 2;
  48.   IntTable['3']= 3;
  49.   IntTable['4']= 4;
  50.   IntTable['5']= 5;
  51.   IntTable['6']= 6;
  52.   IntTable['7']= 7;
  53.   IntTable['8']= 8;
  54.   IntTable['9']= 9;
  55.   Initialized= 1;
  56. }
  57.  
  58. static int pbmReadChar(zf)
  59.      ZFILE *zf;
  60. { int c;
  61.  
  62.   if ((c= zgetc(zf)) == EOF) {
  63.     zclose(zf);
  64.     return(-1);
  65.   }
  66.   if (IntTable[c] == COMMENT)
  67.     do {
  68.       if ((c= zgetc(zf)) == EOF)
  69.     return(-1);
  70.     } while (IntTable[c] != NEWLINE);
  71.   return(c);
  72. }
  73.  
  74. static int pbmReadInt(zf)
  75.      ZFILE *zf;
  76. { int c, value;
  77.  
  78.   for (;;) {
  79.     c= pbmReadChar(zf);
  80.     if (c < 0)
  81.       return(-1);
  82.     if (IntTable[c] >= 0)
  83.       break;
  84.   };
  85.  
  86.   value= IntTable[c];
  87.   for (;;) {
  88.     c= pbmReadChar(zf);
  89.     if (c < 0)
  90.       return(-1);
  91.     if (IntTable[c] < 0)
  92.       return(value);
  93.     value= (value * 10) + IntTable[c];
  94.   }
  95. }
  96.  
  97. static int isPBM(zf, name, width, height, maxval, verbose)
  98.      ZFILE        *zf;
  99.      char         *name;
  100.      int          *width, *height, *maxval;
  101.      unsigned int  verbose;
  102. { byte buf[4];
  103.  
  104.   if (! Initialized)
  105.     initializeTable();
  106.  
  107.   if (zread(zf, buf, 2) != 2)
  108.     return(NOTPBM);
  109.   if (memToVal((byte *)buf, 2) == memToVal((byte *)"P1", 2)) {
  110.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  111.       return(NOTPBM);
  112.     *maxval = 1;
  113.     if (verbose)
  114.       printf("%s is a %dx%d PBM image\n", name, *width, *height);
  115.     return(PBMNORMAL);
  116.   }
  117.   if (memToVal((byte *)buf, 2) == memToVal((byte *)"P4", 2)) {
  118.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  119.       return(NOTPBM);
  120.     *maxval = 1;
  121.     if (verbose)
  122.       printf("%s is a %dx%d RawBits PBM image\n", name, *width, *height);
  123.     return(PBMRAWBITS);
  124.   }
  125.   if (memToVal(buf, 2) == 0x2a17) {
  126.     if (zread(zf, buf, 4) != 4)
  127.       return(NOTPBM);
  128.     *width= memToVal((byte *)buf, 2);
  129.     *height= memToVal((byte *)(buf + 2), 2);
  130.     *maxval = 1;
  131.     if (verbose)
  132.       printf("%s is a %dx%d Compact PBM image\n", name, *width, *height);
  133.     return(PBMCOMPACT);
  134.   }
  135.   if (memToVal(buf, 2) == memToVal((byte *)"P2", 2)) {
  136.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  137.       return(NOTPBM);
  138.     *maxval = pbmReadInt(zf);
  139.     if (verbose)
  140.       printf("%s is a %dx%d PGM image with %d levels\n", name, *width,
  141.     *height, (*maxval+1));
  142.     return(PGMNORMAL);
  143.   }
  144.   if (memToVal(buf, 2) == memToVal((byte *)"P5", 2)) {
  145.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  146.       return(NOTPBM);
  147.     *maxval = pbmReadInt(zf);
  148.     if (verbose)
  149.       printf("%s is a %dx%d Raw PGM image with %d levels\n", name, *width,
  150.     *height, (*maxval+1));
  151.     return(PGMRAWBITS);
  152.   }
  153.   if (memToVal(buf, 2) == memToVal((byte *)"P3", 2)) {
  154.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  155.       return(NOTPBM);
  156.     *maxval = pbmReadInt(zf);
  157.     if (verbose)
  158.       printf("%s is a %dx%d PPM image with %d levels\n", name, *width,
  159.     *height, (*maxval+1));
  160.     return(PPMNORMAL);
  161.   }
  162.   if (memToVal(buf, 2) == memToVal((byte *)"P6", 2)) {
  163.     if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
  164.       return(NOTPBM);
  165.     *maxval = pbmReadInt(zf);
  166.     if (verbose)
  167.       printf("%s is a %dx%d Raw PPM image with %d levels\n", name, *width,
  168.     *height, (*maxval+1));
  169.     return(PPMRAWBITS);
  170.   }
  171.   return(NOTPBM);
  172. }
  173.  
  174. int pbmIdent(fullname, name)
  175.      char *fullname, *name;
  176. { ZFILE *zf;
  177.   int    width, height, maxval, ret;
  178.  
  179.   if (! (zf= zopen(fullname)))
  180.     return(0);
  181.  
  182.   ret= isPBM(zf, name, &width, &height, &maxval, (unsigned int)1);
  183.   zclose(zf);
  184.   return(ret != NOTPBM);
  185. }
  186.  
  187. Image *pbmLoad(fullname, name, verbose)
  188.      char         *fullname, *name;
  189.      unsigned int  verbose;
  190. { ZFILE        *zf;
  191.   Image        *image;
  192.   int           pbm_type;
  193.   int           x, y;
  194.   int           width, height, maxval, depth;
  195.   unsigned int  linelen;
  196.   byte          srcmask, destmask;
  197.   byte         *destptr, *destline;
  198.   int           src, size;
  199.   int           red, grn, blu;
  200.  
  201.   if (! (zf= zopen(fullname)))
  202.     return(NULL);
  203.  
  204.   pbm_type= isPBM(zf, name, &width, &height, &maxval, verbose);
  205.   if (pbm_type == NOTPBM) {
  206.     zclose(zf);
  207.     return(NULL);
  208.   }
  209.   znocache(zf);
  210.   switch (pbm_type) {
  211.   case PBMNORMAL:
  212.     image= newBitImage(width, height);
  213.     linelen= (width / 8) + (width % 8 ? 1 : 0);
  214.     destline= image->data;
  215.     for (y= 0; y < height; y++) {
  216.       destptr= destline;
  217.       destmask= 0x80;
  218.       for (x= 0; x < width; x++) {
  219.     do {
  220.       if ((src= pbmReadChar(zf)) < 0) {
  221.         fprintf(stderr, "%s: Short image\n", fullname);
  222.         zclose(zf);
  223.         return(image);
  224.       }
  225.       if (IntTable[src] == NOTINT) {
  226.         fprintf(stderr, "%s: Bad image data\n", fullname);
  227.         zclose(zf);
  228.         return(image);
  229.       }
  230.     } while (IntTable[src] < 0);
  231.     
  232.     switch (IntTable[src]) {
  233.     case 1:
  234.       *destptr |= destmask;
  235.     case 0:
  236.       if (! (destmask >>= 1)) {
  237.         destmask= 0x80;
  238.         destptr++;
  239.       }
  240.       break;
  241.     default:
  242.       fprintf(stderr, "%s: Bad image data\n", fullname);
  243.       zclose(zf);
  244.       return(image);
  245.     }
  246.       }
  247.       destline += linelen;
  248.     }
  249.     break;
  250.  
  251.   case PBMRAWBITS:
  252.     image= newBitImage(width, height);
  253.     destline= image->data;
  254.     linelen= (width + 7) / 8;
  255.     srcmask= 0;        /* force initial read */
  256.     for (y= 0; y < height; y++) {
  257.       destptr= destline;
  258.       destmask= 0x80;
  259.       if (srcmask != 0x80) {
  260.         srcmask= 0x80;
  261.     src= zgetc(zf);
  262.     if (src == EOF) {
  263.       fprintf(stderr, "%s: Short image\n", fullname);
  264.       zclose(zf);
  265.       return(image);
  266.     }
  267.       }
  268.       for (x= 0; x < width; x++) {
  269.     if (src & srcmask)
  270.       *destptr |= destmask;
  271.     if (! (destmask >>= 1)) {
  272.       destmask= 0x80;
  273.       destptr++;
  274.     }
  275.     if (! (srcmask >>= 1)) {
  276.       srcmask= 0x80;
  277.       src = zgetc(zf);
  278.       if (src == EOF) {
  279.         fprintf(stderr, "%s: Short image\n", fullname);
  280.         zclose(zf);
  281.         return(image);
  282.       }
  283.     }
  284.       }
  285.       destline += linelen;
  286.     }
  287.     break;
  288.  
  289.   case PBMCOMPACT:
  290.     image= newBitImage(width, height);
  291.     destline= image->data;
  292.     linelen= (width / 8) + (width % 8 ? 1 : 0);
  293.     srcmask= 0x80;
  294.     destmask= 0x80;
  295.     src = zgetc(zf);
  296.     if (src == EOF) {
  297.       fprintf(stderr, "%s: Short image\n", fullname);
  298.       zclose(zf);
  299.       return(image);
  300.     }
  301.     for (y= 0; y < height; y++) {
  302.       destptr= destline;
  303.       destmask= 0x80;
  304.       for (x= 0; x < width; x++) {
  305.     if (src & srcmask)
  306.       *destptr |= destmask;
  307.     if (! (destmask >>= 1)) {
  308.       destmask= 0x80;
  309.       destptr++;
  310.     }
  311.     if (! (srcmask >>= 1)) {
  312.       srcmask= 0x80;
  313.       src = zgetc(zf);
  314.       if (src == EOF) {
  315.         fprintf(stderr, "%s: Short image\n", fullname);
  316.         zclose(zf);
  317.         return(image);
  318.       }
  319.     }
  320.       }
  321.       destline += linelen;
  322.     }
  323.     break;
  324.   case PGMRAWBITS:
  325.     depth= colorsToDepth(maxval);
  326.     if (depth > 8)
  327.       image = newTrueImage(width, height);
  328.     else {
  329.       image = newRGBImage(width, height, depth);
  330.       for (y = 0; y <= maxval; y++)
  331.     { /* As in sunraster.c, use simple ramp for grey scale */
  332.       *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff);
  333.       *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff);
  334.       *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff);
  335.     }
  336.       image->rgb.used = maxval+1;
  337.     }
  338.     size= height * width;
  339.  
  340.     switch (image->type) {
  341.     case IRGB:
  342.  
  343.       /* read in the image in a chunk
  344.        */
  345.  
  346.       if (zread(zf, image->data, size) != size) {
  347.     fprintf(stderr, "%s: Short image\n", fullname);
  348.     zclose(zf);
  349.     freeImage(image);
  350.     return(NULL);
  351.       }
  352.       break;
  353.  
  354.     case ITRUE:
  355.       destptr = image->data;
  356.       for (y = 0; y < size; y++) {
  357.     if ((src = zgetc(zf)) == EOF) {
  358.       fprintf(stderr, "%s: Short image\n", fullname);
  359.       zclose(zf);
  360.       freeImage(image);
  361.       return(NULL);
  362.     }
  363.     src = PM_SCALE(src, maxval, 0xff);
  364.     *(destptr++) = src; /* red */
  365.     *(destptr++) = src; /* green */
  366.     *(destptr++) = src; /* blue */
  367.       }
  368.       break;
  369.     }
  370.     break;
  371.   case PGMNORMAL:
  372.     depth= colorsToDepth(maxval);
  373.     if (depth > 8)
  374.       image= newTrueImage(width, height);
  375.     else {
  376.       image= newRGBImage(width, height, depth);
  377.       for (y= 0; y <= maxval; y++)
  378.     { /* As in sunraster.c, use simple ramp for grey scale */
  379.       *(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff);
  380.       *(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff);
  381.       *(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff);
  382.     }
  383.       image->rgb.used = maxval+1;
  384.     }
  385.     destptr= image->data;
  386.     size= height * width;
  387.     for (y= 0; y < size; y++) {
  388.       if ((src = pbmReadInt(zf)) < 0)
  389.     {
  390.       fprintf(stderr, "%s: Short image\n", fullname);
  391.       zclose(zf);
  392.       return(image);
  393.     }
  394.       else {
  395.     if (TRUEP(image)) {
  396.       src= PM_SCALE(src, maxval, 0xff);
  397.       *(destptr++) = src; /* red */
  398.       *(destptr++) = src; /* green */
  399.       *(destptr++) = src; /* blue */
  400.     }
  401.     else
  402.       *(destptr++) = src;
  403.       }
  404.     }
  405.     break;
  406.  
  407.   case PPMRAWBITS:
  408.  
  409.     /* this is nice because the bit format is exactly what we want except
  410.      * for scaling.
  411.      */
  412.  
  413.     image= newTrueImage(width, height);
  414.     size= height * width * 3;
  415.     if (zread(zf, image->data, size) != size) {
  416.       fprintf(stderr, "%s: Short image\n", fullname);
  417.       zclose(zf);
  418.       freeImage(image);
  419.       return(NULL);
  420.     }
  421.     destptr= image->data;
  422.     for (y= 0; y < size; y++) {
  423.       *destptr= PM_SCALE(*destptr, maxval, 0xff);
  424.       destptr++;
  425.     }
  426.     break;
  427.   case PPMNORMAL:
  428.     image= newTrueImage(width, height);
  429.     size= height * width;
  430.     destptr= image->data;
  431.     for (y= 0; y < size; y++) {
  432.       if (((red= pbmReadInt(zf)) == EOF) ||
  433.       ((grn= pbmReadInt(zf)) == EOF) ||
  434.       ((blu= pbmReadInt(zf)) == EOF))
  435.     {
  436.       fprintf(stderr, "%s: Short image\n", fullname);
  437.       zclose(zf);
  438.       return(image);
  439.     }
  440.       *(destptr++)= PM_SCALE(red, maxval, 0xff);
  441.       *(destptr++)= PM_SCALE(grn, maxval, 0xff);
  442.       *(destptr++)= PM_SCALE(blu, maxval, 0xff);
  443.     }
  444.     break;
  445.   }
  446.   image->title= dupString(name);
  447.   zclose(zf);
  448.   return(image);
  449. }
  450.  
  451. void pbmDump(image, options, file, verbose)
  452.      Image *image;
  453.      char *options;
  454.      char *file;
  455.      int verbose;
  456. {
  457.   FILE *f;
  458.   byte *srcptr;
  459.   int srclinelen;
  460.   int x, y;
  461.   int normal = 0; /* raw by default */
  462.   int white, black;
  463.   int mask;
  464.   Pixel pixval;
  465.   int pixlen;
  466.   char *name, *value;
  467.  
  468.   while (getNextTypeOption(&options, &name, &value) > 0) {
  469.     if (!strncmp("normal", name, strlen(name)))
  470.       normal = 1;
  471.     else if (!strncmp("raw", name, strlen(name)))
  472.       normal = 0;
  473.     else
  474.       fprintf(stderr, "pbmDump: unknown option '%s'\n", name);
  475.   }
  476.  
  477.   f = fopen(file, "w");
  478.   if (f == NULL) {
  479.     perror(file);
  480.     return;
  481.   }
  482.  
  483.   srcptr = image->data;
  484.   switch (image->type) {
  485.   case IBITMAP:
  486.     if (verbose)
  487.       printf("Dumping %sPBM image to %s.\n", (normal ? "" : "RawBits "),
  488.          file);
  489.     if (image->rgb.red[1] > image->rgb.red[0]) {
  490.       white = 1;
  491.       black = 0;
  492.     }
  493.     else {
  494.       white = 0;
  495.       black = 1;
  496.     }
  497.     if (normal) {
  498.       fprintf(f, "P1 %d %d\n", image->width, image->height);
  499.       mask = 0x80;
  500.       for (y = 0; y < image->height; y++) {
  501.     for (x = 0; x < image->width; x++) {
  502.       fprintf(f, "%d ", (*srcptr & mask ? black : white));
  503.       mask >>= 1;
  504.       if (mask == 0) {
  505.         mask = 0x80;
  506.         srcptr++;
  507.       }
  508.     }
  509.       }
  510.     }
  511.     else {
  512.       srclinelen = (image->width / 8) + (image->width % 8 ? 1 : 0);
  513.       fprintf(f, "P4 %d %d\n", image->width, image->height);
  514.       for (y = 0; y < image->height; y++) {
  515.     if (black == 1) {
  516.       fwrite(srcptr, srclinelen, 1, f);
  517.       srcptr += srclinelen;
  518.     }
  519.     else
  520.       for (x = 0; x < image->width; x++)
  521.         fputc(*(srcptr++) ^ 0xff, f);
  522.       }
  523.     }
  524.     break;
  525.   case IRGB:
  526.     if (verbose)
  527.       printf("Dumping %sPPM image to %s.\n", (normal ? "" : "RawBits "),
  528.          file);
  529.  
  530.     /* technically we could dump this with 2-byte values but that's
  531.      * a lot bigger and most of the readers don't support it anyway.
  532.      */
  533.     fprintf(f, "P%c %d %d 255\n", (normal ? '3' : '6'),
  534.         image->width, image->height);
  535.     pixlen = image->pixlen;
  536.     for (y = 0; y < image->height; y++) {
  537.       for (x = 0; x < image->width; x++) {
  538.     pixval = memToVal(srcptr, pixlen);
  539.     srcptr += pixlen;
  540.     fprintf(f, (normal ? "%d %d %d " : "%c%c%c"),
  541.         image->rgb.red[pixval] >> 8,
  542.         image->rgb.green[pixval] >> 8,
  543.         image->rgb.blue[pixval] >> 8);
  544.       }
  545.     }
  546.     break;
  547.   case ITRUE:
  548.     if (verbose)
  549.       printf("Dumping %sPPM image to %s.\n", (normal ? "" : "RawBits "),
  550.          file);
  551.     fprintf(f, "P%c %d %d 257\n", (normal ? '3' : '6'),
  552.         image->width, image->height);
  553.     for (y = 0; y < image->height; y++) {
  554.       for (x = 0; x < image->width; x++) {
  555.     if (normal) {
  556.       fprintf(f, "%d %d %d ", *srcptr,
  557.           *(srcptr + 1),
  558.           *(srcptr + 2));
  559.       srcptr += 3;
  560.     }
  561.     else {
  562.       fputc(*(srcptr++), f);
  563.       fputc(*(srcptr++), f);
  564.       fputc(*(srcptr++), f);
  565.     }
  566.       }
  567.     }
  568.     break;
  569.   }
  570.   fclose(f);
  571. }
  572.