home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / graphics / gif-util.zip / GIFFLIP.C < prev    next >
C/C++ Source or Header  |  1989-08-01  |  12KB  |  334 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber            IBM PC Ver 0.1,    Jul. 1989    *
  5. ******************************************************************************
  6. * Program to rotate image 90 degrees to the right/left or flip the image     *
  7. * horizintally/vertically (mirror).                         *
  8. * Options:                                     *
  9. * -r : rotate 90 degrees to the right (default).                 *
  10. * -l : rotate 90 degrees to the left.                         *
  11. * -x : Mirror the image horizontally (first line switch places with last).   *
  12. * -y : Mirror the image vertically (first column switch places with last).   *
  13. * -h : on line help                                 *
  14. ******************************************************************************
  15. * History:                                     *
  16. * 10 Jul 89 - Version 1.0 by Gershon Elber.                     *
  17. *****************************************************************************/
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <ctype.h>
  22. #include <alloc.h>
  23. #include <string.h>
  24. #include "gif_lib.h"
  25. #include "getarg.h"
  26.  
  27. #define PROGRAM_NAME    "GifFlip"
  28. #define VERSION        "ß Version 1.0, "
  29.  
  30. enum {
  31.     FLIP_NONE,
  32.     FLIP_RIGHT,
  33.     FLIP_LEFT,
  34.     FLIP_HORIZ,
  35.     FLIP_VERT
  36. };
  37.  
  38. extern unsigned int
  39.     _stklen = 16384;                  /* Increase default stack size */
  40.  
  41. static char
  42.     *VersionStr =
  43.     PROGRAM_NAME
  44.     "    IBMPC "
  45.     VERSION
  46.     "    Gershon Elber,    "
  47.     __DATE__ ",   " __TIME__ "\n"
  48.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  49. static char
  50.     *CtrlStr =
  51.     PROGRAM_NAME
  52.     " r%- l%- x%- y%- h%- GifFile!*s";
  53. static char
  54.     *ProgramName;
  55.  
  56. /* Make some variables global, so we could access them faster: */
  57. static int
  58.     ImageNum = 0;
  59.  
  60. static int LoadImage(GifFileType *GifFile, RowType **ImageBuffer);
  61. static int DumpImage(GifFileType *GifFile, RowType *ImageBuffer,
  62.                 int Width, int Height, int FlipDirection);
  63. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  64.  
  65. /******************************************************************************
  66. * Interpret the command line and scan the given GIF file.              *
  67. ******************************************************************************/
  68. void main(int argc, char **argv)
  69. {
  70.     int    i, Error, NumFiles, ExtCode, FlipDirection,
  71.     RightFlag = FALSE, LeftFlag = FALSE,
  72.     HorizFlag = FALSE, VertFlag = FALSE, HelpFlag = FALSE;
  73.     GifRecordType RecordType;
  74.     ByteType *Extension;
  75.     char **FileName = NULL;
  76.     RowType *ImageBuffer;
  77.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  78.  
  79.     if (strlen(ProgramName = argv[0]) == 0)            /* DOS 3.x only! */
  80.     ProgramName = PROGRAM_NAME;      /* Do something reasonable for 2.x */
  81.  
  82.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  83.         &RightFlag, &LeftFlag, &HorizFlag, &VertFlag, &HelpFlag,
  84.         &NumFiles, &FileName)) != FALSE ||
  85.         (NumFiles > 1 && !HelpFlag)) {
  86.     if (Error) GAPrintErrMsg(Error);
  87.     else
  88.     if (NumFiles > 1)
  89.         MESSAGE("Error in command line parsing - one GIF file please\n");
  90.     GAPrintHowTo(CtrlStr);
  91.     exit(1);
  92.     }
  93.  
  94.     if (HelpFlag) {
  95.     fprintf(stderr, VersionStr);
  96.     GAPrintHowTo(CtrlStr);
  97.     exit(0);
  98.     }
  99.  
  100.     if ((i = (RightFlag != 0) + (LeftFlag != 0) +
  101.          (HorizFlag != 0) + (VertFlag != 0)) > 1)
  102.     EXIT("Only one of -r, -l, -x, -y please\n");
  103.     if (i == 0) FlipDirection = FLIP_RIGHT;          /* Make it the default */
  104.     else {
  105.     if (RightFlag) FlipDirection = FLIP_RIGHT;
  106.     if (LeftFlag) FlipDirection = FLIP_LEFT;
  107.     if (HorizFlag) FlipDirection = FLIP_HORIZ;
  108.     if (VertFlag) FlipDirection = FLIP_VERT;
  109.     }
  110.  
  111.     if (NumFiles == 1) {
  112.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  113.         QuitGifError(GifFileIn, GifFileOut);
  114.     }
  115.     else {
  116.     /* Use the stdin instead: */
  117.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  118.         QuitGifError(GifFileIn, GifFileOut);
  119.     }
  120.  
  121.     /* Open stdout for the output file: */
  122.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  123.     QuitGifError(GifFileIn, GifFileOut);
  124.  
  125.     if (RightFlag || LeftFlag) {
  126.     /* Dump out same screen information, but flip Screen Width/Height: */
  127.     if (EGifPutScreenDesc(GifFileOut,
  128.         GifFileIn -> SHeight, GifFileIn -> SWidth,
  129.         GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  130.         GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == ERROR)
  131.         QuitGifError(GifFileIn, GifFileOut);
  132.     }
  133.     else {
  134.     /* Dump out exactly same screen information: */
  135.     if (EGifPutScreenDesc(GifFileOut,
  136.         GifFileIn -> SWidth, GifFileIn -> SHeight,
  137.         GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  138.         GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == ERROR)
  139.         QuitGifError(GifFileIn, GifFileOut);
  140.     }
  141.  
  142.     /* Scan the content of the GIF file and load the image(s) in: */
  143.     do {
  144.     if (DGifGetRecordType(GifFileIn, &RecordType) == ERROR)
  145.         QuitGifError(GifFileIn, GifFileOut);
  146.  
  147.     switch (RecordType) {
  148.         case IMAGE_DESC_RECORD_TYPE:
  149.         if (DGifGetImageDesc(GifFileIn) == ERROR)
  150.             QuitGifError(GifFileIn, GifFileOut);
  151.         if (GifFileIn -> IInterlace)
  152.             EXIT("Cannt flip interlaced images - use GifInter first\n");
  153.  
  154.         /* Put the image descriptor to out file: */
  155.         if (RightFlag) {
  156.             /* Rotate to the right: */
  157.             if (EGifPutImageDesc(GifFileOut,
  158.             GifFileIn -> SHeight - GifFileIn -> IHeight -
  159.                         GifFileIn -> ITop,
  160.             GifFileIn -> ILeft,
  161.             GifFileIn -> IHeight, GifFileIn -> IWidth,
  162.             FALSE, GifFileIn -> IBitsPerPixel,
  163.             GifFileIn -> IColorMap) == ERROR)
  164.                 QuitGifError(GifFileIn, GifFileOut);
  165.         }
  166.         else
  167.         if (LeftFlag) {
  168.             /* Rotate to the left: */
  169.             if (EGifPutImageDesc(GifFileOut,
  170.             GifFileIn -> ITop,
  171.             GifFileIn -> SWidth - GifFileIn -> IWidth -
  172.                         GifFileIn -> ILeft,
  173.             GifFileIn -> IHeight, GifFileIn -> IWidth,
  174.             FALSE, GifFileIn -> IBitsPerPixel,
  175.             GifFileIn -> IColorMap) == ERROR)
  176.                 QuitGifError(GifFileIn, GifFileOut);
  177.         }
  178.         else {
  179.             /* No rotation - only flipping vert. or horiz.: */
  180.             if (EGifPutImageDesc(GifFileOut,
  181.             GifFileIn -> ILeft, GifFileIn -> ITop,
  182.             GifFileIn -> IWidth, GifFileIn -> IHeight,
  183.             FALSE, GifFileIn -> IBitsPerPixel,
  184.             GifFileIn -> IColorMap) == ERROR)
  185.                 QuitGifError(GifFileIn, GifFileOut);
  186.         }
  187.  
  188.         /* Load the image (either Interlaced or not), and dump it    */
  189.         /* fliped as requrested by Flags:                 */
  190.         if (LoadImage(GifFileIn, &ImageBuffer) == ERROR)
  191.             QuitGifError(GifFileIn, GifFileOut);
  192.         if (DumpImage(GifFileOut, ImageBuffer, GifFileIn -> IWidth,
  193.                 GifFileIn -> IHeight, FlipDirection) == ERROR)
  194.             QuitGifError(GifFileIn, GifFileOut);
  195.         break;
  196.         case EXTENSION_RECORD_TYPE:
  197.         /* Skip any extension blocks in file: */
  198.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == ERROR)
  199.             QuitGifError(GifFileIn, GifFileOut);
  200.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  201.                             Extension) == ERROR)
  202.             QuitGifError(GifFileIn, GifFileOut);
  203.  
  204.         /* No support to more than one extension blocks, so discard: */
  205.         while (Extension != NULL) {
  206.             if (DGifGetExtensionNext(GifFileIn, &Extension) == ERROR)
  207.             QuitGifError(GifFileIn, GifFileOut);
  208.         }
  209.         break;
  210.         case TERMINATE_RECORD_TYPE:
  211.         break;
  212.         default:             /* Should be traps by DGifGetRecordType */
  213.         break;
  214.     }
  215.     }
  216.     while (RecordType != TERMINATE_RECORD_TYPE);
  217.  
  218.     if (DGifCloseFile(GifFileIn) == ERROR)
  219.     QuitGifError(GifFileIn, GifFileOut);
  220.     if (EGifCloseFile(GifFileOut) == ERROR)
  221.     QuitGifError(GifFileIn, GifFileOut);
  222. }
  223.  
  224. /******************************************************************************
  225. * Routine to read Image out. The image can be Non interlaced only.          *
  226. * The memory required to hold the image is allocate by the routine itself.    *
  227. * Return OK if succesful, ERROR otherwise.                      *
  228. ******************************************************************************/
  229. static int LoadImage(GifFileType *GifFile, RowType **ImageBufferPtr)
  230. {
  231.     int Size, i;
  232.     RowType *ImageBuffer;
  233.  
  234.     /* Allocate the image as vector of column of rows. We cannt allocate     */
  235.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  236.     /* 64k at a time and our image can be bigger than that:             */
  237.     if ((ImageBuffer = (RowType *)
  238.     malloc(GifFile -> IHeight * sizeof(RowType *))) == NULL)
  239.         EXIT("Failed to allocate memory required, aborted");
  240.  
  241.     Size = GifFile -> IWidth * sizeof(PixelType);   /* One row size in bytes */
  242.     for (i=0; i<GifFile -> IHeight; i++) {
  243.     /* Allocate the rows: */
  244.     if ((ImageBuffer[i] = (RowType) malloc(Size)) == NULL)
  245.         EXIT("Failed to allocate memory required, aborted\n");
  246.     }
  247.  
  248.     *ImageBufferPtr = ImageBuffer;
  249.  
  250.     fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  251.     ProgramName, ++ImageNum, GifFile -> ILeft, GifFile -> ITop,
  252.                  GifFile -> IWidth, GifFile -> IHeight);
  253.  
  254.     for (i=0; i<GifFile -> IHeight; i++) {
  255.     fprintf(stderr, "\b\b\b\b%-4d", i);
  256.     if (DGifGetLine(GifFile, ImageBuffer[i], GifFile -> IWidth)
  257.         == ERROR) return ERROR;
  258.     }
  259.  
  260.     return OK;
  261. }
  262.  
  263. /******************************************************************************
  264. * Routine to dump image out. The given Image buffer should always hold the    *
  265. * image sequencially, and Width & Height hold image dimensions BEFORE flip.   *
  266. * Image will be dumped according to FlipDirection.                  *
  267. * Once dumped, the memory holding the image is freed.                  *
  268. * Return OK if succesful, ERROR otherwise.                      *
  269. ******************************************************************************/
  270. static int DumpImage(GifFileType *GifFile, RowType *ImageBuffer,
  271.                 int Width, int Height, int FlipDirection)
  272. {
  273.     int i, j, Count;
  274.     RowType Line;                /* New scan line is copied to it */
  275.  
  276.     /* Allocate scan line that will fit both image width and height: */
  277.     if ((Line = (RowType) malloc((Width > Height ? Width : Height)
  278.                         * sizeof(PixelType))) == NULL)
  279.     EXIT("Failed to allocate memory required, aborted\n");
  280.  
  281.     switch (FlipDirection) {
  282.     case FLIP_RIGHT:
  283.         for (Count=Width, i=0; i<Width; i++) {
  284.         fprintf(stderr, "\b\b\b\b%-4d", Count--);
  285.         for (j=0; j<Height; j++)
  286.             Line[j] = ImageBuffer[Height - j - 1][i];
  287.         if (EGifPutLine(GifFile, Line, Height) == ERROR) return ERROR;
  288.         }
  289.         break;
  290.     case FLIP_LEFT:
  291.         for (i=Width-1; i>=0; i--) {
  292.         fprintf(stderr, "\b\b\b\b%-4d", i + 1);
  293.         for (j=0; j<Height; j++)
  294.             Line[j] = ImageBuffer[j][i];
  295.         if (EGifPutLine(GifFile, Line, Height) == ERROR) return ERROR;
  296.         }
  297.         break;
  298.     case FLIP_HORIZ:
  299.         for (i=Height-1; i>=0; i--) {
  300.         fprintf(stderr, "\b\b\b\b%-4d", i);
  301.         if (EGifPutLine(GifFile, ImageBuffer[i], Width) == ERROR)
  302.             return ERROR;
  303.         }
  304.         break;
  305.     case FLIP_VERT:
  306.         for (Count=Height, i=0; i<Height; i++) {
  307.         fprintf(stderr, "\b\b\b\b%-4d", Count--);
  308.         for (j=0; j<Width; j++)
  309.             Line[j] = ImageBuffer[i][Width - j - 1];
  310.         if (EGifPutLine(GifFile, Line, Width) == ERROR) return ERROR;
  311.         }
  312.         break;
  313.     }
  314.  
  315.     /* Free the memory used for this image, and the temporary scan line: */
  316.     for (i=0; i<Height; i++) free((char *) ImageBuffer[i]);
  317.     free((char *) ImageBuffer);
  318.  
  319.     free((char *) Line);
  320.  
  321.     return OK;
  322. }
  323.  
  324. /******************************************************************************
  325. * Close both input and output file (if open), and exit.                  *
  326. ******************************************************************************/
  327. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  328. {
  329.     PrintGifError();
  330.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  331.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  332.     exit(1);
  333. }
  334.