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

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