/****************************************************************************** * Interpret the command line, prepar global data and call the Gif routines. * ******************************************************************************/ void main(int argc, char **argv) { int Error, NumFiles, ImageWidth, ImageHeight, Dummy, Red, Green, Blue, ColorMapSize, InFileHandle, ImageSizeFlag = FALSE, ColorMapFlag = FALSE, HelpFlag = FALSE; char **FileName = NULL, *ColorMapFile; GifColorType *ColorMap; FILE *InColorMapFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuitePrint, &ImageSizeFlag, &ImageWidth, &ImageHeight, &ColorMapFlag, &ColorMapFile, &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(1); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(0); } if (ColorMapFlag) { /* Read color map from given file: */ if ((InColorMapFile = fopen(ColorMapFile, "rt")) == NULL) { GIF_MESSAGE("Failed to open COLOR MAP file (not exists!?)."); exit(2); } if ((ColorMap = (GifColorType *) malloc(sizeof(GifColorType) * 255)) /* Biggest map. */ == NULL) { GIF_MESSAGE("Failed to allocate bitmap, aborted."); exit(3); } for (ColorMapSize = 0; ColorMapSize < 256 && !feof(InColorMapFile); ColorMapSize++) { fscanf(InColorMapFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue); ColorMap[ColorMapSize].Red = Red; ColorMap[ColorMapSize].Green = Green; ColorMap[ColorMapSize].Blue = Blue; } } else { ColorMap = EGAPallete; ColorMapSize = EGA_PALLETE_SIZE; } if (NumFiles == 1) { #ifdef __MSDOS__ if ((InFileHandle = open(*FileName, O_RDONLY | O_BINARY)) == -1) { #else if ((InFileHandle = open(*FileName, O_RDONLY)) == -1) { #endif /* __MSDOS__ */ GIF_MESSAGE("Failed to open RAW image file (not exists!?)."); exit(2); } dup2(InFileHandle, 0); /* Make stdin from this file. */ } else { #ifdef __MSDOS__ setmode(0, O_BINARY); /* Make sure it is in binary mode. */ #endif /* __MSDOS__ */ } #ifdef __MSDOS__ setvbuf(stdin, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE); #endif /* __MSDOS__ */ /* Conver Raw image from stdin to Gif file in stdout: */ Raw2Gif(ImageWidth, ImageHeight, ColorMap, ColorMapSize); } /****************************************************************************** * Convert Raw image (One byte per pixel) into Gif file. Raw data is read from * * stdin, and Gif is dumped to stdout. ImagwWidth times ImageHeight bytes are * * read. Color map is dumped from ColorMap. * ******************************************************************************/ int Raw2Gif(int ImageWidth, int ImageHeight, GifColorType *ColorMap, int ColorMapSize) { static int BitsPerPixelArray[] = { 2, 4 ,8, 16, 32, 64, 128, 256 }; int i, j, BitsPerPixel; static GifPixelType *ScanLine; GifFileType *GifFile; for (BitsPerPixel = 0; BitsPerPixel < 8 && BitsPerPixelArray[BitsPerPixel] != ColorMapSize; BitsPerPixel++); if (++BitsPerPixel > 8) { GIF_MESSAGE("Number of color map is NOT power of 2 up to 256."); exit(3); } if ((ScanLine = (GifPixelType *) malloc(sizeof(GifPixelType) * ImageWidth)) == NULL) { GIF_MESSAGE("Failed to allocate scan line, aborted."); exit(3); } if ((GifFile = EGifOpenFileHandle(1)) == NULL) { /* Gif to stdout. */ free((char *) ScanLine); return HandleGifError(GifFile); } if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, BitsPerPixel, 0, BitsPerPixel, ColorMap) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, FALSE, 1, NULL) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } /* Here it is - get one raw line from stdin, and dump to stdout Gif: */ GifQprintf("\n%s: Image 1 at (0, 0) [%dx%d]: ", PROGRAM_NAME, ImageWidth, ImageHeight); for (i = 0; i < ImageHeight; i++) { /* Note we assume here PixelSize == Byte, which is not necessarily */ /* so. If not - must read one byte at a time, and coerce to pixel. */ if (fread(ScanLine, 1, ImageWidth, stdin) != ImageWidth) { GIF_MESSAGE("RAW input file ended prematurely."); exit(3); } for (j = 0; j < ImageWidth; j++) if (ScanLine[j] >= ColorMapSize) GIF_MESSAGE("Warning: RAW data color > maximum color map entry."); if (EGifPutLine(GifFile, ScanLine, ImageWidth) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } GifQprintf("\b\b\b\b%-4d", i); } if (EGifCloseFile(GifFile) == GIF_ERROR) { free((char *) ScanLine); return HandleGifError(GifFile); } free((char *) ScanLine); return 0; } /****************************************************************************** * Handle last GIF error. Try to close the file and free all allocated memory. * ******************************************************************************/ static int HandleGifError(GifFileType *GifFile) { int i = GifLastError(); if (EGifCloseFile(GifFile) == GIF_ERROR) { GifLastError(); } return i; }
static void Icon2Gif(char *FileName, FILE *txtin, int fdout) { unsigned int ExtCode, ColorMapSize = 0; GifColorType GlobalColorMap[256], LocalColorMap[256], *ColorMap = GlobalColorMap; char GlobalColorKeys[PRINTABLES], LocalColorKeys[PRINTABLES], *KeyTable = GlobalColorKeys; int red, green, blue; char buf[BUFSIZ * 2], InclusionFile[64]; GifFileType *GifFileOut; SavedImage *NewImage = NULL; int n, LineNum = 0; if ((GifFileOut = EGifOpenFileHandle(fdout)) == NULL) { (void) HandleGifError(GifFileOut); } /* OK, interpret directives */ while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) { char *cp; ++LineNum; /* * Skip lines consisting only of whitespace and comments */ for (cp = buf; isspace((int)(*cp)); cp++) continue; if (*cp == '#' || *cp == '\0') continue; /* * If there's a trailing comment, nuke it and all preceding whitespace. * But preserve the EOL. */ if ((cp = strchr(buf, '#')) && (cp == strrchr(cp, '#'))) { while (isspace((int)(*--cp))) continue; *++cp = '\n'; *++cp = '\0'; } /* * Explicit header declarations */ if (sscanf(buf, "screen width %d\n", &GifFileOut->SWidth) == 1) continue; else if (sscanf(buf, "screen height %d\n", &GifFileOut->SHeight) == 1) continue; else if (sscanf(buf, "screen colors %d\n", &n) == 1) { int ResBits = BitSize(n); if (n > 256 || n < 0 || n != (1 << ResBits)) { PARSE_ERROR("Invalid color resolution value."); exit(EXIT_FAILURE); } GifFileOut->SColorResolution = ResBits; continue; } else if (sscanf(buf, "screen background %d\n", &GifFileOut->SBackGroundColor) == 1) continue; /* * Color table parsing */ else if (strcmp(buf, "screen map\n") == 0) { if (GifFileOut->SColorMap != NULL) { PARSE_ERROR("You've already declared a global color map."); exit(EXIT_FAILURE); } ColorMapSize = 0; ColorMap = GlobalColorMap; KeyTable = GlobalColorKeys; memset(GlobalColorKeys, '\0', sizeof(GlobalColorKeys)); } else if (strcmp(buf, "image map\n") == 0) { if (NewImage == NULL) { PARSE_ERROR("No previous image declaration."); exit(EXIT_FAILURE); } ColorMapSize = 0; ColorMap = LocalColorMap; KeyTable = LocalColorKeys; memset(LocalColorKeys, '\0', sizeof(LocalColorKeys)); } else if (sscanf(buf, " rgb %d %d %d is %c", &red, &green, &blue, &KeyTable[ColorMapSize]) == 4) { ColorMap[ColorMapSize].Red = red; ColorMap[ColorMapSize].Green = green; ColorMap[ColorMapSize].Blue = blue; ColorMapSize++; } else if (strcmp(buf, "end\n") == 0) { ColorMapObject *NewMap; NewMap = MakeMapObject(1 << BitSize(ColorMapSize), ColorMap); if (NewMap == (ColorMapObject *)NULL) { PARSE_ERROR("Out of memory while allocating new color map."); exit(EXIT_FAILURE); } if (NewImage) NewImage->ImageDesc.ColorMap = NewMap; else GifFileOut->SColorMap = NewMap; } /* GIF inclusion */ else if (sscanf(buf, "include %s", InclusionFile) == 1) { GifBooleanType DoTranslation; GifPixelType Translation[256]; GifFileType *Inclusion; SavedImage *NewImage, *CopyFrom; if ((Inclusion = DGifOpenFileName(InclusionFile)) == NULL || DGifSlurp(Inclusion) == GIF_ERROR) { PARSE_ERROR("Inclusion read failed."); QuitGifError(Inclusion, GifFileOut); } if ((DoTranslation = (GifFileOut->SColorMap!=(ColorMapObject*)NULL))) { ColorMapObject *UnionMap; UnionMap = UnionColorMap(GifFileOut->SColorMap, Inclusion->SColorMap, Translation); if (UnionMap == NULL) { PARSE_ERROR("Inclusion failed --- global map conflict."); QuitGifError(Inclusion, GifFileOut); } FreeMapObject(GifFileOut->SColorMap); GifFileOut->SColorMap = UnionMap; } for (CopyFrom = Inclusion->SavedImages; CopyFrom < Inclusion->SavedImages + Inclusion->ImageCount; CopyFrom++) { if ((NewImage = MakeSavedImage(GifFileOut, CopyFrom)) == NULL) { PARSE_ERROR("Inclusion failed --- out of memory."); QuitGifError(Inclusion, GifFileOut); } else if (DoTranslation) ApplyTranslation(NewImage, Translation); GifQprintf( "%s: Image %d at (%d, %d) [%dx%d]: from %s\n", PROGRAM_NAME, GifFileOut->ImageCount, NewImage->ImageDesc.Left, NewImage->ImageDesc.Top, NewImage->ImageDesc.Width, NewImage->ImageDesc.Height, InclusionFile); } (void) DGifCloseFile(Inclusion); } /* * Explicit image declarations */ else if (strcmp(buf, "image\n") == 0) { if ((NewImage = MakeSavedImage(GifFileOut, NULL)) == (SavedImage *)NULL) { PARSE_ERROR("Out of memory while allocating image block."); exit(EXIT_FAILURE); } /* use global table unless user specifies a local one */ ColorMap = GlobalColorMap; KeyTable = GlobalColorKeys; } /* * Nothing past this point is valid unless we've seen a previous * image declaration. */ else if (NewImage == (SavedImage *)NULL) { (void) fputs(buf, stderr); PARSE_ERROR("Syntax error in header block."); exit(EXIT_FAILURE); } /* * Accept image attributes */ else if (sscanf(buf, "image top %d\n", &NewImage->ImageDesc.Top) == 1) continue; else if (sscanf(buf, "image left %d\n", &NewImage->ImageDesc.Left)== 1) continue; else if (strcmp(buf, "image interlaced\n") == 0) { NewImage->ImageDesc.Interlace = TRUE; continue; } else if (sscanf(buf, "image bits %d by %d\n", &NewImage->ImageDesc.Width, &NewImage->ImageDesc.Height) == 2) { int i, j; static GifPixelType *Raster, *cp; int c; if ((Raster = (GifPixelType *) malloc(sizeof(GifPixelType) * NewImage->ImageDesc.Width * NewImage->ImageDesc.Height)) == NULL) { PARSE_ERROR("Failed to allocate raster block, aborted."); exit(EXIT_FAILURE); } if (!GifQuietPrint) fprintf(stderr, "%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFileOut->ImageCount, NewImage->ImageDesc.Left, NewImage->ImageDesc.Top, NewImage->ImageDesc.Width, NewImage->ImageDesc.Height); cp = Raster; for (i = 0; i < NewImage->ImageDesc.Height; i++) { char *dp; for (j = 0; j < NewImage->ImageDesc.Width; j++) if ((c = fgetc(txtin)) == EOF) { PARSE_ERROR("input file ended prematurely."); exit(EXIT_FAILURE); } else if (c == '\n') { --j; ++LineNum; } else if (isspace(c)) --j; else if ((dp = strchr(KeyTable, c))) *cp++ = (dp - KeyTable); else { PARSE_ERROR("Invalid pixel value."); exit(EXIT_FAILURE); } if (!GifQuietPrint) fprintf(stderr, "\b\b\b\b%-4d", i); } if (!GifQuietPrint) putc('\n', stderr); NewImage->RasterBits = (unsigned char *) Raster; } else if (sscanf(buf, "comment")) { MakeExtension(NewImage, COMMENT_EXT_FUNC_CODE); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding comment block."); exit(EXIT_FAILURE); } } } else if (sscanf(buf, "plaintext")) { MakeExtension(NewImage, PLAINTEXT_EXT_FUNC_CODE); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding plaintext block."); exit(EXIT_FAILURE); } } } else if (sscanf(buf, "extension %02x", &ExtCode)) { MakeExtension(NewImage, ExtCode); while (fgets(buf, sizeof(buf), txtin) != (char *)NULL) if (strcmp(buf, "end\n") == 0) break; else { int Len; buf[strlen(buf) - 1] = '\0'; Len = EscapeString(buf, buf); if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) { PARSE_ERROR("out of memory while adding extension block."); exit(EXIT_FAILURE); } } } else { (void) fputs(buf, stderr); PARSE_ERROR("Syntax error in image description."); exit(EXIT_FAILURE); } } if (EGifSpew(GifFileOut) == GIF_ERROR) HandleGifError(GifFileOut); }