home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / jpeg2ps2.zip / readjpeg.c < prev    next >
C/C++ Source or Header  |  1997-01-23  |  9KB  |  303 lines

  1. /* ------------------------- readjpeg.c ------------------------- */
  2. #include <stdio.h>
  3. #include "psimage.h"
  4. #include "string.h"
  5. #include "malloc.h"
  6.  
  7. #ifndef DOS
  8. #include <unistd.h>
  9. #endif
  10.  
  11. /* The following enum is stolen from the IJG JPEG library
  12.  * Comments added by tm
  13.  * This table contains far too many names since jpeg2ps
  14.  * is rather simple-minded about markers
  15.  */
  16.  
  17. typedef enum {        /* JPEG marker codes            */
  18.   M_SOF0  = 0xc0,    /* baseline DCT                */
  19.   M_SOF1  = 0xc1,    /* extended sequential DCT        */
  20.   M_SOF2  = 0xc2,    /* progressive DCT            */
  21.   M_SOF3  = 0xc3,    /* lossless (sequential)        */
  22.   
  23.   M_SOF5  = 0xc5,    /* differential sequential DCT        */
  24.   M_SOF6  = 0xc6,    /* differential progressive DCT        */
  25.   M_SOF7  = 0xc7,    /* differential lossless        */
  26.   
  27.   M_JPG   = 0xc8,    /* JPEG extensions            */
  28.   M_SOF9  = 0xc9,    /* extended sequential DCT        */
  29.   M_SOF10 = 0xca,    /* progressive DCT            */
  30.   M_SOF11 = 0xcb,    /* lossless (sequential)        */
  31.   
  32.   M_SOF13 = 0xcd,    /* differential sequential DCT        */
  33.   M_SOF14 = 0xce,    /* differential progressive DCT        */
  34.   M_SOF15 = 0xcf,    /* differential lossless        */
  35.   
  36.   M_DHT   = 0xc4,    /* define Huffman tables        */
  37.   
  38.   M_DAC   = 0xcc,    /* define arithmetic conditioning table    */
  39.   
  40.   M_RST0  = 0xd0,    /* restart                */
  41.   M_RST1  = 0xd1,    /* restart                */
  42.   M_RST2  = 0xd2,    /* restart                */
  43.   M_RST3  = 0xd3,    /* restart                */
  44.   M_RST4  = 0xd4,    /* restart                */
  45.   M_RST5  = 0xd5,    /* restart                */
  46.   M_RST6  = 0xd6,    /* restart                */
  47.   M_RST7  = 0xd7,    /* restart                */
  48.   
  49.   M_SOI   = 0xd8,    /* start of image            */
  50.   M_EOI   = 0xd9,    /* end of image                */
  51.   M_SOS   = 0xda,    /* start of scan            */
  52.   M_DQT   = 0xdb,    /* define quantization tables        */
  53.   M_DNL   = 0xdc,    /* define number of lines        */
  54.   M_DRI   = 0xdd,    /* define restart interval        */
  55.   M_DHP   = 0xde,    /* define hierarchical progression    */
  56.   M_EXP   = 0xdf,    /* expand reference image(s)        */
  57.   
  58.   M_APP0  = 0xe0,    /* application marker, used for JFIF    */
  59.   M_APP1  = 0xe1,    /* application marker            */
  60.   M_APP2  = 0xe2,    /* application marker            */
  61.   M_APP3  = 0xe3,    /* application marker            */
  62.   M_APP4  = 0xe4,    /* application marker            */
  63.   M_APP5  = 0xe5,    /* application marker            */
  64.   M_APP6  = 0xe6,    /* application marker            */
  65.   M_APP7  = 0xe7,    /* application marker            */
  66.   M_APP8  = 0xe8,    /* application marker            */
  67.   M_APP9  = 0xe9,    /* application marker            */
  68.   M_APP10 = 0xea,    /* application marker            */
  69.   M_APP11 = 0xeb,    /* application marker            */
  70.   M_APP12 = 0xec,    /* application marker            */
  71.   M_APP13 = 0xed,    /* application marker            */
  72.   M_APP14 = 0xee,    /* application marker, used by Adobe    */
  73.   M_APP15 = 0xef,    /* application marker            */
  74.   
  75.   M_JPG0  = 0xf0,    /* reserved for JPEG extensions        */
  76.   M_JPG13 = 0xfd,    /* reserved for JPEG extensions        */
  77.   M_COM   = 0xfe,    /* comment                */
  78.   
  79.   M_TEM   = 0x01,    /* temporary use            */
  80.  
  81.   M_ERROR = 0x100    /* dummy marker, internal use only    */
  82. } JPEG_MARKER;
  83.  
  84. /* read two byte parameter, MSB first */
  85. #define get_2bytes(fp) ((unsigned int) (getc(fp) << 8) + getc(fp))
  86.  
  87. static int 
  88. next_marker P1(FILE *, fp)
  89. { /* look for next JPEG Marker  */
  90.   int c, nbytes = 0;
  91.  
  92.   if (feof(fp))
  93.     return M_ERROR;                 /* dummy marker               */
  94.  
  95.   do {
  96.     do {                            /* skip to FF           */
  97.       nbytes++;
  98.       c = getc(fp);
  99.     } while (c != 0xFF);
  100.     do {                            /* skip repeated FFs        */
  101.       c = getc(fp);
  102.     } while (c == 0xFF);
  103.   } while (c == 0);                 /* repeat if FF/00                 */
  104.  
  105.   return c;
  106. }
  107.  
  108. /* analyze JPEG marker */
  109. BOOL AnalyzeJPEG P1(imagedata *, image) {
  110.   int b, c, i, unit;
  111.   unsigned long length;
  112. #define APP_MAX 255
  113.   unsigned char appstring[APP_MAX];
  114.   BOOL SOF_done = FALSE;
  115.  
  116.   /* Tommy's special trick for Macintosh JPEGs: simply skip some  */
  117.   /* hundred bytes at the beginning of the file!          */
  118.   do {
  119.     do {                            /* skip if not FF           */
  120.       c = getc(image->fp);
  121.     } while (!feof(image->fp) && c != 0xFF);
  122.  
  123.     do {                            /* skip repeated FFs       */
  124.       c = getc(image->fp);
  125.     } while (c == 0xFF);
  126.  
  127.     /* remember start position */
  128.     if ((image->startpos = ftell(image->fp)) < 0L) {
  129.       fprintf(stderr, "Error: internal error in ftell()!\n");
  130.       return FALSE;
  131.     }
  132.     image->startpos -= 2;           /* subtract marker length     */
  133.  
  134.     if (c == M_SOI) {
  135.       fseek(image->fp, image->startpos, SEEK_SET);
  136.       break;
  137.     }
  138.   } while (!feof(image->fp));
  139.  
  140.   if (feof(image->fp)) {
  141.     fprintf(stderr, "Error: SOI marker not found!\n");
  142.     return FALSE;
  143.   }
  144.  
  145.   if (image->startpos > 0L) {
  146.     fprintf(stderr, "Note: skipped %ld bytes ", image->startpos);
  147.     fprintf(stderr, "Probably Macintosh JPEG file?\n");
  148.   }
  149.  
  150.   /* process JPEG markers */
  151.   while (!SOF_done && (c = next_marker(image->fp)) != M_EOI) {
  152.     switch (c) {
  153.       case M_ERROR:
  154.     fprintf(stderr, "Error: unexpected end of JPEG file!\n");
  155.     return FALSE;
  156.  
  157.       /* The following are not officially supported in PostScript level 2 */
  158.       case M_SOF2:
  159.       case M_SOF3:
  160.       case M_SOF5:
  161.       case M_SOF6:
  162.       case M_SOF7:
  163.       case M_SOF9:
  164.       case M_SOF10:
  165.       case M_SOF11:
  166.       case M_SOF13:
  167.       case M_SOF14:
  168.       case M_SOF15:
  169.     fprintf(stderr, 
  170.          "Warning: JPEG file uses compression method %X - proceeding anyway.\n",
  171.           c);
  172.         fprintf(stderr, 
  173.         "PostScript output does not work on all PS interpreters!\n");
  174.     /* FALLTHROUGH */
  175.  
  176.       case M_SOF0:
  177.       case M_SOF1:
  178.     length = get_2bytes(image->fp);    /* read segment length  */
  179.  
  180.     image->bits_per_component = getc(image->fp);
  181.     image->height             = get_2bytes(image->fp);
  182.     image->width              = get_2bytes(image->fp);
  183.     image->components         = getc(image->fp);
  184.  
  185.     SOF_done = TRUE;
  186.     break;
  187.  
  188.       case M_APP0:        /* check for JFIF marker with resolution */
  189.     length = get_2bytes(image->fp);
  190.  
  191.     for (i = 0; i < length-2; i++) {    /* get contents of marker */
  192.       b = getc(image->fp);
  193.       if (i < APP_MAX)            /* store marker in appstring */
  194.         appstring[i] = b;
  195.     }
  196.  
  197.     /* Check for JFIF application marker and read density values
  198.      * per JFIF spec version 1.02.
  199.      * We only check X resolution, assuming X and Y resolution are equal.
  200.      * Use values only if resolution not preset by user or to be ignored.
  201.      */
  202.  
  203. #define ASPECT_RATIO    0    /* JFIF unit byte: aspect ratio only */
  204. #define DOTS_PER_INCH    1    /* JFIF unit byte: dots per inch     */
  205. #define DOTS_PER_CM    2    /* JFIF unit byte: dots per cm       */
  206.  
  207.     if (image->dpi == DPI_USE_FILE && length >= 14 &&
  208.         !strncmp("JFIF", appstring, 4)) {
  209.       unit = appstring[7];                /* resolution unit */
  210.                           /* resolution value */
  211.       image->dpi = (appstring[8]<<8) + appstring[9];    
  212.  
  213.       if (image->dpi == 0.0) {
  214.         image->dpi = DPI_USE_FILE;
  215.         break;
  216.       }
  217.  
  218.       switch (unit) {
  219.         /* tell the caller we didn't find a resolution value */
  220.         case ASPECT_RATIO:
  221.           image->dpi = DPI_USE_FILE;
  222.           break;
  223.  
  224.         case DOTS_PER_INCH:
  225.           break;
  226.  
  227.         case DOTS_PER_CM:
  228.           image->dpi *= 2.54;
  229.           break;
  230.  
  231.         default:                /* unknown ==> ignore */
  232.           fprintf(stderr, 
  233.         "Warning: JPEG file contains unknown JFIF resolution unit - ignored!\n");
  234.           image->dpi = DPI_IGNORE;
  235.           break;
  236.       }
  237.     }
  238.         break;
  239.  
  240.       case M_APP14:                /* check for Adobe marker */
  241.     length = get_2bytes(image->fp);
  242.  
  243.     for (i = 0; i < length-2; i++) {    /* get contents of marker */
  244.       b = getc(image->fp);
  245.       if (i < APP_MAX)            /* store marker in appstring */
  246.         appstring[i] = b;
  247.     }
  248.  
  249.     /* Check for Adobe application marker. It is known (per Adobe's TN5116)
  250.      * to contain the string "Adobe" at the start of the APP14 marker.
  251.      */
  252.     if (length >= 12 && !strncmp("Adobe", appstring, 5))
  253.       image->adobe = TRUE;            /* set Adobe flag */
  254.  
  255.     break;
  256.  
  257.       case M_SOI:        /* ignore markers without parameters */
  258.       case M_EOI:
  259.       case M_TEM:
  260.       case M_RST0:
  261.       case M_RST1:
  262.       case M_RST2:
  263.       case M_RST3:
  264.       case M_RST4:
  265.       case M_RST5:
  266.       case M_RST6:
  267.       case M_RST7:
  268.     break;
  269.  
  270.       default:            /* skip variable length markers */
  271.     length = get_2bytes(image->fp);
  272.     for (length -= 2; length > 0; length--)
  273.       (void) getc(image->fp);
  274.     break;
  275.     }
  276.   }
  277.  
  278.   /* do some sanity checks with the parameters */
  279.   if (image->height <= 0 || image->width <= 0 || image->components <= 0) {
  280.     fprintf(stderr, "Error: DNL marker not supported in PostScript Level 2!\n");
  281.     return FALSE;
  282.   }
  283.  
  284.   /* some broken JPEG files have this but they print anyway... */
  285.   if (length != image->components * 3 + 8)
  286.     fprintf(stderr, "Warning: SOF marker has incorrect length - ignored!\n");
  287.  
  288.   if (image->bits_per_component != 8) {
  289.     fprintf(stderr, "Error: %d bits per color component ",
  290.     image->bits_per_component);
  291.     fprintf(stderr, "not supported in PostScript level 2!\n");
  292.     return FALSE;
  293.   }
  294.  
  295.   if (image->components!=1 && image->components!=3 && image->components!=4) {
  296.     fprintf(stderr, "Error: unknown color space (%d components)!\n",
  297.       image->components);
  298.     return FALSE;
  299.   }
  300.  
  301.   return TRUE;
  302. }
  303.