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

  1. /*****************************************************************************
  2. *   "Gif-Lib" - Yet another gif library.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, Jul. 1989   *
  5. ******************************************************************************
  6. * Program to resize GIF by given factors horizontally and vertically.         *
  7. * Options:                                     *
  8. * -s n : resize both x & y direction by factor n.                 *
  9. * -x n : resize the x direction (horizontally) by factor n.             *
  10. * -y n : resize the y direction (vertically) by factor n.             *
  11. * -u : set up instead of down (default) by factor n.                 *
  12. * -d : scale down (default).                             *
  13. * -h : on line help.                                 *
  14. ******************************************************************************
  15. * History:                                     *
  16. * 4 Jul 89 - Version 1.0 by Gershon Elber.                     *
  17. * 22 Dec 89 - Fix minor bag in discarding last line of input (Version 1.1).  *
  18. *****************************************************************************/
  19.  
  20. #ifdef __MSDOS__
  21. #include <stdlib.h>
  22. #include <alloc.h>
  23. #endif /* __MSDOS__ */
  24.  
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <string.h>
  28. #include "gif_lib.h"
  29. #include "getarg.h"
  30.  
  31. #define PROGRAM_NAME    "GifRSize"
  32.  
  33. #define MAX_SCALE    16              /* Maximum scaling factor. */
  34.  
  35. #ifdef __MSDOS__
  36. extern unsigned int
  37.     _stklen = 16384;                 /* Increase default stack size. */
  38. #endif /* __MSDOS__ */
  39.  
  40. #ifdef SYSV
  41. static char *VersionStr =
  42.         "Gif library module,\t\tGershon Elber\n\
  43.     (C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  44. static char
  45.     *CtrlStr = "GifRSize s%-Scale!d x%-XScale!d y%-YScale!d u%- d%- h%- GifFile!*s";
  46. #else
  47. static char
  48.     *VersionStr =
  49.     PROGRAM_NAME
  50.     GIF_LIB_VERSION
  51.     "    Gershon Elber,    "
  52.     __DATE__ ",   " __TIME__ "\n"
  53.     "(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
  54. static char
  55.     *CtrlStr =
  56.     PROGRAM_NAME
  57.     " s%-Scale!d x%-XScale!d y%-YScale!d u%- d%- h%- GifFile!*s";
  58. #endif /* SYSV */
  59.  
  60. /* Make some variables global, so we could access them faster: */
  61. static GifPixelType
  62.     BackGroundColor = 0;
  63. static int
  64.     XScale = 2,
  65.     YScale = 2,
  66.     ScaleDown = TRUE;
  67.  
  68. static void Average(GifRowType LineIn[], GifRowType LineOut[], int OutLineLen);
  69. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
  70.  
  71. /******************************************************************************
  72. * Interpret the command line and scan the given GIF file.              *
  73. ******************************************************************************/
  74. void main(int argc, char **argv)
  75. {
  76.     int    i, j, Error, NumFiles, ExtCode, ImageNum = 0, Scale, InCount,
  77.     ScaleFlag = FALSE, XScaleFlag = FALSE, YScaleFlag = FALSE,
  78.     UpFlag = FALSE, DownFlag = FALSE, HelpFlag = FALSE;
  79.     GifRecordType RecordType;
  80.     char s[80];
  81.     GifByteType *Extension;
  82.     GifRowType LineIn[MAX_SCALE], LineOut[MAX_SCALE];
  83.     char **FileName = NULL;
  84.     GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
  85.  
  86.     if ((Error = GAGetArgs(argc, argv, CtrlStr, &ScaleFlag, &Scale,
  87.         &XScaleFlag, &XScale, &YScaleFlag, &YScale, &UpFlag, &DownFlag,
  88.         &HelpFlag, &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.     /* Decide if we scale up or down: */
  105.     if (UpFlag) ScaleDown = FALSE;
  106.     if (DownFlag) ScaleDown = TRUE;
  107.  
  108.     /* If specific direction was set, set other direction to 1: */
  109.     if (!XScaleFlag && YScaleFlag) XScale = 1;
  110.     if (!YScaleFlag && XScaleFlag) YScale = 1;
  111.  
  112.     /* If the specific direction was not set, but global one did use it: */
  113.     if (!XScaleFlag && ScaleFlag) XScale = Scale;
  114.     if (!YScaleFlag && ScaleFlag) YScale = Scale;
  115.     if (XScale > MAX_SCALE) {
  116.     sprintf(s, "XScale too big, maximum scale selected instead (%d).",
  117.                                 MAX_SCALE);
  118.     GIF_MESSAGE(s);
  119.     XScale = MAX_SCALE;
  120.     }
  121.     if (YScale > MAX_SCALE) {
  122.     sprintf(s, "YScale too big, maximum scale selected instead (%d).",
  123.                                 MAX_SCALE);
  124.     GIF_MESSAGE(s);
  125.     YScale = MAX_SCALE;
  126.     }
  127.  
  128.     if (NumFiles == 1) {
  129.     if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
  130.         QuitGifError(GifFileIn, GifFileOut);
  131.     }
  132.     else {
  133.     /* Use the stdin instead: */
  134.     if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
  135.         QuitGifError(GifFileIn, GifFileOut);
  136.     }
  137.     BackGroundColor = GifFileIn -> SBackGroundColor;
  138.  
  139.     /* As at this time we know the Screen size of the input gif file, and as */
  140.     /* all image(s) in file must be less/equal to it, we can allocate the    */
  141.     /* scan lines for the input file, and output file. The number of lines   */
  142.     /* to allocate for each is set by ScaleDown & XScale & YScale:         */
  143.     if (ScaleDown) {
  144.     /* Output is smaller than input so we need only one output scanline: */
  145.     LineOut[0] = (GifRowType) malloc(GifFileIn -> SWidth / XScale *
  146.                             sizeof(GifPixelType));
  147.     for (i = 0; i < YScale; i++) LineIn[i] =
  148.         (GifRowType) malloc(GifFileIn -> SWidth * sizeof(GifPixelType));
  149.     if (LineIn[YScale - 1] == NULL)
  150.         GIF_EXIT("Failed to allocate memory required, aborted.");
  151.     }
  152.     else {
  153.     /* Input is smaller than output so we need only one input scanline:  */
  154.     LineIn[0] = (GifRowType) malloc(GifFileIn -> SWidth *
  155.                             sizeof(GifPixelType));
  156.     for (i = 0; i < YScale; i++) LineOut[i] =
  157.         (GifRowType) malloc(GifFileIn -> SWidth * XScale * sizeof(GifPixelType));
  158.     if (LineOut[YScale - 1] == NULL)
  159.         GIF_EXIT("Failed to allocate memory required, aborted.");
  160.     }
  161.  
  162.     /* Open stdout for the output file: */
  163.     if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
  164.     QuitGifError(GifFileIn, GifFileOut);
  165.  
  166.     /* And dump out its new scaled screen information: */
  167.     if (EGifPutScreenDesc(GifFileOut,
  168.     ScaleDown ? GifFileIn -> SWidth / XScale :
  169.             GifFileIn -> SWidth * XScale,
  170.     ScaleDown ? GifFileIn -> SHeight / YScale :
  171.             GifFileIn -> SHeight * YScale,
  172.     GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
  173.     GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR)
  174.     QuitGifError(GifFileIn, GifFileOut);
  175.  
  176.  
  177.     /* Scan the content of the GIF file and load the image(s) in: */
  178.     do {
  179.     if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
  180.         QuitGifError(GifFileIn, GifFileOut);
  181.  
  182.     switch (RecordType) {
  183.         case IMAGE_DESC_RECORD_TYPE:
  184.         if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
  185.             QuitGifError(GifFileIn, GifFileOut);
  186.         /* Put the image descriptor to out file: */
  187.         if (EGifPutImageDesc(GifFileOut,
  188.             ScaleDown ? GifFileIn -> ILeft / XScale :
  189.                 GifFileIn -> ILeft * XScale,
  190.             ScaleDown ? GifFileIn -> ITop / YScale :
  191.                 GifFileIn -> ITop * YScale,
  192.             ScaleDown ? GifFileIn -> IWidth / XScale :
  193.                 GifFileIn -> IWidth * XScale,
  194.             ScaleDown ? GifFileIn -> IHeight / YScale :
  195.                 GifFileIn -> IHeight * YScale,
  196.             GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel,
  197.             GifFileIn -> IColorMap) == GIF_ERROR)
  198.             QuitGifError(GifFileIn, GifFileOut);
  199.  
  200.         if (GifFileIn -> IInterlace) {
  201.             GIF_EXIT("Cannt average4 interlaced images - use GifInter first.");
  202.         }
  203.         else {
  204.             fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]:     ",
  205.             PROGRAM_NAME, ++ImageNum,
  206.             GifFileOut -> ILeft, GifFileOut -> ITop,
  207.             GifFileOut -> IWidth, GifFileOut -> IHeight);
  208.             InCount = 0;
  209.             if (ScaleDown) {
  210.             /* For each line of output, read YScale input lines, */
  211.             /* average them, and dump result out:             */
  212.             for (i = 0; i < GifFileOut -> IHeight; i++) {
  213.                 fprintf(stderr, "\b\b\b\b%-4d", i);
  214.                 for (j = 0; j < YScale; j++)
  215.                 if (DGifGetLine(GifFileIn, LineIn[j],
  216.                         GifFileIn -> IWidth) == GIF_ERROR)
  217.                     QuitGifError(GifFileIn, GifFileOut);
  218.                 InCount += YScale;
  219.                 Average(LineIn, LineOut, GifFileOut -> IWidth);
  220.                 if (EGifPutLine(GifFileOut, LineOut[0],
  221.                         GifFileOut -> IWidth) == GIF_ERROR)
  222.                 QuitGifError(GifFileIn, GifFileOut);
  223.             }
  224.             /* If scale is not dividable - discard last lines: */
  225.             for (i = InCount; i < GifFileIn -> IHeight; i++)
  226.                 DGifGetLine(GifFileIn, LineIn[0],
  227.                             GifFileIn -> IWidth);
  228.             }
  229.             else {
  230.             /* For each line of input, output YScale lines,         */
  231.             /* by averaging up this line to YScale lines:         */
  232.             for (i = 0; i < GifFileIn -> IHeight; i++) {
  233.                 fprintf(stderr, "\b\b\b\b%-4d", i * YScale);
  234.                 if (DGifGetLine(GifFileIn, LineIn[0],
  235.                         GifFileIn -> IWidth) == GIF_ERROR)
  236.                 QuitGifError(GifFileIn, GifFileOut);
  237.                 Average(LineIn, LineOut, GifFileOut -> IWidth);
  238.                 for (j = 0; j < YScale; j++)
  239.                 if (EGifPutLine(GifFileOut, LineOut[j],
  240.                         GifFileOut -> IWidth) == GIF_ERROR)
  241.                     QuitGifError(GifFileIn, GifFileOut);
  242.             }
  243.             }
  244.         }
  245.         break;
  246.         case EXTENSION_RECORD_TYPE:
  247.         /* Skip any extension blocks in file: */
  248.         if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
  249.             QuitGifError(GifFileIn, GifFileOut);
  250.         if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
  251.                             Extension) == GIF_ERROR)
  252.             QuitGifError(GifFileIn, GifFileOut);
  253.  
  254.         /* No support to more than one extension blocks, so discard: */
  255.         while (Extension != NULL) {
  256.             if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR)
  257.             QuitGifError(GifFileIn, GifFileOut);
  258.         }
  259.         break;
  260.         case TERMINATE_RECORD_TYPE:
  261.         break;
  262.         default:            /* Should be traps by DGifGetRecordType. */
  263.         break;
  264.     }
  265.     }
  266.     while (RecordType != TERMINATE_RECORD_TYPE);
  267.  
  268.     if (DGifCloseFile(GifFileIn) == GIF_ERROR)
  269.     QuitGifError(GifFileIn, GifFileOut);
  270.     if (EGifCloseFile(GifFileOut) == GIF_ERROR)
  271.     QuitGifError(GifFileIn, GifFileOut);
  272. }
  273.  
  274. /******************************************************************************
  275. * Average routine - scale given lines as follows:                  *
  276. *   ScaleDown: for each YScale lines, for each box of size XScale by YScale   *
  277. * pick a pixel in it (usually upper left). If that pixel is equal to          *
  278. * background color, and there is in that square, none background pixel, pick  *
  279. * that instead. Use result pixel as output averaged pixel              *
  280. *   ScaleUp: each input pixel, is expanded both in X and in Y by the factors  *
  281. * XScale & YScale respectively.                              *
  282. ******************************************************************************/
  283. static void Average(GifRowType LineIn[], GifRowType LineOut[], int OutLineLen)
  284. {
  285.     int i, j, k, o;
  286.     GifPixelType Color;
  287.  
  288.  
  289.     if (ScaleDown) {
  290.     /* For each XScale by YScale pixels in a box, pick the top left one  */
  291.     /* if not background color, otherwise pick any non background from   */
  292.     /* other pixels in box if one exists.                     */
  293.     for (i = 0, o = 0; o < OutLineLen; i += XScale, o++) {
  294.         if ((Color = LineIn[0][i]) == BackGroundColor) {
  295.         /* Scan all pixels to find non background color if exists: */
  296.         for (j = i; j < i + XScale && Color == BackGroundColor; j++)
  297.             for (k = 0; k<YScale && Color == BackGroundColor; k++)
  298.             if (LineIn[k][j] != BackGroundColor)
  299.                 Color = LineIn[k][j];
  300.         }
  301.         LineOut[0][o] = Color;
  302.     }
  303.     }
  304.     else {
  305.     /* Make each input pixel a box of size XScale bu YScale: */
  306.     for (i = 0, o = 0; o < OutLineLen; i++, o+=XScale) {
  307.         /* Prepare first line. */
  308.         for (j = 0; j < XScale; j++) LineOut[0][o+j] = LineIn[0][i];
  309.         }
  310.     /* And duplicate the other lines from first one: */
  311.     for (i = 1; i < YScale; i++) memcpy(LineOut[i], LineOut[0],
  312.                     OutLineLen * sizeof(GifPixelType));
  313.     }
  314. }
  315.  
  316. /******************************************************************************
  317. * Close both input and output file (if open), and exit.                  *
  318. ******************************************************************************/
  319. static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
  320. {
  321.     PrintGifError();
  322.     if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
  323.     if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
  324.     exit(1);
  325. }
  326.