Category : C Source Code
Archive   : GIF_LIB.ZIP
Filename : GIFRSIZE.C

 
Output of file : GIFRSIZE.C contained in archive : GIF_LIB.ZIP
/*****************************************************************************
* "Gif-Lib" - Yet another gif library. *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Jul. 1989 *
******************************************************************************
* Program to resize GIF by given factors horizontally and vertically. *
* Options: *
* -s n : resize both x & y direction by factor n. *
* -x n : resize the x direction (horizontally) by factor n. *
* -y n : resize the y direction (vertically) by factor n. *
* -u : set up instead of down (default) by factor n. *
* -d : scale down (default). *
* -h : on line help. *
******************************************************************************
* History: *
* 4 Jul 89 - Version 1.0 by Gershon Elber. *
*****************************************************************************/

#include
#include
#include
#include
#include
#include "gif_lib.h"
#include "getarg.h"

#define PROGRAM_NAME "GifRSize"
#define VERSION "á Version 1.0, "

#define MAX_SCALE 16 /* Maximum scaling factor */

extern unsigned int
_stklen = 16384; /* Increase default stack size */

static char
*VersionStr =
PROGRAM_NAME
" IBMPC "
VERSION
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";
static char
*CtrlStr =
PROGRAM_NAME
" s%-Scale!d x%-XScale!d y%-YScale!d u%- d%- h%- GifFile!*s";
static char *ProgramName;

/* Make some variables global, so we could access them faster: */
static PixelType
BackGroundColor = 0;
static int
XScale = 2,
YScale = 2,
ScaleDown = TRUE;

static void Average(RowType LineIn[], RowType LineOut[], int OutLineLen);
static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);

/******************************************************************************
* Interpret the command line and scan the given GIF file. *
******************************************************************************/
void main(int argc, char **argv)
{
int i, j, Error, NumFiles, ExtCode, ImageNum = 0, Scale, InCount,
ScaleFlag = FALSE, XScaleFlag = FALSE, YScaleFlag = FALSE,
UpFlag = FALSE, DownFlag = FALSE, HelpFlag = FALSE;
GifRecordType RecordType;
char s[80];
ByteType *Extension;
RowType LineIn[MAX_SCALE], LineOut[MAX_SCALE];
char **FileName = NULL;
GifFileType *GifFileIn = NULL, *GifFileOut = NULL;

if (strlen(ProgramName = argv[0]) == 0) /* DOS 3.x only! */
ProgramName = PROGRAM_NAME; /* Do something reasonable for 2.x */

if ((Error = GAGetArgs(argc, argv, CtrlStr, &ScaleFlag, &Scale,
&XScaleFlag, &XScale, &YScaleFlag, &YScale, &UpFlag, &DownFlag,
&HelpFlag, &NumFiles, &FileName)) != FALSE ||
(NumFiles > 1 && !HelpFlag)) {
if (Error) GAPrintErrMsg(Error);
else
if (NumFiles > 1)
MESSAGE("Error in command line parsing - one GIF file please\n");
GAPrintHowTo(CtrlStr);
exit(1);
}

if (HelpFlag) {
fprintf(stderr, VersionStr);
GAPrintHowTo(CtrlStr);
exit(0);
}

/* Decide if we scale up or down: */
if (UpFlag) ScaleDown = FALSE;
if (DownFlag) ScaleDown = TRUE;

/* If specific direction was set, set other direction to 1: */
if (!XScaleFlag && YScaleFlag) XScale = 1;
if (!YScaleFlag && XScaleFlag) YScale = 1;

/* If the specific direction was not set, but global one did use it: */
if (!XScaleFlag && ScaleFlag) XScale = Scale;
if (!YScaleFlag && ScaleFlag) YScale = Scale;
if (XScale > MAX_SCALE) {
sprintf(s, "XScale too big, maximum scale selected instead (%d)\n",
MAX_SCALE);
MESSAGE(s);
XScale = MAX_SCALE;
}
if (YScale > MAX_SCALE) {
sprintf(s, "YScale too big, maximum scale selected instead (%d)\n",
MAX_SCALE);
MESSAGE(s);
YScale = MAX_SCALE;
}

if (NumFiles == 1) {
if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL)
QuitGifError(GifFileIn, GifFileOut);
}
else {
/* Use the stdin instead: */
if ((GifFileIn = DGifOpenFileHandle(0)) == NULL)
QuitGifError(GifFileIn, GifFileOut);
}
BackGroundColor = GifFileIn -> SBackGroundColor;

/* As at this time we know the Screen size of the input gif file, and as */
/* all image(s) in file must be less/equal to it, we can allocate the */
/* scan lines for the input file, and output file. The number of lines */
/* to allocate for each is set by ScaleDown & XScale & YScale: */
if (ScaleDown) {
/* Output is smaller than input so we need only one output scanline: */
LineOut[0] = (RowType) malloc(GifFileIn -> SWidth / XScale *
sizeof(PixelType));
for (i=0; i (RowType) malloc(GifFileIn -> SWidth * sizeof(PixelType));
if (LineIn[YScale - 1] == NULL)
EXIT("Failed to allocate memory required, aborted\n");
}
else {
/* Input is smaller than output so we need only one input scanline: */
LineIn[0] = (RowType) malloc(GifFileIn -> SWidth *
sizeof(PixelType));
for (i=0; i (RowType) malloc(GifFileIn -> SWidth * XScale * sizeof(PixelType));
if (LineOut[YScale - 1] == NULL)
EXIT("Failed to allocate memory required, aborted\n");
}

/* Open stdout for the output file: */
if ((GifFileOut = EGifOpenFileHandle(1)) == NULL)
QuitGifError(GifFileIn, GifFileOut);

/* And dump out its new scaled screen information: */
if (EGifPutScreenDesc(GifFileOut,
ScaleDown ? GifFileIn -> SWidth / XScale :
GifFileIn -> SWidth * XScale,
ScaleDown ? GifFileIn -> SHeight / YScale :
GifFileIn -> SHeight * YScale,
GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor,
GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == ERROR)
QuitGifError(GifFileIn, GifFileOut);


/* Scan the content of the GIF file and load the image(s) in: */
do {
if (DGifGetRecordType(GifFileIn, &RecordType) == ERROR)
QuitGifError(GifFileIn, GifFileOut);

switch (RecordType) {
case IMAGE_DESC_RECORD_TYPE:
if (DGifGetImageDesc(GifFileIn) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
/* Put the image descriptor to out file: */
if (EGifPutImageDesc(GifFileOut,
ScaleDown ? GifFileIn -> ILeft / XScale :
GifFileIn -> ILeft * XScale,
ScaleDown ? GifFileIn -> ITop / YScale :
GifFileIn -> ITop * YScale,
ScaleDown ? GifFileIn -> IWidth / XScale :
GifFileIn -> IWidth * XScale,
ScaleDown ? GifFileIn -> IHeight / YScale :
GifFileIn -> IHeight * YScale,
GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel,
GifFileIn -> IColorMap) == ERROR)
QuitGifError(GifFileIn, GifFileOut);

if (GifFileIn -> IInterlace) {
EXIT("Cannt average4 interlaced images - use GifInter first\n");
}
else {
fprintf(stderr, "\n%s: Image %d at (%d, %d) [%dx%d]: ",
ProgramName, ++ImageNum,
GifFileOut -> ILeft, GifFileOut -> ITop,
GifFileOut -> IWidth, GifFileOut -> IHeight);
InCount = 0;
if (ScaleDown) {
/* For each line of output, read YScale input lines, */
/* average them, and dump result out: */
for (i=0; i IHeight; i++) {
fprintf(stderr, "\b\b\b\b%-4d", i);
for (j=0; j if (DGifGetLine(GifFileIn, LineIn[j],
GifFileIn -> IWidth) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
InCount += YScale;
Average(LineIn, LineOut, GifFileOut -> IWidth);
if (EGifPutLine(GifFileOut, LineOut[0],
GifFileOut -> IWidth) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
}
/* If scale is not dividable - discard last lines: */
for (i=InCount; i IHeight; i++)
DGifGetLine(GifFileIn, LineIn[i],
GifFileIn -> IWidth);
}
else {
/* For each line of input, output YScale lines, */
/* by averaging up this line to YScale lines: */
for (i=0; i IHeight; i++) {
fprintf(stderr, "\b\b\b\b%-4d", i * YScale);
if (DGifGetLine(GifFileIn, LineIn[0],
GifFileIn -> IWidth) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
Average(LineIn, LineOut, GifFileOut -> IWidth);
for (j=0; j if (EGifPutLine(GifFileOut, LineOut[j],
GifFileOut -> IWidth) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
}
}
}
break;
case EXTENSION_RECORD_TYPE:
/* Skip any extension blocks in file: */
if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
if (EGifPutExtension(GifFileOut, ExtCode, Extension[0],
Extension) == ERROR)
QuitGifError(GifFileIn, GifFileOut);

/* No support to more than one extension blocks, so discard: */
while (Extension != NULL) {
if (DGifGetExtensionNext(GifFileIn, &Extension) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
}
break;
case TERMINATE_RECORD_TYPE:
break;
default: /* Should be traps by DGifGetRecordType */
break;
}
}
while (RecordType != TERMINATE_RECORD_TYPE);

if (DGifCloseFile(GifFileIn) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
if (EGifCloseFile(GifFileOut) == ERROR)
QuitGifError(GifFileIn, GifFileOut);
}

/******************************************************************************
* Average routine - scale given lines as follows: *
* ScaleDown: for each YScale lines, for each box of size XScale by YScale *
* pick a pixel in it (usually upper left). If that pixel is equal to *
* background color, and there is in that square, none background pixel, pick *
* that instead. Use result pixel as output averaged pixel *
* ScaleUp: each input pixel, is expanded both in X and in Y by the factors *
* XScale & YScale respectively. *
******************************************************************************/
static void Average(RowType LineIn[], RowType LineOut[], int OutLineLen)
{
int i, j, k, o;
PixelType Color;


if (ScaleDown) {
/* For each XScale by YScale pixels in a box, pick the top left one */
/* if not background color, otherwise pick any non background from */
/* other pixels in box if one exists. */
for (i=0, o=0; o if ((Color = LineIn[0][i]) == BackGroundColor) {
/* Scan all pixels to find non background color if exists: */
for (j=i; j for (k=0; k if (LineIn[k][j] != BackGroundColor)
Color = LineIn[k][j];
}
LineOut[0][o] = Color;
}
}
else {
/* Make each input pixel a box of size XScale bu YScale: */
for (i=0, o=0; o for (j=0; j /* And duplicate the other lines from first one: */
for (i=1; i OutLineLen * sizeof(PixelType));
}
}

/******************************************************************************
* Close both input and output file (if open), and exit. *
******************************************************************************/
static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
{
PrintGifError();
if (GifFileIn != NULL) DGifCloseFile(GifFileIn);
if (GifFileOut != NULL) EGifCloseFile(GifFileOut);
exit(1);
}


  3 Responses to “Category : C Source Code
Archive   : GIF_LIB.ZIP
Filename : GIFRSIZE.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/