/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int Error, NumFiles, ExtCode, CodeSize, ImageNum = 0, ImageNFlag = FALSE, ImageN, HelpFlag = FALSE, HasGIFOutput; GifRecordType RecordType; GifByteType *Extension, *CodeBlock; char **FileName = NULL, *ColorFileName, *TranslateFileName; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &SaveFlag, &TranslateFlag, &TranslateFileName, &LoadFlag, &ColorFileName, &GammaFlag, &Gamma, &ImageNFlag, &ImageN, &HelpFlag, &NumFiles, &FileName)) != FALSE || (NumFiles > 1 && !HelpFlag)) { if (Error) GAPrintErrMsg(Error); else if (NumFiles > 1) GIF_MESSAGE("Error in command line parsing - one GIF file please."); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } if (SaveFlag + LoadFlag + GammaFlag + TranslateFlag > 1) GIF_EXIT("Can not handle more than one of -s -l, -t, or -g at the same time."); if (NumFiles == 1) { if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL) QuitGifError(GifFileIn, GifFileOut); } else { /* Use stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0)) == NULL) QuitGifError(GifFileIn, GifFileOut); } if (SaveFlag) { /* We are dumping out the color map as text file to stdout: */ ColorFile = stdout; } else { if (TranslateFlag) { /* We are loading new color map from specified file: */ if ((TranslateFile = fopen(TranslateFileName, "rt")) == NULL) GIF_EXIT("Failed to open specified color translation file."); } if (LoadFlag) { /* We are loading new color map from specified file: */ if ((ColorFile = fopen(ColorFileName, "rt")) == NULL) GIF_EXIT("Failed to open specified color map file."); } } if ((HasGIFOutput = (LoadFlag || TranslateFlag || GammaFlag)) != 0) { /* Open stdout for GIF output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); } if (!ImageNFlag) { /* We are suppose to modify the screen color map, so do it: */ GifFileIn->SColorMap = ModifyColorMap(GifFileIn->SColorMap); if (!HasGIFOutput) { /* We can quit here, as we have the color map: */ if (GifFileIn != NULL) DGifCloseFile(GifFileIn); fclose(ColorFile); exit(EXIT_SUCCESS); } } /* And dump out its new possible repositioned screen information: */ if (HasGIFOutput) if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if ((++ImageNum == ImageN) && ImageNFlag) { /* We are suppose to modify this image color map, do it: */ GifFileIn->SColorMap =ModifyColorMap(GifFileIn->SColorMap); if (!HasGIFOutput) { /* We can quit here, as we have the color map: */ if (GifFileIn != NULL) DGifCloseFile(GifFileIn); fclose(ColorFile); exit(EXIT_SUCCESS); } } if (HasGIFOutput) if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (!TranslateFlag || (ImageNFlag && (ImageN != ImageNum))) { /* Now read image itself in decoded form as we don't */ /* really care what we have there, and this is much */ /* faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (HasGIFOutput) if (EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) { if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (HasGIFOutput) if (EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } } else /* we need to mung pixels intices */ { int i; register GifPixelType *cp; GifPixelType *Line = (GifPixelType *) malloc(GifFileIn->Image.Width * sizeof(GifPixelType)); for (i = 0; i < GifFileIn->Image.Height; i++) { if (DGifGetLine(GifFileIn, Line,GifFileIn->Image.Width) == GIF_ERROR) { QuitGifError(GifFileIn, GifFileOut); } /* translation step goes here */ for (cp = Line; cp < Line+GifFileIn->Image.Width; cp++) *cp = Translation[*cp]; if (EGifPutLine(GifFileOut, Line, GifFileIn->Image.Width) == GIF_ERROR) { QuitGifError(GifFileIn, GifFileOut); } } free((char *) Line); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (HasGIFOutput) if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, so discard: */ while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_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) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (HasGIFOutput) if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); return 0; }
void DDGifSlurp(GifInfo *info, bool shouldDecode) { GifRecordType RecordType; GifByteType *ExtData; int codeSize; int ExtFunction; do { if (DGifGetRecordType(info->gifFilePtr, &RecordType) == GIF_ERROR) return; switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(info->gifFilePtr, !shouldDecode) == GIF_ERROR) return; const uint_fast16_t requiredScreenWidth = info->gifFilePtr->Image.Left + info->gifFilePtr->Image.Width; const uint_fast16_t requiredScreenHeight = info->gifFilePtr->Image.Top + info->gifFilePtr->Image.Height; if (requiredScreenWidth > info->gifFilePtr->SWidth || requiredScreenHeight > info->gifFilePtr->SHeight) { if (shouldDecode) { void *tmpRasterBits = realloc(info->rasterBits, requiredScreenWidth * requiredScreenHeight * sizeof(GifPixelType)); if (tmpRasterBits == NULL) { info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return; } info->rasterBits = tmpRasterBits; } else { info->gifFilePtr->SWidth = requiredScreenWidth; info->gifFilePtr->SHeight = requiredScreenHeight; } } if (shouldDecode) { if (info->gifFilePtr->Image.Interlace) { uint_fast16_t i, j; /* * The way an interlaced image should be read - * offsets and jumps... */ uint_fast8_t InterlacedOffset[] = {0, 4, 2, 1}; uint_fast8_t InterlacedJumps[] = {8, 8, 4, 2}; /* Need to perform 4 passes on the image */ for (i = 0; i < 4; i++) for (j = InterlacedOffset[i]; j < info->gifFilePtr->Image.Height; j += InterlacedJumps[i]) { if (DGifGetLine(info->gifFilePtr, info->rasterBits + j * info->gifFilePtr->Image.Width, info->gifFilePtr->Image.Width) == GIF_ERROR) return; } } else { if (DGifGetLine( info->gifFilePtr, info->rasterBits, info->gifFilePtr->Image.Width * info->gifFilePtr->Image.Height) == GIF_ERROR) return; } return; } else { if (DGifGetCode(info->gifFilePtr, &codeSize, &ExtData) == GIF_ERROR) return; while (ExtData != NULL) { if (DGifGetCodeNext(info->gifFilePtr, &ExtData) == GIF_ERROR) return; } } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(info->gifFilePtr, &ExtFunction, &ExtData) == GIF_ERROR) return; if (!shouldDecode) { GraphicsControlBlock *tmpInfos = realloc(info->controlBlock, (info->gifFilePtr->ImageCount + 1) * sizeof(GraphicsControlBlock)); if (tmpInfos == NULL) { info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return; } info->controlBlock = tmpInfos; info->controlBlock[info->gifFilePtr->ImageCount].DelayTime = DEFAULT_FRAME_DURATION_MS; if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) return; } while (ExtData != NULL) { if (DGifGetExtensionNext(info->gifFilePtr, &ExtData, &ExtFunction) == GIF_ERROR) return; if (!shouldDecode) { if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) return; } } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); info->rewindFunction(info); }
/****************************************************************************** Main sequence ******************************************************************************/ int main(int argc, char **argv) { GifFileType *GifFileIn = NULL, *GifFileOut = NULL; GifRecordType RecordType; int CodeSize, ExtCode, ErrorCode; GifByteType *CodeBlock, *Extension; /* * Command-line processing goes here. */ /* Use stdin as input (note this also read screen descriptor in: */ if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* Use the stdout as output: */ if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } /* And dump out its screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the input GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Put image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont really */ /* care what we have there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) { if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case EXTENSION_RECORD_TYPE: /* pass through extension records */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtensionLeader(GifFileOut, ExtCode) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtensionBlock(GifFileOut, Extension[0], Extension + 1) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension)==GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (Extension != NULL) if (EGifPutExtensionBlock(GifFileOut, Extension[0], Extension + 1) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } if (EGifPutExtensionTrailer(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) { PrintGifError(ErrorCode); if (GifFileIn != NULL) { EGifCloseFile(GifFileIn, NULL); } exit(EXIT_FAILURE); } if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) { PrintGifError(ErrorCode); if (GifFileOut != NULL) { EGifCloseFile(GifFileOut, NULL); } exit(EXIT_FAILURE); } return 0; }
/****************************************************************************** * Perform the disassembly operation - take one input files into few output. * ******************************************************************************/ static int DoDisassemblyNum(const char *InFileName, char *OutFileName, int FileNum) { int ExtCode, CodeSize, FileEmpty; GifRecordType RecordType; char CrntFileName[80], *p; GifByteType *Extension, *CodeBlock; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; int ErrorCode; /* If name has type postfix, strip it out, and make sure name is less */ /* or equal to 6 chars, so we will have 2 chars in name for numbers. */ //strupr(OutFileName); /* Make sure all is upper case */ #if 0 printf("OutFileName : %s\n", OutFileName); if ((p = strrchr(OutFileName, '.')) != NULL && strlen(p) <= 4) p[0] = 0; if ((p = strrchr(OutFileName, '/')) != NULL || (p = strrchr(OutFileName, '\\')) != NULL || (p = strrchr(OutFileName, ':')) != NULL) { if (strlen(p) > 7) p[7] = 0; /* p includes the '/', '\\', ':' char */ } else { /* Only name is given for current directory: */ //if (strlen(OutFileName) > 6) OutFileName[6] = 0; } printf("OutFileName : %s\n", OutFileName); #endif /* Open input file: */ if (InFileName != NULL) { if ((GifFileIn = DGifOpenFileName(InFileName, &ErrorCode)) == NULL) return QuitGifError(GifFileIn, GifFileOut); } else { /* Use the stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) return QuitGifError(GifFileIn, GifFileOut); } /* Scan the content of GIF file and dump image(s) to seperate file(s): */ //sprintf(CrntFileName, "%s_%02d.gif", OutFileName, FileNum); sprintf(CrntFileName, "%s", OutFileName); if ((GifFileOut = EGifOpenFileName(CrntFileName, TRUE, &ErrorCode)) == NULL) return QuitGifError(GifFileIn, GifFileOut); FileEmpty = TRUE; /* And dump out its exactly same screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: FileEmpty = FALSE; if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); /* Put same image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont */ /* really care what is there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); break; case EXTENSION_RECORD_TYPE: FileEmpty = FALSE; /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, discard */ while (Extension != NULL) if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType */ break; } } while (RecordType != IMAGE_DESC_RECORD_TYPE && RecordType != TERMINATE_RECORD_TYPE); if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); if (FileEmpty) { /* Might happen on last file - delete it if so: */ unlink(CrntFileName); } if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); }
/****************************************************************************** * Perform the assembly operation - take few input files into one output. * ******************************************************************************/ static void DoAssembly(int NumFiles, char **FileNames) { int i, ExtCode, CodeSize; GifRecordType RecordType; GifByteType *Extension, *CodeBlock; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; /* Open stdout for the output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the GIF file and load the image(s) in: */ for (i = 0; i < NumFiles; i++) { if ((GifFileIn = DGifOpenFileName(FileNames[i])) == NULL) QuitGifError(GifFileIn, GifFileOut); /* And dump out screen descriptor iff its first image. */ if (i == 0) if (EGifPutScreenDesc(GifFileOut, GifFileIn -> SWidth, GifFileIn -> SHeight, GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor, GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Put image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn -> ILeft, GifFileIn -> ITop, GifFileIn -> IWidth, GifFileIn -> IHeight, GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel, GifFileIn -> IColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont */ /* dont care what is there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, discard.*/ while (Extension != NULL) if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_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) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int i, Error, NumFiles, ExtCode, CodeSize, ImageNum = 0, ImageFlag = FALSE, ImageNFlag = FALSE, ImageN, ImageX1, ImageY1, ImageX2, ImageY2, ImageWidth, ImageDepth, Complement = FALSE, HelpFlag = FALSE; GifRecordType RecordType; GifByteType *Extension, *CodeBlock; char **FileName = NULL; GifRowType Line; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; /* Same image dimension vars for both Image & ImageN as only one allowed.*/ if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &Complement, &ImageFlag, &ImageX1, &ImageY1, &ImageX2, &ImageY2, &ImageNFlag, &ImageN, &ImageX1, &ImageY1, &ImageX2, &ImageY2, &HelpFlag, &NumFiles, &FileName)) != FALSE || (NumFiles > 1 && !HelpFlag)) { if (Error) GAPrintErrMsg(Error); else if (NumFiles > 1) GIF_MESSAGE("Error in command line parsing - one GIF file please."); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } /* Test to make sure exactly one of ImageFlag & ImageNFlag is set: */ if ((ImageFlag && ImageNFlag) || (!ImageFlag && !ImageNFlag)) { GIF_MESSAGE("Exactly one of [-i ...] && [-n ...] please."); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (ImageFlag) ImageN = 1; /* Its first image we are after. */ /* Make sure the first coordinates of clipping box are smaller: */ if (ImageX1 > ImageX2) { i = ImageX1; ImageX1 = ImageX2; ImageX2 = i; } if (ImageY1 > ImageY2) { i = ImageX1; ImageY1 = ImageY2; ImageY2 = i; } if (NumFiles == 1) { if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL) QuitGifError(GifFileIn, GifFileOut); } else { /* Use the stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0)) == NULL) QuitGifError(GifFileIn, GifFileOut); } /* Open stdout for the output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* Width and depth of clipped image. */ if (!Complement) ImageWidth = ImageX2 - ImageX1 + 1; else ImageWidth = GifFileIn->SWidth - (ImageX2 != ImageX1) * (ImageX2 - ImageX1 + 1); if (!Complement) ImageDepth = ImageY2 - ImageY1 + 1; else ImageDepth = GifFileIn->SHeight - (ImageY2 != ImageY1) * (ImageY2 - ImageY1 + 1); /* And dump out exactly same screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (++ImageNum == ImageN) { /* We can handle only non interlaced images here: */ if (GifFileIn->Image.Interlace) GIF_EXIT("Image to clip is interlaced - use GifInter first."); /* This is the image we should clip - test sizes and */ /* dump out new clipped screen descriptor if o.k. */ if (GifFileIn->Image.Width <= ImageX2 || GifFileIn->Image.Height <= ImageY2) GIF_EXIT("Image is smaller than given clip dimensions."); /* Put the image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, ImageWidth, ImageDepth, FALSE, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* o.k. - read the image and clip it: */ Line = (GifRowType) malloc(GifFileIn->Image.Width * sizeof(GifPixelType)); GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, ImageNum, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height); /* Skip lines below ImageY1: */ for (i = 0; i < ImageY1; i++) { if (DGifGetLine(GifFileIn, Line, GifFileIn->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (Complement) { if (ImageX1 == ImageX2) { /* don't remove any vertical band */ if (EGifPutLine(GifFileOut, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } else { if (EGifPutLine(GifFileOut, Line, ImageX1) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutLine(GifFileOut, &Line[ImageX2 + 1], GifFileIn->SWidth - (ImageX2 + 1) ) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } } GifQprintf("\b\b\b\b%-4d", i); } /* Clip the lines from ImageY1 to ImageY2 (to X1 - X2): */ for (i = ImageY1; i <= ImageY2; i++) { if (DGifGetLine(GifFileIn, Line, GifFileIn->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (!Complement) if (EGifPutLine(GifFileOut, &Line[ImageX1], ImageWidth) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); GifQprintf("\b\b\b\b%-4d", i); } /* Skip lines above ImageY2: */ for (i = ImageY2 + 1; i < GifFileIn->Image.Height; i++) { if (DGifGetLine(GifFileIn, Line, GifFileIn->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (Complement) { if (ImageX1 == ImageX2) { /* don't remove any vertical band */ if (EGifPutLine(GifFileOut, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } else { if (EGifPutLine(GifFileOut, Line, ImageX1) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutLine(GifFileOut, &Line[ImageX2 + 1], GifFileIn->SWidth - (ImageX2 + 1) ) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } } GifQprintf("\b\b\b\b%-4d", i); } free((char *) Line); } else { /* Copy the image as is (we dont modify this one): */ if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont */ /* really care what is there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, so discard: */ while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_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) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); return 0; }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int i, j, Size, Error, NumFiles, ExtCode, CodeSize, NumColors = 2, Color, Count, ImageNum = 0, TextFlag = FALSE, SizeFlag = FALSE, ImageNFlag = FALSE, BackGroundFlag = FALSE, HelpFlag = FALSE; long Scaler, Histogram[256]; GifRecordType RecordType; GifByteType *Extension, *CodeBlock; char **FileName = NULL; GifRowType Line; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; /* Same image dimension vars for both Image & ImageN as only one allowed */ if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &TextFlag, &SizeFlag, &ImageWidth, &ImageHeight, &ImageNFlag, &ImageN, &BackGroundFlag, &HelpFlag, &NumFiles, &FileName)) != FALSE || (NumFiles > 1 && !HelpFlag)) { if (Error) GAPrintErrMsg(Error); else if (NumFiles > 1) GIF_MESSAGE("Error in command line parsing - one GIF file please."); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } if (NumFiles == 1) { if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL) QuitGifError(GifFileIn, GifFileOut); } else { /* Use the stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0)) == NULL) QuitGifError(GifFileIn, GifFileOut); } for (i = 0; i < 256; i++) Histogram[i] = 0; /* Reset counters. */ /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (GifFileIn->Image.ColorMap) NumColors = GifFileIn->Image.ColorMap->ColorCount; else if (GifFileIn->SColorMap) NumColors = GifFileIn->SColorMap->ColorCount; else GIF_EXIT("Neither Screen nor Image color map exists."); if ((ImageHeight / NumColors) * NumColors != ImageHeight) GIF_EXIT("Image height specified not dividable by #colors."); if (++ImageNum == ImageN) { /* This is the image we should make histogram for: */ Line = (GifRowType) malloc(GifFileIn->Image.Width * sizeof(GifPixelType)); GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, ImageNum, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height); for (i = 0; i < GifFileIn->Image.Height; i++) { if (DGifGetLine(GifFileIn, Line, GifFileIn->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); for (j = 0; j < GifFileIn->Image.Width; j++) Histogram[Line[j]]++; GifQprintf("\b\b\b\b%-4d", i); } free((char *) Line); } else { /* Skip the image: */ /* Now read image itself in decoded form as we dont */ /* really care what is there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* We we requested to kill back ground count: */ if (BackGroundFlag) Histogram[GifFileIn->SBackGroundColor] = 0; if (DGifCloseFile(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* We may required to dump out the histogram as text file: */ if (TextFlag) { for (i = 0; i < NumColors; i++) printf("%12ld %3d\n", Histogram[i], i); } else { /* Open stdout for the histogram output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* Dump out screen descriptor to fit histogram dimensions: */ if (EGifPutScreenDesc(GifFileOut, ImageWidth, ImageHeight, HISTO_BITS_PER_PIXEL, 0, MakeMapObject(4, HistoColorMap)) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Dump out image descriptor to fit histogram dimensions: */ if (EGifPutImageDesc(GifFileOut, 0, 0, ImageWidth, ImageHeight, FALSE, NULL) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Prepare scan line for histogram file, and find scaler to scale */ /* histogram to be between 0 and ImageWidth: */ Line = (GifRowType) malloc(ImageWidth * sizeof(GifPixelType)); for (Scaler = 0, i = 0; i < NumColors; i++) if (Histogram[i] > Scaler) Scaler = Histogram[i]; Scaler /= ImageWidth; if (Scaler == 0) Scaler = 1; /* In case maximum is less than width. */ /* Dump out the image itself: */ for (Count = ImageHeight, i = 0, Color = 1; i < NumColors; i++) { if ((Size = Histogram[i] / Scaler) > ImageWidth) Size = ImageWidth; for (j = 0; j < Size; j++) Line[j] = Color; for (j = Size; j < ImageWidth; j++) Line[j] = GifFileOut->SBackGroundColor; /* Move to next color: */ if (++Color >= (1 << HISTO_BITS_PER_PIXEL)) Color = 1; /* Dump this histogram entry as many times as required: */ for (j = 0; j < ImageHeight / NumColors; j++) { if (EGifPutLine(GifFileOut, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); GifQprintf("\b\b\b\b%-4d", Count--); } } if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } return 0; }
/****************************************************************************** Interpret the command line and scan the given GIF file. ******************************************************************************/ int main(int argc, char **argv) { int i, j, ExtCode, ErrorCode, CodeSize, NumFiles, Len, ImageNum = 1; bool Error, ColorMapFlag = false, EncodedFlag = false, LZCodesFlag = false, PixelFlag = false, HelpFlag = false, RawFlag = false; char *GifFileName, **FileName = NULL; GifPixelType *Line; GifRecordType RecordType; GifByteType *CodeBlock, *Extension; GifFileType *GifFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint, &ColorMapFlag, &EncodedFlag, &LZCodesFlag, &PixelFlag, &RawFlag, &HelpFlag, &NumFiles, &FileName)) != false || (NumFiles > 1 && !HelpFlag)) { if (Error) GAPrintErrMsg(Error); else if (NumFiles > 1) GIF_MESSAGE("Error in command line parsing - one GIF file please."); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { (void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } if (NumFiles == 1) { GifFileName = *FileName; if ((GifFile = DGifOpenFileName(*FileName, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } } else { /* Use stdin instead: */ GifFileName = "Stdin"; if ((GifFile = DGifOpenFileHandle(0, &ErrorCode)) == NULL) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } } /* Because we write binary data - make sure no text will be written. */ if (RawFlag) { ColorMapFlag = EncodedFlag = LZCodesFlag = PixelFlag = false; #ifdef _WIN32 _setmode(1, O_BINARY); /* Make sure it is in binary mode. */ #endif /* _WIN32 */ } else { printf("\n%s:\n\n\tScreen Size - Width = %d, Height = %d.\n", GifFileName, GifFile->SWidth, GifFile->SHeight); printf("\tColorResolution = %d, BitsPerPixel = %d, BackGround = %d, Aspect = %d.\n", GifFile->SColorResolution, GifFile->SColorMap ? GifFile->SColorMap->BitsPerPixel : 0, GifFile->SBackGroundColor, GifFile->AspectByte); if (GifFile->SColorMap) printf("\tHas Global Color Map.\n\n"); else printf("\tNo Global Color Map.\n\n"); if (ColorMapFlag && GifFile->SColorMap) { printf("\tGlobal Color Map:\n"); Len = GifFile->SColorMap->ColorCount; printf("\tSort Flag: %s\n", GifFile->SColorMap->SortFlag ? "on":"off"); for (i = 0; i < Len; i+=4) { for (j = 0; j < 4 && j < Len; j++) { printf("%3d: %02xh %02xh %02xh ", i + j, GifFile->SColorMap->Colors[i + j].Red, GifFile->SColorMap->Colors[i + j].Green, GifFile->SColorMap->Colors[i + j].Blue); } printf("\n"); } } } do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } if (!RawFlag) { printf("\nImage #%d:\n\n\tImage Size - Left = %d, Top = %d, Width = %d, Height = %d.\n", ImageNum++, GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height); printf("\tImage is %s", GifFile->Image.Interlace ? "Interlaced" : "Non Interlaced"); if (GifFile->Image.ColorMap != NULL) printf(", BitsPerPixel = %d.\n", GifFile->Image.ColorMap->BitsPerPixel); else printf(".\n"); if (GifFile->Image.ColorMap) printf("\tImage Has Color Map.\n"); else printf("\tNo Image Color Map.\n"); if (ColorMapFlag && GifFile->Image.ColorMap) { printf("\tSort Flag: %s\n", GifFile->Image.ColorMap->SortFlag ? "on":"off"); Len = 1 << GifFile->Image.ColorMap->BitsPerPixel; for (i = 0; i < Len; i+=4) { for (j = 0; j < 4 && j < Len; j++) { printf("%3d: %02xh %02xh %02xh ", i + j, GifFile->Image.ColorMap->Colors[i + j].Red, GifFile->Image.ColorMap->Colors[i + j].Green, GifFile->Image.ColorMap->Colors[i + j].Blue); } printf("\n"); } } } if (EncodedFlag) { if (DGifGetCode(GifFile, &CodeSize, &CodeBlock) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } printf("\nImage LZ compressed Codes (Code Size = %d):\n", CodeSize); PrintCodeBlock(GifFile, CodeBlock, true); while (CodeBlock != NULL) { if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } PrintCodeBlock(GifFile, CodeBlock, false); } } else if (LZCodesFlag) { PrintLZCodes(GifFile); } else if (PixelFlag) { Line = (GifPixelType *) malloc(GifFile->Image.Width * sizeof(GifPixelType)); for (i = 0; i < GifFile->Image.Height; i++) { if (DGifGetLine(GifFile, Line, GifFile->Image.Width) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } PrintPixelBlock(Line, GifFile->Image.Width, i == 0); } PrintPixelBlock(NULL, GifFile->Image.Width, false); free((char *) Line); } else if (RawFlag) { Line = (GifPixelType *) malloc(GifFile->Image.Width * sizeof(GifPixelType)); for (i = 0; i < GifFile->Image.Height; i++) { if (DGifGetLine(GifFile, Line, GifFile->Image.Width) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } fwrite(Line, 1, GifFile->Image.Width, stdout); } free((char *) Line); } else { /* Skip the image: */ if (DGifGetCode(GifFile, &CodeSize, &CodeBlock) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } while (CodeBlock != NULL) { if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } } } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } if (!RawFlag) { putchar('\n'); switch (ExtCode) { case COMMENT_EXT_FUNC_CODE: printf("GIF89 comment"); break; case GRAPHICS_EXT_FUNC_CODE: printf("GIF89 graphics control"); break; case PLAINTEXT_EXT_FUNC_CODE: printf("GIF89 plaintext"); break; case APPLICATION_EXT_FUNC_CODE: printf("GIF89 application block"); break; default: printf("Extension record of unknown type"); break; } printf(" (Ext Code = %d [%c]):\n", ExtCode, MAKE_PRINTABLE(ExtCode)); PrintExtBlock(Extension, true); if (ExtCode == GRAPHICS_EXT_FUNC_CODE) { GraphicsControlBlock gcb; if (DGifExtensionToGCB(Extension[0], Extension+1, &gcb) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } printf("\tDisposal Mode: %d\n", gcb.DisposalMode); printf("\tUser Input Flag: %d\n", gcb.UserInputFlag); printf("\tTransparency on: %s\n", gcb.TransparentColor != -1 ? "yes" : "no"); printf("\tDelayTime: %d\n", gcb.DelayTime); printf("\tTransparent Index: %d\n", gcb.TransparentColor); } } for (;;) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } if (Extension == NULL) break; PrintExtBlock(Extension, false); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR) { PrintGifError(ErrorCode); exit(EXIT_FAILURE); } if (!RawFlag) printf("\nGIF file terminated normally.\n"); return 0; }