home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / graphics / gif-util.zip / GIFCLIP.C < prev    next >
C/C++ Source or Header  |  1989-08-01  |  9KB  |  250 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 clip an image and dump out only portion of it.             *
  7. * Options:                                     *
  8. * -i left top width bottom : clipping information for first image.         *
  9. * -n n left top width bottom : clipping information for nth image.         *
  10. * -h : on line help                                 *
  11. ******************************************************************************
  12. * History:                                     *
  13. * 8 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    "GifClip"
  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%-Xmin|Ymin|Xmax|Ymax!d!d!d!d n%-n|Xmin|Ymin|Xmax|Ymax!d!d!d!d!d h%- GifFile!*s";
  42. static char
  43.     *ProgramName;
  44.  
  45. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  46.  
  47. /******************************************************************************
  48. * Interpret the command line and scan the given GIF file.              *
  49. ******************************************************************************/
  50. void main(int argc, char **argv)
  51. {
  52.     int    i, Error, NumFiles, ExtCode, CodeSize, ImageNum = 0,
  53.     ImageFlag = FALSE, ImageNFlag = FALSE, ImageN, ImageX1, ImageY1,
  54.     ImageX2, ImageY2, ImageWidth, HelpFlag = FALSE;
  55.     GifRecordType RecordType;
  56.     ByteType *Extension, *CodeBlock;
  57.     char **FileName = NULL;
  58.     RowType Line;
  59.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  60.  
  61.     if (strlen(ProgramName = argv[0]) == 0)            /* DOS 3.x only! */
  62.     ProgramName = PROGRAM_NAME;      /* Do something reasonable for 2.x */
  63.  
  64.     /* Same image dimension vars for both Image & ImageN as only one allowed */
  65.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  66.         &ImageFlag, &ImageX1, &ImageY1, &ImageX2, &ImageY2,
  67.         &ImageNFlag, &ImageN, &ImageX1, &ImageY1, &ImageX2, &ImageY2,
  68.         &HelpFlag, &NumFiles, &FileName)) != FALSE ||
  69.         (NumFiles > 1 && !HelpFlag)) {
  70.     if (Error) GAPrintErrMsg(Error);
  71.     else
  72.     if (NumFiles > 1)
  73.         MESSAGE("Error in command line parsing - one GIF file please\n");
  74.     GAPrintHowTo(CtrlStr);
  75.     exit(1);
  76.     }
  77.  
  78.     if (HelpFlag) {
  79.     fprintf(stderr, VersionStr);
  80.     GAPrintHowTo(CtrlStr);
  81.     exit(0);
  82.     }
  83.  
  84.     /* Test to make sure exactly one of ImageFlag & ImageNFlag is set: */
  85.     if ((ImageFlag && ImageNFlag) || (!ImageFlag && !ImageNFlag)) {
  86.     MESSAGE("Exactly one of [-i ...] && [-n ...] please\n");
  87.     GAPrintHowTo(CtrlStr);
  88.     exit(1);
  89.     }
  90.     if (ImageFlag) ImageN = 1;             /* Its first image we are after */
  91.  
  92.     /* Make sure the first coordinates of clipping box are smaller: */
  93.     if (ImageX1 > ImageX2) {
  94.     i = ImageX1;
  95.     ImageX1 = ImageX2;
  96.     ImageX2 = i;
  97.     }
  98.     if (ImageY1 > ImageY2) {
  99.     i = ImageX1;
  100.     ImageY1 = ImageY2;
  101.     ImageY2 = i;
  102.     }
  103.     ImageWidth = ImageX2 - ImageX1 + 1;            /* Width of clipped image */
  104.  
  105.     if (NumFiles == 1) {
  106.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  107.         QuitGifError(GifFileIn, GifFileOut);
  108.     }
  109.     else {
  110.     /* Use the stdin instead: */
  111.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  112.         QuitGifError(GifFileIn, GifFileOut);
  113.     }
  114.  
  115.     /* Open stdout for the output file: */
  116.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  117.     QuitGifError(GifFileIn, GifFileOut);
  118.  
  119.     /* And dump out exactly same screen information: */
  120.     if (EGifPutScreenDesc(GifFileOut,
  121.     GifFileIn -> SWidth, GifFileIn -> SHeight,
  122.     GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  123.     GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == ERROR)
  124.     QuitGifError(GifFileIn, GifFileOut);
  125.  
  126.     /* Scan the content of the GIF file and load the image(s) in: */
  127.     do {
  128.     if (DGifGetRecordType(GifFileIn, &RecordType) == ERROR)
  129.         QuitGifError(GifFileIn, GifFileOut);
  130.  
  131.     switch (RecordType) {
  132.         case IMAGE_DESC_RECORD_TYPE:
  133.         if (DGifGetImageDesc(GifFileIn) == ERROR)
  134.             QuitGifError(GifFileIn, GifFileOut);
  135.         if (++ImageNum == ImageN) {
  136.             /* We can handle only non interlaced images here: */
  137.             if (GifFileIn -> IInterlace)
  138.             EXIT("Image to clip is interlaced - use GifInter first\n");
  139.  
  140.             /* This is the image we should clip - test sizes and     */
  141.             /* dump out new clipped screen descriptor if o.k.         */
  142.             if (GifFileIn -> IWidth <= ImageX2 ||
  143.             GifFileIn -> IHeight <= ImageY2)
  144.             EXIT("Image is smaller than given clip dimensions\n");
  145.  
  146.             /* Put the image descriptor to out file: */
  147.             if (EGifPutImageDesc(GifFileOut,
  148.             GifFileIn -> ILeft, GifFileIn -> ITop,
  149.             ImageWidth, ImageY2 - ImageY1 + 1,
  150.             FALSE, GifFileIn -> IBitsPerPixel,
  151.             GifFileIn -> IColorMap) == ERROR)
  152.             QuitGifError(GifFileIn, GifFileOut);
  153.  
  154.             /* o.k. - read the image and clip it: */
  155.             Line = (RowType) malloc(GifFileIn -> IWidth *
  156.                             sizeof(PixelType));
  157.             fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  158.             ProgramName, ImageNum,
  159.             GifFileIn -> ILeft, GifFileIn -> ITop,
  160.             GifFileIn -> IWidth, GifFileIn -> IHeight);
  161.  
  162.             /* Skip lines below ImageY1: */
  163.             for (i=0; i<ImageY1; i++) {
  164.             if (DGifGetLine(GifFileIn, Line, GifFileIn -> IWidth)
  165.                 == ERROR)
  166.                 QuitGifError(GifFileIn, GifFileOut);
  167.             fprintf(stderr, "\b\b\b\b%-4d", i);
  168.             }
  169.  
  170.             /* Clip the lines from ImageY1 to ImageY2 (to X1 - X2): */
  171.             for (i=ImageY1; i<=ImageY2; i++) {
  172.             if (DGifGetLine(GifFileIn, Line, GifFileIn -> IWidth)
  173.                 == ERROR)
  174.                 QuitGifError(GifFileIn, GifFileOut);
  175.             if (EGifPutLine(GifFileOut, &Line[ImageX1],
  176.                             ImageWidth) == ERROR)
  177.                 QuitGifError(GifFileIn, GifFileOut);
  178.             fprintf(stderr, "\b\b\b\b%-4d", i);
  179.             }
  180.  
  181.             /* Skip lines above ImageY2: */
  182.             for (i=ImageY2+1; i<GifFileIn -> IHeight; i++) {
  183.             if (DGifGetLine(GifFileIn, Line, GifFileIn -> IWidth)
  184.                 == ERROR)
  185.                 QuitGifError(GifFileIn, GifFileOut);
  186.             fprintf(stderr, "\b\b\b\b%-4d", i);
  187.             }
  188.  
  189.             free((char *) Line);
  190.         }
  191.         else {
  192.             /* Copy the image as is (we dont modify this one): */
  193.             if (EGifPutImageDesc(GifFileOut,
  194.             GifFileIn -> ILeft, GifFileIn -> ITop,
  195.             GifFileIn -> IWidth, GifFileIn -> IHeight,
  196.             GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel,
  197.             GifFileIn -> IColorMap) == ERROR)
  198.             QuitGifError(GifFileIn, GifFileOut);
  199.  
  200.             /* Now read image itself in decoded form as we dont      */
  201.             /* really care what is there, and this is much faster.   */
  202.             if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == ERROR
  203.              || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == ERROR)
  204.             QuitGifError(GifFileIn, GifFileOut);
  205.             while (CodeBlock != NULL)
  206.             if (DGifGetCodeNext(GifFileIn, &CodeBlock) == ERROR ||
  207.                 EGifPutCodeNext(GifFileOut, CodeBlock) == ERROR)
  208.                 QuitGifError(GifFileIn, GifFileOut);
  209.         }
  210.         break;
  211.         case EXTENSION_RECORD_TYPE:
  212.         /* Skip any extension blocks in file: */
  213.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == ERROR)
  214.             QuitGifError(GifFileIn, GifFileOut);
  215.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  216.                             Extension) == ERROR)
  217.             QuitGifError(GifFileIn, GifFileOut);
  218.  
  219.         /* No support to more than one extension blocks, so discard: */
  220.         while (Extension != NULL) {
  221.             if (DGifGetExtensionNext(GifFileIn, &Extension) == ERROR)
  222.             QuitGifError(GifFileIn, GifFileOut);
  223.         }
  224.         break;
  225.         case TERMINATE_RECORD_TYPE:
  226.         break;
  227.         default:             /* Should be traps by DGifGetRecordType */
  228.         break;
  229.     }
  230.     }
  231.     while (RecordType != TERMINATE_RECORD_TYPE);
  232.  
  233.     if (DGifCloseFile(GifFileIn) == ERROR)
  234.     QuitGifError(GifFileIn, GifFileOut);
  235.     if (EGifCloseFile(GifFileOut) == ERROR)
  236.     QuitGifError(GifFileIn, GifFileOut);
  237. }
  238.  
  239. /******************************************************************************
  240. * Close both input and output file (if open), and exit.                  *
  241. ******************************************************************************/
  242. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  243. {
  244.     PrintGifError();
  245.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  246.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  247.     exit(1);
  248. }
  249.  
  250.