home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / graphics / gif-util.zip / GIFINTER.C < prev    next >
C/C++ Source or Header  |  1989-08-01  |  10KB  |  263 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 flip interlaced and non interlaced images in GIF files.         *
  7. * Options:                                     *
  8. * -i : Force all images to be intelaced.                     *
  9. * -s : Force all images to be sequencial (non interlaced). This is default.  *
  10. * -h : on line help                                 *
  11. ******************************************************************************
  12. * History:                                     *
  13. * 5 Jul 89 - Version 1.0 by Gershon Elber.                     *
  14. *****************************************************************************/
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19. #include <alloc.h>
  20. #include <string.h>
  21. #include "gif_lib.h"
  22. #include "getarg.h"
  23.  
  24. #define PROGRAM_NAME    "GifInter"
  25. #define VERSION        "ß Version 1.0, "
  26.  
  27. extern unsigned int
  28.     _stklen = 16384;                  /* Increase default stack size */
  29.  
  30. static char
  31.     *VersionStr =
  32.     PROGRAM_NAME
  33.     "    IBMPC "
  34.     VERSION
  35.     "    Gershon Elber,    "
  36.     __DATE__ ",   " __TIME__ "\n"
  37.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  38. static char
  39.     *CtrlStr =
  40.     PROGRAM_NAME
  41.     " i%- s%- h%- GifFile!*s";
  42. static char
  43.     *ProgramName;
  44.  
  45. /* Make some variables global, so we could access them faster: */
  46. static int
  47.     ImageNum = 0,
  48.     SequencialFlag = FALSE,
  49.     InterlacedFlag = FALSE,
  50.     HelpFlag = FALSE,
  51.     InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should  */
  52.     InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */
  53.  
  54. static int LoadImage(GifFileType *GifFile, RowType **ImageBuffer);
  55. static int DumpImage(GifFileType *GifFile, RowType *ImageBuffer);
  56. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  57.  
  58. /******************************************************************************
  59. * Interpret the command line and scan the given GIF file.              *
  60. ******************************************************************************/
  61. void main(int argc, char **argv)
  62. {
  63.     int    Error, NumFiles, ExtCode;
  64.     GifRecordType RecordType;
  65.     ByteType *Extension;
  66.     char **FileName = NULL;
  67.     RowType *ImageBuffer;
  68.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  69.  
  70.     if (strlen(ProgramName = argv[0]) == 0)            /* DOS 3.x only! */
  71.     ProgramName = PROGRAM_NAME;      /* Do something reasonable for 2.x */
  72.  
  73.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  74.         &SequencialFlag, &InterlacedFlag, &HelpFlag,
  75.         &NumFiles, &FileName)) != FALSE ||
  76.         (NumFiles > 1 && !HelpFlag)) {
  77.     if (Error) GAPrintErrMsg(Error);
  78.     else
  79.     if (NumFiles > 1)
  80.         MESSAGE("Error in command line parsing - one GIF file please\n");
  81.     GAPrintHowTo(CtrlStr);
  82.     exit(1);
  83.     }
  84.  
  85.     if (HelpFlag) {
  86.     fprintf(stderr, VersionStr);
  87.     GAPrintHowTo(CtrlStr);
  88.     exit(0);
  89.     }
  90.     if (!InterlacedFlag && SequencialFlag)
  91.     InterlacedFlag = TRUE;
  92.  
  93.     if (NumFiles == 1) {
  94.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  95.         QuitGifError(GifFileIn, GifFileOut);
  96.     }
  97.     else {
  98.     /* Use the stdin instead: */
  99.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  100.         QuitGifError(GifFileIn, GifFileOut);
  101.     }
  102.  
  103.     /* Open stdout for the output file: */
  104.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  105.     QuitGifError(GifFileIn, GifFileOut);
  106.  
  107.     /* And dump out exactly same screen information: */
  108.     if (EGifPutScreenDesc(GifFileOut,
  109.     GifFileIn -> SWidth, GifFileIn -> SHeight,
  110.     GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  111.     GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == ERROR)
  112.     QuitGifError(GifFileIn, GifFileOut);
  113.  
  114.     /* Scan the content of the GIF file and load the image(s) in: */
  115.     do {
  116.     if (DGifGetRecordType(GifFileIn, &RecordType) == ERROR)
  117.         QuitGifError(GifFileIn, GifFileOut);
  118.  
  119.     switch (RecordType) {
  120.         case IMAGE_DESC_RECORD_TYPE:
  121.         if (DGifGetImageDesc(GifFileIn) == ERROR)
  122.             QuitGifError(GifFileIn, GifFileOut);
  123.  
  124.         /* Put the image descriptor to out file: */
  125.         if (EGifPutImageDesc(GifFileOut,
  126.             GifFileIn -> ILeft, GifFileIn -> ITop,
  127.             GifFileIn -> IWidth, GifFileIn -> IHeight,
  128.             InterlacedFlag, GifFileIn -> IBitsPerPixel,
  129.             GifFileIn -> IColorMap) == ERROR)
  130.             QuitGifError(GifFileIn, GifFileOut);
  131.  
  132.         /* Load the image (either Interlaced or not), and dump it as */
  133.         /* defined in GifFileOut -> IInterlaced.             */
  134.         if (LoadImage(GifFileIn, &ImageBuffer) == ERROR)
  135.             QuitGifError(GifFileIn, GifFileOut);
  136.         if (DumpImage(GifFileOut, ImageBuffer) == ERROR)
  137.             QuitGifError(GifFileIn, GifFileOut);
  138.         break;
  139.         case EXTENSION_RECORD_TYPE:
  140.         /* Skip any extension blocks in file: */
  141.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == ERROR)
  142.             QuitGifError(GifFileIn, GifFileOut);
  143.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  144.                             Extension) == ERROR)
  145.             QuitGifError(GifFileIn, GifFileOut);
  146.  
  147.         /* No support to more than one extension blocks, so discard: */
  148.         while (Extension != NULL) {
  149.             if (DGifGetExtensionNext(GifFileIn, &Extension) == ERROR)
  150.             QuitGifError(GifFileIn, GifFileOut);
  151.         }
  152.         break;
  153.         case TERMINATE_RECORD_TYPE:
  154.         break;
  155.         default:             /* Should be traps by DGifGetRecordType */
  156.         break;
  157.     }
  158.     }
  159.     while (RecordType != TERMINATE_RECORD_TYPE);
  160.  
  161.     if (DGifCloseFile(GifFileIn) == ERROR)
  162.     QuitGifError(GifFileIn, GifFileOut);
  163.     if (EGifCloseFile(GifFileOut) == ERROR)
  164.     QuitGifError(GifFileIn, GifFileOut);
  165. }
  166.  
  167. /******************************************************************************
  168. * Routine to read Image out. The image can be Interlaced or None interlaced.  *
  169. * The memory required to hold the image is allocate by the routine itself.    *
  170. * The image is always loaded sequencially into the buffer.              *
  171. * Return OK if succesful, ERROR otherwise.                      *
  172. ******************************************************************************/
  173. static int LoadImage(GifFileType *GifFile, RowType **ImageBufferPtr)
  174. {
  175.     int Size, i, j, Count;
  176.     RowType *ImageBuffer;
  177.  
  178.     /* Allocate the image as vector of column of rows. We cannt allocate     */
  179.     /* the all screen at once, as this broken minded CPU can allocate up to  */
  180.     /* 64k at a time and our image can be bigger than that:             */
  181.     if ((ImageBuffer = (RowType *)
  182.     malloc(GifFile -> IHeight * sizeof(RowType *))) == NULL)
  183.         EXIT("Failed to allocate memory required, aborted");
  184.  
  185.     Size = GifFile -> IWidth * sizeof(PixelType);   /* One row size in bytes */
  186.     for (i=0; i<GifFile -> IHeight; i++) {
  187.     /* Allocate the rows: */
  188.     if ((ImageBuffer[i] = (RowType) malloc(Size)) == NULL)
  189.         EXIT("Failed to allocate memory required, aborted\n");
  190.     }
  191.  
  192.     *ImageBufferPtr = ImageBuffer;
  193.  
  194.     fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  195.     ProgramName, ++ImageNum, GifFile -> ILeft, GifFile -> ITop,
  196.                  GifFile -> IWidth, GifFile -> IHeight);
  197.     if (GifFile -> IInterlace) {
  198.     /* Need to perform 4 passes on the images: */
  199.     for (Count=i=0; i<4; i++)
  200.         for (j=InterlacedOffset[i]; j<GifFile -> IHeight;
  201.                          j += InterlacedJumps[i]) {
  202.         fprintf(stderr, "\b\b\b\b%-4d", Count++);
  203.         if (DGifGetLine(GifFile, ImageBuffer[j], GifFile -> IWidth)
  204.             == ERROR) return ERROR;
  205.         }
  206.     }
  207.     else {
  208.     for (i=0; i<GifFile -> IHeight; i++) {
  209.         fprintf(stderr, "\b\b\b\b%-4d", i);
  210.         if (DGifGetLine(GifFile, ImageBuffer[i], GifFile -> IWidth)
  211.         == ERROR) return ERROR;
  212.     }
  213.     }
  214.  
  215.     return OK;
  216. }
  217.  
  218. /******************************************************************************
  219. * Routine to dump image out. The given Image buffer should always hold the    *
  220. * image sequencially. Image will be dumped according to IInterlaced flag in   *
  221. * GifFile structure. Once dumped, the memory holding the image is freed.      *
  222. * Return OK if succesful, ERROR otherwise.                      *
  223. ******************************************************************************/
  224. static int DumpImage(GifFileType *GifFile, RowType *ImageBuffer)
  225. {
  226.     int i, j, Count;
  227.  
  228.     if (GifFile -> IInterlace) {
  229.     /* Need to perform 4 passes on the images: */
  230.     for (Count=GifFile -> IHeight, i=0; i<4; i++)
  231.         for (j=InterlacedOffset[i]; j<GifFile -> IHeight;
  232.                          j += InterlacedJumps[i]) {
  233.         fprintf(stderr, "\b\b\b\b%-4d", Count--);
  234.         if (EGifPutLine(GifFile, ImageBuffer[j], GifFile -> IWidth)
  235.             == ERROR) return ERROR;
  236.         }
  237.     }
  238.     else {
  239.     for (Count=GifFile -> IHeight, i=0; i<GifFile -> IHeight; i++) {
  240.         fprintf(stderr, "\b\b\b\b%-4d", Count--);
  241.         if (EGifPutLine(GifFile, ImageBuffer[i], GifFile -> IWidth)
  242.         == ERROR) return ERROR;
  243.     }
  244.     }
  245.  
  246.     /* Free the memory used for this image: */
  247.     for (i=0; i<GifFile -> IHeight; i++) free((char *) ImageBuffer[i]);
  248.     free((char *) ImageBuffer);
  249.  
  250.     return OK;
  251. }
  252.  
  253. /******************************************************************************
  254. * Close both input and output file (if open), and exit.                  *
  255. ******************************************************************************/
  256. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  257. {
  258.     PrintGifError();
  259.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  260.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  261.     exit(1);
  262. }
  263.