home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / viewers / giflib12 / util / gifclip.c < prev    next >
C/C++ Source or Header  |  1991-05-12  |  9KB  |  257 lines

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Jul. 1989   *
  5. ******************************************************************************
  6. * Program to clip an image and dump out only portion of it.             *
  7. * Options:                                     *
  8. * -q : quite printing mode.                             *
  9. * -i left top width bottom : clipping information for first image.         *
  10. * -n n left top width bottom : clipping information for nth image.         *
  11. * -h : on line help                                 *
  12. ******************************************************************************
  13. * History:                                     *
  14. * 8 Jul 89 - Version 1.0 by Gershon Elber.                     *
  15. *****************************************************************************/
  16.  
  17. #ifdef __MSDOS__
  18. #include <stdlib.h>
  19. #include <alloc.h>
  20. #endif /* __MSDOS__ */
  21.  
  22. #include <stdio.h>
  23. #include <ctype.h>
  24. #include <string.h>
  25. #include "gif_lib.h"
  26. #include "getarg.h"
  27.  
  28. #define PROGRAM_NAME    "GifClip"
  29.  
  30. #ifdef __MSDOS__
  31. extern unsigned int
  32.     _stklen = 16384;                 /* Increase default stack size. */
  33. #endif /* __MSDOS__ */
  34.  
  35. #ifdef SYSV
  36. static char *VersionStr =
  37.         "Gif library module,\t\tGershon Elber\n\
  38.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  39. static char
  40.     *CtrlStr = "GifClip q%- i%-Xmin|Ymin|Xmax|Ymax!d!d!d!d n%-n|Xmin|Ymin|Xmax|Ymax!d!d!d!d!d h%- GifFile!*s";
  41. #else
  42. static char
  43.     *VersionStr =
  44.     PROGRAM_NAME
  45.     GIF_LIB_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.     " q%- i%-Xmin|Ymin|Xmax|Ymax!d!d!d!d n%-n|Xmin|Ymin|Xmax|Ymax!d!d!d!d!d h%- GifFile!*s";
  53. #endif /* SYSV */
  54.  
  55. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  56.  
  57. /******************************************************************************
  58. * Interpret the command line and scan the given GIF file.              *
  59. ******************************************************************************/
  60. void main(int argc, char **argv)
  61. {
  62.     int    i, Error, NumFiles, ExtCode, CodeSize, ImageNum = 0,
  63.     ImageFlag = FALSE, ImageNFlag = FALSE, ImageN, ImageX1, ImageY1,
  64.     ImageX2, ImageY2, ImageWidth, HelpFlag = FALSE;
  65.     GifRecordType RecordType;
  66.     GifByteType *Extension, *CodeBlock;
  67.     char **FileName = NULL;
  68.     GifRowType Line;
  69.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  70.  
  71.     /* Same image dimension vars for both Image & ImageN as only one allowed.*/
  72.     if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuitePrint,
  73.         &ImageFlag, &ImageX1, &ImageY1, &ImageX2, &ImageY2,
  74.         &ImageNFlag, &ImageN, &ImageX1, &ImageY1, &ImageX2, &ImageY2,
  75.         &HelpFlag, &NumFiles, &FileName)) != FALSE ||
  76.         (NumFiles > 1 && !HelpFlag)) {
  77.     if (Error)
  78.         GAPrintErrMsg(Error);
  79.     else if (NumFiles > 1)
  80.         GIF_MESSAGE("Error in command line parsing - one GIF file please.");
  81.     GAPrintHowTo(CtrlStr);
  82.     exit(1);
  83.     }
  84.  
  85.     if (HelpFlag) {
  86.     fprintf(stderr, VersionStr);
  87.     GAPrintHowTo(CtrlStr);
  88.     exit(0);
  89.     }
  90.  
  91.     /* Test to make sure exactly one of ImageFlag & ImageNFlag is set: */
  92.     if ((ImageFlag && ImageNFlag) || (!ImageFlag && !ImageNFlag)) {
  93.     GIF_MESSAGE("Exactly one of [-i ...] && [-n ...] please.");
  94.     GAPrintHowTo(CtrlStr);
  95.     exit(1);
  96.     }
  97.     if (ImageFlag) ImageN = 1;            /* Its first image we are after. */
  98.  
  99.     /* Make sure the first coordinates of clipping box are smaller: */
  100.     if (ImageX1 > ImageX2) {
  101.     i = ImageX1;
  102.     ImageX1 = ImageX2;
  103.     ImageX2 = i;
  104.     }
  105.     if (ImageY1 > ImageY2) {
  106.     i = ImageX1;
  107.     ImageY1 = ImageY2;
  108.     ImageY2 = i;
  109.     }
  110.     ImageWidth = ImageX2 - ImageX1 + 1;           /* Width of clipped image. */
  111.  
  112.     if (NumFiles == 1) {
  113.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  114.         QuitGifError(GifFileIn, GifFileOut);
  115.     }
  116.     else {
  117.     /* Use the stdin instead: */
  118.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  119.         QuitGifError(GifFileIn, GifFileOut);
  120.     }
  121.  
  122.     /* Open stdout for the output file: */
  123.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  124.     QuitGifError(GifFileIn, GifFileOut);
  125.  
  126.     /* And dump out exactly same screen information: */
  127.     if (EGifPutScreenDesc(GifFileOut,
  128.     GifFileIn -> SWidth, GifFileIn -> SHeight,
  129.     GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  130.     GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR)
  131.     QuitGifError(GifFileIn, GifFileOut);
  132.  
  133.     /* Scan the content of the GIF file and load the image(s) in: */
  134.     do {
  135.     if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
  136.         QuitGifError(GifFileIn, GifFileOut);
  137.  
  138.     switch (RecordType) {
  139.         case IMAGE_DESC_RECORD_TYPE:
  140.         if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
  141.             QuitGifError(GifFileIn, GifFileOut);
  142.         if (++ImageNum == ImageN) {
  143.             /* We can handle only non interlaced images here: */
  144.             if (GifFileIn -> IInterlace)
  145.             GIF_EXIT("Image to clip is interlaced - use GifInter first.");
  146.  
  147.             /* This is the image we should clip - test sizes and     */
  148.             /* dump out new clipped screen descriptor if o.k.         */
  149.             if (GifFileIn -> IWidth <= ImageX2 ||
  150.             GifFileIn -> IHeight <= ImageY2)
  151.             GIF_EXIT("Image is smaller than given clip dimensions.");
  152.  
  153.             /* Put the image descriptor to out file: */
  154.             if (EGifPutImageDesc(GifFileOut,
  155.             GifFileIn -> ILeft, GifFileIn -> ITop,
  156.             ImageWidth, ImageY2 - ImageY1 + 1,
  157.             FALSE, GifFileIn -> IBitsPerPixel,
  158.             GifFileIn -> IColorMap) == GIF_ERROR)
  159.             QuitGifError(GifFileIn, GifFileOut);
  160.  
  161.             /* o.k. - read the image and clip it: */
  162.             Line = (GifRowType) malloc(GifFileIn -> IWidth *
  163.                             sizeof(GifPixelType));
  164.             GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  165.             PROGRAM_NAME, ImageNum,
  166.             GifFileIn -> ILeft, GifFileIn -> ITop,
  167.             GifFileIn -> IWidth, GifFileIn -> IHeight);
  168.  
  169.             /* Skip lines below ImageY1: */
  170.             for (i = 0; i < ImageY1; i++) {
  171.             if (DGifGetLine(GifFileIn, Line, GifFileIn -> IWidth)
  172.                 == GIF_ERROR)
  173.                 QuitGifError(GifFileIn, GifFileOut);
  174.             GifQprintf("\b\b\b\b%-4d", i);
  175.             }
  176.  
  177.             /* Clip the lines from ImageY1 to ImageY2 (to X1 - X2): */
  178.             for (i = ImageY1; i <= ImageY2; i++) {
  179.             if (DGifGetLine(GifFileIn, Line, GifFileIn -> IWidth)
  180.                 == GIF_ERROR)
  181.                 QuitGifError(GifFileIn, GifFileOut);
  182.             if (EGifPutLine(GifFileOut, &Line[ImageX1],
  183.                             ImageWidth) == GIF_ERROR)
  184.                 QuitGifError(GifFileIn, GifFileOut);
  185.             GifQprintf("\b\b\b\b%-4d", i);
  186.             }
  187.  
  188.             /* Skip lines above ImageY2: */
  189.             for (i = ImageY2 + 1; i < GifFileIn -> IHeight; i++) {
  190.             if (DGifGetLine(GifFileIn, Line, GifFileIn -> IWidth)
  191.                 == GIF_ERROR)
  192.                 QuitGifError(GifFileIn, GifFileOut);
  193.             GifQprintf("\b\b\b\b%-4d", i);
  194.             }
  195.  
  196.             free((char *) Line);
  197.         }
  198.         else {
  199.             /* Copy the image as is (we dont modify this one): */
  200.             if (EGifPutImageDesc(GifFileOut,
  201.             GifFileIn -> ILeft, GifFileIn -> ITop,
  202.             GifFileIn -> IWidth, GifFileIn -> IHeight,
  203.             GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel,
  204.             GifFileIn -> IColorMap) == GIF_ERROR)
  205.             QuitGifError(GifFileIn, GifFileOut);
  206.  
  207.             /* Now read image itself in decoded form as we dont      */
  208.             /* really care what is there, and this is much faster.   */
  209.             if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR
  210.              || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR)
  211.             QuitGifError(GifFileIn, GifFileOut);
  212.             while (CodeBlock != NULL)
  213.             if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR ||
  214.                 EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR)
  215.                 QuitGifError(GifFileIn, GifFileOut);
  216.         }
  217.         break;
  218.         case EXTENSION_RECORD_TYPE:
  219.         /* Skip any extension blocks in file: */
  220.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
  221.             QuitGifError(GifFileIn, GifFileOut);
  222.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  223.                             Extension) == GIF_ERROR)
  224.             QuitGifError(GifFileIn, GifFileOut);
  225.  
  226.         /* No support to more than one extension blocks, so discard: */
  227.         while (Extension != NULL) {
  228.             if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR)
  229.             QuitGifError(GifFileIn, GifFileOut);
  230.         }
  231.         break;
  232.         case TERMINATE_RECORD_TYPE:
  233.         break;
  234.         default:            /* Should be traps by DGifGetRecordType. */
  235.         break;
  236.     }
  237.     }
  238.     while (RecordType != TERMINATE_RECORD_TYPE);
  239.  
  240.     if (DGifCloseFile(GifFileIn) == GIF_ERROR)
  241.     QuitGifError(GifFileIn, GifFileOut);
  242.     if (EGifCloseFile(GifFileOut) == GIF_ERROR)
  243.     QuitGifError(GifFileIn, GifFileOut);
  244. }
  245.  
  246. /******************************************************************************
  247. * Close both input and output file (if open), and exit.                  *
  248. ******************************************************************************/
  249. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  250. {
  251.     PrintGifError();
  252.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  253.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  254.     exit(1);
  255. }
  256.  
  257.