home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / giflib11 / util / gif2ps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-03  |  12.0 KB  |  387 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Jul. 1989   *
  5. ******************************************************************************
  6. * Program to dump GIF file into PostScript type printers             *
  7. * Options:                                     *
  8. * -x : force image to be horizontal.                         *
  9. * -y : force image to be vertical.                         *
  10. * -s x y : force image to be of given size.                     *
  11. * -p x y : force image to be positioned at given position in page.         *
  12. * -i : invert the image.                             *
  13. * -n n : number of copies.                             *
  14. * -h : on line help.                                 *
  15. ******************************************************************************
  16. * History:                                     *
  17. * 22 Dec 89 - Version 1.0 by Gershon Elber.                     *
  18. *****************************************************************************/
  19.  
  20. #ifdef __MSDOS__
  21. #include <graphics.h>
  22. #include <stdlib.h>
  23. #include <alloc.h>
  24. #include <io.h>
  25. #include <dos.h>
  26. #include <bios.h>
  27. #endif /* __MSDOS__ */
  28.  
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include <string.h>
  32. #include <fcntl.h>
  33. #include "gif_lib.h"
  34. #include "getarg.h"
  35.  
  36. #define PROGRAM_NAME    "Gif2PS"
  37.  
  38. #define PAGE_WIDTH      7.5            /* All dimensions are in inches. */
  39. #define PAGE_HEIGHT     9.0
  40. #define FULL_PAGE_WIDTH 8.5
  41. #define FULL_PAGE_HEIGHT 11.0
  42.  
  43. #define UNKNOWN_ORIENT        0
  44. #define HORIZONTAL_ORIENT    1 
  45. #define VERTICAL_ORIENT        2
  46.  
  47. #ifdef __MSDOS__
  48. extern unsigned int
  49.     _stklen = 16384;                 /* Increase default stack size. */
  50. #endif /* __MSDOS__ */
  51.  
  52. #ifdef SYSV
  53. static char *VersionStr =
  54.         "Gif library module,\t\tGershon Elber\n\
  55.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  56. static char
  57.     *CtrlStr = "Gif2PS x%- y%- s%-SizeX|SizeY!F!F p%-PosX|PosY!F!F i%- n%-#Copies!d h%- GifFile!*s";
  58. #else
  59. static char
  60.     *VersionStr =
  61.     PROGRAM_NAME
  62.     GIF_LIB_VERSION
  63.     "    Gershon Elber,    "
  64.     __DATE__ ",   " __TIME__ "\n"
  65.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  66. static char
  67.     *CtrlStr =
  68.     PROGRAM_NAME
  69.     " x%- y%- s%-SizeX|SizeY!F!F p%-PosX|PosY!F!F i%- n%-#Copies!d h%- GifFile!*s";
  70. #endif /* SYSV */
  71.  
  72. /* Make some variables global, so we could access them faster: */
  73. static int
  74.     ImageNum = 0,
  75.     BackGround = 0,
  76.     ForceXFlag = FALSE,
  77.     ForceYFlag = FALSE,
  78.     SizeFlag = FALSE,
  79.     PosFlag = FALSE,
  80.     InvertFlag = FALSE,
  81.     NumCopiesFlag = FALSE,
  82.     HelpFlag = FALSE,
  83.     NumOfCopies = 1,
  84.     InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
  85.     InterlacedJumps[] = { 8, 8, 4, 2 },    /* be read - offsets and jumps... */
  86.     PSOrientation;
  87. static double PSSizeX, PSSizeY, PSPosX, PSPosY;
  88. static GifColorType
  89.     *ColorMap;
  90.  
  91. static void DumpScreen2PS(GifRowType *ScreenBuffer,
  92.                     int ScreenWidth, int ScreenHeight);
  93. static void PutString(unsigned char *Line, int Len);
  94.  
  95. /******************************************************************************
  96. * Interpret the command line and scan the given GIF file.              *
  97. ******************************************************************************/
  98. void main(int argc, char **argv)
  99. {
  100.     int    i, j, Error, NumFiles, Size, Row, Col, Width, Height, ExtCode, Count;
  101.     GifRecordType RecordType;
  102.     GifByteType *Extension;
  103.     char **FileName = NULL;
  104.     GifRowType *ScreenBuffer;
  105.     GifFileType *GifFile;
  106.  
  107.     if ((Error = GAGetArgs(argc, argv, CtrlStr, &ForceXFlag, &ForceYFlag,
  108.         &SizeFlag, &PSSizeX, &PSSizeY,
  109.         &PosFlag, &PSPosX, &PSPosY,
  110.         &InvertFlag, &NumCopiesFlag, &NumOfCopies, &HelpFlag,
  111.         &NumFiles, &FileName)) != FALSE ||
  112.         (NumFiles > 1 && !HelpFlag)) {
  113.     if (Error)
  114.         GAPrintErrMsg(Error);
  115.     else if (NumFiles > 1)
  116.         GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  117.     GAPrintHowTo(CtrlStr);
  118.     exit(1);
  119.     }
  120.  
  121.     if (HelpFlag) {
  122.     fprintf(stderr, VersionStr);
  123.     GAPrintHowTo(CtrlStr);
  124.     exit(0);
  125.     }
  126.  
  127.     if (ForceXFlag)
  128.         PSOrientation = HORIZONTAL_ORIENT;
  129.     else if (ForceYFlag)
  130.         PSOrientation = VERTICAL_ORIENT;
  131.     else
  132.     PSOrientation = UNKNOWN_ORIENT;
  133.     
  134.     if (NumFiles == 1) {
  135.     if ((GifFile = DGifOpenFileName(*FileName)) == NULL) {
  136.         PrintGifError();
  137.         exit(-1);
  138.     }
  139.     }
  140.     else {
  141.     /* Use the stdin instead: */
  142.  
  143. #ifdef __MSDOS__
  144.     setmode(0, O_BINARY);
  145. #endif /* __MSDOS__ */
  146.     if ((GifFile = DGifOpenFileHandle(0)) == NULL) {
  147.         PrintGifError();
  148.         exit(-1);
  149.     }
  150.     }
  151.  
  152.     /* Allocate the screen as vector of column of rows. We cannt allocate    */
  153.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  154.     /* 64k at a time and our image can be bigger than that:             */
  155.     /* Note this screen is device independent - its the screen as defined by */
  156.     /* the GIF file parameters itself.                         */
  157.     if ((ScreenBuffer = (GifRowType *)
  158.     malloc(GifFile -> SHeight * sizeof(GifRowType *))) == NULL)
  159.         GIF_EXIT("Failed to allocate memory required, aborted.");
  160.  
  161.     Size = GifFile -> SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/
  162.     if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */
  163.     GIF_EXIT("Failed to allocate memory required, aborted.");
  164.  
  165.     for (i = 0; i < GifFile -> SWidth; i++) /* Set its color to BackGround. */
  166.     ScreenBuffer[0][i] = GifFile -> SBackGroundColor;
  167.     for (i = 1; i < GifFile -> SHeight; i++) {
  168.     /* Allocate the other rows, and set their color to background too:  */
  169.     if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL)
  170.         GIF_EXIT("Failed to allocate memory required, aborted.");
  171.  
  172.     memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
  173.     }
  174.  
  175.     /* Scan the content of the GIF file and load the image(s) in: */
  176.     do {
  177.     if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
  178.         PrintGifError();
  179.         exit(-1);
  180.     }
  181.     switch (RecordType) {
  182.         case IMAGE_DESC_RECORD_TYPE:
  183.         if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
  184.             PrintGifError();
  185.             exit(-1);
  186.         }
  187.         Row = GifFile -> ITop; /* Image Position relative to Screen. */
  188.         Col = GifFile -> ILeft;
  189.         Width = GifFile -> IWidth;
  190.         Height = GifFile -> IHeight;
  191.         fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  192.             PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height);
  193.         if (GifFile -> ILeft + GifFile -> IWidth > GifFile -> SWidth ||
  194.            GifFile -> ITop + GifFile -> IHeight > GifFile -> SHeight) {
  195.             fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n");
  196.             exit(-2);
  197.         }
  198.         if (GifFile -> IInterlace) {
  199.             /* Need to perform 4 passes on the images: */
  200.              for (Count = i = 0; i < 4; i++)
  201.             for (j = Row + InterlacedOffset[i]; j < Row + Height;
  202.                          j += InterlacedJumps[i]) {
  203.                 fprintf(stderr, "\b\b\b\b%-4d", Count++);
  204.                 if (DGifGetLine(GifFile, &ScreenBuffer[j][Col],
  205.                 Width) == GIF_ERROR) {
  206.                 PrintGifError();
  207.                 exit(-1);
  208.                 }
  209.             }
  210.         }
  211.         else {
  212.             for (i = 0; i < Height; i++) {
  213.             fprintf(stderr, "\b\b\b\b%-4d", i);
  214.             if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col],
  215.                 Width) == GIF_ERROR) {
  216.                 PrintGifError();
  217.                 exit(-1);
  218.             }
  219.             }
  220.         }
  221.         break;
  222.         case EXTENSION_RECORD_TYPE:
  223.         /* Skip any extension blocks in file: */
  224.         if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
  225.             PrintGifError();
  226.             exit(-1);
  227.         }
  228.         while (Extension != NULL) {
  229.             if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
  230.             PrintGifError();
  231.             exit(-1);
  232.             }
  233.         }
  234.         break;
  235.         case TERMINATE_RECORD_TYPE:
  236.         break;
  237.         default:            /* Should be traps by DGifGetRecordType. */
  238.         break;
  239.     }
  240.     }
  241.     while (RecordType != TERMINATE_RECORD_TYPE);
  242.  
  243.     /* Lets display it - set the global variables required and do it: */
  244.     BackGround = GifFile -> SBackGroundColor;
  245.     ColorMap = (GifFile -> IColorMap ? GifFile -> IColorMap :
  246.                        GifFile -> SColorMap);
  247.     DumpScreen2PS(ScreenBuffer, GifFile -> SWidth, GifFile -> SHeight);
  248.  
  249.     if (DGifCloseFile(GifFile) == GIF_ERROR) {
  250.     PrintGifError();
  251.     exit(-1);
  252.     }
  253. }
  254.  
  255. /******************************************************************************
  256. * The real dumping routine.                              *
  257. ******************************************************************************/
  258. static void DumpScreen2PS(GifRowType *ScreenBuffer,
  259.                     int ScreenWidth, int ScreenHeight)
  260. {
  261.     int i, j;
  262.     double Aspect;
  263.     GifByteType *OutLine, Data;
  264.     GifPixelType *Line;
  265.     GifColorType *ColorMapEntry;
  266.  
  267.     /* If user did not enforce orientation, pick the best one. */
  268.     if (PSOrientation == UNKNOWN_ORIENT)
  269.     if (ScreenWidth > ScreenHeight)
  270.         PSOrientation = VERTICAL_ORIENT;
  271.     else
  272.         PSOrientation = HORIZONTAL_ORIENT;
  273.  
  274.     Aspect = ((double) ScreenHeight) / ((double) ScreenWidth);
  275.  
  276.     if (!SizeFlag)
  277.     switch (PSOrientation) {
  278.             case HORIZONTAL_ORIENT:
  279.             if (Aspect > PAGE_HEIGHT / PAGE_WIDTH) {
  280.             PSSizeX = PAGE_HEIGHT / Aspect; 
  281.             PSSizeY = PAGE_HEIGHT;
  282.         }
  283.         else {
  284.             PSSizeX = PAGE_WIDTH;
  285.             PSSizeY = PAGE_WIDTH * Aspect;
  286.         }
  287.         break;
  288.         case VERTICAL_ORIENT:
  289.             if (1 / Aspect > PAGE_HEIGHT / PAGE_WIDTH) {
  290.             PSSizeX = PAGE_HEIGHT * Aspect; 
  291.             PSSizeY = PAGE_HEIGHT;
  292.         }
  293.         else {
  294.             PSSizeX = PAGE_WIDTH;
  295.             PSSizeY = PAGE_WIDTH / Aspect;
  296.         }
  297.         break;
  298.     }
  299.     else {
  300.     if (PAGE_WIDTH < PSSizeX) {
  301.         GIF_MESSAGE("X Size specified is too big, page size selected.");
  302.         PSSizeX = PAGE_WIDTH;
  303.     }
  304.     if (PAGE_HEIGHT < PSSizeY) {
  305.         GIF_MESSAGE("Y Size specified is too big, page size selected.");
  306.         PSSizeX = PAGE_HEIGHT;
  307.     }
  308.     }
  309.  
  310.     if (!PosFlag) {
  311.     PSPosX = (FULL_PAGE_WIDTH - PSSizeX) / 2;
  312.     PSPosY = (FULL_PAGE_HEIGHT - PSSizeY) / 2;
  313.     }
  314.     else {
  315.     if (PSPosX + PSSizeX > PAGE_WIDTH || PSPosY + PSSizeY > PAGE_HEIGHT)
  316.         GIF_EXIT("Requested position will put image out of page, aborted.");
  317.     }
  318.  
  319.     /* Time to dump out the PostScript header: */
  320.     printf("%%!\n");
  321.     printf("%%%%Creator: %s\n", PROGRAM_NAME);
  322.     printf("/#copies %d def\n", NumOfCopies);
  323.     printf("gsave\n");
  324.     printf("72 72 scale\t\t\t\t%% Lets talk inches.\n");
  325.     printf("/oneline %d string def\t\t\t%% Allocate one scan line.\n",
  326.        ScreenWidth);
  327.     printf("/drawimage {\n");
  328.     printf("\t%d %d 8 [%d 0 0 %d 0 %d]\n", ScreenWidth, ScreenHeight,
  329.        ScreenWidth, -ScreenHeight, ScreenHeight);
  330.     printf("\t{ currentfile oneline readhexstring pop } image\n");
  331.     printf("} def\n");
  332.     switch (PSOrientation) {
  333.         case HORIZONTAL_ORIENT:
  334.         printf("%lf %lf translate\n", PSPosX, PSPosY);
  335.         printf("%lf %lf scale\n", PSSizeX, PSSizeY);
  336.         break;
  337.     case VERTICAL_ORIENT:
  338.         printf("%lf %lf translate\n", PSPosX + PSSizeX, PSPosY);
  339.         printf("90 rotate\n");
  340.         printf("%lf %lf scale\n", PSSizeY, PSSizeX);
  341.         break;
  342.     }
  343.     printf("drawimage\n");
  344.  
  345.     if ((OutLine = (GifByteType *) malloc(sizeof(GifByteType) * ScreenWidth))
  346.                                 == NULL)
  347.     GIF_EXIT("Failed to allocate memory required, aborted.");
  348.  
  349.     for (i = 0; i < ScreenHeight; i++) {
  350.     fprintf(stderr, "\b\b\b\b%-4d", ScreenHeight - i);
  351.  
  352.     Line = ScreenBuffer[i];
  353.     for (j = 0; j < ScreenWidth; j++) {
  354.         ColorMapEntry = &ColorMap[Line[j]];
  355.         Data = (30 * ((unsigned int) ColorMapEntry->Red) +
  356.             59 * ((unsigned int) ColorMapEntry->Green) +
  357.             11 * ((unsigned int) ColorMapEntry->Blue)) / 100;
  358.         OutLine[j] = InvertFlag ? 255 - Data : Data;
  359.     }
  360.  
  361.     PutString(OutLine, ScreenWidth);
  362.     }
  363.     free(OutLine);
  364.  
  365.     printf("\nshowpage\n");
  366.     printf("grestore\n");
  367. }
  368.  
  369. /******************************************************************************
  370. * Dumps the string of given length as 2 hexdigits per byte 39 bytes per line. *
  371. ******************************************************************************/
  372. static void PutString(unsigned char *Line, int Len)
  373. {
  374.     int i;
  375.     static Counter = 0;
  376.     static char *Hex = "0123456789ABCDEF";
  377.  
  378.     for (i = 0; i < Len; i++) {
  379.     if (++Counter % 40 == 0) {
  380.         putchar('\n');
  381.         Counter = 1;
  382.     }
  383.     putchar(Hex[Line[i] >> 4]);
  384.     putchar(Hex[Line[i] & 0x0f]);
  385.     }
  386. }
  387.