home *** CD-ROM | disk | FTP | other *** search
/ swCHIP 1991 January / swCHIP_95-1.bin / utility / gsview13 / epstool / epstool.c next >
C/C++ Source or Header  |  1995-12-09  |  16KB  |  602 lines

  1. /* Copyright (C) 1993, 1994, Russell Lang.  All rights reserved.
  2.   
  3.   This file is part of GSview.
  4.   
  5.   This program is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the GSview Free Public Licence 
  9.   (the "Licence") for full details.
  10.   
  11.   Every copy of GSview must include a copy of the Licence, normally in a 
  12.   plain ASCII text file named LICENCE.  The Licence grants you the right 
  13.   to copy, modify and redistribute GSview, but only under certain conditions 
  14.   described in the Licence.  Among other things, the Licence requires that 
  15.   the copyright notice and this notice be preserved on all copies.
  16. */
  17.  
  18. /* epstool.c */
  19. #include "epstool.h"
  20.  
  21. char iname[MAXSTR];
  22. char oname[MAXSTR];
  23. char gsname[MAXSTR] = GSCOMMAND;
  24. char bmpname[MAXSTR];
  25. char szScratch[] = "ep";
  26. char szAppName[] = "epstool";
  27. char szVersion[] = "0.2 alpha 1995-04-26";
  28. int resolution = 72;
  29. int page = 1;    /* default is page 1 */
  30. BOOL calc_bbox = FALSE;
  31. BOOL got_op = FALSE;
  32. BOOL debug = FALSE;
  33. int op = 0;
  34. #define EXTRACTPS    1
  35. #define EXTRACTPRE    2
  36. #define INTERCHANGE    3
  37. #define TIFF4         4
  38. #define TIFF5        5
  39.  
  40. /* KLUDGE variables */
  41. PSDOC *doc;
  42. PSFILE psfile;
  43. OPTION option;
  44. char GVFAR *bitmap_base;
  45. LPBITMAP2 bitmap_pbmi;
  46.  
  47. /* function prototypes */
  48. BOOL load_bitmap(void);
  49. int scan_args(int argc, char *argv[]);
  50. void do_help(void);
  51. int extract_section(void);
  52. int add_preview(void);
  53. void psfile_extract_header(FILE *f);
  54. void psfile_extract_page(FILE *f, int page);
  55.  
  56. /* KLUDGE functions */
  57. LPBITMAP2 get_bitmap(void)
  58. {
  59.     return bitmap_pbmi;
  60. }
  61. void release_bitmap(void)
  62. {
  63. }
  64. void play_sound(int i)
  65. {
  66. }
  67.  
  68.  
  69. int
  70. main(int argc, char *argv[])
  71. {
  72.     if (scan_args(argc, argv))
  73.        return 1;
  74.  
  75.     if (calc_bbox && op!=INTERCHANGE) {
  76.        fprintf(stderr, "Calculation of bbox only works for interchange preview\n");
  77.     }
  78.  
  79.     strcpy(psfile.name, iname);
  80.     if ((psfile.file = fopen(psfile.name, READBIN)) == (FILE *)NULL) {
  81.        fprintf(stderr, "Can't open %s\n", psfile.name);
  82.        return 1;
  83.     }
  84.     doc = psscan(psfile.file);
  85.     if (doc == (PSDOC *)NULL) {
  86.        fprintf(stderr, "File %s does not contain DSC comments\n", psfile.file);
  87.        fclose(psfile.file);
  88.        return 1;
  89.     }
  90.  
  91.     if (op==INTERCHANGE || op==TIFF4 || op==TIFF5)
  92.        return add_preview();
  93.     if (op==EXTRACTPS || op==EXTRACTPRE)
  94.        return extract_section();
  95.  
  96.     psfree(doc);
  97.     return 0;
  98. }
  99.  
  100. int
  101. extract_section(void)
  102. {
  103.     if (op == EXTRACTPS)
  104.         extract_doseps(IDM_EXTRACTPS);
  105.     else if (op == EXTRACTPRE)
  106.         extract_doseps(IDM_EXTRACTPRE);
  107.     else
  108.       fprintf(stderr, "Unknown operation %d\n", op);
  109.     return 0;
  110. }
  111.  
  112. int
  113. add_preview(void)
  114. {
  115. char ename[MAXSTR];
  116. char tempname[MAXSTR];
  117. FILE *tempfile;
  118. FILE *bmpfile;
  119. char gscommand[MAXSTR+MAXSTR];
  120. int width, height;
  121.     if ( !calc_bbox &&
  122.              ((doc->boundingbox[URX] == doc->boundingbox[LLX]) ||
  123.           (doc->boundingbox[URY] == doc->boundingbox[LLY])) ) {
  124.        fprintf(stderr, "Bounding Box is empty");
  125.        return 1;
  126.        /* if calc_bbox, this shouldn't be an error */
  127.     }
  128.     if (doc->numpages==0) {
  129.         fprintf(stderr, "\nFile %s does not contain any pages\n", psfile.name);
  130.         return 1;
  131.     }
  132.         if (doc->numpages > 1) {
  133.         /* create temporary file to hold extracted page */
  134.         tempfile = gp_open_scratch_file(szScratch, ename, WRITEBIN);
  135.         if (tempfile == (FILE *)NULL) {
  136.             fprintf(stderr, "Couldn't open temporary file %s\n", ename);
  137.             return 1;
  138.         }
  139.         /* copy page to new file */
  140.         psfile_extract_header(tempfile);
  141.         psfile_extract_page(tempfile, page);
  142.         fclose(tempfile);
  143.         psfree(doc);    /* forget original file */
  144.         /* scan new file */
  145.         strcpy(psfile.name, ename);
  146.         if ((psfile.file = fopen(psfile.name, READBIN)) == (FILE *)NULL) {
  147.            fprintf(stderr, "Can't open %s\n", psfile.file);
  148.            return 1;
  149.         }
  150.         doc = psscan(psfile.file);
  151.         if (doc == (PSDOC *)NULL) {
  152.            fprintf(stderr, "File %s does not contain DSC comments\n", psfile.file);
  153.            fclose(psfile.file);
  154.            return 1;
  155.         }
  156.         page = 1;    /* we want the one and only remaining page */
  157.     }
  158.     tempfile = gp_open_scratch_file(szScratch, tempname, WRITEBIN);
  159.     if (tempfile == (FILE *)NULL) {
  160.         fprintf(stderr, "Couldn't open temporary file %s\n", tempname);
  161.         return 1;
  162.     }
  163.     bmpfile = gp_open_scratch_file(szScratch, bmpname, WRITEBIN);
  164.     if (bmpfile == (FILE *)NULL) {
  165.         fprintf(stderr, "Couldn't open temporary file %s\n", bmpname);
  166.         return 1;
  167.     }
  168.     fclose(bmpfile);
  169.     if (!debug)
  170.        unlink(bmpname);
  171.     /* offset to bottom left corner of bounding box */
  172.     if (!calc_bbox)
  173.        fprintf(tempfile, "%d %d translate\r\n", -doc->boundingbox[LLX], -doc->boundingbox[LLY]);
  174.     /* calculate page size */
  175.     if (calc_bbox) {
  176.        if (doc->default_page_media) {
  177.            width = doc->default_page_media->width*resolution/72;
  178.            height = doc->default_page_media->height*resolution/72;
  179.        }
  180.        else {
  181.            width = 612*resolution/72;
  182.            height = 792*resolution/72;
  183.        }
  184.     }
  185.     else {
  186.        width = (doc->boundingbox[URX] - doc->boundingbox[LLX])*resolution/72;
  187.        height = (doc->boundingbox[URY] - doc->boundingbox[LLY])*resolution/72;
  188.     }
  189.     /* copy page to temporary file */
  190.     if (doc->numpages != 0) {
  191.         psfile_extract_header(tempfile);
  192.         psfile_extract_page(tempfile, page);
  193.         if (doc->numpages > 1)
  194.         fprintf(stderr,"Can't handle multiple page PostScript files\n");
  195.     }
  196.     else {
  197.         pscopyuntil(psfile.file, tempfile, doc->beginheader, doc->beginpreview, NULL);
  198.         pscopyuntil(psfile.file, tempfile, doc->endpreview, doc->endtrailer, NULL);
  199.     }
  200.     fprintf(tempfile, "\nquit\n");
  201.     fclose(tempfile);
  202. #ifdef UNIX
  203. #define DEVICE "pbmraw"
  204. #else
  205. #define DEVICE "bmpmono"
  206. #endif
  207.     sprintf(gscommand, "%s -dNOPAUSE -sDEVICE=%s -sOutputFile=%s -r%d -g%dx%d %s",
  208.        gsname, DEVICE, bmpname, resolution, width, height, tempname);
  209.     fprintf(stderr,"%s\n", gscommand);
  210.     system(gscommand);
  211.     if (!load_bitmap()) {
  212.         if (!debug) {
  213.             unlink(bmpname);
  214.             unlink(tempname);
  215.         }
  216.         fprintf(stderr, "no bitmap\n");
  217.         return 1;
  218.     }
  219.     if (!debug) {
  220.         unlink(bmpname);
  221.         unlink(tempname);
  222.     }
  223.     /* now create new file with preview */
  224.     if (op == INTERCHANGE)
  225.         make_eps_interchange(calc_bbox);
  226.     else if (op == TIFF4)
  227.         make_eps_tiff(IDM_MAKEEPST4);
  228.     else if (op == TIFF5)
  229.         make_eps_tiff(IDM_MAKEEPST);
  230.     else
  231.         fprintf(stderr, "Unknown operation %d\n", op);
  232.  
  233.     if (*ename) {
  234.         fclose(psfile.file);
  235.         if (!debug)
  236.             unlink(ename);    /* remove temporary file */
  237.     }
  238.  
  239.     fprintf(stderr, "Add_preview was successful\n");
  240.     return 0;
  241. }
  242.  
  243. int 
  244. scan_args(int argc, char *argv[])
  245. {
  246. char *argp;
  247. int count;
  248.     if (argc == 1) {
  249.         do_help();
  250.         return 1;
  251.     }
  252.     for (count=1, argp = argv[1]; count < argc; count++, argp=argv[count]) {
  253.       if (*argp == '-') {
  254.         switch(argp[1]) {
  255.         case 'h':
  256.           do_help();
  257.           return 1;
  258.         case 'o':
  259.           if (argp[2])
  260.             strcpy(oname, argp+2);
  261.           else {
  262.             count++;
  263.             if (count >= argc) {
  264.               fprintf(stderr,"Missing output filename for -o\n");
  265.               return 1;
  266.             }
  267.             argp=argv[count];
  268.             strcpy(oname, argp);
  269.           }
  270.           break;
  271.         case 'n':
  272.           if (argp[2])
  273.             page = atoi(argp+2);
  274.           else {
  275.             count++;
  276.             if (count >= argc) {
  277.               fprintf(stderr,"Missing page number for -n\n");
  278.               return 1;
  279.             }
  280.             argp=argv[count];
  281.             page = atoi(argp);
  282.           }
  283.           break;
  284.         case 'r':
  285.           if (argp[2])
  286.             resolution = atoi(argp+2);
  287.           else {
  288.             count++;
  289.             if (count >= argc) {
  290.               fprintf(stderr,"Missing resolution for -r\n");
  291.               return 1;
  292.             }
  293.             argp=argv[count];
  294.             resolution = atoi(argp);
  295.           }
  296.           break;
  297.         case 'b':
  298.           calc_bbox = !calc_bbox;
  299.           break;
  300.         case 'd':
  301.           debug = !debug;
  302.           break;
  303.         case 'g':
  304.           if (argp[2])
  305.             strcpy(gsname, argp+2);
  306.           else {
  307.             count++;
  308.             if (count >= argc) {
  309.               fprintf(stderr,"Missing Ghostscript command for -g\n");
  310.               return 1;
  311.             }
  312.             argp=argv[count];
  313.             strcpy(gsname, argp);
  314.           }
  315.           break;
  316.         case 't':
  317.           if (got_op) {
  318.             fprintf(stderr,"Can't select two operations");
  319.             return 1;
  320.           }
  321.           if (argp[2]=='4') {
  322.             op = TIFF4;
  323.             got_op = TRUE;
  324.           }
  325.           else if (argp[2]=='5') {
  326.             op = TIFF5;
  327.             got_op = TRUE;
  328.           }
  329.           else {
  330.             fprintf(stderr,"Unknown option %s\n", argp);
  331.           }
  332.           break;
  333.         case 'i':
  334.           if (got_op) {
  335.             fprintf(stderr,"Can't select two operations");
  336.             return 1;
  337.           }
  338.           op = INTERCHANGE;
  339.           got_op = TRUE;
  340.           break;
  341.         case 'p':
  342.           if (got_op) {
  343.             fprintf(stderr,"Can't select two operations");
  344.             return 1;
  345.           }
  346.           op = EXTRACTPS;
  347.           got_op = TRUE;
  348.           break;
  349.         case 'v':
  350.           if (got_op) {
  351.             fprintf(stderr,"Can't select two operations");
  352.             return 1;
  353.           }
  354.           op = EXTRACTPRE;
  355.           got_op = TRUE;
  356.           break;
  357.         default:
  358.           fprintf(stderr,"Unknown option %s\n", argp);
  359.           return 1;
  360.         }
  361.       }
  362.       else {
  363.           /* input filename */
  364.           if (*iname) {
  365.               fprintf(stderr,"Only one input file permitted\n");
  366.               return 1;
  367.           }
  368.           strcpy(iname, argp);
  369.       }
  370.     }
  371.     option.xdpi = option.ydpi = resolution;
  372.     if (*iname == '\0') {
  373.         fprintf(stderr, "No input file specified");
  374.         return 1;
  375.     }
  376.     if (!got_op) {
  377.         fprintf(stderr, "No operation specified");
  378.         return 1;
  379.     }
  380.     return 0;
  381. }
  382.  
  383. void
  384. do_help(void)
  385. {
  386.    fprintf(stderr,"Usage:  epstool [option] operation filename\n");
  387.    fprintf(stderr,"  Version: %s\n", szVersion);
  388.    fprintf(stderr,"  Options:\n");
  389.    fprintf(stderr,"     -b             Calculate BoundingBox from image\n");
  390.    fprintf(stderr,"     -g command     Ghostscript command\n");
  391.    fprintf(stderr,"     -n number      Page number to extract\n");
  392.    fprintf(stderr,"     -o filename    Output filename\n");
  393.    fprintf(stderr,"     -r number      Preview resolution in dpi\n");
  394.    fprintf(stderr,"  Operations: (one only)\n");
  395.    fprintf(stderr,"     -i             Add Interchange preview (EPSI)\n");
  396.    fprintf(stderr,"     -t4            Add TIFF4 preview       (DOS EPS)\n");
  397.    fprintf(stderr,"     -t5            Add TIFF5 preview       (DOS EPS)\n");
  398.    fprintf(stderr,"     -p             Extract PostScript      (DOS EPS)\n");
  399.    fprintf(stderr,"     -v             Extract Preview         (DOS EPS)\n");
  400. }
  401.  
  402. char *err_msgs[] = {"No preview in input file", ""};
  403. void 
  404. gserror(UINT id, char *str, UINT icon, int sound)
  405. {
  406.     fprintf(stderr, "%s %s\n", err_msgs[id], str);
  407. }
  408.  
  409. /* Create and open a scratch file with a given name prefix. */
  410. /* Write the actual file name at fname. */
  411. FILE *
  412. gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
  413. {    char *temp;
  414.     if ( (temp = getenv("TEMP")) == NULL )
  415.         _getcwd(fname, MAXSTR);
  416.     else
  417.         strcpy(fname, temp);
  418.  
  419.     /* Prevent X's in path from being converted by mktemp. */
  420.     for ( temp = fname; *temp; temp++ ) {
  421.         *temp = (char)tolower(*temp);
  422.         if (*temp == '/')
  423.             *temp = DIRSEP;
  424.     }
  425.     if ( strlen(fname) && (fname[strlen(fname)-1] != DIRSEP ) ) {
  426.         fname[strlen(fname)+1] = '\0';
  427.         fname[strlen(fname)] = DIRSEP;
  428.     }
  429.  
  430.     strcat(fname, prefix);
  431.     strcat(fname, "XXXXXX");
  432.     mktemp(fname);
  433.     return fopen(fname, mode);
  434. }
  435.  
  436. char * 
  437. _getcwd(char *dirname, int size)
  438. {
  439. #ifdef __EMX__
  440.     return _getcwd2(dirname, size);
  441. #else
  442.     return getcwd(dirname, size);
  443. #endif
  444. }
  445.  
  446.  
  447. void pserror(char *str)
  448. {
  449.     fputs(str, stderr);
  450. }
  451.  
  452.  
  453.  
  454. /* general purpose read file into memory */
  455. /* should work for files > 64k under MSDOS */
  456. /* malloc's memory to hold file contents and returns pointer to this memory */
  457. char GVFAR *
  458. read_file(char *fname)
  459. {
  460.   FILE *f;
  461.   LONG length, nread, count;
  462.   char GVFAR *base;
  463.   char GVHUGE *bp;
  464.  
  465.   if ( (f = fopen(fname, READBIN)) == (FILE *)NULL ) {
  466.     fprintf(stderr, "Can't open %s\n", fname);
  467.     return NULL;
  468.   }
  469.   fseek(f, 0, SEEK_END);
  470.   length = ftell(f);
  471.   fseek(f, 0, SEEK_SET);
  472.   if (length == 0) {
  473.     fprintf(stderr, "File %s is empty\n", fname);
  474.   }
  475. #ifdef MSDOS    /* I hate segmented architectures */
  476.   if ( (base = farmalloc(length)) == (char *)NULL ) {
  477. #else
  478.   if ( (base = malloc(length)) == (char *)NULL ) {
  479. #endif
  480.     fprintf(stderr, "Can't malloc memory to hold file %s\n", fname);
  481.     fclose(f);
  482.     return NULL;
  483.   }
  484.   bp = base;
  485.   while (length > 0) {
  486. #ifdef MSDOS
  487.     /* get smaller of 16k, length, remaining bytes in segment */
  488.     count = min( min(16384, length), (DWORD)(65536UL-((WORD)(bp))) );
  489. #else
  490.     count = length;
  491. #endif
  492.     nread = fread(bp, 1, (int)count, f);
  493.     if (nread == 0) {
  494.         fprintf(stderr, "Can't read file %s\n", fname);
  495.         fclose(f);
  496.         free(base);
  497.         return NULL;
  498.     }
  499.         length -= nread;
  500.     bp += nread;
  501.   }
  502.   fclose(f);
  503.   return base;  
  504. }
  505.  
  506. BOOL
  507. load_bitmap(void) 
  508. {
  509.   LPBITMAPFILE pbmf;
  510.  
  511.   /* extract some info about bitmap */
  512.   pbmf = (LPBITMAPFILE)read_file(bmpname);
  513.   if (pbmf == NULL)
  514.     return FALSE;
  515.   switch (*(char *)(pbmf)) {
  516.       case 'B':  /* BMP format */
  517.           bitmap_pbmi = (LPBITMAP2)( (char *)pbmf + sizeof(BITMAPFILE) );
  518.       break;
  519.       case 'P': /* PBMPLUS format */
  520.           bitmap_pbmi = (LPBITMAP2)(pbmf);  /* a KLUDGE */
  521.       break;
  522.       default:
  523.       fprintf(stderr,"Unknown bitmap format\n");
  524.       return FALSE;
  525.   }
  526.   return TRUE;
  527. }
  528.  
  529.  
  530. /* Copy the header to file f */
  531. /* change first line to EPSF if needed */
  532. void
  533. psfile_extract_header(FILE *f)
  534. {
  535.     char text[PSLINELENGTH];
  536.     char *comment;
  537.     BOOL pages_written = FALSE;
  538.     long position;
  539.  
  540.     fseek(psfile.file, doc->beginheader, SEEK_SET);
  541.     fgets(text, PSLINELENGTH, psfile.file);
  542.     if (doc->epsf)
  543.         fputs(text,f);
  544.     else {
  545.     switch(text[11]) {
  546.         case 1:
  547.                 fputs("%!PS-Adobe-1.0 EPSF-1.0\r\n",f);
  548.         break;
  549.         case 2:
  550.                 fputs("%!PS-Adobe-2.0 EPSF-2.0\r\n",f);
  551.         break;
  552.         default:
  553.                 fputs("%!PS-Adobe-3.0 EPSF-3.0\r\n",f);
  554.     }
  555.     }
  556.     position = ftell(psfile.file);
  557.     while ( (comment = pscopyuntil(psfile.file, f, position,
  558.                doc->endheader, "%%Pages:")) != (char *)NULL ) {
  559.     position = ftell(psfile.file);
  560.     if (pages_written) {
  561.         free(comment);
  562.         continue;
  563.     }
  564.     fprintf(f, "%%%%Pages: 1\r\n");
  565.     pages_written = TRUE;
  566.     free(comment);
  567.     }
  568. }
  569.  
  570. /* Copy the selected page and trailer to file f */
  571. void
  572. psfile_extract_page(FILE *f, int page)
  573. {
  574.     char *comment;
  575.     int i;
  576.     long position;
  577.  
  578.     /* don't copy preview because we might be adding our own */
  579.     pscopyuntil(psfile.file, f, doc->begindefaults, doc->enddefaults, NULL);
  580.     pscopyuntil(psfile.file, f, doc->beginprolog, doc->endprolog, NULL);
  581.     pscopyuntil(psfile.file, f, doc->beginsetup, doc->endsetup, NULL);
  582.  
  583.     if (doc->pageorder == DESCEND) 
  584.     i = (doc->numpages - 1) - page;
  585.     else
  586.     i = page - 1;
  587.     comment = pscopyuntil(psfile.file, f, doc->pages[i].begin,
  588.               doc->pages[i].end, "%%Page:");
  589.     fprintf(f, "%%%%Page: %s %d\r\n",
  590.         doc->pages[i].label, page++);
  591.     free(comment);
  592.     pscopyuntil(psfile.file, f, -1, doc->pages[i].end, NULL);
  593.  
  594.     position = doc->begintrailer;
  595.     while ( (comment = pscopyuntil(psfile.file, f, position,
  596.                doc->endtrailer, "%%Pages:")) != (char *)NULL ) {
  597.     position = ftell(psfile.file);
  598.     free(comment);
  599.     }
  600. }
  601.  
  602.