void save_image (image* img, char* file, image_format fmt) { if (fmt == imgIRMID) { FILE* fp; fp = fopen (file, "w"); fwrite (img, img->size, 1, fp); fclose (fp); } else if (fmt == imgGIF) { GifFileType* GifFileOut = (GifFileType *)NULL; GifFileOut = EGifOpenFileName (file, 0); GifColorType* color_map = new GifColorType[0x100 * 3]; for (uint n = 0; n < 0x100 ; ++n) { color_map[n].Red = n; color_map[n].Green = n; color_map[n].Blue = n; } ColorMapObject* map_object = MakeMapObject (0x100, color_map); GifRowType pixels = (GifRowType) new GifPixelType[img->xy]; for (uint n = 0; n < img->xy; ++n) pixels[n] = (GifPixelType)data(img)[n]; EGifPutScreenDesc (GifFileOut, img->dimx, img->dimy, 0x100, 0x100, map_object); EGifPutImageDesc (GifFileOut, 0, 0, img->dimx, img->dimy, 0, map_object); EGifPutLine (GifFileOut, pixels, img->xy); EGifCloseFile (GifFileOut); } }
int get_gif_image_desc( GifFileType *gif, SavedImage *im ) { long start_pos, end_pos ; int status; start_pos = ftell(gif->UserData); status = DGifGetImageDesc( gif ); end_pos = ftell(gif->UserData); if( status == GIF_OK ) { int ext_count = im->ExtensionBlockCount ; ExtensionBlock *ext_ptr = im->ExtensionBlocks ; im->ExtensionBlocks = NULL ; im->ExtensionBlockCount = 0 ; free_gif_saved_image( im, True ); memset( im, 0x00, sizeof(SavedImage)); im->ExtensionBlocks = ext_ptr ; im->ExtensionBlockCount = ext_count ; memcpy( &(im->ImageDesc), &(gif->Image), sizeof(GifImageDesc)); if( gif->Image.ColorMap ) { im->ImageDesc.ColorMap = MakeMapObject(gif->Image.ColorMap->ColorCount, NULL); fseek( gif->UserData, start_pos+9, SEEK_SET ); fread( im->ImageDesc.ColorMap->Colors, 1, gif->Image.ColorMap->ColorCount*3, gif->UserData); fseek( gif->UserData, end_pos, SEEK_SET ); gif->Image.ColorMap = NULL ; } } return status; }
static int DGifGetScreenDesc(GifFileType * GifFile) { int i, BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; if (Buf[0] & 0x80) { GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { FreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; GifFile->SColorMap->Colors[i].Green = Buf[1]; GifFile->SColorMap->Colors[i].Blue = Buf[2]; } } else { GifFile->SColorMap = NULL; } return GIF_OK; }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int i, j, Error, NumFiles, Width, Height; char **FileName = NULL; GifByteType *RedBuffer = NULL, *GreenBuffer = NULL, *BlueBuffer = NULL, *OutputBuffer = NULL; ColorMapObject *OutputColorMap = NULL; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &ColorFlag, &ExpNumOfColors, &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); } ColorMapSize = 1 << ExpNumOfColors; if (NumFiles == 1) { LoadRle(*FileName, &RedBuffer, &GreenBuffer, &BlueBuffer, &Width, &Height); } else { LoadRle(NULL, &RedBuffer, &GreenBuffer, &BlueBuffer, &Width, &Height); } if ((OutputColorMap = MakeMapObject(ColorMapSize, NULL)) == NULL || (OutputBuffer = (GifByteType *) malloc(Width * Height * sizeof(GifByteType))) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (QuantizeBuffer(Width, Height, &ColorMapSize, RedBuffer, GreenBuffer, BlueBuffer, OutputBuffer, OutputColorMap->Colors) == GIF_ERROR) QuitGifError(NULL); free((char *) RedBuffer); free((char *) GreenBuffer); free((char *) BlueBuffer); SaveGif(OutputBuffer, OutputColorMap, ExpNumOfColors, Width, Height); return 0; }
/****************************************************************************** * This routine should be called before any other DGif calls. Note that * this routine is called automatically from DGif file open routines. *****************************************************************************/ int DGifGetScreenDesc(GifFileType * GifFile) { int BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } /* Put the screen descriptor into the file: */ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; if (Buf[0] & 0x80) { /* Do we have global color map? */ int i; GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the global color map: */ for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { FreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; GifFile->SColorMap->Colors[i].Green = Buf[1]; GifFile->SColorMap->Colors[i].Blue = Buf[2]; } } else { GifFile->SColorMap = NULL; } return GIF_OK; }
/****************************************************************************** * This routine should be called before any attemp to read an image. * * Note it is assumed the Image desc. header (',') has been read. * ******************************************************************************/ int DGifGetImageDesc(GifFileType *GifFile) { int i, BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(Private, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(Private, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(Private, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(Private, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (my_fread(Buf, 1, 1, Private) != 1) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->Image.Interlace = (Buf[0] & 0x40); if (Buf[0] & 0x80) { /* Does this image have local color map? */ if (GifFile->Image.ColorMap) FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); /* Get the image local color map: */ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (my_fread(Buf, 1, 3, Private) != 3) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } GifFile->ImageCount++; Private->PixelCount = (s32) GifFile->Image.Width * (s32) GifFile->Image.Height; DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ return GIF_OK; }
/****************************************************************************** * This routine should be called before any other DGif calls. Note that * this routine is called automatically from DGif file open routines. *****************************************************************************/ static int DGifGetScreenDesc(GifFileType * GifFile) { int i, BitsPerPixel, SortFlag; GifByteType Buf[3]; /* Put the screen descriptor into the file: */ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; SortFlag = (Buf[0] & 0x08) != 0; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; GifFile->SAspectRatio = Buf[2]; if (Buf[0] & 0x80) { /* Do we have global color map? */ GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { return GIF_ERROR; } /* Get the global color map: */ GifFile->SColorMap->SortFlag = SortFlag; for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { FreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; GifFile->SColorMap->Colors[i].Green = Buf[1]; GifFile->SColorMap->Colors[i].Blue = Buf[2]; } } else { GifFile->SColorMap = NULL; } return GIF_OK; }
void init_gifs(char *fileName, int sizex, int sizey) { if(gifFileIn==NULL) { gifFileIn = DGifOpenFileName("kaavyhdi.gif"); if(gifFileIn==NULL) {failExit;} printf("%i,%i: %i\n", gifFileIn->SWidth, gifFileIn->SHeight, gifFileIn->SColorResolution); if(DGifSlurp(gifFileIn) == GIF_ERROR) failExit; printf("slurp done\n"); } gifFileOut = EGifOpenFileName(fileName, FALSE); if(gifFileOut==NULL) failExit; printf("making output...\n"); if(EGifPutScreenDesc(gifFileOut, sizex, sizey, gifFileIn->SColorResolution, gifFileIn->SBackGroundColor, MakeMapObject(gifFileIn->SColorMap->ColorCount, gifFileIn->SColorMap->Colors)) == GIF_ERROR) failExit; if(EGifPutImageDesc(gifFileOut, 0, 0, sizex, sizey, FALSE, NULL) == GIF_ERROR) failExit; }
/****************************************************************************** * This routine should be called before any attemp to read an image. * * Note it is assumed the Image desc. header (',') has been read. * ******************************************************************************/ int DGifGetImageDesc(GifFileType *GifFile) { int i, BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile,Buf, 1) != 1) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->Image.Interlace = (Buf[0] & 0x40); if (Buf[0] & 0x80) { /* Does this image have local color map? */ if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL) FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); /* Get the image local color map: */ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (READ(GifFile,Buf, 3) != 3) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } if (GifFile->SavedImages) { if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { if ((GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { sp->ImageDesc.ColorMap = MakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); } sp->RasterBits = (char *)NULL; sp->ExtensionBlockCount = 0; sp->ExtensionBlocks = (ExtensionBlock *)NULL; GifFile->ImageCount++; Private->PixelCount = (long) GifFile->Image.Width * (long) GifFile->Image.Height; DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ return GIF_OK; }
bool CxImageGIF::Encode(CxFile * fp) { if (EncodeSafeCheck(fp)) return false; GifFileType *GifFile = NULL; ColorMapObject *OutputColorMap = NULL; int i, ColorMapSize; if(head.biBitCount != 8) { if(head.biBitCount < 8)IncreaseBpp(8); else DecreaseBpp(8, true); } try { GifFile = EGifOpen(fp, writeCxFile); ColorMapSize = head.biClrUsed; OutputColorMap = MakeMapObject(ColorMapSize, NULL); RGBQUAD* pPal = GetPalette(); for(i=0; i<ColorMapSize; ++i) { OutputColorMap->Colors[i].Red = pPal[i].rgbRed; OutputColorMap->Colors[i].Green = pPal[i].rgbGreen; OutputColorMap->Colors[i].Blue = pPal[i].rgbBlue; } EGifPutScreenDesc(GifFile, head.biWidth, head.biHeight, OutputColorMap->ColorCount, info.nBkgndIndex== -1 ? 0 : info.nBkgndIndex, OutputColorMap); FreeMapObject(OutputColorMap); OutputColorMap = NULL; if(info.nBkgndIndex != -1) { unsigned char ExtStr[4] = { 1, 0, 0, info.nBkgndIndex }; EGifPutExtension(GifFile, GRAPHICS_EXT_FUNC_CODE, 4, ExtStr); } EGifPutImageDesc(GifFile, 0, 0, head.biWidth, head.biHeight, FALSE, NULL); for (i = 0; i < head.biHeight; i++) EGifPutLine(GifFile, GetBits(head.biHeight - i - 1), head.biWidth); EGifCloseFile(GifFile); GifFile = NULL; } catch (int errid) { strncpy(info.szLastError,GifGetErrorMessage(errid),255); if(OutputColorMap) { FreeMapObject(OutputColorMap); OutputColorMap = NULL; } if(GifFile) { EGifCloseFile(GifFile); GifFile = NULL; } return false; } catch (char *message) { strncpy(info.szLastError,message,255); if(OutputColorMap) { FreeMapObject(OutputColorMap); OutputColorMap = NULL; } if(GifFile) { EGifCloseFile(GifFile); GifFile = NULL; } return false; } return true; }
/****************************************************************************** * Image block allocation functions * ******************************************************************************/ SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom) /* * Append an image block to the SavedImages array */ { SavedImage *sp; if (GifFile->SavedImages == NULL) GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); else GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount+1)); if (GifFile->SavedImages == NULL) return((SavedImage *)NULL); else { sp = &GifFile->SavedImages[GifFile->ImageCount++]; memset((char *)sp, '\0', sizeof(SavedImage)); if (CopyFrom) { memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); /* * Make our own allocated copies of the heap fields in the * copied record. This guards against potential aliasing * problems. */ /* first, the local color map */ if (sp->ImageDesc.ColorMap) sp->ImageDesc.ColorMap = MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount, CopyFrom->ImageDesc.ColorMap->Colors); /* next, the raster */ sp->RasterBits = (char *)malloc(sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * CopyFrom->ImageDesc.Width); memcpy(sp->RasterBits, CopyFrom->RasterBits, sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * CopyFrom->ImageDesc.Width); /* finally, the extension blocks */ if (sp->ExtensionBlocks) { sp->ExtensionBlocks = (ExtensionBlock*)malloc(sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); /* * For the moment, the actual blocks can take their * chances with free(). We'll fix this later. */ } } return(sp); } }
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); }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { unsigned int Ratio; int i, j, l, LevelHeight, LevelWidth, Error, LogNumLevels, FlipDir, Accumulator, StartX, StepX, Count = 0, DoAllMaximum = FALSE, DirectionFlag = FALSE, LevelsFlag = FALSE, ColorFlag = FALSE, MinFlag = FALSE, MaxFlag = FALSE, SizeFlag = FALSE, HelpFlag = FALSE; GifPixelType Color; char *DirectionStr = DEFAULT_DIR; GifRowType Line; ColorMapObject *ColorMap; GifFileType *GifFile; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &DirectionFlag, &DirectionStr, &LevelsFlag, &NumLevels, &ColorFlag, &RedColor, &GreenColor, &BlueColor, &MinFlag, &MinimumIntensity, &MaxFlag, &MaximumIntensity, &SizeFlag, &ImageWidth, &ImageHeight, &HelpFlag)) != FALSE) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); exit(EXIT_FAILURE); } if (HelpFlag) { fprintf(stderr, VersionStr); GAPrintHowTo(CtrlStr); exit(EXIT_SUCCESS); } /* Make sure intensities are in the right range: */ if (MinimumIntensity < 0 || MinimumIntensity > 100 || MaximumIntensity < 0 || MaximumIntensity > 100) GIF_EXIT("Intensities (-m or -M options) are not in [0..100] range (percent)."); /* Convert DirectionStr to our local representation: */ Direction = DIR_NONE; FlipDir = FALSE; for (i = 0; i < (int)strlen(DirectionStr); i++) /* Make sure its upper case. */ if (islower(DirectionStr[i])) DirectionStr[i] = toupper(DirectionStr[i]); switch(DirectionStr[0]) { case 'T': /* Top or North */ case 'N': if (strlen(DirectionStr) < 2) Direction = DIR_TOP; else switch(DirectionStr[1]) { case 'R': case 'E': Direction = DIR_TOP_RIGHT; break; case 'L': case 'W': Direction = DIR_TOP_LEFT; FlipDir = TRUE; break; } break; case 'R': /* Right or East */ case 'E': Direction = DIR_RIGHT; break; case 'B': /* Bottom or South */ case 'S': if (strlen(DirectionStr) < 2) { Direction = DIR_BOT; FlipDir = TRUE; } else switch(DirectionStr[1]) { case 'R': case 'E': Direction = DIR_BOT_RIGHT; break; case 'L': case 'W': Direction = DIR_BOT_LEFT; FlipDir = TRUE; break; } break; case 'L': /* Left or West */ case 'W': Direction = DIR_LEFT; FlipDir = TRUE; break; } if (Direction == DIR_NONE) GIF_EXIT("Direction requested (-d option) is wierd!"); /* We are going to handle only TOP, TOP_RIGHT, RIGHT, BOT_RIGHT so flip */ /* the complement cases (TOP <-> BOT for example) by flipping the */ /* Color i with color (NumLevels - i - 1). */ if (FlipDir) { switch (Direction) { case DIR_BOT: Direction = DIR_TOP; break; case DIR_BOT_LEFT: Direction = DIR_TOP_RIGHT; break; case DIR_LEFT: Direction = DIR_RIGHT; break; case DIR_TOP_LEFT: Direction = DIR_BOT_RIGHT; break; } } /* If binary mask is requested (special case): */ if (MinimumIntensity == 100 && MaximumIntensity == 100 && NumLevels == 2) { MinimumIntensity = 0; DoAllMaximum = TRUE; Direction = DIR_RIGHT; } /* Make sure colors are in the right range: */ if (RedColor > 255 || GreenColor > 255 || BlueColor > 255) GIF_EXIT("Colors are not in the ragne [0..255]."); /* Make sure number of levels is power of 2 (up to 8 bits per pixel). */ for (i = 1; i < 8; i++) if (NumLevels == (1 << i)) break; if (i == 8) GIF_EXIT("#Lvls (-l option) is not power of 2."); LogNumLevels = i; /* Open stdout for the output file: */ if ((GifFile = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFile); /* Dump out screen description with given size and generated color map: */ if ((ColorMap = MakeMapObject(NumLevels, NULL)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 1; i <= NumLevels; i++) { /* Ratio will be in the range of 0..100 for required intensity: */ Ratio = (MaximumIntensity * (i * (256 / NumLevels)) + MinimumIntensity * ((NumLevels - i) * (256 / NumLevels))) / 256; ColorMap->Colors[i-1].Red = (RedColor * Ratio) / 100; ColorMap->Colors[i-1].Green = (GreenColor * Ratio) / 100; ColorMap->Colors[i-1].Blue = (BlueColor * Ratio) / 100; } if (EGifPutScreenDesc(GifFile, ImageWidth, ImageHeight, LogNumLevels, 0, ColorMap) == GIF_ERROR) QuitGifError(GifFile); /* Dump out the image descriptor: */ if (EGifPutImageDesc(GifFile, 0, 0, ImageWidth, ImageHeight, FALSE, NULL) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\n%s: Image 1 at (%d, %d) [%dx%d]: ", PROGRAM_NAME, GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height); /* Allocate one scan line twice as big as image is as we are going to */ /* shift along it, while we dump the scan lines: */ if ((Line = (GifRowType) malloc(sizeof(GifPixelType) * ImageWidth * 2)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); if (Direction == DIR_TOP) { /* We must evaluate the line each time level is changing: */ LevelHeight = ImageHeight / NumLevels; for (Color = NumLevels, i = l = 0; i < ImageHeight; i++) { if (i == l) { /* Time to update the line to next color level: */ if (Color != 0) Color--; for (j = 0; j < ImageWidth; j++) Line[j] = (FlipDir ? NumLevels - Color - 1 : Color); l += LevelHeight; } if (EGifPutLine(GifFile, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", Count++); } } else if (Direction == DIR_RIGHT) { /* We pre-prepare the scan lines as going from color zero to maximum */ /* color and dump the same scan line Height times: */ /* Note this case should handle the Boolean Mask special case. */ LevelWidth = ImageWidth / NumLevels; if (DoAllMaximum) { /* Special case - do all in maximum color: */ for (i = 0; i < ImageWidth; i++) Line[i] = 1; } else { for (Color = i = 0, l = LevelWidth; i < ImageWidth; i++, l--) { if (l == 0) { l = LevelWidth; if (Color < NumLevels - 1) Color++; } Line[i] = (FlipDir ? NumLevels - Color - 1 : Color); } } for (i = 0; i < ImageHeight; i++) { if (EGifPutLine(GifFile, Line, ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", Count++); } } else { /* We are in one of the TOP_RIGHT, BOT_RIGHT cases: we will */ /* initialize the Line with its double ImageWidth length from the */ /* minimum intensity to the maximum intensity and shift along it */ /* while we go along the image height. */ LevelWidth = ImageWidth * 2 / NumLevels; for (Color = i = 0, l = LevelWidth; i < ImageWidth * 2; i++, l--) { if (l == 0) { l = LevelWidth; if (Color < NumLevels - 1) Color++; } Line[i] = (FlipDir ? NumLevels - Color - 1 : Color); } /* We need to implement a DDA to know how much to shift Line while */ /* we go down along image height. we set the parameters for it now: */ Accumulator = 0; switch(Direction) { case DIR_TOP_RIGHT: StartX = ImageWidth; StepX = -1; break; case DIR_BOT_RIGHT: default: StartX = 0; StepX = 1; break; } /* Time to dump information out: */ for (i = 0; i < ImageHeight; i++) { if (EGifPutLine(GifFile, &Line[StartX], ImageWidth) == GIF_ERROR) QuitGifError(GifFile); GifQprintf("\b\b\b\b%-4d", Count++); if ((Accumulator += ImageWidth) > ImageHeight) { while (Accumulator > ImageHeight) { Accumulator -= ImageHeight; StartX += StepX; } if (Direction < 0) Direction = 0; if (Direction > ImageWidth) Direction = ImageWidth; } } } if (EGifCloseFile(GifFile) == GIF_ERROR) QuitGifError(GifFile); return 0; }
/* * Updates the background objects as necessary. Removes existing ones, * and then looks at the interface and builds new ones. */ void UpdateBackgroundObjects ( WindowObjectType *wo, int potIndex ) { MetObjectType *mot, *mlist[MAXMETOBJS]; int i, count, nmaps; char mapfile[GEMPAKSTRING]; char mapname[GEMPAKSTRING]; char *latinc, *loninc, *lblinc; char line_color[GEMPAKSTRING]; char line_type[GEMPAKSTRING]; char line_width[GEMPAKSTRING]; char sysM [] = "M"; float lat1, lat2, lon1, lon2, latdiff; double fminscale, fmaxscale; char *minscale, *maxscale; Widget stateW; BooleanType stateChanged; GuiMapBackgroundDialogType *mbg; GuiLatLonGridDialogType *llg; PixmapObjectType *po, *ppo; llg = GetGuiLatLonGridDialog(); mbg = GetGuiMapBackgroundDialog(); po = wo->pixmapObjects[potIndex]; /* * First, decide if we need to rebuild the background objects. If there * are no MAP class objects, or if the backgrounds * dialog info has changed, then we will build new ones. */ nmaps = 0; for ( i = 0; i < po->numMetObjects; i++ ) { mot = po->metObjects [i]; if ( GetMetObjectClass ( mot->type ) == MAP ) nmaps++; } stateChanged =( GetLatLonGridChangeState (llg) || GetMapListChangeState (mbg) ); if ( nmaps == 0 || stateChanged ) RemoveBackgroundObjects( po ); else return; /* * Get the latitude range of the current window */ if ( (getbounds ( sysM, &lat1, &lon1, &lat2, &lon2 )) == 0 ) latdiff = -9999; else latdiff = (float) fabs (lat2 - lat1); count = 0; /* * Loop over all the map objects. See if any are turned on. If so, * check the scale range and add them if they are in the right scale. */ for ( i = 0; i < mbg->nmaps; i++ ) { if ( XmToggleButtonGetState ( GetMapListOnToggleW(mbg,i)) ) { maxscale = XmTextGetString( GetMapListMaxScaleW(mbg,i)); minscale = XmTextGetString( GetMapListMinScaleW(mbg,i)); fmaxscale = atof ( maxscale); fminscale = atof ( minscale); XtFree ( maxscale); XtFree ( minscale); if ( ( fmaxscale <= 0.0 ) || ( latdiff >= fminscale && latdiff <= fmaxscale) ) { strcpy ( mapfile, mbg->path[i] ); strcpy ( mapname, mbg->name[i].string ); sprintf ( line_color, "%d", GetMapListLineColor(mbg,i)); sprintf ( line_type, "%d", GetMapListLineType(mbg,i)); sprintf ( line_width, "%d", GetMapListLineWidth(mbg,i)); mlist[count] = (MetObjectType *) MakeMapObject( mapname, mapfile, line_color, line_type, line_width); count++; } } } /* * Add a lat/lon grid */ if ( XmToggleButtonGetState ( GetLatLonGridStateW (llg) )) { latinc = XmTextGetString ( GetLatIncrementW (llg) ); loninc = XmTextGetString ( GetLonIncrementW (llg) ); lblinc = XmTextGetString ( GetLatLonGridLabelIncW(llg) ); sprintf ( line_color, "%d", GetLatLonGridColor (llg)); sprintf ( line_type, "%d", GetLatLonGridType (llg)); sprintf ( line_width, "%d", GetLatLonGridWidth (llg)); mlist[count] = (MetObjectType *) MakeLatLonGridObject( latinc, loninc, lblinc, line_color, line_type, line_width); XtFree ( latinc ); XtFree ( loninc ); XtFree ( lblinc ); count++; } /* * Add all the created objects in as background objects */ AddMapBackgroundObjects ( po, count, mlist ); /* * Since we have new maps, set all the drawn flags of all the metObjects * in this pixmapObject false so that they will be redrawn. */ SetPixmapObjectDrawnFlag ( po, False ); /* * Reset the change state of the map and lat/lon dialogs for the last * pixmap */ if ( potIndex == wo->numPixmapObjects - 1 ) { SetLatLonGridChangeState ( llg, False); SetMapListChangeState ( mbg, False); } }
void * gif_encode(Image *image, int single, int *size) { int width = image->columns; int height = image->rows; int total = width * height; GifByteType output[total]; GifByteType red[total]; GifByteType green[total]; GifByteType blue[total]; // Quantize the images using IM/GM first, to reduce // their number of colors to 256. int count = GetImageListLength(image); QuantizeInfo info; GetQuantizeInfo(&info); info.dither = 1; info.number_colors = NCOLORS; QuantizeImage(&info, image); if (count > 1) { #ifdef _MAGICK_USES_IM RemapImages(&info, image->next, image); #else MapImages(image->next, image, 0); #endif } if (!acquire_image_pixels(image, red, green, blue)) { return NULL; } Frame *frames = calloc(count, sizeof(*frames)); ColorMapObject *palette = MakeMapObject(NCOLORS, NULL); int palette_size = NCOLORS; // Quantize again using giflib, since it yields a palette which produces // better compression, reducing the file size by 20%. Note that this second // quantization is very fast, because the image already has 256 colors, so // its effect on performance is negligible. if (QuantizeBuffer(width, height, &palette_size, red, green, blue, output, palette->Colors) == GIF_ERROR) { FreeMapObject(palette); gif_frames_free(frames, count); return NULL; } frames[0].data = malloc(total); memcpy(frames[0].data, output, total); frames[0].width = width; frames[0].height = height; frames[0].duration = image->delay; GifColorType *colors = palette->Colors; Image *cur = image->next; PixelCache *cache = pixel_cache_new(); int ii; for (ii = 1; ii < count; ii++, cur = cur->next) { frames[ii].width = width; frames[ii].height = height; frames[ii].duration = cur->delay; GifPixelType *data = malloc(total); frames[ii].data = data; if (!aprox_image_pixels(cur, colors, palette_size, cache, data)) { FreeMapObject(palette); gif_frames_free(frames, count); pixel_cache_free(cache); return NULL; } } pixel_cache_free(cache); void *ret = gif_save(image, palette, frames, count, size); FreeMapObject(palette); gif_frames_free(frames, count); return ret; }
static int encode_gif_data(psx_image_header* header, psx_image_frame* frame, int idx, const ps_byte* buffer, size_t buffer_len, int* ret) { int x, y; ColorMapObject *output_map = NULL; int map_size = 256; struct gif_image_ctx* ctx = (struct gif_image_ctx*)header->priv; if ((output_map = MakeMapObject(map_size, NULL)) == NULL) { if (ret) *ret = S_FAILURE; return -1; } for (y = 0; y < header->height; y++) { ps_byte* row = (ps_byte*)(buffer + header->pitch * y); for (x = 0; x < header->width; x++) { uint32_t rgba[4] = {0}; // r, g, b, a gif_get_pixel_rgba_premultiply(header->format, row, x, rgba); ctx->red_buf[header->width * y + x] = rgba[0]; ctx->green_buf[header->width * y + x] = rgba[1]; ctx->blue_buf[header->width * y + x] = rgba[2]; } } if (QuantizeBuffer(header->width, header->height, &map_size, ctx->red_buf, ctx->green_buf, ctx->blue_buf, ctx->output_buffer, output_map->Colors) == GIF_ERROR) { FreeMapObject(output_map); if (ret) *ret = S_FAILURE; return -1; } if (frame->duration > 0) { GifByteType extension[4]; #if GIFLIB_MAJOR >= 5 GraphicsControlBlock gcb; gcb.DisposalMode = DISPOSAL_UNSPECIFIED; // FIXME: need specified ? gcb.UserInputFlag = false; gcb.DelayTime = frame->duration / 10; gcb.TransparentColor = -1; // FIXME: need specified ? EGifGCBToExtension(&gcb, extension); #else int delay = frame->duration / 10; extension[0] = 0; extension[1] = LOBYTE(delay); extension[2] = HIBYTE(delay); extension[3] = (char)-1; #endif if (EGifPutExtension(ctx->gif, GRAPHICS_EXT_FUNC_CODE, 4, extension) == GIF_ERROR) { FreeMapObject(output_map); if (ret) *ret = S_FAILURE; return -1; } } if (EGifPutImageDesc(ctx->gif, 0, 0, header->width, header->height, FALSE, output_map) == GIF_ERROR) { FreeMapObject(output_map); if (ret) *ret = S_FAILURE; return -1; } for (y = 0; y < header->height; y++) { EGifPutLine(ctx->gif, ctx->output_buffer + y * header->width, header->width); } FreeMapObject(output_map); return 0; }
int write_gif(const char *filename, int width, int height, char *rgb) { int i; int colormap_size = 256; GifByteType *red, *green, *blue, *buffer, *ptr; GifFileType *outfile; ColorMapObject *colormap; red = malloc(width * height * sizeof(GifByteType)); green = malloc(width * height * sizeof(GifByteType)); blue = malloc(width * height * sizeof(GifByteType)); buffer = malloc(width * height * sizeof(GifByteType)); if (red == NULL || green == NULL || blue == NULL || buffer == NULL) { fprintf(stderr, "Can't allocate memory for GIF file.\n"); return(0); } colormap = MakeMapObject(colormap_size, NULL); for (i = 0; i < width * height; i++) { red[i] = (GifByteType) rgb[3*i ]; green[i] = (GifByteType) rgb[3*i+1]; blue[i] = (GifByteType) rgb[3*i+2]; } if (QuantizeBuffer(width, height, &colormap_size, red, green, blue, buffer, colormap->Colors) == GIF_ERROR) { PrintGifError(); return(0); } free(red); free(green); free(blue); outfile = EGifOpenFileName((char *) filename, FALSE); if (outfile == NULL) { PrintGifError(); return(0); } if (EGifPutScreenDesc(outfile, width, height, colormap_size, 0, colormap) == GIF_ERROR) { PrintGifError(); return(0); } if (EGifPutImageDesc(outfile, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) { PrintGifError(); return(0); } ptr = buffer; for (i = 0; i < height; i++) { if (EGifPutLine(outfile, ptr, width) == GIF_ERROR) { PrintGifError(); return(0); } ptr += width; } EGifSpew(outfile); if (EGifCloseFile(outfile) == GIF_ERROR) PrintGifError(); free(buffer); return(1); }
int main(int argc, char **argv) { int i,j,k,l,c,h; char fname[16]="test.gif"; unsigned char img[64]; GifColorType ScratchMap2[2]; GifColorType ScratchMap4[4]; GifColorType ScratchMap[16]; #define SETCOL(x,y) {\ ScratchMap[x].Red = (y>>16)&0xFF;\ ScratchMap[x].Green = (y>>8)&0xFF;\ ScratchMap[x].Blue = y&0xFF;\ } SETCOL( 0,0x000000); SETCOL( 1,0x0000AA); SETCOL( 2,0x00AA00); SETCOL( 3,0x00AAAA); SETCOL( 4,0xAA0000); SETCOL( 5,0xAA00AA); SETCOL( 6,0xAA5500); SETCOL( 7,0xAAAAAA); SETCOL( 8,0x555555); SETCOL( 9,0x5555FF); SETCOL(10,0x55FF55); SETCOL(11,0x55FFFF); SETCOL(12,0xFF5555); SETCOL(13,0xFF55FF); SETCOL(14,0xFFFF55); SETCOL(15,0xFFFFFF); for(h=0;h<5;h++) { ScratchMap2[0] = ScratchMap[0]; switch(h) { case 0: ScratchMap2[1] = ScratchMap[2]; break; case 1: ScratchMap2[1] = ScratchMap[7]; break; case 2: ScratchMap2[1] = ScratchMap[12]; break; case 3: ScratchMap2[1] = ScratchMap[11]; break; case 4: ScratchMap2[1] = ScratchMap[0]; ScratchMap2[0] = ScratchMap[2]; break; } colormap = MakeMapObject(2,ScratchMap2); if(colormap==NULL) return -1; for(k=0;k<FONT8X8_CHARS;k++) { sprintf(fname,"0%i%2.2x.gif",h,k+FONT8X8_FIRST); l = 0; for(j=0;j<8;j++) { c = font8x8[k][j]; for(i=0;i<8;i++) { if(c&0x80) img[l] = 1; else img[l] = 0; l++;c<<=1; } } SaveGif(fname,img,colormap,2,8,8); } } #if 1 /* special PCB characters */ for(h=0;h<5;h++) { if(h==0) { ScratchMap4[0] = ScratchMap[0]; ScratchMap4[1] = ScratchMap[1]; ScratchMap4[2] = ScratchMap[2]; ScratchMap4[3] = ScratchMap[4]; colormap = MakeMapObject(4,ScratchMap4); if(colormap==NULL) return -2; } if(h==1) { ScratchMap4[0] = ScratchMap[0]; ScratchMap4[1] = ScratchMap[7]; ScratchMap4[2] = ScratchMap[12]; ScratchMap4[3] = ScratchMap[11]; colormap = MakeMapObject(4,ScratchMap4); if(colormap==NULL) return -3; } if(h==4) { ScratchMap4[0] = ScratchMap[2]; ScratchMap4[1] = ScratchMap[0]; ScratchMap4[2] = ScratchMap[0]; ScratchMap4[3] = ScratchMap[0]; colormap = MakeMapObject(4,ScratchMap4); if(colormap==NULL) return -3; } for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[63]=2; } else { img[63]=h; } sprintf(fname,"0%i00.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<64;i++) img[i]=1; img[18]=2;img[19]=2;img[20]=2;img[21]=2; img[26]=2;img[27]=0;img[28]=0;img[29]=2; img[34]=2;img[35]=0;img[36]=0;img[37]=2; img[42]=2;img[43]=2;img[44]=2;img[45]=2; img[24]=3;img[25]=3; img[32]=3;img[33]=3; } else { for(i=0;i<64;i++) img[i]=h; img[18]=h;img[19]=h;img[20]=h;img[21]=h; img[26]=h;img[27]=0;img[28]=0;img[29]=h; img[34]=h;img[35]=0;img[36]=0;img[37]=h; img[42]=h;img[43]=h;img[44]=h;img[45]=h; img[24]=h;img[25]=h; img[32]=h;img[33]=h; } sprintf(fname,"0%i01.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[30]=3;img[31]=3; img[38]=3;img[39]=3; } else { img[30]=h;img[31]=h; img[38]=h;img[39]=h; } sprintf(fname,"0%i03.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[24]=1;img[25]=1; img[32]=1;img[33]=1; } else { img[24]=h;img[25]=h; img[32]=h;img[33]=h; } sprintf(fname,"0%i02.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<64;i++) img[i]=1; for(i=0;i<8;i++){img[24+i]=3;img[32+i]=3;} } else { for(i=0;i<64;i++) img[i]=h; } sprintf(fname,"0%i04.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[18]=2;img[19]=2;img[20]=2;img[21]=2; img[26]=2;img[27]=0;img[28]=0;img[29]=2; img[34]=2;img[35]=0;img[36]=0;img[37]=2; img[42]=2;img[43]=2;img[44]=2;img[45]=2; img[ 3]=1;img[ 4]=1; img[11]=1;img[12]=1; img[24]=3;img[25]=3; img[32]=3;img[33]=3; } else { img[18]=h;img[19]=h;img[20]=h;img[21]=h; img[26]=h;img[27]=0;img[28]=0;img[29]=h; img[34]=h;img[35]=0;img[36]=0;img[37]=h; img[42]=h;img[43]=h;img[44]=h;img[45]=h; img[ 3]=h;img[ 4]=h; img[11]=h;img[12]=h; img[24]=h;img[25]=h; img[32]=h;img[33]=h; } sprintf(fname,"0%i05.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[30]=3;img[31]=3; img[38]=3;img[39]=3; } else { img[30]=h;img[31]=h; img[38]=h;img[39]=h; } sprintf(fname,"0%i07.gif",h); SaveGif(fname,img,colormap,4,8,8); img[24]=0;img[25]=0; img[32]=0;img[33]=0; sprintf(fname,"0%i06.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[24]=1;img[32]=1;img[40]=1; img[33]=1;img[41]=1;img[49]=1; img[42]=1;img[50]=1;img[58]=1; img[51]=1;img[59]=1; img[60]=1; } else { img[24]=h;img[32]=h;img[40]=h; img[33]=h;img[41]=h;img[49]=h; img[42]=h;img[50]=h;img[58]=h; img[51]=h;img[59]=h; img[60]=h; } sprintf(fname,"0%i08.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[18]=2;img[19]=2;img[20]=2;img[21]=2; img[26]=2;img[27]=0;img[28]=0;img[29]=2; img[34]=2;img[35]=0;img[36]=0;img[37]=2; img[42]=2;img[43]=2;img[44]=2;img[45]=2; img[51]=1;img[52]=1; img[59]=1;img[60]=1; img[24]=3;img[25]=3; img[32]=3;img[33]=3; } else { img[18]=h;img[19]=h;img[20]=h;img[21]=h; img[26]=h;img[27]=0;img[28]=0;img[29]=h; img[34]=h;img[35]=0;img[36]=0;img[37]=h; img[42]=h;img[43]=h;img[44]=h;img[45]=h; img[51]=h;img[52]=h; img[59]=h;img[60]=h; img[24]=h;img[25]=h; img[32]=h;img[33]=h; } sprintf(fname,"0%i09.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[30]=3;img[31]=3; img[38]=3;img[39]=3; } else { img[30]=h;img[31]=h; img[38]=h;img[39]=h; } sprintf(fname,"0%i0b.gif",h); SaveGif(fname,img,colormap,4,8,8); img[24]=0;img[25]=0; img[32]=0;img[33]=0; sprintf(fname,"0%i0a.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[3]=1;img[4]=1;img[5]=1; img[12]=1;img[13]=1;img[14]=1; img[21]=1;img[22]=1;img[23]=1; img[30]=1;img[31]=1; img[39]=1; } else { img[3]=h;img[4]=h;img[5]=h; img[12]=h;img[13]=h;img[14]=h; img[21]=h;img[22]=h;img[23]=h; img[30]=h;img[31]=h; img[39]=h; } sprintf(fname,"0%i0c.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[18]=2;img[19]=2;img[20]=2;img[21]=2; img[26]=2;img[27]=0;img[28]=0;img[29]=2; img[34]=2;img[35]=0;img[36]=0;img[37]=2; img[42]=2;img[43]=2;img[44]=2;img[45]=2; img[ 3]=1;img[ 4]=1; img[11]=1;img[12]=1; img[24]=3;img[25]=3; img[32]=3;img[33]=3; img[51]=1;img[52]=1; img[59]=1;img[60]=1; } else { img[18]=h;img[19]=h;img[20]=h;img[21]=h; img[26]=h;img[27]=0;img[28]=0;img[29]=h; img[34]=h;img[35]=0;img[36]=0;img[37]=h; img[42]=h;img[43]=h;img[44]=h;img[45]=h; img[ 3]=h;img[ 4]=h; img[11]=h;img[12]=h; img[24]=h;img[25]=h; img[32]=h;img[33]=h; img[51]=h;img[52]=h; img[59]=h;img[60]=h; } sprintf(fname,"0%i0d.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[30]=3;img[31]=3; img[38]=3;img[39]=3; } else { img[30]=h;img[31]=h; img[38]=h;img[39]=h; } sprintf(fname,"0%i0f.gif",h); SaveGif(fname,img,colormap,4,8,8); img[24]=0;img[25]=0; img[32]=0;img[33]=0; sprintf(fname,"0%i0e.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<64;i++) img[i]=1; } else { for(i=0;i<64;i++) img[i]=h; } sprintf(fname,"0%i10.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { for(i=0;i<8;i++){img[24+i]=3;img[32+i]=3;} } else { for(i=0;i<8;i++){img[24+i]=h;img[32+i]=h;} } sprintf(fname,"0%i11.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { for(i=0;i<8;i++){img[3+i*8]=1;img[4+i*8]=1;} } else { for(i=0;i<8;i++){img[3+i*8]=h;img[4+i*8]=h;} } sprintf(fname,"0%i12.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<8;i++) img[24+i]=3; for(i=0;i<8;i++) img[32+i]=3; img[18]=0;img[19]=1;img[20]=1;img[21]=0; img[42]=0;img[43]=1;img[44]=1;img[45]=0; } else { for(i=0;i<8;i++) img[24+i]=h; for(i=0;i<8;i++) img[32+i]=h; img[18]=0;img[19]=h;img[20]=h;img[21]=0; img[42]=0;img[43]=h;img[44]=h;img[45]=0; } sprintf(fname,"0%i13.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { for(i=0;i<8;i++){img[6+i*8]=2;img[7+i*8]=2;} for(i=1;i<7;i++){img[4+i*8]=2;img[5+i*8]=2;} for(i=2;i<6;i++) img[3+i*8]=2; } else { for(i=0;i<8;i++){img[6+i*8]=h;img[7+i*8]=h;} for(i=1;i<7;i++){img[4+i*8]=h;img[5+i*8]=h;} for(i=2;i<6;i++) img[3+i*8]=h; } sprintf(fname,"0%i14.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[24]=3;img[25]=3;img[26]=3; img[32]=3;img[33]=3;img[34]=3; } else { img[24]=h;img[25]=h;img[26]=h; img[32]=h;img[33]=h;img[34]=h; } sprintf(fname,"0%i15.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { for(i=0;i<8;i++){img[i*8]=2;img[1+i*8]=2;} for(i=1;i<7;i++){img[2+i*8]=2;img[3+i*8]=2;} for(i=2;i<6;i++) img[4+i*8]=2; } else { for(i=0;i<8;i++){img[i*8]=h;img[1+i*8]=h;} for(i=1;i<7;i++){img[2+i*8]=h;img[3+i*8]=h;} for(i=2;i<6;i++) img[4+i*8]=h; } sprintf(fname,"0%i16.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { img[29]=3;img[30]=3;img[31]=3; img[37]=3;img[38]=3;img[39]=3; } else { img[29]=h;img[30]=h;img[31]=h; img[37]=h;img[38]=h;img[39]=h; } sprintf(fname,"0%i17.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<64;i++) img[i]=2; } else { for(i=0;i<64;i++) img[i]=h; } img[19]=0;img[20]=0; img[26]=0;img[27]=0;img[28]=0;img[29]=0; img[34]=0;img[35]=0;img[36]=0;img[37]=0; img[43]=0;img[44]=0; sprintf(fname,"0%i18.gif",h); SaveGif(fname,img,colormap,4,8,8); img[0]=0;img[1]=0;img[8]=0; img[6]=0;img[7]=0;img[15]=0; img[56]=0;img[57]=0;img[48]=0; img[62]=0;img[63]=0;img[55]=0; sprintf(fname,"0%i19.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<64;i++) { if(i>=16 && i<48) img[i]=3; else img[i]=0; } } else { for(i=0;i<64;i++) { if(i>=16 && i<48) img[i]=h; else img[i]=0; } } sprintf(fname,"0%i1a.gif",h); SaveGif(fname,img,colormap,4,8,8); if(h==0||h==4) { for(i=0;i<64;i++) img[i]=3; } else { for(i=0;i<64;i++) img[i]=h; } sprintf(fname,"0%i1b.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[16]=3;img[24]=3;img[32]=3; img[9]=3;img[17]=3;img[25]=3; img[2]=3;img[10]=3;img[18]=3; img[3]=3;img[11]=3; img[4]=3; } else { img[16]=h;img[24]=h;img[32]=h; img[9]=h;img[17]=h;img[25]=h; img[2]=h;img[10]=h;img[18]=h; img[3]=h;img[11]=h; img[4]=h; } sprintf(fname,"0%i1c.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[31]=3;img[39]=3;img[47]=3; img[38]=3;img[46]=3;img[54]=3; img[45]=3;img[53]=3;img[61]=3; img[52]=3;img[60]=3; img[59]=3; } else { img[31]=h;img[39]=h;img[47]=h; img[38]=h;img[46]=h;img[54]=h; img[45]=h;img[53]=h;img[61]=h; img[52]=h;img[60]=h; img[59]=h; } sprintf(fname,"0%i1d.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[4]=2; img[12]=2; img[19]=2;img[20]=2;img[21]=2; img[27]=2;img[28]=2;img[29]=2; img[34]=2;img[35]=2;img[36]=2;img[37]=2;img[38]=2; img[42]=2;img[43]=2;img[44]=2;img[45]=2;img[46]=2; img[49]=2;img[50]=2;img[52]=2;img[54]=2;img[55]=2; img[57]=2;img[60]=2;img[63]=2; } else { img[4]=h; img[12]=h; img[19]=h;img[20]=h;img[21]=h; img[27]=h;img[28]=h;img[29]=h; img[34]=h;img[35]=h;img[36]=h;img[37]=h;img[38]=h; img[42]=h;img[43]=h;img[44]=h;img[45]=h;img[46]=h; img[49]=h;img[50]=h;img[52]=h;img[54]=h;img[55]=h; img[57]=h;img[60]=h;img[63]=h; } sprintf(fname,"0%i1e.gif",h); SaveGif(fname,img,colormap,4,8,8); for(i=0;i<64;i++) img[i]=0; if(h==0||h==4) { img[60]=2; img[52]=2; img[43]=2;img[44]=2;img[45]=2; img[35]=2;img[36]=2;img[37]=2; img[26]=2;img[27]=2;img[28]=2;img[29]=2;img[30]=2; img[18]=2;img[19]=2;img[20]=2;img[21]=2;img[22]=2; img[9]=2;img[10]=2;img[12]=2;img[14]=2;img[15]=2; img[1]=2;img[4]=2;img[7]=2; } else { img[60]=h; img[52]=h; img[43]=h;img[44]=h;img[45]=h; img[35]=h;img[36]=h;img[37]=h; img[26]=h;img[27]=h;img[28]=h;img[29]=h;img[30]=h; img[18]=h;img[19]=h;img[20]=h;img[21]=h;img[22]=h; img[9]=h;img[10]=h;img[12]=h;img[14]=h;img[15]=h; img[1]=h;img[4]=h;img[7]=h; } sprintf(fname,"0%i1f.gif",h); SaveGif(fname,img,colormap,4,8,8); } #endif return 0; }
GDALDataset * GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData ) { int nBands = poSrcDS->GetRasterCount(); int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); int bInterlace = FALSE; /* -------------------------------------------------------------------- */ /* Check for interlaced option. */ /* -------------------------------------------------------------------- */ bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE); /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ if( nBands != 1 ) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver only supports one band images.\n" ); return NULL; } if (nXSize > 65535 || nYSize > 65535) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver only supports datasets up to 65535x65535 size.\n" ); return NULL; } if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "GIF driver doesn't support data type %s. " "Only eight bit bands supported.\n", GDALGetDataTypeName( poSrcDS->GetRasterBand(1)->GetRasterDataType()) ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the output file. */ /* -------------------------------------------------------------------- */ GifFileType *hGifFile; VSILFILE *fp; fp = VSIFOpenL( pszFilename, "wb" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to create %s:\n%s", pszFilename, VSIStrerror( errno ) ); return NULL; } hGifFile = EGifOpen( fp, VSIGIFWriteFunc ); if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "EGifOpenFilename(%s) failed. Does file already exist?", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Prepare colortable. */ /* -------------------------------------------------------------------- */ GDALRasterBand *poBand = poSrcDS->GetRasterBand(1); ColorMapObject *psGifCT; int iColor; if( poBand->GetColorTable() == NULL ) { psGifCT = MakeMapObject( 256, NULL ); for( iColor = 0; iColor < 256; iColor++ ) { psGifCT->Colors[iColor].Red = (GifByteType) iColor; psGifCT->Colors[iColor].Green = (GifByteType) iColor; psGifCT->Colors[iColor].Blue = (GifByteType) iColor; } } else { GDALColorTable *poCT = poBand->GetColorTable(); int nFullCount = 1; while( nFullCount < poCT->GetColorEntryCount() ) nFullCount = nFullCount * 2; psGifCT = MakeMapObject( nFullCount, NULL ); for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ ) { GDALColorEntry sEntry; poCT->GetColorEntryAsRGB( iColor, &sEntry ); psGifCT->Colors[iColor].Red = (GifByteType) sEntry.c1; psGifCT->Colors[iColor].Green = (GifByteType) sEntry.c2; psGifCT->Colors[iColor].Blue = (GifByteType) sEntry.c3; } for( ; iColor < nFullCount; iColor++ ) { psGifCT->Colors[iColor].Red = 0; psGifCT->Colors[iColor].Green = 0; psGifCT->Colors[iColor].Blue = 0; } } /* -------------------------------------------------------------------- */ /* Setup parameters. */ /* -------------------------------------------------------------------- */ if (EGifPutScreenDesc(hGifFile, nXSize, nYSize, psGifCT->ColorCount, 255, psGifCT) == GIF_ERROR) { FreeMapObject(psGifCT); PrintGifError(); CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); EGifCloseFile(hGifFile); VSIFCloseL( fp ); return NULL; } FreeMapObject(psGifCT); psGifCT = NULL; /* Support for transparency */ int bNoDataValue; double noDataValue = poBand->GetNoDataValue(&bNoDataValue); if (bNoDataValue && noDataValue >= 0 && noDataValue <= 255) { unsigned char extensionData[4]; extensionData[0] = 1; /* Transparent Color Flag */ extensionData[1] = 0; extensionData[2] = 0; extensionData[3] = (unsigned char)noDataValue; EGifPutExtension(hGifFile, 0xf9, 4, extensionData); } if (EGifPutImageDesc(hGifFile, 0, 0, nXSize, nYSize, bInterlace, NULL) == GIF_ERROR ) { PrintGifError(); CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); EGifCloseFile(hGifFile); VSIFCloseL( fp ); return NULL; } /* -------------------------------------------------------------------- */ /* Loop over image, copying image data. */ /* -------------------------------------------------------------------- */ CPLErr eErr; GDALPamDataset *poDS; GByte *pabyScanline; pabyScanline = (GByte *) CPLMalloc( nXSize ); if( !pfnProgress( 0.0, NULL, pProgressData ) ) eErr = CE_Failure; if( !bInterlace ) { for( int iLine = 0; iLine < nYSize; iLine++ ) { eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, pabyScanline, nXSize, 1, GDT_Byte, nBands, nBands * nXSize ); if( eErr != CE_None || EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR ) { CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); goto error; } if( !pfnProgress( (iLine + 1) * 1.0 / nYSize, NULL, pProgressData ) ) { goto error; } } } else { int i, j; int nLinesRead = 0; int nLinesToRead = 0; for ( i = 0; i < 4; i++) { for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) { nLinesToRead ++; } } /* Need to perform 4 passes on the images: */ for ( i = 0; i < 4; i++) { for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) { eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1, pabyScanline, nXSize, 1, GDT_Byte, 1, nXSize ); if (eErr != CE_None || EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR) { CPLError( CE_Failure, CPLE_AppDefined, "Error writing gif file." ); goto error; } nLinesRead ++; if( !pfnProgress( nLinesRead * 1.0 / nYSize, NULL, pProgressData ) ) { goto error; } } } } CPLFree( pabyScanline ); pabyScanline = NULL; /* -------------------------------------------------------------------- */ /* cleanup */ /* -------------------------------------------------------------------- */ if (EGifCloseFile(hGifFile) == GIF_ERROR) { CPLError( CE_Failure, CPLE_AppDefined, "EGifCloseFile() failed.\n" ); hGifFile = NULL; goto error; } hGifFile = NULL; VSIFCloseL( fp ); fp = NULL; /* -------------------------------------------------------------------- */ /* Do we need a world file? */ /* -------------------------------------------------------------------- */ if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) ) { double adfGeoTransform[6]; if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None ) GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform ); } /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxilary pam information. */ /* -------------------------------------------------------------------- */ /* If outputing to stdout, we can't reopen it, so we'll return */ /* a fake dataset to make the caller happy */ CPLPushErrorHandler(CPLQuietErrorHandler); poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly); CPLPopErrorHandler(); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; } else { CPLErrorReset(); GIFDataset* poGIF_DS = new GIFDataset(); poGIF_DS->nRasterXSize = nXSize; poGIF_DS->nRasterYSize = nYSize; for(int i=0;i<nBands;i++) poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) ); return poGIF_DS; } error: if (hGifFile) EGifCloseFile(hGifFile); if (fp) VSIFCloseL( fp ); if (pabyScanline) CPLFree( pabyScanline ); return NULL; }
unsigned char * gifconv_lossless2gif(void *image_data, unsigned short width, unsigned short height, void *index_data, unsigned short index_data_count, int tag_no, int format, unsigned long *length) { GifFileType *GifFile = NULL; GifColorType *Colors = NULL; int ColorCount; my_gif_buffer gif_buff; gif_uint_32 gif_width = 0, gif_height = 0; int bpp; gif_bytep gif_image_data = NULL; gif_uint_32 x, y; gif_colorp gif_palette = NULL; // int trans_index = -1; int i; if (format != 3) { fprintf(stderr, "jpegconv_lossless2gif: format=%d not implemented yes.\n", format); return NULL; } bpp = 8; gif_width = width; gif_height = height; ColorCount = 256; Colors = calloc(sizeof(GifColorType), ColorCount); gif_buff.data = NULL; gif_buff.data_len = 0; gif_buff.data_offset = 0; #if GIFLIB_MAJOR >= 5 GifFile = EGifOpen(& gif_buff, gif_data_write_func, NULL); #else GifFile = EGifOpen(& gif_buff, gif_data_write_func); #endif if (GifFile == NULL) { fprintf(stderr, "gifconv_lossless2gif: can't open GIFFile\n"); return NULL; } GifFile->SWidth = gif_width; GifFile->SHeight = gif_height; GifFile->SColorResolution = bpp; gif_palette = (gif_colorp) malloc(sizeof(gif_color)*index_data_count); if (tag_no == 20) { swf_rgb_t *rgb_list = index_data; for (i=0 ; i < index_data_count ; i++) { Colors[i].Red = rgb_list[i].red; Colors[i].Green = rgb_list[i].green; Colors[i].Blue = rgb_list[i].blue; } } else { swf_rgba_t *rgba_list = index_data; for (i=0 ; i < index_data_count ; i++) { // if (rgba_list[i].alpha) Colors[i].Red = rgba_list[i].red; Colors[i].Green = rgba_list[i].green; Colors[i].Blue = rgba_list[i].blue; // gif_palette[i].alpha = ; } } GifFile->SBackGroundColor = 0; // XXX gif_image_data = (gif_bytep) calloc(sizeof(unsigned char), gif_width * gif_height); i = 0; for (y=0 ; y < gif_height ; y++) { for (x=0 ; x < gif_width ; x++) { unsigned char *data = image_data; gif_image_data[i] = data[x + y*((gif_width +3) & -4)]; i++; } } GifFile->SavedImages[0].RasterBits = gif_image_data; #if GIFLIB_MAJOR >= 5 GifFile->SColorMap = GifMakeMapObject(ColorCount, Colors); #else GifFile->SColorMap = MakeMapObject(ColorCount, Colors); #endif EGifSpew(GifFile); // XXX free(gif_image_data); if (GifFile) { #if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1 || GIFLIB_MAJOR > 5 EGifCloseFile(GifFile, NULL); #else EGifCloseFile(GifFile); #endif } *length = gif_buff.data_offset; return gif_buff.data; }
/****************************************************************************** * Modify the given colormap according to global variables setting. * ******************************************************************************/ static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap) { int i, Dummy, Red, Green, Blue, Max = 0; double Gamma1; if (SaveFlag) { /* Save this color map to ColorFile: */ for (i = 0; i < ColorMap->ColorCount; i++) fprintf(ColorFile, "%3d %3d %3d %3d\n", i, ColorMap->Colors[i].Red, ColorMap->Colors[i].Green, ColorMap->Colors[i].Blue); return(ColorMap); } else if (LoadFlag) { /* Read the color map in ColorFile into this color map: */ for (i = 0; i < ColorMap->ColorCount; i++) { if (feof(ColorFile)) GIF_EXIT("Color file to load color map from, too small."); fscanf(ColorFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue); ColorMap->Colors[i].Red = Red; ColorMap->Colors[i].Green = Green; ColorMap->Colors[i].Blue = Blue; } return(ColorMap); } else if (GammaFlag) { /* Apply gamma correction to this color map: */ Gamma1 = 1.0 / Gamma; for (i = 0; i < ColorMap->ColorCount; i++) { ColorMap->Colors[i].Red = ((int) (255 * pow(ColorMap->Colors[i].Red / 255.0, Gamma1))); ColorMap->Colors[i].Green = ((int) (255 * pow(ColorMap->Colors[i].Green / 255.0, Gamma1))); ColorMap->Colors[i].Blue = ((int) (255 * pow(ColorMap->Colors[i].Blue / 255.0, Gamma1))); } return(ColorMap); } else if (TranslateFlag) { ColorMapObject *NewMap; /* Read the translation table in TranslateFile: */ for (i = 0; i < ColorMap->ColorCount; i++) { int tmp; if (feof(TranslateFile)) GIF_EXIT("Color file to load color map from, too small."); fscanf(TranslateFile, "%3d %3d\n", &Dummy, &tmp); Translation[i] = tmp; if (Translation[i] > Max) Max = Translation[i]; } if ((NewMap = MakeMapObject(1 << BitSize(Max+1), NULL)) == NULL) GIF_EXIT("Out of memory while allocating color map!"); /* Apply the translation; we'll do it to the pixels, too */ for (i = 0; i < ColorMap->ColorCount; i++) { NewMap->Colors[i] = ColorMap->Colors[Translation[i]]; } return(NewMap); } else { GIF_EXIT("Nothing to do!"); return(ColorMap); } }
/* * Compute the union of two given color maps and return it. If result can't * fit into 256 colors, NULL is returned, the allocated union otherwise. * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are * copied iff they didn't exist before. ColorTransIn2 maps the old * ColorIn2 into ColorUnion color map table. */ ColorMapObject * UnionColorMap(const ColorMapObject * ColorIn1, const ColorMapObject * ColorIn2, GifPixelType ColorTransIn2[]) { int i, j, CrntSlot, RoundUpTo, NewBitSize; ColorMapObject *ColorUnion; /* * Allocate table which will hold the result for sure. */ ColorUnion = MakeMapObject(MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL); if (ColorUnion == NULL) return (NULL); /* Copy ColorIn1 to ColorUnionSize; */ /*** FIXME: What if there are duplicate entries into the colormap to begin * with? */ for (i = 0; i < ColorIn1->ColorCount; i++) ColorUnion->Colors[i] = ColorIn1->Colors[i]; CrntSlot = ColorIn1->ColorCount; /* * Potentially obnoxious hack: * * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end * of table 1. This is very useful if your display is limited to * 16 colors. */ while (ColorIn1->Colors[CrntSlot - 1].Red == 0 && ColorIn1->Colors[CrntSlot - 1].Green == 0 && ColorIn1->Colors[CrntSlot - 1].Blue == 0) CrntSlot--; /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */ for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { /* Let's see if this color already exists: */ /*** FIXME: Will it ever occur that ColorIn2 will contain duplicate * entries? So we should search from 0 to CrntSlot rather than * ColorIn1->ColorCount? */ for (j = 0; j < ColorIn1->ColorCount; j++) if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0) break; if (j < ColorIn1->ColorCount) ColorTransIn2[i] = j; /* color exists in Color1 */ else { /* Color is new - copy it to a new slot: */ ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; ColorTransIn2[i] = CrntSlot++; } } if (CrntSlot > 256) { FreeMapObject(ColorUnion); return ((ColorMapObject *) NULL); } NewBitSize = BitSize(CrntSlot); RoundUpTo = (1 << NewBitSize); if (RoundUpTo > 0 && RoundUpTo != ColorUnion->ColorCount) { register GifColorType *Map = ColorUnion->Colors; /* * Zero out slots up to next power of 2. * We know these slots exist because of the way ColorUnion's * start dimension was computed. */ for (j = CrntSlot; j < RoundUpTo; j++) Map[j].Red = Map[j].Green = Map[j].Blue = 0; /* perhaps we can shrink the map? */ if (RoundUpTo < ColorUnion->ColorCount) { GifColorType *new_map = (GifColorType *)realloc(Map, RoundUpTo * sizeof(GifColorType)); if( new_map == NULL ) { FreeMapObject(ColorUnion); return ((ColorMapObject *) NULL); } ColorUnion->Colors = new_map; } } ColorUnion->ColorCount = RoundUpTo; ColorUnion->BitsPerPixel = NewBitSize; return (ColorUnion); }
ColorMapObject *UnionColorMap( ColorMapObject *ColorIn1, ColorMapObject *ColorIn2, GifPixelType ColorTransIn2[]) /* * Compute the union of two given color maps and return it. If result can't * fit into 256 colors, NULL is returned, the allocated union otherwise. * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are * copied iff they didn't exist before. ColorTransIn2 maps the old * ColorIn2 into ColorUnion color map table. */ { int i, j, CrntSlot, RoundUpTo, NewBitSize; ColorMapObject *ColorUnion; /* * Allocate table which will hold the result for sure. */ ColorUnion = MakeMapObject(MAX(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL); if (ColorUnion == NULL) return(NULL); /* Copy ColorIn1 to ColorUnionSize; */ for (i = 0; i < ColorIn1->ColorCount; i++) ColorUnion->Colors[i] = ColorIn1->Colors[i]; CrntSlot = ColorIn1->ColorCount; /* * Potentially obnoxious hack: * * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end * of table 1. This is very useful if your display is limited to * 16 colors. */ while (ColorIn1->Colors[CrntSlot-1].Red == 0 && ColorIn1->Colors[CrntSlot-1].Green == 0 && ColorIn1->Colors[CrntSlot-1].Red == 0) CrntSlot--; /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */ for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++) { /* Let's see if this color already exists: */ for (j = 0; j < ColorIn1->ColorCount; j++) if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0) break; if (j < ColorIn1->ColorCount) ColorTransIn2[i] = j; /* color exists in Color1 */ else { /* Color is new - copy it to a new slot: */ ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; ColorTransIn2[i] = CrntSlot++; } } if (CrntSlot > 256) { FreeMapObject(ColorUnion); return((ColorMapObject *)NULL); } NewBitSize = BitSize(CrntSlot); RoundUpTo = (1 << NewBitSize); if (RoundUpTo != ColorUnion->ColorCount) { register GifColorType *Map = ColorUnion->Colors; /* * Zero out slots up to next power of 2. * We know these slots exist because of the way ColorUnion's * start dimension was computed. */ for (j = CrntSlot; j < RoundUpTo; j++) Map[j].Red = Map[j].Green = Map[j].Blue = 0; /* perhaps we can shrink the map? */ if (RoundUpTo < ColorUnion->ColorCount) ColorUnion->Colors = (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo); } ColorUnion->ColorCount = RoundUpTo; ColorUnion->BitsPerPixel = NewBitSize; return(ColorUnion); }
int main(int argc, char **argv) { FILE *input_file; float arg,size,rx,ry,rz; float f,fmin=1e10,fmax=-1e10; uint16_t i; uint64_t count; int xi,yi,zi,xo,yo,zo,nx,ny,nz,dx,dy,dz,x0,y0,z0,h; int **image; char format,type,comment[256]; GifFileType *GIFfile; ColorMapObject *GIFcmap; GifPixelType *GIFline; // // command line args // if (!((argc == 6) || (argc == 7) || (argc == 8) || (argc == 9) || (argc == 10) || (argc == 13) || (argc == 16) || (argc == 19))) { printf("command line: vol_gif in.vol out.gif nx ny nz [format [type [arg [size [dx dy dz [x0 y0 z0 [rx ry rz]]]]]]]\n"); printf(" in.vol = input volume file\n"); printf(" out.gif = output GIF file\n"); printf(" nx,ny,nz = x,y,z input voxel number\n"); printf(" format = 'f' for float 32, 'i' for uint16_t (default 'f')\n"); printf(" type = 's' for section, 'h' for height (default 's')\n"); printf(" arg = gamma for 's', threshold for 'h' (default 1)\n"); printf(" size = mm per voxel (default 1)\n"); printf(" dx,dy,dz = x,y,z output voxel number (default all)\n"); printf(" x0,y0,z0 = x,y,z output voxel origin (default 0)\n"); printf(" to be implemented: rx,ry,rz = view rotation angles (degrees; default 0)\n"); exit(-1); } format = 'f'; type = 's'; arg = 1; size = 1.0; rx = ry = rz = 0; sscanf(argv[3],"%d",&nx); sscanf(argv[4],"%d",&ny); sscanf(argv[5],"%d",&nz); dx = nx; dy = ny; dz = nz; x0 = y0 = z0 = 0; if (argc >= 7) { sscanf(argv[6],"%c",&format); if (!((format == 'f') || (format == 'i'))) { printf("vol_gif: oops -- format must be 'f' or 'i'\n"); exit(-1); } } if (argc >= 8) { sscanf(argv[7],"%c",&type); if (!((type == 's') || (type == 'h'))) { printf("vol_gif: oops -- type must be 's' or 'h'\n"); exit(-1); } } if (argc >= 9) { sscanf(argv[8],"%f",&arg); } if (argc >= 10) { sscanf(argv[9],"%f",&size); } if (argc >= 13) { sscanf(argv[10],"%d",&x0); sscanf(argv[11],"%d",&y0); sscanf(argv[12],"%d",&z0); } if (argc >= 16) { sscanf(argv[13],"%d",&dx); sscanf(argv[14],"%d",&dy); sscanf(argv[15],"%d",&dz); } if (argc >= 19) { sscanf(argv[16],"%f",&rx); sscanf(argv[17],"%f",&ry); sscanf(argv[18],"%f",&rz); } // // check and find limits // input_file = fopen(argv[1],"rb"); if (input_file == NULL) { printf("vol_gif: oops -- can not open %s\n",argv[1]); exit(-1); } if (((x0 + dx) > nx) || ((y0 + dy) > ny) || ((z0 + dz) > nz)) { printf("vol_gif: oops -- region too large\n"); exit(-1); } printf("read %s\n",argv[1]); if (format == 'f') { count = 0; while (fread(&f,sizeof(f),1,input_file) != 0) { if (f > fmax) fmax = f; if (f < fmin) fmin = f; count += 1; } } else if (format == 'i') { count = 0; while (fread(&i,sizeof(i),1,input_file) != 0) { if (i > fmax) fmax = i; if (i < fmin) fmin = i; count += 1; } } printf(" %" PRIu64 " points, min %f, max %f\n",count,fmin,fmax); printf(" nx ny nz: %d %d %d\n",nx,ny,nz); rewind(input_file); // // set up color map // #if GIFLIB_MAJOR >= 5 GIFcmap = GifMakeMapObject(256, NULL); #else GIFcmap = MakeMapObject(256, NULL); #endif for (i = 0; i < 256; i++) { GIFcmap->Colors[i].Red = i; GIFcmap->Colors[i].Green = i; GIFcmap->Colors[i].Blue = i; } // // open GIF file // printf("write %s\n",argv[2]); EGifPutScreenDesc(GIFfile,dx,dy,8,0,GIFcmap); unsigned char loop_count[] = {1,0,0}; #if GIFLIB_MAJOR >= 5 GIFfile = EGifOpenFileName(argv[2], 0, NULL); EGifPutExtension(GIFfile, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0"); EGifPutExtension(GIFfile, APPLICATION_EXT_FUNC_CODE, 3, loop_count); #else GIFfile = EGifOpenFileName(argv[2], 0); EGifPutExtensionFirst(GIFfile, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0"); EGifPutExtensionLast(GIFfile, APPLICATION_EXT_FUNC_CODE, 3, loop_count); #endif unsigned char delay_count[5] = { 0, // no transparency 0, // delay time 0, // delay time 0 // transparent index not used }; // // allocate image // image = malloc(dy*sizeof(int *)); for (yo = 0; yo < dy; ++yo) { image[yo] = malloc(dx*sizeof(int)); for (xo = 0; xo < dx; ++xo) image[yo][xo] = 0; } GIFline = malloc(dx*sizeof(GifPixelType)); // // scan file // xi = yi = zi = 0; for (zo = 0; zo < dz; ++zo) { printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",zo); EGifPutExtension(GIFfile,GRAPHICS_EXT_FUNC_CODE,4,delay_count); EGifPutImageDesc(GIFfile,0,0,dx,dy,0,NULL); // // read layer // for (yo = 0; yo < dy; ++yo) { for (xo = 0; xo < dx; ++xo) { if (format == 'f') { read_voxel_f(input_file,&f,xo+x0,yo+y0,zo+z0,&xi,&yi,&zi,nx,ny,nz); if (type == 'h') { h = 255*zo/(nz-1.0); if ((h > image[yo][xo]) && (f > arg)) image[yo][xo] = h; GIFline[xo] = image[yo][xo]*(nz-1.0)/zo; } else if (type == 's') { GIFline[xo] = 255*pow((f-fmin)/(fmax-fmin),arg); } } else if (format == 'i') { read_voxel_i(input_file,&i,xo+x0,yo+y0,zo+z0,&xi,&yi,&zi,nx,ny,nz); if (type == 'h') { h = 255*zo/(nz-1.0); if ((h > image[yo][xo]) && (i > arg)) image[yo][xo] = h; GIFline[xo] = image[yo][xo]*(nz-1.0)/zo; } else if (type == 's') { GIFline[xo] = 255*pow((i-fmin)/(fmax-fmin),arg); } } } EGifPutLine(GIFfile,GIFline,dx); } } printf("\n"); // // put mm per pixel in comment // sprintf(comment,"mm per pixel: %f;",size); EGifPutComment(GIFfile,comment); // // exit // fclose(input_file); EGifCloseFile(GIFfile); exit(0); }
/*! * pixWriteStreamGif() * * Input: stream * pix (1, 2, 4, 8, 16 or 32 bpp) * Return: 0 if OK, 1 on error * * Notes: * (1) All output gif have colormaps. If the pix is 32 bpp rgb, * this quantizes the colors and writes out 8 bpp. * If the pix is 16 bpp grayscale, it converts to 8 bpp first. * (2) We can't write to memory using open_memstream() because * the gif functions write through a file descriptor, not a * file stream. */ l_int32 pixWriteStreamGif(FILE *fp, PIX *pix) { char *text; l_int32 fd, wpl, i, j, w, h, d, ncolor, rval, gval, bval; l_int32 gif_ncolor = 0; l_uint32 *data, *line; PIX *pixd; PIXCMAP *cmap; GifFileType *gif; ColorMapObject *gif_cmap; GifByteType *gif_line; PROCNAME("pixWriteStreamGif"); if (!fp) return ERROR_INT("stream not open", procName, 1); if (!pix) return ERROR_INT("pix not defined", procName, 1); rewind(fp); if ((fd = fileno(fp)) < 0) return ERROR_INT("invalid file descriptor", procName, 1); d = pixGetDepth(pix); if (d == 32) { pixd = pixConvertRGBToColormap(pix, 1); } else if (d > 1) { pixd = pixConvertTo8(pix, TRUE); } else { /* d == 1; make sure there's a colormap */ pixd = pixClone(pix); if (!pixGetColormap(pixd)) { cmap = pixcmapCreate(1); pixcmapAddColor(cmap, 255, 255, 255); pixcmapAddColor(cmap, 0, 0, 0); pixSetColormap(pixd, cmap); } } if (!pixd) return ERROR_INT("failed to convert image to indexed", procName, 1); d = pixGetDepth(pixd); if ((cmap = pixGetColormap(pixd)) == NULL) { pixDestroy(&pixd); return ERROR_INT("cmap is missing", procName, 1); } /* 'Round' the number of gif colors up to a power of 2 */ ncolor = pixcmapGetCount(cmap); for (i = 0; i <= 8; i++) { if ((1 << i) >= ncolor) { gif_ncolor = (1 << i); break; } } if (gif_ncolor < 1) { pixDestroy(&pixd); return ERROR_INT("number of colors is invalid", procName, 1); } /* Save the cmap colors in a gif_cmap */ if ((gif_cmap = MakeMapObject(gif_ncolor, NULL)) == NULL) { pixDestroy(&pixd); return ERROR_INT("failed to create GIF color map", procName, 1); } for (i = 0; i < gif_ncolor; i++) { rval = gval = bval = 0; if (ncolor > 0) { if (pixcmapGetColor(cmap, i, &rval, &gval, &bval) != 0) { pixDestroy(&pixd); FreeMapObject(gif_cmap); return ERROR_INT("failed to get color from color map", procName, 1); } ncolor--; } gif_cmap->Colors[i].Red = rval; gif_cmap->Colors[i].Green = gval; gif_cmap->Colors[i].Blue = bval; } /* Get the gif file handle */ if ((gif = EGifOpenFileHandle(fd)) == NULL) { pixDestroy(&pixd); FreeMapObject(gif_cmap); return ERROR_INT("failed to create GIF image handle", procName, 1); } pixGetDimensions(pixd, &w, &h, NULL); if (EGifPutScreenDesc(gif, w, h, gif_cmap->BitsPerPixel, 0, gif_cmap) != GIF_OK) { pixDestroy(&pixd); FreeMapObject(gif_cmap); EGifCloseFile(gif); return ERROR_INT("failed to write screen description", procName, 1); } FreeMapObject(gif_cmap); /* not needed after this point */ if (EGifPutImageDesc(gif, 0, 0, w, h, FALSE, NULL) != GIF_OK) { pixDestroy(&pixd); EGifCloseFile(gif); return ERROR_INT("failed to image screen description", procName, 1); } data = pixGetData(pixd); wpl = pixGetWpl(pixd); if (d != 1 && d != 2 && d != 4 && d != 8) { pixDestroy(&pixd); EGifCloseFile(gif); return ERROR_INT("image depth is not in {1, 2, 4, 8}", procName, 1); } if ((gif_line = (GifByteType *)CALLOC(sizeof(GifByteType), w)) == NULL) { pixDestroy(&pixd); EGifCloseFile(gif); return ERROR_INT("mem alloc fail for data line", procName, 1); } for (i = 0; i < h; i++) { line = data + i * wpl; /* Gif's way of setting the raster line up for compression */ for (j = 0; j < w; j++) { switch(d) { case 8: gif_line[j] = GET_DATA_BYTE(line, j); break; case 4: gif_line[j] = GET_DATA_QBIT(line, j); break; case 2: gif_line[j] = GET_DATA_DIBIT(line, j); break; case 1: gif_line[j] = GET_DATA_BIT(line, j); break; } } /* Compress and save the line */ if (EGifPutLine(gif, gif_line, w) != GIF_OK) { FREE(gif_line); pixDestroy(&pixd); EGifCloseFile(gif); return ERROR_INT("failed to write data line into GIF", procName, 1); } } /* Write a text comment. This must be placed after writing the * data (!!) Note that because libgif does not provide a function * for reading comments from file, you will need another way * to read comments. */ if ((text = pixGetText(pix)) != NULL) { if (EGifPutComment(gif, text) != GIF_OK) L_WARNING("gif comment not written", procName); } FREE(gif_line); pixDestroy(&pixd); EGifCloseFile(gif); return 0; }
/* * Append an image block to the SavedImages array */ SavedImage * MakeSavedImage(GifFileType * GifFile, const SavedImage * CopyFrom) { SavedImage *sp; if (GifFile->SavedImages == NULL) GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); else GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1)); if (GifFile->SavedImages == NULL) return ((SavedImage *)NULL); else { sp = &GifFile->SavedImages[GifFile->ImageCount++]; memset((char *)sp, '\0', sizeof(SavedImage)); if (CopyFrom) { memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); /* * Make our own allocated copies of the heap fields in the * copied record. This guards against potential aliasing * problems. */ /* first, the local color map */ if (CopyFrom->ImageDesc.ColorMap) { sp->ImageDesc.ColorMap = MakeMapObject( CopyFrom->ImageDesc.ColorMap->ColorCount, CopyFrom->ImageDesc.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } } /* next, the raster */ sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * CopyFrom->ImageDesc.Width); if (sp->RasterBits == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } memcpy(sp->RasterBits, CopyFrom->RasterBits, sizeof(GifPixelType) * CopyFrom->ImageDesc.Height * CopyFrom->ImageDesc.Width); /* finally, the extension blocks */ if (CopyFrom->ExtensionBlocks) { sp->ExtensionBlocks = (ExtensionBlock *)malloc( sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); if (sp->ExtensionBlocks == NULL) { FreeLastSavedImage(GifFile); return (SavedImage *)(NULL); } memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks, sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount); /* * For the moment, the actual blocks can take their * chances with free(). We'll fix this later. *** FIXME: [Better check this out... Toshio] * 2004 May 27: Looks like this was an ESR note. * It means the blocks are shallow copied from InFile to * OutFile. However, I don't see that in this code.... * Did ESR fix it but never remove this note (And other notes * in gifspnge?) */ } } return (sp); } }
/****************************************************************************** * This routine should be called before any attempt to read an image. * Note it is assumed the Image desc. header (',') has been read. *****************************************************************************/ static int DGifGetImageDesc(GifFileType * GifFile) { int i, BitsPerPixel, SortFlag; GifByteType Buf[3]; GifFilePrivateType *Private = GifFile->Private; SavedImage *sp; if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; SortFlag = (Buf[0] & 0x20) != 0; GifFile->Image.Interlace = (Buf[0] & 0x40); if (Buf[0] & 0x80) { /* Does this image have local color map? */ FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { return GIF_ERROR; } /* Get the image local color map: */ GifFile->Image.ColorMap->SortFlag = SortFlag; for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } else if (GifFile->Image.ColorMap) { FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } if (GifFile->SavedImages) { if ((GifFile->SavedImages = ungif_realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) { return GIF_ERROR; } } else { if ((GifFile->SavedImages = ungif_alloc(sizeof(SavedImage))) == NULL) { return GIF_ERROR; } } sp = &GifFile->SavedImages[GifFile->ImageCount]; sp->ImageDesc = GifFile->Image; if (GifFile->Image.ColorMap != NULL) { sp->ImageDesc.ColorMap = MakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { return GIF_ERROR; } sp->ImageDesc.ColorMap->SortFlag = GifFile->Image.ColorMap->SortFlag; } sp->RasterBits = NULL; sp->Extensions.ExtensionBlockCount = 0; sp->Extensions.ExtensionBlocks = NULL; GifFile->ImageCount++; Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ return GIF_OK; }
static int DGifGetImageDesc(GifFileType * GifFile) { int i, BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->Image.Interlace = (Buf[0] & 0x40); if (Buf[0] & 0x80) { if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL) FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { FreeMapObject(GifFile->Image.ColorMap); _GifError = D_GIF_ERR_READ_FAILED; GifFile->Image.ColorMap = NULL; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } else if (GifFile->Image.ColorMap) { FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } if (GifFile->SavedImages) { if ((GifFile->SavedImages = (SavedImage *) realloc(GifFile->SavedImages, sizeof(SavedImage) * (GifFile->ImageCount + 1))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { if ((GifFile->SavedImages = (SavedImage *) gif_malloc(sizeof(SavedImage))) == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { sp->ImageDesc.ColorMap = MakeMapObject(GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp->RasterBits = (unsigned char *) NULL; sp->ExtensionBlockCount = 0; sp->ExtensionBlocks = (ExtensionBlock *) NULL; GifFile->ImageCount++; Private->PixelCount = (long) GifFile->Image.Width * (long) GifFile->Image.Height; DGifSetupDecompress(GifFile); return GIF_OK; }
/****************************************************************************** * 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; }