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

  1. /* --------------------------------------------------------------------
  2.  * jpeg2ps: convert JPEG files to compressed PostScript Level 2 EPS
  3.  *
  4.  * (C) 1994-97 Thomas Merz 
  5.  *
  6.  * 1.0  Dec. 94  first public release
  7.  *
  8.  * 1.1  Jan. 95  Several improvements:
  9.  *               - invert color components for Adobe Photoshop CMYK
  10.  *                 files; check APP14 marker to detect Adobe files.
  11.  *               - process SOF2-SOF15 compression markers; print
  12.  *                 warning because these are not guaranteed to work
  13.  *                 in all PostScript Level 2 interpreters.
  14.  *                 Files with compression types other than SOF0 and 
  15.  *                 SOF1 have not really been tested yet.
  16.  *               - Look for JFIF marker APP0 and use resolution
  17.  *                 values, if any.
  18.  * 1.2  Jan. 96  Fixed "unsigned" bug when reading JFIF density 
  19.  *         marker
  20.  * 1.3  Jan. 96  Fixed bug in ASCII85 encoding (asc85ec.c). The
  21.  *               ASCII85 EOF markers ~> could get separated in
  22.  *               rare cases.
  23.  * 1.4  Aug. 96  - included getopt.c in distribution, changed option 
  24.  *           handling
  25.  *         - prepared readjpeg.c for use with jpeg2pdf program
  26.  * 1.5  Jan. 97  - Added ASCIIHex encoding (again). This is necessary
  27.  *                 for buggy dvips files (dvips strips lines beginning
  28.  *                 with %% from EPS data sections!)
  29.  *               - Removed jpeg2pdf again
  30.  * ------------------------------------------------------------------*/
  31.  
  32. #define VERSION        "V1.5"
  33.  
  34. #include <stdio.h>
  35. #include <time.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38.  
  39. #ifdef DOS
  40. #include <dos.h>
  41. #include <io.h>
  42. #include <fcntl.h>
  43. #else
  44. #include <unistd.h>
  45. #endif
  46.  
  47. #include "psimage.h"
  48.  
  49. #ifdef DOS
  50. #define READMODE "rb"           /* read JPEG files in binary mode */
  51. #else
  52. #define READMODE "r"
  53. #endif
  54.  
  55. #ifdef A4
  56. int PageHeight = 842;           /* a4 page */
  57. int PageWidth  = 595;           /* a4 page */
  58. #else
  59. int PageHeight = 792;           /* letter page */
  60. int PageWidth  = 612;           /* letter page */
  61. #endif
  62.  
  63. int Margin     = 20;            /* safety margin */
  64.  
  65. extern BOOL    AnalyzeJPEG P1(imagedata *, image);
  66. extern int    ASCII85Encode P2(FILE *, in, FILE *, out);
  67. extern void     ASCIIHexEncode P2(FILE *, in, FILE *, out);
  68.  
  69. #ifdef DOS
  70. extern int      getopt P3(int, nargc, char **, nargv, char *, ostr);
  71. #endif
  72.  
  73. #define BUFFERSIZE 1024
  74. static char buffer[BUFFERSIZE];
  75. static char *ColorSpaceNames[] = {"", "Gray", "", "RGB", "CMYK" };
  76.  
  77. static void 
  78. JPEGtoPS P2(imagedata *, JPEG, FILE *, PSfile) {
  79.   int llx, lly, urx, ury;        /* Bounding box coordinates */
  80.   size_t n;
  81.   float scale, sx, sy;           /* scale factors            */
  82.   time_t t;
  83.   int i;
  84.  
  85.   /* read image parameters and fill JPEG struct*/
  86.   if (!AnalyzeJPEG(JPEG)) {
  87.     fprintf(stderr, "Error: '%s' is not a proper JPEG file!\n", JPEG->filename);
  88.     return;
  89.   }
  90.  
  91.   fprintf(stderr, "Note on file '%s': %dx%d pixel, %d color component%s\n",
  92.     JPEG->filename, JPEG->width, JPEG->height, JPEG->components,
  93.     (JPEG->components == 1 ? "" : "s"));
  94.  
  95.   /* "Use resolution from file" was requested, but we couldn't find any */
  96.   if (JPEG->dpi == DPI_USE_FILE) { 
  97.     fprintf(stderr, "Note: no resolution values found in JPEG file - using standard scaling.\n");
  98.     JPEG->dpi = DPI_IGNORE;
  99.   }
  100.  
  101.   if (JPEG->dpi == DPI_IGNORE) {
  102.     if (JPEG->width > JPEG->height) {    /* switch to landscape if needed */
  103.       JPEG->landscape = TRUE;
  104.       fprintf(stderr, 
  105.           "Note: image width exceeds height - producing landscape output!\n");
  106.     }
  107.     if (!JPEG->landscape) {       /* calculate scaling factors */
  108.       sx = (float) (PageWidth - 2*Margin) / JPEG->width;
  109.       sy = (float) (PageHeight - 2*Margin) / JPEG->height;
  110.     }else {
  111.       sx = (float) (PageHeight - 2*Margin) / JPEG->width;
  112.       sy = (float) (PageWidth - 2*Margin) / JPEG->height;
  113.     }
  114.     scale = min(sx, sy);    /* We use at least one edge of the page */
  115.   } else {
  116.     fprintf(stderr, "Note: Using resolution %d dpi.\n", (int) JPEG->dpi);
  117.     scale = 72 / JPEG->dpi;     /* use given image resolution */
  118.   }
  119.  
  120.   if (JPEG->landscape) {
  121.     /* landscape: move to (urx, lly) */
  122.     urx = PageWidth - Margin;
  123.     lly = Margin;
  124.     ury = (int) (Margin + scale*JPEG->width + 0.9);    /* ceiling */
  125.     llx = (int) (urx - scale * JPEG->height);          /* floor  */
  126.   }else {
  127.     /* portrait: move to (llx, lly) */
  128.     llx = lly = Margin;
  129.     urx = (int) (llx + scale * JPEG->width + 0.9);     /* ceiling */
  130.     ury = (int) (lly + scale * JPEG->height + 0.9);    /* ceiling */
  131.   }
  132.  
  133.   time(&t);
  134.  
  135.   /* produce EPS header comments */
  136.   fprintf(PSfile, "%%!PS-Adobe-3.0 EPSF-3.0\n");
  137.   fprintf(PSfile, "%%%%Creator: jpeg2ps %s by Thomas Merz\n", VERSION);
  138.   fprintf(PSfile, "%%%%Title: %s\n", JPEG->filename);
  139.   fprintf(PSfile, "%%%%CreationDate: %s", ctime(&t));
  140.   fprintf(PSfile, "%%%%BoundingBox: %d %d %d %d\n", 
  141.                    llx, lly, urx, ury);
  142.   fprintf(PSfile, "%%%%DocumentData: %s\n", 
  143.                   JPEG->mode == BINARY ? "Binary" : "Clean7Bit");
  144.   fprintf(PSfile, "%%%%LanguageLevel: 2\n");
  145.   fprintf(PSfile, "%%%%EndComments\n");
  146.   fprintf(PSfile, "%%%%BeginProlog\n");
  147.   fprintf(PSfile, "%%%%EndProlog\n");
  148.   fprintf(PSfile, "%%%%Page: 1 1\n");
  149.  
  150.   fprintf(PSfile, "/languagelevel where {pop languagelevel 2 lt}");
  151.   fprintf(PSfile, "{true} ifelse {\n");
  152.   fprintf(PSfile, "  (JPEG file '%s' needs PostScript Level 2!",
  153.                   JPEG->filename);
  154.   fprintf(PSfile, "\\n) dup print flush\n");
  155.   fprintf(PSfile, "  /Helvetica findfont 20 scalefont setfont ");
  156.   fprintf(PSfile, "100 100 moveto show showpage stop\n");
  157.   fprintf(PSfile, "} if\n");
  158.  
  159.   fprintf(PSfile, "save\n");
  160.   fprintf(PSfile, "/RawData currentfile ");
  161.  
  162.   if (JPEG->mode == ASCIIHEX)            /* hex representation... */
  163.     fprintf(PSfile, "/ASCIIHexDecode filter ");
  164.   else if (JPEG->mode == ASCII85)        /* ...or ASCII85         */
  165.     fprintf(PSfile, "/ASCII85Decode filter ");
  166.   /* else binary mode: don't use any additional filter! */
  167.  
  168.   fprintf(PSfile, "def\n");
  169.  
  170.   fprintf(PSfile, "/Data RawData << ");
  171.   fprintf(PSfile, ">> /DCTDecode filter def\n");
  172.  
  173.   /* translate to lower left corner of image */
  174.   fprintf(PSfile, "%d %d translate\n", (JPEG->landscape ? 
  175.                    PageWidth - Margin : Margin), Margin);
  176.  
  177.   if (JPEG->landscape)                 /* rotation for landscape */
  178.     fprintf(PSfile, "90 rotate\n");
  179.       
  180.   fprintf(PSfile, "%.2f %.2f scale\n", /* scaling */
  181.                    JPEG->width * scale, JPEG->height * scale);
  182.   fprintf(PSfile, "/Device%s setcolorspace\n", 
  183.                   ColorSpaceNames[JPEG->components]);
  184.   fprintf(PSfile, "{ << /ImageType 1\n");
  185.   fprintf(PSfile, "     /Width %d\n", JPEG->width);
  186.   fprintf(PSfile, "     /Height %d\n", JPEG->height);
  187.   fprintf(PSfile, "     /ImageMatrix [ %d 0 0 %d 0 %d ]\n",
  188.                   JPEG->width, -JPEG->height, JPEG->height);
  189.   fprintf(PSfile, "     /DataSource Data\n");
  190.   fprintf(PSfile, "     /BitsPerComponent %d\n", 
  191.                   JPEG->bits_per_component);
  192.  
  193.   /* workaround for color-inverted CMYK files produced by Adobe Photoshop:
  194.    * compensate for the color inversion in the PostScript code
  195.    */
  196.   if (JPEG->adobe && JPEG->components == 4) {
  197.     fprintf(stderr, "Note: Adobe-conforming CMYK file - applying workaround for color inversion.\n");
  198.     fprintf(PSfile, "     /Decode [1 0 1 0 1 0 1 0]\n");
  199.   }else {
  200.     fprintf(PSfile, "     /Decode [0 1");
  201.     for (i = 1; i < JPEG->components; i++) 
  202.       fprintf(PSfile," 0 1");
  203.     fprintf(PSfile, "]\n");
  204.   }
  205.  
  206.   fprintf(PSfile, "  >> image\n");
  207.   fprintf(PSfile, "  Data closefile\n");
  208.   fprintf(PSfile, "  RawData flushfile\n");
  209.   fprintf(PSfile, "  showpage\n");
  210.   fprintf(PSfile, "  restore\n");
  211.   fprintf(PSfile, "} exec");
  212.  
  213.   /* seek to start position of JPEG data */
  214.   fseek(JPEG->fp, JPEG->startpos, SEEK_SET);
  215.  
  216.   switch (JPEG->mode) {
  217.   case BINARY:
  218.     /* important: ONE blank and NO newline */
  219.     fprintf(PSfile, " ");
  220. #ifdef DOS
  221.     fflush(PSfile);               /* up to now we have CR/NL mapping */
  222.     setmode(fileno(PSfile), O_BINARY);    /* continue in binary mode */
  223. #endif
  224.     /* copy data without change */
  225.     while ((n = fread(buffer, 1, sizeof(buffer), JPEG->fp)) != 0)
  226.       fwrite(buffer, 1, n, PSfile);
  227. #ifdef DOS
  228.     fflush(PSfile);                      /* binary yet */
  229.     setmode(fileno(PSfile), O_TEXT);    /* text mode */
  230. #endif
  231.     break;
  232.  
  233.   case ASCII85:
  234.     fprintf(PSfile, "\n");
  235.  
  236.     /* ASCII85 representation of image data */
  237.     if (ASCII85Encode(JPEG->fp, PSfile)) {
  238.       fprintf(stderr, "Error: internal problems with ASCII85Encode!\n");
  239.       exit(1);
  240.     }
  241.     break;
  242.  
  243.   case ASCIIHEX:
  244.     /* hex representation of image data (useful for buggy dvips) */
  245.     ASCIIHexEncode(JPEG->fp, PSfile);
  246.     break;
  247.   }
  248.   fprintf(PSfile, "\n%%%%EOF\n");
  249. }
  250.  
  251. static
  252. void usage P0(void) {
  253.   fprintf(stderr, "jpeg2ps %s: convert JPEG files to PostScript Level 2. ",
  254.            VERSION);
  255.   fprintf(stderr, "(C) Thomas Merz 1994-97\n\n");
  256.   fprintf(stderr, "usage: jpeg2ps [-b] [-h] [-r] jpegfile > epsfile\n");
  257.   fprintf(stderr, "-b        binary mode: output 8 bit data (default: 7 bit with ASCII85)\n");
  258.   fprintf(stderr, "-h        hex mode: output 7 bit data in ASCIIHex encoding\n");
  259.   fprintf(stderr, "-o name   output file name\n");
  260.   fprintf(stderr, "-r <dpi>  resolution value (dots per inch)\n");
  261.   fprintf(stderr, "          0 means use value given in file (if any)\n");
  262.   exit(1);
  263. }
  264.  
  265. int
  266. main P2(int, argc, char **, argv) {
  267.   int opt;
  268.   char *arg;
  269.   imagedata image;
  270.   FILE *outfile = stdout;
  271.   extern char *optarg;
  272.   extern int optind;
  273.  
  274.   image.filename = NULL;
  275.   image.mode     = ASCII85;
  276.   image.startpos = 0L;
  277.   image.landscape= FALSE;
  278.   image.dpi      = DPI_IGNORE;
  279.   image.adobe    = FALSE;
  280.  
  281.   while ((opt = getopt(argc, argv, "bho:r:")) != -1)
  282.     switch (opt) {
  283.       case 'b':
  284.       image.mode = BINARY;
  285.       break;
  286.       case 'h':
  287.       image.mode = ASCIIHEX;
  288.       break;
  289.       case 'o':
  290.       outfile = fopen(optarg, "w");
  291.       if (outfile == NULL) {
  292.         fprintf(stderr, "Error: cannot open output file %s.\n", optarg);
  293.         exit(-2);
  294.       } 
  295.       break;
  296.       case 'r':
  297.       image.dpi = atof(optarg);
  298.       if (image.dpi < 0) {
  299.         fprintf(stderr, "Error: bad resolution value %f !\n", image.dpi);
  300.         exit(1);
  301.       }
  302.       break;
  303.       case '?':
  304.       usage();
  305.     }
  306.  
  307.   if (optind == argc)    /* filename missing */
  308.     usage();
  309.   else
  310.     image.filename = argv[optind];
  311.  
  312.   if (!image.filename)
  313.     usage();
  314.  
  315.   if ((image.fp = fopen(image.filename, READMODE)) == NULL) {
  316.     fprintf(stderr, "Error: couldn't read JPEG file '%s'!\n", 
  317.       image.filename),
  318.     exit(1);
  319.   }
  320.  
  321.   JPEGtoPS(&image, outfile);      /* convert JPEG data */
  322.   return 0;
  323. }
  324.  
  325.