/* Originally based on, but in its current form merely inspired by Imlib2's * src/modules/loaders/loader_gif.c:load(), written by Carsten Haitzler. */ bool img_load_gif(img_t *img, const fileinfo_t *file) { GifFileType *gif; GifRowType *rows = NULL; GifRecordType rec; ColorMapObject *cmap; DATA32 bgpixel, *data, *ptr; DATA32 *prev_frame = NULL; Imlib_Image *im; int i, j, bg, r, g, b; int x, y, w, h, sw, sh; int intoffset[] = { 0, 4, 2, 1 }; int intjump[] = { 8, 8, 4, 2 }; int transp = -1; unsigned int delay = 0; bool err = false; if (img->multi.cap == 0) { img->multi.cap = 8; img->multi.frames = (img_frame_t*) s_malloc(sizeof(img_frame_t) * img->multi.cap); } img->multi.cnt = 0; img->multi.sel = 0; gif = DGifOpenFileName(file->path); if (gif == NULL) { warn("could not open gif file: %s", file->name); return false; } bg = gif->SBackGroundColor; sw = gif->SWidth; sh = gif->SHeight; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { err = true; break; } if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if (ext_code == 0xf9) { if (ext[1] & 1) transp = (int) ext[4]; else transp = -1; delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); if (delay) delay = MAX(delay, MIN_GIF_DELAY); /* TODO: handle disposal method, section 23.c.iv of http://www.w3.org/Graphics/GIF/spec-gif89a.txt */ } ext = NULL; DGifGetExtensionNext(gif, &ext); } } else if (rec == IMAGE_DESC_RECORD_TYPE) { if (DGifGetImageDesc(gif) == GIF_ERROR) { err = true; break; } x = gif->Image.Left; y = gif->Image.Top; w = gif->Image.Width; h = gif->Image.Height; rows = (GifRowType*) s_malloc(h * sizeof(GifRowType)); for (i = 0; i < h; i++) rows[i] = (GifRowType) s_malloc(w * sizeof(GifPixelType)); if (gif->Image.Interlace) { for (i = 0; i < 4; i++) { for (j = intoffset[i]; j < h; j += intjump[i]) DGifGetLine(gif, rows[j], w); } } else { for (i = 0; i < h; i++) DGifGetLine(gif, rows[i], w); } ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * sw * sh); cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; r = cmap->Colors[bg].Red; g = cmap->Colors[bg].Green; b = cmap->Colors[bg].Blue; bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); for (i = 0; i < sh; i++) { for (j = 0; j < sw; j++) { if (i < y || i >= y + h || j < x || j >= x + w || rows[i-y][j-x] == transp) { if (prev_frame != NULL) *ptr = prev_frame[i * sw + j]; else *ptr = bgpixel; } else { r = cmap->Colors[rows[i-y][j-x]].Red; g = cmap->Colors[rows[i-y][j-x]].Green; b = cmap->Colors[rows[i-y][j-x]].Blue; *ptr = 0xff << 24 | r << 16 | g << 8 | b; } ptr++; } } im = imlib_create_image_using_copied_data(sw, sh, data); for (i = 0; i < h; i++) free(rows[i]); free(rows); free(data); if (im == NULL) { err = true; break; } imlib_context_set_image(im); prev_frame = imlib_image_get_data_for_reading_only(); imlib_image_set_format("gif"); if (transp >= 0) imlib_image_set_has_alpha(1); if (img->multi.cnt == img->multi.cap) { img->multi.cap *= 2; img->multi.frames = (img_frame_t*) s_realloc(img->multi.frames, img->multi.cap * sizeof(img_frame_t)); } img->multi.frames[img->multi.cnt].im = im; img->multi.frames[img->multi.cnt].delay = delay ? delay : GIF_DELAY; img->multi.cnt++; } } while (rec != TERMINATE_RECORD_TYPE); DGifCloseFile(gif); if (err && !file->loaded) warn("corrupted gif file: %s", file->name); if (img->multi.cnt > 1) { imlib_context_set_image(img->im); imlib_free_image(); img->im = img->multi.frames[0].im; img->multi.animate = GIF_AUTOPLAY; } else if (img->multi.cnt == 1) { imlib_context_set_image(img->multi.frames[0].im); imlib_free_image(); img->multi.cnt = 0; img->multi.animate = false; } imlib_context_set_image(img->im); return !err; }
GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) ) return NULL; if( poOpenInfo->eAccess == GA_Update ) { CPLError( CE_Failure, CPLE_NotSupported, "The GIF driver does not support update access to existing" " files.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the file and ingest. */ /* -------------------------------------------------------------------- */ GifFileType *hGifFile; VSILFILE *fp; int nGifErr; fp = VSIFOpenL( poOpenInfo->pszFilename, "r" ); if( fp == NULL ) return NULL; hGifFile = GIFAbstractDataset::myDGifOpen( fp, VSIGIFReadFunc ); if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "DGifOpen() failed for %s.\n" "Perhaps the gif file is corrupt?\n", poOpenInfo->pszFilename ); return NULL; } /* The following code enables us to detect GIF datasets eligible */ /* for BIGGIF driver even with an unpatched giflib */ /* -------------------------------------------------------------------- */ /* Find the first image record. */ /* -------------------------------------------------------------------- */ GifRecordType RecordType = TERMINATE_RECORD_TYPE; while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR && RecordType != TERMINATE_RECORD_TYPE && RecordType != IMAGE_DESC_RECORD_TYPE ) { /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */ if (RecordType == EXTENSION_RECORD_TYPE) { int nFunction; GifByteType *pExtData; if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR) break; while (pExtData != NULL) { if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR) break; } } } if( RecordType == IMAGE_DESC_RECORD_TYPE && DGifGetImageDesc(hGifFile) != GIF_ERROR) { int width = hGifFile->SavedImages[0].ImageDesc.Width; int height = hGifFile->SavedImages[0].ImageDesc.Height; if ((double) width * (double) height > 100000000.0 ) { CPLDebug( "GIF", "Due to limitations of the GDAL GIF driver we deliberately avoid\n" "opening large GIF files (larger than 100 megapixels)."); GIFAbstractDataset::myDGifCloseFile( hGifFile ); VSIFCloseL( fp ); return NULL; } } GIFAbstractDataset::myDGifCloseFile( hGifFile ); VSIFSeekL( fp, 0, SEEK_SET); hGifFile = GIFAbstractDataset::myDGifOpen( fp, VSIGIFReadFunc ); if( hGifFile == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OpenFailed, "DGifOpen() failed for %s.\n" "Perhaps the gif file is corrupt?\n", poOpenInfo->pszFilename ); return NULL; } nGifErr = DGifSlurp( hGifFile ); if( nGifErr != GIF_OK || hGifFile->SavedImages == NULL ) { VSIFCloseL( fp ); GIFAbstractDataset::myDGifCloseFile(hGifFile); if( nGifErr == D_GIF_ERR_DATA_TOO_BIG ) { CPLDebug( "GIF", "DGifSlurp() failed for %s because it was too large.\n" "Due to limitations of the GDAL GIF driver we deliberately avoid\n" "opening large GIF files (larger than 100 megapixels).", poOpenInfo->pszFilename ); return NULL; } else CPLError( CE_Failure, CPLE_OpenFailed, "DGifSlurp() failed for %s.\n" "Perhaps the gif file is corrupt?\n", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ GIFDataset *poDS; poDS = new GIFDataset(); poDS->fp = fp; poDS->eAccess = GA_ReadOnly; poDS->hGifFile = hGifFile; /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = hGifFile->SavedImages[0].ImageDesc.Width; poDS->nRasterYSize = hGifFile->SavedImages[0].ImageDesc.Height; /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iImage = 0; iImage < hGifFile->ImageCount; iImage++ ) { SavedImage *psImage = hGifFile->SavedImages + iImage; if( psImage->ImageDesc.Width != poDS->nRasterXSize || psImage->ImageDesc.Height != poDS->nRasterYSize ) continue; poDS->SetBand( poDS->nBands+1, new GIFRasterBand( poDS, poDS->nBands+1, psImage, hGifFile->SBackGroundColor )); } /* -------------------------------------------------------------------- */ /* Check for georeferencing. */ /* -------------------------------------------------------------------- */ poDS->DetectGeoreferencing(poOpenInfo); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int i, iy, last_iy, l, t, w, h, Error, NumFiles, ExtCode, ImageNum = 0, SizeFlag = FALSE, ScaleFlag = FALSE, XScaleFlag = FALSE, YScaleFlag = FALSE, HelpFlag = FALSE; double Scale, y; GifRecordType RecordType; char s[80]; GifByteType *Extension; GifRowType LineIn, LineOut; char **FileName = NULL; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &SizeFlag, &XSize, &YSize, &ScaleFlag, &Scale, &XScaleFlag, &XScale, &YScaleFlag, &YScale, &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 specific direction was set, set other direction to 1: */ if (!XScaleFlag && YScaleFlag) XScale = 1.0; if (!YScaleFlag && XScaleFlag) YScale = 1.0; /* If the specific direction was not set, but global one did use it: */ if (!XScaleFlag && ScaleFlag) XScale = Scale; if (!YScaleFlag && ScaleFlag) YScale = Scale; if (XScale > MAX_SCALE) { sprintf(s, "XScale too big, maximum scale selected instead (%f).", MAX_SCALE); GIF_MESSAGE(s); XScale = MAX_SCALE; } if (YScale > MAX_SCALE) { sprintf(s, "YScale too big, maximum scale selected instead (%f).", MAX_SCALE); GIF_MESSAGE(s); YScale = MAX_SCALE; } if (NumFiles == 1) { if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL) QuitGifError(GifFileIn, GifFileOut); } else { /* Use the stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0)) == NULL) QuitGifError(GifFileIn, GifFileOut); } BackGroundColor = GifFileIn->SBackGroundColor; /* If size was specified, it is used to derive the scale: */ if (SizeFlag) { XScale = XSize / ((double) GifFileIn->SWidth); YScale = YSize / ((double) GifFileIn->SHeight); } else { XSize = (int) (GifFileIn->SWidth * XScale + 0.5); YSize = (int) (GifFileIn->SHeight * YScale + 0.5); } /* As at this time we know the Screen size of the input gif file, and as */ /* all image(s) in file must be less/equal to it, we can allocate the */ /* scan lines for the input file, and output file. The number of lines */ /* to allocate for each is set by ScaleDown & XScale & YScale: */ LineOut = (GifRowType) malloc(XSize * sizeof(GifPixelType)); LineIn = (GifRowType) malloc(GifFileIn->SWidth * sizeof(GifPixelType)); /* Open stdout for the output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* And dump out its new scaled screen information: */ if (EGifPutScreenDesc(GifFileOut, XSize, YSize, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Put the image descriptor to out file: */ l = (int) (GifFileIn->Image.Left * XScale + 0.5); w = (int) (GifFileIn->Image.Width * XScale + 0.5); t = (int) (GifFileIn->Image.Top * YScale + 0.5); h = (int) (GifFileIn->Image.Height * YScale + 0.5); if (l < 0) l = 0; if (t < 0) t = 0; if (l + w > XSize) w = XSize - l; if (t + h > YSize) h = YSize - t; if (EGifPutImageDesc(GifFileOut, l, t, w, h, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (GifFileIn->Image.Interlace) { GIF_EXIT("Cannt resize interlaced images - use GifInter first."); } else { GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, ++ImageNum, GifFileOut->Image.Left, GifFileOut->Image.Top, GifFileOut->Image.Width, GifFileOut->Image.Height); for (i = GifFileIn->Image.Height, y = 0.0, last_iy = -1; i-- > 0; y += YScale) { if (DGifGetLine(GifFileIn, LineIn, GifFileIn->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); iy = (int) y; if (last_iy < iy && last_iy < YSize) { ResizeLine(LineIn, LineOut, GifFileIn->Image.Width, GifFileOut->Image.Width); for (; last_iy < iy && last_iy < GifFileOut->Image.Height - 1; last_iy++) { GifQprintf("\b\b\b\b%-4d", last_iy + 1); if (EGifPutLine(GifFileOut, LineOut, GifFileOut->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } } } /* If scale is not dividable - dump last lines: */ while (++last_iy < GifFileOut->Image.Height) { GifQprintf("\b\b\b\b%-4d", last_iy); if (EGifPutLine(GifFileOut, LineOut, GifFileOut->Image.Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, so discard: */ while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); free(LineOut); free(LineIn); return 0; }
unsigned char * loader_gif(FILE *f, int *w, int *h, int *t) { unsigned char *data, *ptr; GifFileType *gif; GifRowType *rows; GifRecordType rec; ColorMapObject *cmap; int i, j, done, bg, csize, r, g, b; int intoffset[] = {0, 4, 2, 1}; int intjump[] = {8, 8, 4, 2}; int istransp, transp; int fd; done = 0; istransp = 0; fd = fileno(f); /* Apparently rewind(f) isn't sufficient */ lseek(fd, (long) 0, 0); gif = DGifOpenFileHandle(fd); transp = -1; data = NULL; rows = NULL; if (!gif) return NULL; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { PrintGifError(); rec = TERMINATE_RECORD_TYPE; } if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done)) { if (DGifGetImageDesc(gif) == GIF_ERROR) { PrintGifError(); rec = TERMINATE_RECORD_TYPE; } *w = gif->Image.Width; *h = gif->Image.Height; if(*h > 32767 || *w > 32767) { return NULL; } rows = malloc(*h * sizeof(GifRowType *)); if (!rows) { DGifCloseFile(gif); return NULL; } data = _gdk_malloc_image(*w, *h); if (!data) { DGifCloseFile(gif); free(rows); return NULL; } for (i = 0; i < *h; i++) rows[i] = NULL; for (i = 0; i < *h; i++) { rows[i] = malloc(*w * sizeof(GifPixelType)); if (!rows[i]) { DGifCloseFile(gif); for (i = 0; i < *h; i++) if (rows[i]) free(rows[i]); free(rows); free(data); return NULL; } } if (gif->Image.Interlace) { for (i = 0; i < 4; i++) { for (j = intoffset[i]; j < *h; j += intjump[i]) DGifGetLine(gif, rows[j], *w); } } else { for (i = 0; i < *h; i++) DGifGetLine(gif, rows[i], *w); } done = 1; } else if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext; ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0)) { istransp = 1; transp = (int)ext[4]; } ext = NULL; DGifGetExtensionNext(gif, &ext); } } } while (rec != TERMINATE_RECORD_TYPE); bg = gif->SBackGroundColor; cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap); csize = cmap->ColorCount; ptr = data; if (!istransp) { for (i = 0; i < *h; i++) { for (j = 0; j < *w; j++) { r = cmap->Colors[rows[i][j]].Red; g = cmap->Colors[rows[i][j]].Green; b = cmap->Colors[rows[i][j]].Blue; *ptr++ = r; *ptr++ = g; *ptr++ = b; } } } else { for (i = 0; i < *h; i++) { for (j = 0; j < *w; j++) { if (rows[i][j] == transp) { *ptr++ = 255; *ptr++ = 0; *ptr++ = 255; } else { r = cmap->Colors[rows[i][j]].Red; g = cmap->Colors[rows[i][j]].Green; b = cmap->Colors[rows[i][j]].Blue; if (r == 255 && g == 0 && b == 255) r = 254; *ptr++ = r; *ptr++ = g; *ptr++ = b; } } } } DGifCloseFile(gif); for (i = 0; i < *h; i++) free(rows[i]); free(rows); *t = istransp; return data; }
int main(int argc, char **argv) { // // local vars // GifFileType *GIFfile; GifRecordType GIFtype; GifByteType *GIFextension; GifPixelType *GIFline; uint32_t w[8],**lower_array,**upper_array; int x,y,z,i,j,k,n,p,imin,imax; int image_width,image_height,image_count,color_resolution,GIFcode,ret; float threshold,voxel_size; char comment[256],rules[255][20]; struct fab_vars v; init_vars(&v); // // command line args // if (!((argc == 3) || (argc == 4) || (argc == 5) || (argc == 6))) { printf("command line: gif_stl in.gif out.stl [threshold [size [points [angle]]]]\n"); printf(" in.gif = input GIF section file\n"); printf(" out.stl = output STL file\n"); printf(" threshold: surface intensity threshold (0 = min, 1 = max, default 0.5))\n"); printf(" size = voxel size (mm, default from file))\n"); printf(" points = points to interpolate per point (default 0)\n"); printf(" to be implemented: angle = minimum relative face angle to decimate vertices (default 0)\n"); exit(-1); } p = 0; threshold = 0.5; voxel_size = -1; image_width = -1; image_height = -1; image_count = -1; if (argc >= 4) sscanf(argv[3],"%f",&threshold); if (argc >= 5) sscanf(argv[4],"%f",&voxel_size); if (argc >= 6) sscanf(argv[5],"%d",&p); // // initialize the rule table // init_rules(rules); // // scan the file // printf("read %s\n",argv[1]); color_resolution = -1; #if GIFLIB_MAJOR >= 5 GIFfile = DGifOpenFileName(argv[1], NULL); #else GIFfile = DGifOpenFileName(argv[1]); #endif if (GIFfile == NULL) { printf("gif_stl: oops -- can not open %s\n",argv[1]); exit(-1); } GIFline = malloc(MAX_LINE*sizeof(GifPixelType)); imin = 256; imax = 0; do { DGifGetRecordType(GIFfile,&GIFtype); switch (GIFtype) { case IMAGE_DESC_RECORD_TYPE: DGifGetImageDesc(GIFfile); image_width = GIFfile->SWidth; image_height = GIFfile->SHeight; image_count = GIFfile->ImageCount; color_resolution = GIFfile->SColorResolution; for (y = 0; y < GIFfile->SHeight; ++y) { ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth); if (ret != GIF_OK) { printf("gif_stl: oops -- error reading line\n"); exit(-1); } for (x = 0; x < GIFfile->SWidth; ++x) { if (GIFline[x] < imin) imin = GIFline[x]; if (GIFline[x] > imax) imax = GIFline[x]; } } break; case EXTENSION_RECORD_TYPE: DGifGetExtension(GIFfile,&GIFcode,&GIFextension); if (GIFcode == COMMENT_EXT_FUNC_CODE) { n = GIFextension[0]; for (i = 1; i <= n; ++i) comment[i-1] = GIFextension[i]; comment[n] = 0; if (voxel_size == -1) sscanf(comment,"mm per pixel: %f;",&voxel_size); } while (GIFextension != NULL) DGifGetExtensionNext(GIFfile,&GIFextension); break; case SCREEN_DESC_RECORD_TYPE: DGifGetScreenDesc(GIFfile); break; case TERMINATE_RECORD_TYPE: break; case UNDEFINED_RECORD_TYPE: printf("gif_stl: oops -- undefined GIF record type\n"); exit(-1); break; } } while (GIFtype != TERMINATE_RECORD_TYPE); if (GIFfile == NULL) { printf("gif_stl: oops -- can not open %s\n",argv[1]); exit(-1); } if (voxel_size == -1) { voxel_size = 1.0; printf(" no pixel size found, assuming 1 mm\n"); } printf(" voxel size (mm): %f, color resolution (bits): %d\n",voxel_size,color_resolution); printf(" intensity min: %d max: %d\n",imin,imax); printf(" number of images: %d, image width %d, image height %d\n",image_count,image_width,image_height); // // set threshold // threshold = imin + threshold*(imax-imin); // // add empty border // image_width += 2; image_height += 2; image_count += 2; // // allocate arrays // lower_array = malloc(image_height*sizeof(uint32_t *)); for (y = 0; y < image_height; ++y) { lower_array[y] = malloc(image_width*sizeof(uint32_t)); for (x = 0; x < image_width; ++x) lower_array[y][x] = 0; } upper_array = malloc(image_height*sizeof(uint32_t *)); for (y = 0; y < image_height; ++y) { upper_array[y] = malloc(image_width*sizeof(uint32_t)); for (x = 0; x < image_width; ++x) upper_array[y][x] = 0; } // // read the file // DGifCloseFile(GIFfile); #if GIFLIB_MAJOR >= 5 GIFfile = DGifOpenFileName(argv[1], NULL); #else GIFfile = DGifOpenFileName(argv[1]); #endif if (GIFfile == NULL) { printf("gif_stl: oops -- can not open %s\n",argv[1]); exit(-1); } z = 0; v.mesh = malloc(sizeof(struct fab_mesh_type)); v.mesh->triangle = malloc(sizeof(struct fab_mesh_triangle_type)); v.mesh->first = v.mesh->triangle; v.mesh->last = v.mesh->triangle; v.mesh->triangle->previous = v.mesh->triangle->next = 0; do { DGifGetRecordType(GIFfile,&GIFtype); switch (GIFtype) { case IMAGE_DESC_RECORD_TYPE: // // read image // DGifGetImageDesc(GIFfile); printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",z); // // read layer // for (y = 0; y < (image_height-2); ++y) { ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth); if (ret != GIF_OK) { printf("gif_stl: oops -- error reading line\n"); exit(-1); } for (x = 0; x < (image_width-2); ++x) { lower_array[y+1][x+1] = upper_array[y+1][x+1]; upper_array[y+1][x+1] = GIFline[x]; } } if (p == 0) { // // no interpolation, loop over layer voxels // for (x = 0; x < (image_width-1); ++x) { for (y = 0; y < (image_height-1); ++y) { w[0] = lower_array[y][x]; w[1] = lower_array[y][x+1]; w[2] = lower_array[y+1][x]; w[3] = lower_array[y+1][x+1]; w[4] = upper_array[y][x]; w[5] = upper_array[y][x+1]; w[6] = upper_array[y+1][x]; w[7] = upper_array[y+1][x+1]; triangulate(x,y,z,voxel_size,threshold,w,rules,&v); } } } else { // // yes interpolation, loop over layer sub-voxels // for (x = 0; x < (image_width-1); ++x) { for (y = 0; y < (image_height-1); ++y) { for (i = 0; i <= p; ++i) { for (j = 0; j <= p; ++j) { for (k = 0; k <= p; ++k) { w[0] = interp(x,y,i,j,k,lower_array,upper_array,p); w[1] = interp(x,y,i+1,j,k,lower_array,upper_array,p); w[2] = interp(x,y,i,j+1,k,lower_array,upper_array,p); w[3] = interp(x,y,i+1,j+1,k,lower_array,upper_array,p); w[4] = interp(x,y,i,j,k+1,lower_array,upper_array,p); w[5] = interp(x,y,i+1,j,k+1,lower_array,upper_array,p); w[6] = interp(x,y,i,j+1,k+1,lower_array,upper_array,p); w[7] = interp(x,y,i+1,j+1,k+1,lower_array,upper_array,p); triangulate((1+p)*x+i,(1+p)*y+j,(1+p)*z+k,voxel_size,threshold,w,rules,&v); } } } } } } z += 1; break; case EXTENSION_RECORD_TYPE: DGifGetExtension(GIFfile,&GIFcode,&GIFextension); while (GIFextension != NULL) DGifGetExtensionNext(GIFfile,&GIFextension); break; case SCREEN_DESC_RECORD_TYPE: DGifGetScreenDesc(GIFfile); break; case TERMINATE_RECORD_TYPE: break; case UNDEFINED_RECORD_TYPE: printf("gif_stl: oops -- undefined GIF record type\n"); exit(-1); break; } } while (GIFtype != TERMINATE_RECORD_TYPE); // // add empty top layer // printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",z); for (y = 0; y < (image_height-2); ++y) { for (x = 0; x < (image_width-2); ++x) { lower_array[y+1][x+1] = upper_array[y+1][x+1]; upper_array[y+1][x+1] = 0; } } if (p == 0) { // // no interpolation, loop over layer voxels // for (x = 0; x < (image_width-1); ++x) { for (y = 0; y < (image_height-1); ++y) { w[0] = lower_array[y][x]; w[1] = lower_array[y][x+1]; w[2] = lower_array[y+1][x]; w[3] = lower_array[y+1][x+1]; w[4] = upper_array[y][x]; w[5] = upper_array[y][x+1]; w[6] = upper_array[y+1][x]; w[7] = upper_array[y+1][x+1]; triangulate(x,y,z,voxel_size,threshold,w,rules,&v); } } } else { // // yes interpolation, loop over layer sub-voxels // for (x = 0; x < (image_width-1); ++x) { for (y = 0; y < (image_height-1); ++y) { for (i = 0; i <= p; ++i) { for (j = 0; j <= p; ++j) { for (k = 0; k <= p; ++k) { w[0] = interp(x,y,i,j,k,lower_array,upper_array,p); w[1] = interp(x,y,i+1,j,k,lower_array,upper_array,p); w[2] = interp(x,y,i,j+1,k,lower_array,upper_array,p); w[3] = interp(x,y,i+1,j+1,k,lower_array,upper_array,p); w[4] = interp(x,y,i,j,k+1,lower_array,upper_array,p); w[5] = interp(x,y,i+1,j,k+1,lower_array,upper_array,p); w[6] = interp(x,y,i,j+1,k+1,lower_array,upper_array,p); w[7] = interp(x,y,i+1,j+1,k+1,lower_array,upper_array,p); triangulate((1+p)*x+i,(1+p)*y+j,(1+p)*z+k,voxel_size,threshold,w,rules,&v); } } } } } } printf("\n"); // // write STL // fab_write_stl(&v,argv[2]); // // exit // DGifCloseFile(GIFfile); exit(0); }
/* * Partially based on code in gif2rgb from giflib, by Gershon Elber. */ RImage *RLoadGIF(const char *file, int index) { RImage *image = NULL; unsigned char *cptr; GifFileType *gif = NULL; GifPixelType *buffer = NULL; int i, j, k; int width, height; GifRecordType recType; ColorMapObject *colormap; unsigned char rmap[256]; unsigned char gmap[256]; unsigned char bmap[256]; if (index < 0) index = 0; /* default error message */ RErrorCode = RERR_BADINDEX; gif = DGifOpenFileName(file); if (!gif) { switch (GifLastError()) { case D_GIF_ERR_OPEN_FAILED: RErrorCode = RERR_OPEN; break; case D_GIF_ERR_READ_FAILED: RErrorCode = RERR_READ; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } return NULL; } if (gif->SWidth < 1 || gif->SHeight < 1) { DGifCloseFile(gif); RErrorCode = RERR_BADIMAGEFILE; return NULL; } colormap = gif->SColorMap; i = 0; do { int extCode; GifByteType *extension; if (DGifGetRecordType(gif, &recType) == GIF_ERROR) { goto giferr; } switch (recType) { case IMAGE_DESC_RECORD_TYPE: if (i++ != index) break; if (DGifGetImageDesc(gif) == GIF_ERROR) { goto giferr; } width = gif->Image.Width; height = gif->Image.Height; if (gif->Image.ColorMap) colormap = gif->Image.ColorMap; /* the gif specs talk about a default colormap, but it * doesnt say what the heck is this default colormap */ if (!colormap) { /* * Well, since the spec says the colormap can be anything, * lets just render it with whatever garbage the stack * has :) * goto bye; */ } else { for (j = 0; j < colormap->ColorCount; j++) { rmap[j] = colormap->Colors[j].Red; gmap[j] = colormap->Colors[j].Green; bmap[j] = colormap->Colors[j].Blue; } } buffer = malloc(width * sizeof(GifColorType)); if (!buffer) { RErrorCode = RERR_NOMEMORY; goto bye; } image = RCreateImage(width, height, False); if (!image) { goto bye; } if (gif->Image.Interlace) { int l; int pelsPerLine; if (RRGBAFormat == image->format) pelsPerLine = width * 4; else pelsPerLine = width * 3; for (j = 0; j < 4; j++) { for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) { if (DGifGetLine(gif, buffer, width) == GIF_ERROR) { goto giferr; } cptr = image->data + (k * pelsPerLine); for (l = 0; l < width; l++) { int pixel = buffer[l]; *cptr++ = rmap[pixel]; *cptr++ = gmap[pixel]; *cptr++ = bmap[pixel]; } } } } else { cptr = image->data; for (j = 0; j < height; j++) { if (DGifGetLine(gif, buffer, width) == GIF_ERROR) { goto giferr; } for (k = 0; k < width; k++) { int pixel = buffer[k]; *cptr++ = rmap[pixel]; *cptr++ = gmap[pixel]; *cptr++ = bmap[pixel]; if (RRGBAFormat == image->format) cptr++; } } } break; case EXTENSION_RECORD_TYPE: /* skip all extension blocks */ if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR) { goto giferr; } while (extension) { if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR) { goto giferr; } } break; default: break; } } while (recType != TERMINATE_RECORD_TYPE && i <= index); /* yuck! */ goto did_not_get_any_errors; giferr: switch (GifLastError()) { case D_GIF_ERR_OPEN_FAILED: RErrorCode = RERR_OPEN; break; case D_GIF_ERR_READ_FAILED: RErrorCode = RERR_READ; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } bye: if (image) RReleaseImage(image); image = NULL; did_not_get_any_errors: if (buffer) free(buffer); if (gif) DGifCloseFile(gif); return image; }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ int main(int argc, char **argv) { int i, j, Error, NumFiles, ExtCode, Row, Col, Width, Height, DarkestColor = 0, ColorIntens = 10000, HelpFlag = FALSE; GifRecordType RecordType; GifByteType *Extension; char **FileName = NULL; GifRowType LineBuffer; ColorMapObject *ColorMap; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint, &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); } /* Open stdout for the output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* Dump out exactly same screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if ((LineBuffer = (GifRowType) malloc(GifFileIn->SWidth)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); /* 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.Interlace) GIF_EXIT("Cannt fix interlaced images."); Row = GifFileIn->Image.Top; /* Image Position relative to Screen. */ Col = GifFileIn->Image.Left; Width = GifFileIn->Image.Width; Height = GifFileIn->Image.Height; GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height); /* Put the image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, Col, Row, Width, Height, FALSE, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Find the darkest color in color map to use as a filler. */ ColorMap = (GifFileIn->Image.ColorMap ? GifFileIn->Image.ColorMap : GifFileIn->SColorMap); for (i = 0; i < ColorMap->ColorCount; i++) { j = ((int) ColorMap->Colors[i].Red) * 30 + ((int) ColorMap->Colors[i].Green) * 59 + ((int) ColorMap->Colors[i].Blue) * 11; if (j < ColorIntens) { ColorIntens = j; DarkestColor = i; } } /* Load the image, and dump it. */ for (i = 0; i < Height; i++) { GifQprintf("\b\b\b\b%-4d", i); if (DGifGetLine(GifFileIn, LineBuffer, Width) == GIF_ERROR) break; if (EGifPutLine(GifFileOut, LineBuffer, Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } if (i < Height) { fprintf(stderr, "\nFollowing error occured (and ignored):"); PrintGifError(); /* Fill in with the darkest color in color map. */ for (j = 0; j < Width; j++) LineBuffer[j] = DarkestColor; for (; i < Height; i++) if (EGifPutLine(GifFileOut, LineBuffer, Width) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (Extension && EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, so discard: */ while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); return 0; }
/****************************************************************************** * Main sequence ******************************************************************************/ int main(int argc, char **argv) { GifFileType *GifFileIn = NULL, *GifFileOut = NULL; GifRecordType RecordType; int CodeSize, ExtCode; GifByteType *CodeBlock, *Extension; /* * Command-line processing goes here. */ /* Use the stdin as input (note this also read screen descriptor in: */ if ((GifFileIn = DGifOpenFileHandle(0)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* Use the stdout as output: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* And dump out its screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the input GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Put image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont really */ /* care what we have there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) { if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension + 1) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, so discard: */ while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); return 0; }
static Image* readGif ( GifFileType *gf ) { Image* firstImg = 0; Image* img = 0; int i, extCode, width, height, row, cmapSize; int trans = -1, nFrames = 0, delay = 0; GifRecordType rec; GifByteType *ext; ColorMapObject *cmap; GifColorType *clrs; GifPixelType *rowBuf = (GifPixelType*) AWT_MALLOC( gf->SWidth * sizeof( GifPixelType) ); do { CHECK( DGifGetRecordType( gf, &rec)); switch ( rec ) { case IMAGE_DESC_RECORD_TYPE: CHECK( DGifGetImageDesc( gf)); width = gf->Image.Width; height = gf->Image.Height; cmap = (gf->Image.ColorMap) ? gf->Image.ColorMap : gf->SColorMap; clrs = cmap->Colors; cmapSize = cmap->ColorCount; /* * create our image objects and keep track of frames */ if ( !firstImg ) { /* this is the first (maybe only) frame */ firstImg = img = createImage( width, height); } else { /* this is a subsequent gif-movie frame, link it in */ img->next = createImage( width, height); img = img->next; } /* * The trans index might have been cached by a preceeding extension record. Now * that we have the Image object, it's time to store it in img and to create the * mask */ if ( trans != -1 ) { img->trans = trans; createXMaskImage( X, img); trans = -1; } /* * Some browsers seem to assume minimal values, and some animations * seem to rely on this. But there's no safe guess, so we * skip it completely */ /* if ( delay == 0 ) delay = 1000; else if ( delay < 100 ) delay = 100; */ img->latency = delay; img->left = gf->Image.Left; img->top = gf->Image.Top; img->frame = nFrames; nFrames++; createXImage( X, img); /* * start reading in the image data */ if ( gf->Image.Interlace ) { /* Need to perform 4 passes on the images: */ for ( i = 0; i < 4; i++ ) { for (row = iOffset[i]; row < height; row += iJumps[i]) { memset( rowBuf, gf->SBackGroundColor, width); CHECK( DGifGetLine( gf, rowBuf, width)); writeRow( img, rowBuf, clrs, row); } } } else { for ( row = 0; row < height; row++) { memset( rowBuf, gf->SBackGroundColor, width); CHECK( DGifGetLine(gf, rowBuf, width)); writeRow( img, rowBuf, clrs, row); } } break; case EXTENSION_RECORD_TYPE: CHECK( DGifGetExtension( gf, &extCode, &ext)); if ( extCode == 0xf9 ) { /* graphics extension */ /* * extension record with transparency spec are preceeding description records * (which create new Images), so just cache the transp index, here */ if ( ext[1] & 1 ) { /* transparent index following */ trans = ext[4]; } delay = ((ext[3] << 8) | ext[2]) * 10; /* delay in 1/100 secs */ } else if ( extCode == 0xff ) { /* application extension block */ } while ( ext != NULL ) { CHECK( DGifGetExtensionNext( gf, &ext)); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while ( rec != TERMINATE_RECORD_TYPE ); if ( firstImg && (img != firstImg) ){ img->next = firstImg; /* link it together (as a ring) */ } return firstImg; }
int DGifSlurp(GifFileType *GifFile) { size_t ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; int ExtFunction; GifFile->ExtensionBlocks = NULL; GifFile->ExtensionBlockCount = 0; //主循环 do { //判断当前读取的块类型 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) return (GIF_ERROR); switch (RecordType) { //每一帧图片的图片头 Descriptor 也就是0x2c //包含当前帧的上下左右位置(为了节省空间,GIF的单个帧可以不是完整的GIF的大小,如果小于GIF的分辨率 就需要上下左右来定位) //局部的颜色空间(每一帧可以有自己的颜色空间,是可选的) case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) return (GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; /* Allocate memory for the image */ if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 && sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { return GIF_ERROR; } ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { return GIF_ERROR; } //分配空间给解码后的图像像素 sp->RasterBits = (unsigned char *)malloc(ImageSize * sizeof(GifPixelType)); if (sp->RasterBits == NULL) { return GIF_ERROR; } if (sp->ImageDesc.Interlace) { int i, j; /* * The way an interlaced image should be read - * offsets and jumps... */ int InterlacedOffset[] = { 0, 4, 2, 1 }; int InterlacedJumps[] = { 8, 8, 4, 2 }; /* Need to perform 4 passes on the image */ for (i = 0; i < 4; i++) for (j = InterlacedOffset[i]; j < sp->ImageDesc.Height; j += InterlacedJumps[i]) { if (DGifGetLine(GifFile, sp->RasterBits+j*sp->ImageDesc.Width, sp->ImageDesc.Width) == GIF_ERROR) return GIF_ERROR; } } else { if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) return (GIF_ERROR); } if (GifFile->ExtensionBlocks) { sp->ExtensionBlocks = GifFile->ExtensionBlocks; sp->ExtensionBlockCount = GifFile->ExtensionBlockCount; GifFile->ExtensionBlocks = NULL; GifFile->ExtensionBlockCount = 0; } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR) return (GIF_ERROR); /* Create an extension block with our data */ if (ExtData != NULL) { if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks, ExtFunction, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); } while (ExtData != NULL) { if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); /* Continue the extension block */ if (ExtData != NULL) if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks, CONTINUE_EXT_FUNC_CODE, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } //当类型为Terminate也就是0x3b的时候 表示已经读到GIF文件尾 退出循环 } while (RecordType != TERMINATE_RECORD_TYPE); return (GIF_OK); }
//int fh_gif_load(char *name,unsigned char *buffer, unsigned char ** alpha, int x,int y) int fh_gif_load(aml_dec_para_t* para , aml_image_info_t* image) { int in_nextrow[4]={8,8,4,2}; //interlaced jump to the row current+in_nextrow int in_beginrow[4]={0,4,2,1}; //begin pass j from that row number int transparency=-1; //-1 means not transparency present int px,py,i,ibxs; int j; char *fbptr; char *lb; char *slb; GifFileType *gft; GifByteType *extension; int extcode; GifRecordType rt; ColorMapObject *cmap; int cmaps; char *p,*q; int buf_len; char* name; char* buffer; char* alpha = NULL; int x,y; name = para->fn; buffer = (unsigned char*) malloc(para->iwidth * para->iheight * 4); buf_len = para->iwidth * para->iheight; x = para->iwidth; y = para->iheight; gft=DGifOpenFileName(name); if(gft==NULL){printf("err5\n"); gflush;} ////////// do { if(DGifGetRecordType(gft,&rt) == GIF_ERROR) grflush; switch(rt) { case IMAGE_DESC_RECORD_TYPE: if(DGifGetImageDesc(gft)==GIF_ERROR) grflush; px=gft->Image.Width; py=gft->Image.Height; lb=(char*)malloc(px*3); slb=(char*) malloc(px); // printf("reading...\n"); if(lb!=NULL && slb!=NULL) { unsigned char *alphaptr = NULL; cmap=(gft->Image.ColorMap ? gft->Image.ColorMap : gft->SColorMap); cmaps=cmap->ColorCount; ibxs=ibxs*3; fbptr=(char*)buffer; if(transparency != -1) { alphaptr = malloc(px * py); alpha = alphaptr; } if(!(gft->Image.Interlace)) { for(i=0;i<py;i++,fbptr+=px*3) { int j; if(DGifGetLine(gft,(GifPixelType*)slb,px)==GIF_ERROR) mgrflush; m_rend_gif_decodecolormap((unsigned char*)slb,(unsigned char*)lb,cmap,cmaps,px,transparency); memcpy(fbptr,lb,px*3); if(alphaptr) for(j = 0; j<px; j++) *(alphaptr++) = (((unsigned char*) slb)[j] == transparency) ? 0x00 : 0xff; } } else { unsigned char * aptr = NULL; for(j=0;j<4;j++) { int k; if(alphaptr) aptr = alphaptr + (in_beginrow[j] * px); fbptr=(char*)buffer + (in_beginrow[j] * px * 3); for(i = in_beginrow[j]; i<py; i += in_nextrow[j], fbptr += px * 3 * in_nextrow[j], aptr += px * in_nextrow[j]) { if(DGifGetLine(gft,(GifPixelType*)slb,px)==GIF_ERROR) mgrflush; ///////////// m_rend_gif_decodecolormap((unsigned char*)slb,(unsigned char*)lb,cmap,cmaps,px,transparency); memcpy(fbptr,lb,px*3); if(alphaptr) for(k = 0; k<px; k++) aptr[k] = (((unsigned char*) slb)[k] == transparency) ? 0x00 : 0xff; } } } } if(lb) free(lb); if(slb) free(slb); break; case EXTENSION_RECORD_TYPE: if(DGifGetExtension(gft,&extcode,&extension)==GIF_ERROR) grflush; ////////// if(extcode==0xf9) //look image transparency in graph ctr extension { if(extension[1] & 1) { transparency = extension[4]; } // tran_off=(int)*extension; // transparency=(int)*(extension+tran_off); // printf("transparency: %d\n", transparency); } while(extension!=NULL) if(DGifGetExtensionNext(gft,&extension) == GIF_ERROR) grflush break; default: break; } } while( rt!= TERMINATE_RECORD_TYPE ); DGifCloseFile(gft); p = buffer; q = alpha ; for(i = buf_len ; i >0 ;i--){ if(!q){ p[4*i - 1] = 0xff; }else{ p[4*i - 1] = q[i-1]; //a } p[4*i - 2] = p[3*i - 3]; //r p[4*i - 3] = p[3*i - 2]; //g p[4*i - 4] = p[3*i - 1]; //b } image->data = buffer; image->width = x; image->height = y; image->depth = 32; image->bytes_per_line = x << 2 ; image->nbytes = image->bytes_per_line * y; return(FH_ERROR_OK); }
void* open_gif_file (const char *filename, int *width, int *height) { int interlace_offset[] = { 0, 4, 2, 1 }; int interlace_jump[] = { 8, 8, 4, 2 }; GifColorType *colormap; GifRecordType record_type; GifRowType *buffer = NULL; int i, j; int color_index; unsigned char *ptr = NULL; gif_data_t *data = (gif_data_t*)malloc(sizeof(gif_data_t)); assert(data != 0); int error; data->file = DGifOpenFileName(filename, &error); assert(data->file !=0); do { assert(DGifGetRecordType(data->file, &record_type) != GIF_ERROR) ; switch (record_type) { case IMAGE_DESC_RECORD_TYPE: assert(DGifGetImageDesc(data->file) != GIF_ERROR); *width = data->file->Image.Width; *height = data->file->Image.Height; data->width = *width; data->height = *height; buffer = malloc(*height * sizeof(GifRowType *)); assert(buffer != NULL); for (i = 0; i < *height; i++) { buffer[i] = malloc(*width * sizeof(GifPixelType)); assert(buffer[i] != NULL); } if (data->file->Image.Interlace) { for (i = 0; i < 4; i++) for (j = interlace_offset[i]; j < *height; j += interlace_jump[i]) DGifGetLine(data->file, buffer[j], *width); } else { for (i = 0; i < *height; i++) DGifGetLine(data->file, buffer[i], *width); } break; case EXTENSION_RECORD_TYPE: { /* Skip extension blocks */ int ext_code; GifByteType *ext; assert(DGifGetExtension(data->file, &ext_code, &ext) != GIF_ERROR); while (ext != NULL) { assert(DGifGetExtensionNext(data->file, &ext) != GIF_ERROR); } } break; case TERMINATE_RECORD_TYPE: break; default: fprintf(stderr, "unknown record type in GIF file\n"); break; } } while (record_type != TERMINATE_RECORD_TYPE); colormap = (data->file->Image.ColorMap ? data->file->Image.ColorMap->Colors : data->file->SColorMap->Colors); data->rgb = (unsigned char*)malloc( (data->width* data->height * 3) ); assert(data->rgb != NULL); ptr = data->rgb; for (j = 0; j < *height; j++) { for (i = 0; i < *width; i++) { color_index = (int) buffer[j][i]; *ptr++ = (unsigned char) colormap[color_index].Red; *ptr++ = (unsigned char) colormap[color_index].Green; *ptr++ = (unsigned char) colormap[color_index].Blue; } free(buffer[j]); } free(buffer); assert(DGifCloseFile(data->file) == GIF_OK); return data; }
static void GIF2RGB(int NumFiles, char *FileName, bool OneFileFlag, char *OutFileName) { int i, j, Size, Row, Col, Width, Height, ExtCode, Count; GifRecordType RecordType; GifByteType *Extension; GifRowType *ScreenBuffer; GifFileType *GifFile; int InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */ InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */ int ImageNum = 0; ColorMapObject *ColorMap; int Error; if (NumFiles == 1) { int Error; if ((GifFile = DGifOpenFileName(FileName, &Error)) == NULL) { PrintGifError(Error); exit(EXIT_FAILURE); } } else { int Error; /* Use stdin instead: */ if ((GifFile = DGifOpenFileHandle(0, &Error)) == NULL) { PrintGifError(Error); exit(EXIT_FAILURE); } } /* * Allocate the screen as vector of column of rows. Note this * screen is device independent - it's the screen defined by the * GIF file parameters. */ if ((ScreenBuffer = (GifRowType *) malloc(GifFile->SHeight * sizeof(GifRowType))) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); Size = GifFile->SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/ if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */ GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 0; i < GifFile->SWidth; i++) /* Set its color to BackGround. */ ScreenBuffer[0][i] = GifFile->SBackGroundColor; for (i = 1; i < GifFile->SHeight; i++) { /* Allocate the other rows, and set their color to background too: */ if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); memcpy(ScreenBuffer[i], ScreenBuffer[0], Size); } /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: { if (DGifGetImageDesc(GifFile) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } Row = GifFile->Image.Top; /* Image Position relative to Screen. */ Col = GifFile->Image.Left; Width = GifFile->Image.Width; Height = GifFile->Image.Height; GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height); if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth || GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) { fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n",ImageNum); exit(EXIT_FAILURE); } if (GifFile->Image.Interlace) { /* Need to perform 4 passes on the images: */ for (Count = i = 0; i < 4; i++) for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) { GifQprintf("\b\b\b\b%-4d", Count++); if (DGifGetLine(GifFile, &ScreenBuffer[j][Col], Width) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } } } else { for (i = 0; i < Height; i++) { GifQprintf("\b\b\b\b%-4d", i); if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col], Width) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } } } break; } case EXTENSION_RECORD_TYPE: { /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } while (Extension != NULL) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { PrintGifError(GifFile->Error); exit(EXIT_FAILURE); } } break; } case TERMINATE_RECORD_TYPE: { break; } default: /* Should be trapped by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Lets dump it - set the global variables required and do it: */ ColorMap = (GifFile->Image.ColorMap ? GifFile->Image.ColorMap : GifFile->SColorMap); if (ColorMap == NULL) { fprintf(stderr, "Gif Image does not have a colormap\n"); exit(EXIT_FAILURE); } DumpScreen2RGB(OutFileName, OneFileFlag, ColorMap, ScreenBuffer, GifFile->SWidth, GifFile->SHeight); (void)free(ScreenBuffer); if (DGifCloseFile(GifFile, &Error) == GIF_ERROR) { PrintGifError(Error); exit(EXIT_FAILURE); } }
/** * Reads an image from a stream. Earlier functions have decided that * this is the proper function to use for this stream. Therefore, we * will not lay much weight on excessive error checking when it comes * to the possibility of wrong image types. * The end product is converted into an appropriate format for the * user interface. * * @param fd The file descriptor of the stream to read the image data from. * @param width The requested width of the image, or a negative value if the * @param width width is to be taken from the image. * @param height The requested height of the image, or a negative value if the * @param height height is to be taken from the image. * * @return an allocated struct with the converted image and information * @return about it, or NULL if an error occurred. */ struct image_data *image_gif_read(int fd, int width, int height) { GifFileType *gifp; GifRecordType record; GifByteType *extension; int i, j, ret, extcode, rowsize, images_read, step; int row, col, image_width, image_height; struct image_data *picture; unsigned char *picturep; GifRowType *buffer; ColorMapObject *colourmap; GifColorType *colour; char *status; int interlaceoffset[] = { 0, 4, 2, 1 }; int interlacejump[] = { 8, 8, 4, 2 }; gifp = DGifOpenFileHandle(fd); if(gifp == NULL) { return NULL; } #if 0 /* First duplicate the file descriptor, so that we can close it in the * correct way, without interfering with the method libmagick has chosen * to operate in. */ #ifndef _WIN32_WCE new_fd = dup(fd); #else new_fd = fd; #endif #if defined _WIN32_WCE || WIN32 if(fd == -1) { #else if(fd < 0) { #endif /* If there is an error here, we could theoretically proceed with some * special treatment of the streams, but it indicates that something is * more wrong that we want it to be, so we just return an error here. */ return NULL; } #ifndef _WIN32_WCE fp = _fdopen(new_fd, "r"); if(fp == NULL) { RalCloseFile(new_fd); return NULL; } #endif #endif ui_functions_set_status("Reading and processing GIF image..."); picture = (struct image_data *)malloc(sizeof(struct image_data)); if(picture == NULL) { DGifCloseFile(gifp); return NULL; } picture->data = NULL; #if 0 fprintf(stderr, "screen width=%d, height=%d\n", gifp->SWidth, gifp->SHeight); #endif buffer = (GifRowType *)malloc(gifp->SHeight * sizeof(GifRowType *)); if(buffer == NULL) { free(picture); DGifCloseFile(gifp); return NULL; } rowsize = gifp->SWidth * sizeof(GifPixelType); buffer[0] = (GifRowType)malloc(rowsize); if(buffer[0] == NULL) { free(buffer); free(picture); DGifCloseFile(gifp); return NULL; } for(i = 0 ; i < gifp->SWidth ; i++) buffer[0][i] = gifp->SBackGroundColor; for(i = 0 ; i < gifp->SHeight ; i++) { buffer[i] = (GifRowType)malloc(rowsize); if(buffer[i] == NULL) { while(--i >= 0) free(buffer[i]); free(buffer); free(picture); DGifCloseFile(gifp); return NULL; } memcpy(buffer[i], buffer[0], rowsize); } /* We only read the first GIF image right now, since we are not * supporting animated GIF images. Perhaps the last image would * actually be a better choice. Oh well. */ images_read = 0; do { DGifGetRecordType(gifp, &record); ret = GIF_OK; switch(record) { case IMAGE_DESC_RECORD_TYPE: ret = DGifGetImageDesc(gifp); if(ret == GIF_ERROR) break; #if 0 fprintf(stderr, "image width=%d, height=%d, interlace=%d\n", gifp->Image.Width, gifp->Image.Height, gifp->Image.Interlace); #endif row = gifp->Image.Top; col = gifp->Image.Left; image_width = gifp->Image.Width; image_height = gifp->Image.Height; if(gifp->Image.Interlace) { for(i = 0 ; i < 4 ; i++) { for(j = row + interlaceoffset[i] ; j < row + image_height ; j += interlacejump[i]) { DGifGetLine(gifp, &buffer[j][col], image_width); } } } else { for(i = 0 ; i < image_height ; i++) { DGifGetLine(gifp, &buffer[row++][col], image_width); } } images_read++; break; /* Read and skip any extension. */ case EXTENSION_RECORD_TYPE: ret = DGifGetExtension(gifp, &extcode, &extension); while(extension != NULL) ret = DGifGetExtensionNext(gifp, &extension); break; default: break; } } while(images_read == 0 && ret == GIF_OK && record != TERMINATE_RECORD_TYPE); if(ret == GIF_ERROR) { for(i = 0 ; i < gifp->SHeight ; i++) free(buffer[i]); free(buffer); free(picture); DGifCloseFile(gifp); return NULL; } /* Since scaling is not possible yet, we only use the original * geometry of the image. */ picture->width = gifp->SWidth; picture->height = gifp->SHeight; /* Allocate space for the image data in our struct. */ picture->size = (picture->width * picture->height * user_interface.ui_display.bit_depth) / 8; picture->data = (unsigned char *)malloc(picture->size); if(picture->data == NULL) { free(picture); for(i = 0 ; i < gifp->SHeight ; i++) free(buffer[i]); free(buffer); DGifCloseFile(gifp); return NULL; } if(gifp->Image.ColorMap != NULL) colourmap = gifp->Image.ColorMap; else colourmap = gifp->SColorMap; status = (char *)malloc(128); picturep = picture->data; for(i = 0 ; i < picture->height ; i++) { for(j = 0 ; j < picture->width ; j++) { colour = &colourmap->Colors[buffer[i][j]]; step = image_get_real_colour(picturep, colour->Red, colour->Green, colour->Blue); picturep += step; } if(status != NULL) { sprintf(status, "Reading and processing GIF image... %d%%", (int)((100 * (i+1)) / picture->height)); ui_functions_set_status(status); } } for(i = 0 ; i < gifp->SHeight ; i++) free(buffer[i]); free(buffer); DGifCloseFile(gifp); return picture; }
void DDGifSlurp(GifInfo *info, bool shouldDecode) { GifRecordType RecordType; GifByteType *ExtData; int codeSize; int ExtFunction; do { if (DGifGetRecordType(info->gifFilePtr, &RecordType) == GIF_ERROR) return; switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(info->gifFilePtr, !shouldDecode) == GIF_ERROR) return; const uint_fast16_t requiredScreenWidth = info->gifFilePtr->Image.Left + info->gifFilePtr->Image.Width; const uint_fast16_t requiredScreenHeight = info->gifFilePtr->Image.Top + info->gifFilePtr->Image.Height; if (requiredScreenWidth > info->gifFilePtr->SWidth || requiredScreenHeight > info->gifFilePtr->SHeight) { if (shouldDecode) { void *tmpRasterBits = realloc(info->rasterBits, requiredScreenWidth * requiredScreenHeight * sizeof(GifPixelType)); if (tmpRasterBits == NULL) { info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return; } info->rasterBits = tmpRasterBits; } else { info->gifFilePtr->SWidth = requiredScreenWidth; info->gifFilePtr->SHeight = requiredScreenHeight; } } if (shouldDecode) { if (info->gifFilePtr->Image.Interlace) { uint_fast16_t i, j; /* * The way an interlaced image should be read - * offsets and jumps... */ uint_fast8_t InterlacedOffset[] = {0, 4, 2, 1}; uint_fast8_t InterlacedJumps[] = {8, 8, 4, 2}; /* Need to perform 4 passes on the image */ for (i = 0; i < 4; i++) for (j = InterlacedOffset[i]; j < info->gifFilePtr->Image.Height; j += InterlacedJumps[i]) { if (DGifGetLine(info->gifFilePtr, info->rasterBits + j * info->gifFilePtr->Image.Width, info->gifFilePtr->Image.Width) == GIF_ERROR) return; } } else { if (DGifGetLine( info->gifFilePtr, info->rasterBits, info->gifFilePtr->Image.Width * info->gifFilePtr->Image.Height) == GIF_ERROR) return; } return; } else { if (DGifGetCode(info->gifFilePtr, &codeSize, &ExtData) == GIF_ERROR) return; while (ExtData != NULL) { if (DGifGetCodeNext(info->gifFilePtr, &ExtData) == GIF_ERROR) return; } } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(info->gifFilePtr, &ExtFunction, &ExtData) == GIF_ERROR) return; if (!shouldDecode) { GraphicsControlBlock *tmpInfos = realloc(info->controlBlock, (info->gifFilePtr->ImageCount + 1) * sizeof(GraphicsControlBlock)); if (tmpInfos == NULL) { info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return; } info->controlBlock = tmpInfos; info->controlBlock[info->gifFilePtr->ImageCount].DelayTime = DEFAULT_FRAME_DURATION_MS; if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) return; } while (ExtData != NULL) { if (DGifGetExtensionNext(info->gifFilePtr, &ExtData, &ExtFunction) == GIF_ERROR) return; if (!shouldDecode) { if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) return; } } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); info->rewindFunction(info); }
/****************************************************************************** * This routine reads an entire GIF into core, hanging all its state info off * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() * first to initialize I/O. Its inverse is EGifSpew(). ******************************************************************************/ int DGifSlurp(GifFileType * GifFile) { int ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; Extensions temp_save; temp_save.ExtensionBlocks = NULL; temp_save.ExtensionBlockCount = 0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) return (GIF_ERROR); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) return (GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; sp->RasterBits = ungif_alloc(ImageSize * sizeof(GifPixelType)); if (sp->RasterBits == NULL) { return GIF_ERROR; } if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) == GIF_ERROR) return (GIF_ERROR); if (temp_save.ExtensionBlocks) { sp->Extensions.ExtensionBlocks = temp_save.ExtensionBlocks; sp->Extensions.ExtensionBlockCount = temp_save.ExtensionBlockCount; temp_save.ExtensionBlocks = NULL; temp_save.ExtensionBlockCount = 0; /* FIXME: The following is wrong. It is left in only for * backwards compatibility. Someday it should go away. Use * the sp->ExtensionBlocks->Function variable instead. */ sp->Extensions.Function = sp->Extensions.ExtensionBlocks[0].Function; } break; case EXTENSION_RECORD_TYPE: { int Function; Extensions *Extensions; if (DGifGetExtension(GifFile, &Function, &ExtData) == GIF_ERROR) return (GIF_ERROR); if (GifFile->ImageCount || Function == GRAPHICS_EXT_FUNC_CODE) Extensions = &temp_save; else Extensions = &GifFile->Extensions; Extensions->Function = Function; /* Create an extension block with our data */ if (AddExtensionBlock(Extensions, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); while (ExtData != NULL) { int Len; GifByteType *Data; if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); if (ExtData) { Len = ExtData[0]; Data = &ExtData[1]; } else { Len = 0; Data = NULL; } if (AppendExtensionBlock(Extensions, Len, Data) == GIF_ERROR) return (GIF_ERROR); } break; } case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Just in case the Gif has an extension block without an associated * image... (Should we save this into a savefile structure with no image * instead? Have to check if the present writing code can handle that as * well.... */ if (temp_save.ExtensionBlocks) FreeExtension(&temp_save); return (GIF_OK); }
CPLErr BIGGIFDataset::ReOpen() { /* -------------------------------------------------------------------- */ /* If the file is already open, close it so we can restart. */ /* -------------------------------------------------------------------- */ if( hGifFile != NULL ) DGifCloseFile( hGifFile ); /* -------------------------------------------------------------------- */ /* If we are actually reopening, then we assume that access to */ /* the image data is not strictly once through sequential, and */ /* we will try to create a working database in a temporary */ /* directory to hold the image as we read through it the second */ /* time. */ /* -------------------------------------------------------------------- */ if( hGifFile != NULL ) { GDALDriver *poGTiffDriver = (GDALDriver*) GDALGetDriverByName("GTiff"); if( poGTiffDriver != NULL ) { /* Create as a sparse file to avoid filling up the whole file */ /* while closing and then destroying this temporary dataset */ const char* apszOptions[] = { "COMPRESS=LZW", "SPARSE_OK=YES", NULL }; CPLString osTempFilename = CPLGenerateTempFilename("biggif"); osTempFilename += ".tif"; poWorkDS = poGTiffDriver->Create( osTempFilename, nRasterXSize, nRasterYSize, 1, GDT_Byte, const_cast<char**>(apszOptions)); } } /* -------------------------------------------------------------------- */ /* Open */ /* -------------------------------------------------------------------- */ VSIFSeekL( fp, 0, SEEK_SET ); nLastLineRead = -1; #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 int nError; hGifFile = DGifOpen( fp, VSIGIFReadFunc, &nError ); #else hGifFile = DGifOpen( fp, VSIGIFReadFunc ); #endif if( hGifFile == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "DGifOpen() failed. Perhaps the gif file is corrupt?\n" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Find the first image record. */ /* -------------------------------------------------------------------- */ GifRecordType RecordType = TERMINATE_RECORD_TYPE; while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR && RecordType != TERMINATE_RECORD_TYPE && RecordType != IMAGE_DESC_RECORD_TYPE ) { /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */ if (RecordType == EXTENSION_RECORD_TYPE) { int nFunction; GifByteType *pExtData; if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR) break; while (pExtData != NULL) { if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR) break; } } } if( RecordType != IMAGE_DESC_RECORD_TYPE ) { DGifCloseFile( hGifFile ); hGifFile = NULL; CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find image description record in GIF file." ); return CE_Failure; } if (DGifGetImageDesc(hGifFile) == GIF_ERROR) { DGifCloseFile( hGifFile ); hGifFile = NULL; CPLError( CE_Failure, CPLE_OpenFailed, "Image description reading failed in GIF file." ); return CE_Failure; } return CE_None; }
int image_gif_load(image *im) { int x, y, ofs; GifRecordType RecordType; GifPixelType *line = NULL; int ExtFunction = 0; GifByteType *ExtData; SavedImage *sp; SavedImage temp_save; int BackGround = 0; int trans_index = 0; // transparent index if any ColorMapObject *ColorMap; GifColorType *ColorMapEntry; temp_save.ExtensionBlocks = NULL; temp_save.ExtensionBlockCount = 0; // If reusing the object a second time, start over if (im->used) { DEBUG_TRACE("Recreating giflib objects\n"); image_gif_finish(im); if (im->fh != NULL) { // reset file to begining of image PerlIO_seek(im->fh, im->image_offset, SEEK_SET); } else { // reset SV read im->sv_offset = im->image_offset; } buffer_clear(im->buf); image_gif_read_header(im); } do { if (DGifGetRecordType(im->gif, &RecordType) == GIF_ERROR) { warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(im->gif) == GIF_ERROR) { warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } sp = &im->gif->SavedImages[im->gif->ImageCount - 1]; im->width = sp->ImageDesc.Width; im->height = sp->ImageDesc.Height; BackGround = im->gif->SBackGroundColor; // XXX needed? ColorMap = im->gif->Image.ColorMap ? im->gif->Image.ColorMap : im->gif->SColorMap; if (ColorMap == NULL) { warn("Image::Scale GIF image has no colormap (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } // Allocate storage for decompressed image image_alloc(im, im->width, im->height); New(0, line, im->width, GifPixelType); if (im->gif->Image.Interlace) { int i; for (i = 0; i < 4; i++) { for (x = InterlacedOffset[i]; x < im->height; x += InterlacedJumps[i]) { ofs = x * im->width; if (DGifGetLine(im->gif, line, 0) != GIF_OK) { warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } for (y = 0; y < im->width; y++) { ColorMapEntry = &ColorMap->Colors[line[y]]; im->pixbuf[ofs++] = COL_FULL( ColorMapEntry->Red, ColorMapEntry->Green, ColorMapEntry->Blue, trans_index == line[y] ? 0 : 255 ); } } } } else { ofs = 0; for (x = 0; x < im->height; x++) { if (DGifGetLine(im->gif, line, 0) != GIF_OK) { warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } for (y = 0; y < im->width; y++) { ColorMapEntry = &ColorMap->Colors[line[y]]; im->pixbuf[ofs++] = COL_FULL( ColorMapEntry->Red, ColorMapEntry->Green, ColorMapEntry->Blue, trans_index == line[y] ? 0 : 255 ); } } } Safefree(line); break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(im->gif, &ExtFunction, &ExtData) == GIF_ERROR) { warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } if (ExtFunction == 0xF9) { // transparency info if (ExtData[1] & 1) trans_index = ExtData[4]; else trans_index = -1; im->has_alpha = 1; DEBUG_TRACE("GIF transparency index: %d\n", trans_index); } while (ExtData != NULL) { /* Create an extension block with our data */ #ifdef GIFLIB_API_50 if (GifAddExtensionBlock(&im->gif->ExtensionBlockCount, &im->gif->ExtensionBlocks, ExtFunction, ExtData[0], &ExtData[1]) == GIF_ERROR) { #else temp_save.Function = ExtFunction; if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1]) == GIF_ERROR) { #endif #ifdef GIFLIB_API_41 PrintGifError(); #endif warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } if (DGifGetExtensionNext(im->gif, &ExtData) == GIF_ERROR) { #ifdef GIFLIB_API_41 PrintGifError(); #endif warn("Image::Scale unable to read GIF file (%s)\n", SvPVX(im->path)); image_gif_finish(im); return 0; } ExtFunction = 0; // CONTINUE_EXT_FUNC_CODE } break; case TERMINATE_RECORD_TYPE: default: break; } } while (RecordType != TERMINATE_RECORD_TYPE); return 1; } void image_gif_finish(image *im) { if (im->gif != NULL) { #ifdef GIFLIB_API_51 if (DGifCloseFile(im->gif, NULL) != GIF_OK) { #else if (DGifCloseFile(im->gif) != GIF_OK) { #endif #ifdef GIFLIB_API_41 PrintGifError(); #endif warn("Image::Scale unable to close GIF file (%s)\n", SvPVX(im->path)); } im->gif = NULL; DEBUG_TRACE("image_gif_finish\n"); } }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ void main(int argc, char **argv) { int Error, NumFiles, ExtCode; GifRecordType RecordType; GifByteType *Extension; char **FileName = NULL; GifRowType *ImageBuffer; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuitePrint, &InterlacedFlag, &SequencialFlag, &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 (NumFiles == 1) { if ((GifFileIn = DGifOpenFileName(*FileName)) == NULL) QuitGifError(GifFileIn, GifFileOut); } else { /* Use the stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0)) == NULL) QuitGifError(GifFileIn, GifFileOut); } /* Open stdout for the output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* And dump out exactly same screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn -> SWidth, GifFileIn -> SHeight, GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor, GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Put the image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn -> ILeft, GifFileIn -> ITop, GifFileIn -> IWidth, GifFileIn -> IHeight, InterlacedFlag, GifFileIn -> IBitsPerPixel, GifFileIn -> IColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Load the image (either Interlaced or not), and dump it as */ /* defined in GifFileOut -> IInterlaced. */ if (LoadImage(GifFileIn, &ImageBuffer) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (DumpImage(GifFileOut, ImageBuffer) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, so discard: */ while (Extension != NULL) { if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); }
static void Gif2Icon(char *FileName, int fdin, int fdout, char NameTable[]) { int i, ExtCode, ImageNum = 1; GifPixelType *Line, *cp; GifRecordType RecordType; GifByteType *Extension; GifFileType *GifFile; if (fdin == -1) { if ((GifFile = DGifOpenFileName(FileName)) == NULL) { PrintGifError(); exit(EXIT_FAILURE); } } else { /* Use stdin instead: */ if ((GifFile = DGifOpenFileHandle(fdin)) == NULL) { PrintGifError(); exit(EXIT_FAILURE); } } printf("screen width %d\nscreen height %d\n", GifFile->SWidth, GifFile->SHeight); printf("screen colors %d\nscreen background %d\n\n", GifFile->SColorResolution, GifFile->SBackGroundColor); if (GifFile->SColorMap) { if (GifFile->SColorMap->ColorCount >= (int)strlen(NameTable)) { (void) fprintf(stderr, "%s: global color map has unprintable pixels\n", FileName); exit(EXIT_FAILURE); } printf("screen map\n"); for (i = 0; i < GifFile->SColorMap->ColorCount; i++) printf("\trgb %03d %03d %03d is %c\n", GifFile->SColorMap ->Colors[i].Red, GifFile->SColorMap ->Colors[i].Green, GifFile->SColorMap ->Colors[i].Blue, NameTable[i]); printf("end\n\n"); } do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } printf("image # %d\nimage left %d\nimage top %d\n", ImageNum++, GifFile->Image.Left, GifFile->Image.Top); if (GifFile->Image.Interlace) printf("interlaced\n"); if (GifFile->Image.ColorMap) { if (GifFile->Image.ColorMap->ColorCount >= (int)strlen(NameTable)) { (void) fprintf(stderr, "%s: global color map has unprintable pixels\n", FileName); exit(EXIT_FAILURE); } printf("image map\n"); for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) printf("\trgb %03d %03d %03d is %c\n", GifFile->Image.ColorMap ->Colors[i].Red, GifFile->Image.ColorMap ->Colors[i].Green, GifFile->Image.ColorMap ->Colors[i].Blue, NameTable[i]); printf("end\n\n"); } printf("image bits %d by %d\n", GifFile->Image.Width, GifFile->Image.Height); Line = (GifPixelType *) malloc(GifFile->Image.Width * sizeof(GifPixelType)); for (i = 0; i < GifFile->Image.Height; i++) { if (DGifGetLine(GifFile, Line, GifFile->Image.Width) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } for (cp = Line; cp < Line + GifFile->Image.Width; cp++) putchar(NameTable[*cp]); putchar('\n'); } free((char *) Line); putchar('\n'); break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } if (ExtCode == COMMENT_EXT_FUNC_CODE) printf("comment\n"); else if (ExtCode == PLAINTEXT_EXT_FUNC_CODE) printf("plaintext\n"); else if (isalpha(ExtCode)) printf("extension %02x # %c\n", ExtCode, ExtCode); else printf("extension %02x\n", ExtCode); while (Extension != NULL) { VisibleDumpBuffer((char *)(Extension + 1), Extension[0]); putchar('\n'); if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } } printf("end\n\n"); break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Tell EMACS this is a picture... */ printf("# The following sets edit modes for GNU EMACS\n"); printf("# Local "); /* ...break this up, so that EMACS doesn't */ printf("Variables:\n"); /* get confused when visiting *this* file! */ printf("# mode:picture\n"); printf("# truncate-lines:t\n"); printf("# End:\n"); if (fdin == -1) (void) printf("# End of %s dump\n", FileName); if (DGifCloseFile(GifFile) == GIF_ERROR) { PrintGifError(); exit(EXIT_FAILURE); } }
/****************************************************************************** * This routine reads an entire GIF into core, hanging all its state info off * * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() * * first to initialize I/O. Its inverse is EGifSpew(). * * ******************************************************************************/ int DGifSlurp(GifFileType *GifFile) { int i, j, Error, ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; SavedImage temp_save; temp_save.ExtensionBlocks=NULL; temp_save.ExtensionBlockCount=0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) return(GIF_ERROR); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) return(GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount-1]; ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; sp->RasterBits = (char *) malloc(ImageSize * sizeof(GifPixelType)); if (DGifGetLine(GifFile, (GifByteType*)sp->RasterBits, ImageSize) == GIF_ERROR) return(GIF_ERROR); if (temp_save.ExtensionBlocks) { sp->ExtensionBlocks = temp_save.ExtensionBlocks; sp->ExtensionBlockCount = temp_save.ExtensionBlockCount; temp_save.ExtensionBlocks = NULL; temp_save.ExtensionBlockCount=0; /* FIXME: The following is wrong. It is left in only for backwards * compatibility. Someday it should go away. Use the * sp->ExtensionBlocks->Function variable instead. */ sp->Function = sp->ExtensionBlocks[0].Function; } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(GifFile,&temp_save.Function,&ExtData)==GIF_ERROR) return(GIF_ERROR); while (ExtData != NULL) { /* Create an extension block with our data */ if (AddExtensionBlock(&temp_save, ExtData[0], (char*)&ExtData[1]) == GIF_ERROR) return (GIF_ERROR); if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return(GIF_ERROR); temp_save.Function = 0; } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Just in case the Gif has an extension block without an associated * image... (Should we save this into a savefile structure with no image * instead? Have to check if the present writing code can handle that as * well.... */ if (temp_save.ExtensionBlocks) FreeExtension(&temp_save); return(GIF_OK); }
/* * Read enough of the stream to initialize the SkGifCodec. * Returns a bool representing success or failure. * * @param codecOut * If it returned true, and codecOut was not nullptr, * codecOut will be set to a new SkGifCodec. * * @param gifOut * If it returned true, and codecOut was nullptr, * gifOut must be non-nullptr and gifOut will be set to a new * GifFileType pointer. * * @param stream * Deleted on failure. * codecOut will take ownership of it in the case where we created a codec. * Ownership is unchanged when we returned a gifOut. * */ bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) { SkAutoTDelete<SkStream> streamDeleter(stream); // Read gif header, logical screen descriptor, and global color table SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream)); if (nullptr == gif) { gif_error("DGifOpen failed.\n"); return false; } // Read through gif extensions to get to the image data. Set the // transparent index based on the extension data. uint32_t transIndex; SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex); if (kSuccess != result){ return false; } // Read the image descriptor if (GIF_ERROR == DGifGetImageDesc(gif)) { return false; } // If reading the image descriptor is successful, the image count will be // incremented. SkASSERT(gif->ImageCount >= 1); if (nullptr != codecOut) { SkISize size; SkIRect frameRect; if (!GetDimensions(gif, &size, &frameRect)) { gif_error("Invalid gif size.\n"); return false; } bool frameIsSubset = (size != frameRect.size()); // Determine the recommended alpha type. The transIndex might be valid if it less // than 256. We are not certain that the index is valid until we process the color // table, since some gifs have color tables with less than 256 colors. If // there might be a valid transparent index, we must indicate that the image has // alpha. // In the case where we must support alpha, we have the option to set the // suggested alpha type to kPremul or kUnpremul. Both are valid since the alpha // component will always be 0xFF or the entire 32-bit pixel will be set to zero. // We prefer kPremul because we support kPremul, and it is more efficient to use // kPremul directly even when kUnpremul is supported. SkAlphaType alphaType = (transIndex < 256) ? kPremul_SkAlphaType : kOpaque_SkAlphaType; // Return the codec // kIndex is the most natural color type for gifs, so we set this as // the default. SkImageInfo imageInfo = SkImageInfo::Make(size.width(), size.height(), kIndex_8_SkColorType, alphaType); *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach(), transIndex, frameRect, frameIsSubset); } else { SkASSERT(nullptr != gifOut); streamDeleter.detach(); *gifOut = gif.detach(); } return true; }
bool img_load_gif(img_t *img, const fileinfo_t *file) { GifFileType *gif; GifRowType *rows = NULL; GifRecordType rec; ColorMapObject *cmap; DATA32 bgpixel, *data, *ptr; DATA32 *prev_frame = NULL; Imlib_Image im; int i, j, bg, r, g, b; int x, y, w, h, sw, sh; int px, py, pw, ph; int intoffset[] = { 0, 4, 2, 1 }; int intjump[] = { 8, 8, 4, 2 }; int transp = -1; unsigned int disposal = 0, prev_disposal = 0; unsigned int delay = 0; bool err = false; if (img->multi.cap == 0) { img->multi.cap = 8; img->multi.frames = (img_frame_t*) s_malloc(sizeof(img_frame_t) * img->multi.cap); } img->multi.cnt = img->multi.sel = 0; img->multi.length = 0; #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5 gif = DGifOpenFileName(file->path, NULL); #else gif = DGifOpenFileName(file->path); #endif if (gif == NULL) { warn("could not open gif file: %s", file->name); return false; } bg = gif->SBackGroundColor; sw = gif->SWidth; sh = gif->SHeight; px = py = pw = ph = 0; do { if (DGifGetRecordType(gif, &rec) == GIF_ERROR) { err = true; break; } if (rec == EXTENSION_RECORD_TYPE) { int ext_code; GifByteType *ext = NULL; DGifGetExtension(gif, &ext_code, &ext); while (ext) { if (ext_code == GRAPHICS_EXT_FUNC_CODE) { if (ext[1] & 1) transp = (int) ext[4]; else transp = -1; delay = 10 * ((unsigned int) ext[3] << 8 | (unsigned int) ext[2]); disposal = (unsigned int) ext[1] >> 2 & 0x7; } ext = NULL; DGifGetExtensionNext(gif, &ext); } } else if (rec == IMAGE_DESC_RECORD_TYPE) { if (DGifGetImageDesc(gif) == GIF_ERROR) { err = true; break; } x = gif->Image.Left; y = gif->Image.Top; w = gif->Image.Width; h = gif->Image.Height; rows = (GifRowType*) s_malloc(h * sizeof(GifRowType)); for (i = 0; i < h; i++) rows[i] = (GifRowType) s_malloc(w * sizeof(GifPixelType)); if (gif->Image.Interlace) { for (i = 0; i < 4; i++) { for (j = intoffset[i]; j < h; j += intjump[i]) DGifGetLine(gif, rows[j], w); } } else { for (i = 0; i < h; i++) DGifGetLine(gif, rows[i], w); } ptr = data = (DATA32*) s_malloc(sizeof(DATA32) * sw * sh); cmap = gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap; r = cmap->Colors[bg].Red; g = cmap->Colors[bg].Green; b = cmap->Colors[bg].Blue; bgpixel = 0x00ffffff & (r << 16 | g << 8 | b); for (i = 0; i < sh; i++) { for (j = 0; j < sw; j++) { if (i < y || i >= y + h || j < x || j >= x + w || rows[i-y][j-x] == transp) { if (prev_frame != NULL && (prev_disposal != 2 || i < py || i >= py + ph || j < px || j >= px + pw)) { *ptr = prev_frame[i * sw + j]; } else { *ptr = bgpixel; } } else { r = cmap->Colors[rows[i-y][j-x]].Red; g = cmap->Colors[rows[i-y][j-x]].Green; b = cmap->Colors[rows[i-y][j-x]].Blue; *ptr = 0xff << 24 | r << 16 | g << 8 | b; } ptr++; } } im = imlib_create_image_using_copied_data(sw, sh, data); for (i = 0; i < h; i++) free(rows[i]); free(rows); free(data); if (im == NULL) { err = true; break; } imlib_context_set_image(im); imlib_image_set_format("gif"); if (transp >= 0) imlib_image_set_has_alpha(1); if (disposal != 3) prev_frame = imlib_image_get_data_for_reading_only(); prev_disposal = disposal; px = x, py = y, pw = w, ph = h; if (img->multi.cnt == img->multi.cap) { img->multi.cap *= 2; img->multi.frames = (img_frame_t*) s_realloc(img->multi.frames, img->multi.cap * sizeof(img_frame_t)); } img->multi.frames[img->multi.cnt].im = im; img->multi.frames[img->multi.cnt].delay = delay > 0 ? delay : DEF_GIF_DELAY; img->multi.length += img->multi.frames[img->multi.cnt].delay; img->multi.cnt++; } } while (rec != TERMINATE_RECORD_TYPE);
int main(int argc, char **argv) { // // local vars // GifFileType *GIFfile; GifRecordType GIFtype; GifByteType *GIFextension; GifPixelType *GIFline; uint32_t **lower_array,**upper_array; double **image_array; double f,fmin,fmax; int x,y,z,h,i,j,k,n,p; int image_width,image_height,image_count,color_resolution,GIFcode,ret; float pixel_size,arg,rx,ry,rz; char type,comment[256]; struct fab_vars v; init_vars(&v); // // command line args // if (!((argc == 3) || (argc == 4) || (argc == 5) || (argc == 6) || (argc == 7) || (argc == 10))) { printf("command line: gif_png in.gif out.png [type [arg [points [size [rx ry rz]]]]]\n"); printf(" in.gif = input gif file\n"); printf(" out.png = output PNG file\n"); printf(" type = 'z' of density, 'h' for height (default z)\n"); printf(" arg = gamma for 'z', threshold for 'h' (default 1)\n"); printf(" points = points to interpolate per point (linear, default 0)\n"); printf(" size = voxel size (mm, default from file))\n"); printf(" to be implemented: rx,ry,rz = x,y,z rotation angles (degrees; default 0)\n"); exit(-1); } type = 'z'; p = 0; arg = 1; rx = ry = rz = 0; pixel_size = -1; image_width = -1; image_height = -1; if (argc >= 4) { sscanf(argv[3],"%c",&type); if (!((type == 'z') || (type == 'h'))) { printf("gif_png: oops -- type must be 'z' or 'h'\n"); exit(-1); } if (argc >= 5) sscanf(argv[4],"%f",&arg); } if (argc >= 6) sscanf(argv[5],"%d",&p); if (argc >= 7) sscanf(argv[6],"%f",&pixel_size); if (argc >= 10) { sscanf(argv[7],"%f",&rx); sscanf(argv[8],"%f",&ry); sscanf(argv[9],"%f",&rz); } // // scan the file // printf("read %s\n",argv[1]); color_resolution = -1; GIFfile = DGifOpenFileName(argv[1]); if (GIFfile == NULL) { printf("gif_png: oops -- can not open %s\n",argv[1]); exit(-1); } GIFline = malloc(MAX_LINE*sizeof(GifPixelType)); do { DGifGetRecordType(GIFfile,&GIFtype); switch (GIFtype) { case IMAGE_DESC_RECORD_TYPE: DGifGetImageDesc(GIFfile); image_width = GIFfile->SWidth; image_height = GIFfile->SHeight; image_count = GIFfile->ImageCount; color_resolution = GIFfile->SColorResolution; for (y = 0; y < GIFfile->SHeight; ++y) { ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth); if (ret != GIF_OK) { printf("gif_png: oops -- error reading line\n"); exit(-1); } } break; case EXTENSION_RECORD_TYPE: DGifGetExtension(GIFfile,&GIFcode,&GIFextension); if (GIFcode == COMMENT_EXT_FUNC_CODE) { n = GIFextension[0]; for (i = 1; i <= n; ++i) comment[i-1] = GIFextension[i]; comment[n] = 0; if (pixel_size == -1) sscanf(comment,"mm per pixel: %f;",&pixel_size); } while (GIFextension != NULL) DGifGetExtensionNext(GIFfile,&GIFextension); break; case SCREEN_DESC_RECORD_TYPE: DGifGetScreenDesc(GIFfile); break; case TERMINATE_RECORD_TYPE: break; case UNDEFINED_RECORD_TYPE: printf("gif_png: oops -- undefined GIF record type\n"); exit(-1); break; } } while (GIFtype != TERMINATE_RECORD_TYPE); if (GIFfile == NULL) { printf("gif_png: oops -- can not open %s\n",argv[1]); exit(-1); } if (pixel_size == -1) { pixel_size = 1.0; printf(" no pixel size found, assuming 1 mm\n"); } printf(" pixel size (mm): %f, color resolution (bits): %d\n",pixel_size,color_resolution); printf(" number of images: %d, image width %d, image height %d\n",image_count,image_width,image_height); // // check and set limits // v.nx = image_width + (image_width-1)*p; v.ny = image_height + (image_height-1)*p; v.nz = image_count + (image_count-1)*p; v.dx = v.nx*pixel_size; v.dy = v.ny*pixel_size; v.dz = v.nz*pixel_size; v.xmin = 0; v.ymin = 0; v.zmin = 0; // // allocate arrays // lower_array = malloc(image_height*sizeof(uint32_t *)); for (y = 0; y < image_height; ++y) { lower_array[y] = malloc(image_width*sizeof(uint32_t)); for (x = 0; x < image_width; ++x) lower_array[y][x] = 0; } upper_array = malloc(image_height*sizeof(uint32_t *)); for (y = 0; y < image_height; ++y) { upper_array[y] = malloc(image_width*sizeof(uint32_t)); for (x = 0; x < image_width; ++x) upper_array[y][x] = 0; } image_array = malloc(v.ny*sizeof(double *)); for (y = 0; y < v.ny; ++y) { image_array[y] = malloc(v.nx*sizeof(double)); for (x = 0; x < v.nx; ++x) image_array[y][x] = 0; } v.array = malloc(v.ny*sizeof(uint32_t *)); for (y = 0; y < v.ny; ++y) { v.array[y] = malloc(v.nx*sizeof(uint32_t)); for (x = 0; x < v.nx; ++x) v.array[y][x] = 0; } // // read the file // DGifCloseFile(GIFfile); GIFfile = DGifOpenFileName(argv[1]); if (GIFfile == NULL) { printf("gif_png: oops -- can not open %s\n",argv[1]); exit(-1); } z = 0; do { DGifGetRecordType(GIFfile,&GIFtype); switch (GIFtype) { case IMAGE_DESC_RECORD_TYPE: // // read image // DGifGetImageDesc(GIFfile); printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b layer = %d",z); if (z == 0) { // // read first layer // for (y = 0; y < image_height; ++y) { ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth); if (ret != GIF_OK) { printf("gif_png: oops -- error reading first line\n"); exit(-1); } for (x = 0; x < image_width; ++x) upper_array[y][x] = GIFline[x]; } } else { // // read next layer // for (y = 0; y < image_height; ++y) { ret = DGifGetLine(GIFfile,GIFline,GIFfile->SWidth); if (ret != GIF_OK) { printf("gif_png: oops -- error reading line\n"); exit(-1); } for (x = 0; x < image_width; ++x) { lower_array[y][x] = upper_array[y][x]; upper_array[y][x] = GIFline[x]; } } // // interpolate layer image // for (x = 0; x < (image_width-1); ++x) { for (y = 0; y < (image_height-1); ++y) { for (i = 0; i <= p; ++i) { for (j = 0; j <= p; ++j) { for (k = 0; k <= p; ++k) { f = lower_array[y][x]*((p+1.0-i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((p+1.0-k)/(p+1.0)) + lower_array[y][x+1]*((i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((p+1.0-k)/(p+1.0)) + lower_array[y+1][x]*((p+1.0-i)/(p+1.0))*((j)/(p+1.0))*((p+1.0-k)/(p+1.0)) + lower_array[y+1][x+1]*((i)/(p+1.0))*((j)/(p+1.0))*((p+1.0-k)/(p+1.0)) + upper_array[y][x]*((p+1.0-i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((k)/(p+1.0)) + upper_array[y][x+1]*((i)/(p+1.0))*((p+1.0-j)/(p+1.0))*((k)/(p+1.0)) + upper_array[y+1][x]*((p+1.0-i)/(p+1.0))*((j)/(p+1.0))*((k)/(p+1.0)) + upper_array[y+1][x+1]*((i)/(p+1.0))*((j)/(p+1.0))*((k)/(p+1.0)); if (type == 'z') { image_array[(1+p)*y+j][(1+p)*x+i] += f; } else if (type == 'h') { h = (1+p)*z+k; if ((f > arg) && (h > image_array[(1+p)*y+j][(1+p)*x+i])) image_array[(1+p)*y+j][(1+p)*x+i] = h; } } } } } } } z += 1; break; case EXTENSION_RECORD_TYPE: DGifGetExtension(GIFfile,&GIFcode,&GIFextension); while (GIFextension != NULL) DGifGetExtensionNext(GIFfile,&GIFextension); break; case SCREEN_DESC_RECORD_TYPE: DGifGetScreenDesc(GIFfile); break; case TERMINATE_RECORD_TYPE: break; case UNDEFINED_RECORD_TYPE: printf("gif_png: oops -- undefined GIF record type\n"); exit(-1); break; } } while (GIFtype != TERMINATE_RECORD_TYPE); printf("\n"); // // scale image and copy to PNG array // if (type == 'z') { fmin = BIG; fmax = 0; for (x = 0; x < v.nx; ++x) { for (y = 0; y < v.ny; ++y) { if (image_array[y][x] > fmax) fmax = image_array[y][x]; if (image_array[y][x] < fmin) fmin = image_array[y][x]; } } if (arg == 1) { for (x = 0; x < v.nx; ++x) for (y = 0; y < v.ny; ++y) v.array[y][x] = 65536*(image_array[y][x]-fmin)/(fmax-fmin); } else { for (x = 0; x < v.nx; ++x) for (y = 0; y < v.ny; ++y) v.array[y][x] = 65536*pow((image_array[y][x]-fmin)/(fmax-fmin),arg); } } else if (type == 'h') { for (x = 0; x < v.nx; ++x) for (y = 0; y < v.ny; ++y) v.array[y][x] = 65536*image_array[y][x]/(v.nz-1.0); } // // write PNG // v.bit_depth = 16; fab_write_png_K(&v,argv[2]); // // exit // DGifCloseFile(GIFfile); exit(0); }
/****************************************************************************** * Interpret the command line and scan the given GIF file. * ******************************************************************************/ void main(int argc, char **argv) { int i, j, k, Error, NumFiles, Size, Row, Col, Width, Height, ExtCode, Count, ColorMapSize, GraphDriver, GraphMode, Sum, HelpFlag = FALSE, BGIPathFlag = FALSE, BGIUserDriverFlag = FALSE, ZoomFlag = FALSE; GifRecordType RecordType; GifByteType *Extension; char Str[80], *BGIUserDriverNameMode, **FileName = NULL; GifRowType *ScreenBuffer; GifFileType *GifFile; struct text_info TextInfo; /* So we can restore starting text mode. */ if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuitePrint, &BGIPathFlag, &BGIPath, &BGIUserDriverFlag, &BGIUserDriverNameMode, &ZoomFlag, &ZoomFactor, &BeepsDisabled, &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 (BGIUserDriverFlag) { /* Use the driver supplied by the user! */ BGIInstallUserDriver(BGIUserDriverNameMode); installuserdriver(BGIUserDriverName, detectVGA); GraphDriver = BGI_USER_INSTALL; } else { /* Sense type of display we have and attempt to load right driver. */ detectgraph(&GraphDriver, &GraphMode); if (GraphDriver < 0) GIF_EXIT("BGI Auto detect: No graphics device detected."); } /* Put in the following any graphic driver specific setup: */ switch (GraphDriver) { case CGA: GraphMode = CGAHI; break; case EGA: GraphMode = EGAHI; break; case EGA64: GraphMode = EGA64HI; break; case EGAMONO: GraphMode = EGAMONOHI; break; case HERCMONO: GraphMode = HERCMONOHI; break; case VGA: GraphMode = VGAHI; break; case BGI_USER_INSTALL: GraphDriver = DETECT; GraphMode = BGIUserDriverMode; break; default: GIF_EXIT("Requested graphic device is not supported."); break; } if (NumFiles == 1) { GifFileName = *FileName; if ((GifFile = DGifOpenFileName(*FileName)) == NULL) { PrintGifError(); exit(-1); } } else { /* Use the stdin instead: */ GifFileName = "Stdin"; setmode(0, O_BINARY); if ((GifFile = DGifOpenFileHandle(0)) == NULL) { PrintGifError(); exit(-1); } } /* Allocate the screen as vector of column of rows. We cannt allocate */ /* the all screen at once, as this broken minded CPU can allocate up to */ /* 64k at a time and our image can be bigger than that: */ /* Note this screen is device independent - its the screen as defined by */ /* the GIF file parameters itself. */ if ((ScreenBuffer = (GifRowType *) malloc(GifFile -> SHeight * sizeof(GifRowType *))) == NULL) GIF_EXIT("Failed to allocate memory required, aborted."); Size = GifFile -> SWidth * sizeof(GifPixelType);/* Size in bytes of one row.*/ if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */ GIF_EXIT("Failed to allocate memory required, aborted."); for (i = 0; i < GifFile -> SWidth; i++) /* Set its color to BackGround. */ ScreenBuffer[0][i] = GifFile -> SBackGroundColor; MaximumScreenHeight = GifFile -> SHeight - 1; for (i = 1; i < GifFile -> SHeight; i++) { /* Allocate the other rows, and set their color to background too: */ if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL) { if (i > 30) { /* Free some memory for the BGI driver and auxilary. */ for (j = 1; j < 28; j++) free((char *) ScreenBuffer[i - j]); MaximumScreenHeight = i - 28; fprintf(stderr, "\n%s: Failed to allocate all memory required, last line %d.\n", PROGRAM_NAME, MaximumScreenHeight); break; } else GIF_EXIT("Failed to allocate memory required, aborted."); } memcpy(ScreenBuffer[i], ScreenBuffer[0], Size); } /* Scan the content of the GIF file and load the image(s) in: */ do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { PrintGifError(); break; } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) { PrintGifError(); exit(-1); } Row = GifFile -> ITop; /* Image Position relative to Screen. */ Col = GifFile -> ILeft; Width = GifFile -> IWidth; Height = GifFile -> IHeight; GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ", PROGRAM_NAME, ++ImageNum, Col, Row, Width, Height); if (GifFile -> ILeft + GifFile -> IWidth > GifFile -> SWidth || GifFile -> ITop + GifFile -> IHeight > GifFile -> SHeight) { fprintf(stderr, "Image %d is not confined to screen dimension, aborted.\n"); exit(-2); } if (GifFile -> IInterlace) { /* Need to perform 4 passes on the images: */ for (Count = i = 0; i < 4; i++) for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) { GifQprintf("\b\b\b\b%-4d", Count++); if (DGifGetLine(GifFile, &ScreenBuffer[MIN(j, MaximumScreenHeight)][Col], Width) == GIF_ERROR) { PrintGifError(); exit(-1); } } } else { for (i = 0; i < Height; i++, Row++) { GifQprintf("\b\b\b\b%-4d", i); if (DGifGetLine(GifFile, &ScreenBuffer[MIN(Row, MaximumScreenHeight)][Col], Width) == GIF_ERROR) { PrintGifError(); MaximumScreenHeight = MIN(i - 1, MaximumScreenHeight); } } } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { PrintGifError(); exit(-1); } while (Extension != NULL) { if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { PrintGifError(); exit(-1); } } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); /* Lets display it - set the global variables required and do it: */ BackGround = GifFile -> SBackGroundColor; ColorMap = (GifFile -> IColorMap ? GifFile -> IColorMap : GifFile -> SColorMap); ColorMapSize = 1 << (GifFile -> IColorMap ? GifFile -> IBitsPerPixel : GifFile -> SBitsPerPixel); gettextinfo(&TextInfo); /* Save current mode so we can recover. */ initgraph(&GraphDriver, &GraphMode, BGIPath); if (graphresult() != grOk) /* Error occured during init. */ GIF_EXIT("Graphics System Error, failed to initialize driver."); if (getmaxcolor() + 1 < ColorMapSize) { sprintf(Str, "GIF Image color map (%d) is too big for device (%d).\n", ColorMapSize, getmaxcolor() + 1); closegraph(); GIF_EXIT(Str); } /* Initialize hardware pallete and also select fore/background color. */ BackGround = ForeGround = 1; Sum = ((int) ColorMap[1].Red) + ((int) ColorMap[1].Green) + ((int) ColorMap[1].Blue); j = k = Sum; for (i = 0; i < ColorMapSize; i++) { setrgbpalette(i, ColorMap[i].Red >> 2, ColorMap[i].Green >> 2, ColorMap[i].Blue >> 2); Sum = ((int) ColorMap[i].Red) + ((int) ColorMap[i].Green) + ((int) ColorMap[i].Blue); if (i != 0 && Sum > j) { /* Dont use color 0. */ ForeGround = i; j = Sum; } if (i != 0 && Sum <= k) { /* Dont use color 0. */ BackGround = i; k = Sum; } } DeviceMaxX = getmaxx(); /* Read size of physical screen. */ DeviceMaxY = getmaxy(); ScreenWidth = GifFile -> SWidth; ScreenHeight = MIN(GifFile -> SHeight, MaximumScreenHeight); Tone(500, 10); DisplayScreen(ScreenBuffer, GifFile); if (DGifCloseFile(GifFile) == GIF_ERROR) { PrintGifError(); closegraph(); exit(-1); } closegraph(); textmode(TextInfo.currmode); }
/****************************************************************************** * Perform the disassembly operation - take one input files into few output. * ******************************************************************************/ static int DoDisassemblyNum(const char *InFileName, char *OutFileName, int FileNum) { int ExtCode, CodeSize, FileEmpty; GifRecordType RecordType; char CrntFileName[80], *p; GifByteType *Extension, *CodeBlock; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; int ErrorCode; /* If name has type postfix, strip it out, and make sure name is less */ /* or equal to 6 chars, so we will have 2 chars in name for numbers. */ //strupr(OutFileName); /* Make sure all is upper case */ #if 0 printf("OutFileName : %s\n", OutFileName); if ((p = strrchr(OutFileName, '.')) != NULL && strlen(p) <= 4) p[0] = 0; if ((p = strrchr(OutFileName, '/')) != NULL || (p = strrchr(OutFileName, '\\')) != NULL || (p = strrchr(OutFileName, ':')) != NULL) { if (strlen(p) > 7) p[7] = 0; /* p includes the '/', '\\', ':' char */ } else { /* Only name is given for current directory: */ //if (strlen(OutFileName) > 6) OutFileName[6] = 0; } printf("OutFileName : %s\n", OutFileName); #endif /* Open input file: */ if (InFileName != NULL) { if ((GifFileIn = DGifOpenFileName(InFileName, &ErrorCode)) == NULL) return QuitGifError(GifFileIn, GifFileOut); } else { /* Use the stdin instead: */ if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) return QuitGifError(GifFileIn, GifFileOut); } /* Scan the content of GIF file and dump image(s) to seperate file(s): */ //sprintf(CrntFileName, "%s_%02d.gif", OutFileName, FileNum); sprintf(CrntFileName, "%s", OutFileName); if ((GifFileOut = EGifOpenFileName(CrntFileName, TRUE, &ErrorCode)) == NULL) return QuitGifError(GifFileIn, GifFileOut); FileEmpty = TRUE; /* And dump out its exactly same screen information: */ if (EGifPutScreenDesc(GifFileOut, GifFileIn->SWidth, GifFileIn->SHeight, GifFileIn->SColorResolution, GifFileIn->SBackGroundColor, GifFileIn->SColorMap) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: FileEmpty = FALSE; if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); /* Put same image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn->Image.Left, GifFileIn->Image.Top, GifFileIn->Image.Width, GifFileIn->Image.Height, GifFileIn->Image.Interlace, GifFileIn->Image.ColorMap) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont */ /* really care what is there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); break; case EXTENSION_RECORD_TYPE: FileEmpty = FALSE; /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, discard */ while (Extension != NULL) if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType */ break; } } while (RecordType != IMAGE_DESC_RECORD_TYPE && RecordType != TERMINATE_RECORD_TYPE); if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); if (FileEmpty) { /* Might happen on last file - delete it if so: */ unlink(CrntFileName); } if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR) return QuitGifError(GifFileIn, GifFileOut); }
CPLErr BIGGIFDataset::ReOpen() { /* -------------------------------------------------------------------- */ /* If the file is already open, close it so we can restart. */ /* -------------------------------------------------------------------- */ if( hGifFile != NULL ) GIFAbstractDataset::myDGifCloseFile( hGifFile ); /* -------------------------------------------------------------------- */ /* If we are actually reopening, then we assume that access to */ /* the image data is not strictly once through sequential, and */ /* we will try to create a working database in a temporary */ /* directory to hold the image as we read through it the second */ /* time. */ /* -------------------------------------------------------------------- */ if( hGifFile != NULL ) { GDALDriver *poGTiffDriver = (GDALDriver*) GDALGetDriverByName("GTiff"); if( poGTiffDriver != NULL ) { /* Create as a sparse file to avoid filling up the whole file */ /* while closing and then destroying this temporary dataset */ const char* apszOptions[] = { "COMPRESS=LZW", "SPARSE_OK=YES", NULL }; CPLString osTempFilename = CPLGenerateTempFilename("biggif"); osTempFilename += ".tif"; poWorkDS = poGTiffDriver->Create( osTempFilename, nRasterXSize, nRasterYSize, 1, GDT_Byte, const_cast<char**>(apszOptions)); } } /* -------------------------------------------------------------------- */ /* Open */ /* -------------------------------------------------------------------- */ VSIFSeekL( fp, 0, SEEK_SET ); nLastLineRead = -1; hGifFile = GIFAbstractDataset::myDGifOpen( fp, GIFAbstractDataset::ReadFunc ); if( hGifFile == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "DGifOpen() failed. Perhaps the gif file is corrupt?\n" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Find the first image record. */ /* -------------------------------------------------------------------- */ GifRecordType RecordType = FindFirstImage(hGifFile); if( RecordType != IMAGE_DESC_RECORD_TYPE ) { GIFAbstractDataset::myDGifCloseFile( hGifFile ); hGifFile = NULL; CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find image description record in GIF file." ); return CE_Failure; } if (DGifGetImageDesc(hGifFile) == GIF_ERROR) { GIFAbstractDataset::myDGifCloseFile( hGifFile ); hGifFile = NULL; CPLError( CE_Failure, CPLE_OpenFailed, "Image description reading failed in GIF file." ); return CE_Failure; } return CE_None; }
bool CxImageGIF::Decode(CxFile *fp) { if (fp == NULL) return false; GifFileType *GifFile = NULL; GifRecordType RecordType; GifByteType *Extension; GifColorType *ColorMap; int i, j, Count, Row, Col, Width, Height, ExtCode, ColorMapSize; static int InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */ InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */ try { GifFile = DGifOpen(fp, readCxFile); if (!Create(GifFile->SWidth,GifFile->SHeight,8,CXIMAGE_FORMAT_GIF)) throw "Can't allocate memory"; do { DGifGetRecordType(GifFile, &RecordType); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: DGifGetImageDesc(GifFile); Row = GifFile->Image.Top; /* Image Position relative to Screen. */ Col = GifFile->Image.Left; Width = GifFile->Image.Width; Height = GifFile->Image.Height; if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth || GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) throw "Image is not confined to screen dimension, aborted.\n"; if (GifFile->Image.Interlace) { /* Need to perform 4 passes on the images: */ for (Count = i = 0; i < 4; i++) for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) DGifGetLine(GifFile, GetBits(GifFile->SHeight - j - 1) + Col, Width); } else { for (i = 0; i < Height; i++) DGifGetLine(GifFile,GetBits(GifFile->SHeight - Row++ - 1) + Col,Width); } break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ DGifGetExtension(GifFile, &ExtCode, &Extension); while (Extension != NULL) DGifGetExtensionNext(GifFile, &Extension); break; default: break; } }while (RecordType != TERMINATE_RECORD_TYPE); ColorMap = (GifFile->Image.ColorMap ? GifFile->Image.ColorMap->Colors : GifFile->SColorMap->Colors); ColorMapSize = GifFile->Image.ColorMap ? GifFile->Image.ColorMap->ColorCount : GifFile->SColorMap->ColorCount; if(ColorMap && ColorMapSize) { RGBQUAD* ppal=GetPalette(); for (i=0; i < ColorMapSize; i++) { ppal[i].rgbRed = ColorMap[i].Red; ppal[i].rgbGreen = ColorMap[i].Green; ppal[i].rgbBlue = ColorMap[i].Blue; } head.biClrUsed = ColorMapSize; if(GifFile->SBackGroundColor) { info.nBkgndIndex = GifFile->SBackGroundColor; info.nBkgndColor.rgbRed = ColorMap[info.nBkgndIndex].Red; info.nBkgndColor.rgbGreen = ColorMap[info.nBkgndIndex].Green; info.nBkgndColor.rgbBlue = ColorMap[info.nBkgndIndex].Blue; } } DGifCloseFile(GifFile); GifFile = NULL; } catch (int errid) { strncpy(info.szLastError,GifGetErrorMessage(errid),255); if(GifFile != NULL) DGifCloseFile(GifFile); return false; } catch (char *message) { strncpy(info.szLastError,message,255); if(GifFile != NULL) DGifCloseFile(GifFile); return false; } return true; }
/****************************************************************************** This routine reads an entire GIF into core, hanging all its state info off the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() first to initialize I/O. Its inverse is EGifSpew(). *******************************************************************************/ int DGifSlurp(GifFileType *GifFile) { size_t ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; int ExtFunction; GifFile->ExtensionBlocks = NULL; GifFile->ExtensionBlockCount = 0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) return (GIF_ERROR); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) return (GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; /* Allocate memory for the image */ if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 && sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { return GIF_ERROR; } ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { return GIF_ERROR; } sp->RasterBits = (unsigned char *)malloc(ImageSize * sizeof(GifPixelType)); if (sp->RasterBits == NULL) { return GIF_ERROR; } if (sp->ImageDesc.Interlace) { int i, j; /* * The way an interlaced image should be read - * offsets and jumps... */ int InterlacedOffset[] = { 0, 4, 2, 1 }; int InterlacedJumps[] = { 8, 8, 4, 2 }; /* Need to perform 4 passes on the image */ for (i = 0; i < 4; i++) for (j = InterlacedOffset[i]; j < sp->ImageDesc.Height; j += InterlacedJumps[i]) { if (DGifGetLine(GifFile, sp->RasterBits+j*sp->ImageDesc.Width, sp->ImageDesc.Width) == GIF_ERROR) return GIF_ERROR; } } else { if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) return (GIF_ERROR); } if (GifFile->ExtensionBlocks) { sp->ExtensionBlocks = GifFile->ExtensionBlocks; sp->ExtensionBlockCount = GifFile->ExtensionBlockCount; GifFile->ExtensionBlocks = NULL; GifFile->ExtensionBlockCount = 0; } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR) return (GIF_ERROR); /* Create an extension block with our data */ if (ExtData != NULL) { if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks, ExtFunction, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); } while (ExtData != NULL) { if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); /* Continue the extension block */ if (ExtData != NULL) if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks, CONTINUE_EXT_FUNC_CODE, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); return (GIF_OK); }
/****************************************************************************** * Perform the assembly operation - take few input files into one output. * ******************************************************************************/ static void DoAssembly(int NumFiles, char **FileNames) { int i, ExtCode, CodeSize; GifRecordType RecordType; GifByteType *Extension, *CodeBlock; GifFileType *GifFileIn = NULL, *GifFileOut = NULL; /* Open stdout for the output file: */ if ((GifFileOut = EGifOpenFileHandle(1)) == NULL) QuitGifError(GifFileIn, GifFileOut); /* Scan the content of the GIF file and load the image(s) in: */ for (i = 0; i < NumFiles; i++) { if ((GifFileIn = DGifOpenFileName(FileNames[i])) == NULL) QuitGifError(GifFileIn, GifFileOut); /* And dump out screen descriptor iff its first image. */ if (i == 0) if (EGifPutScreenDesc(GifFileOut, GifFileIn -> SWidth, GifFileIn -> SHeight, GifFileIn -> SColorResolution, GifFileIn -> SBackGroundColor, GifFileIn -> SBitsPerPixel, GifFileIn -> SColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); do { if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Put image descriptor to out file: */ if (EGifPutImageDesc(GifFileOut, GifFileIn -> ILeft, GifFileIn -> ITop, GifFileIn -> IWidth, GifFileIn -> IHeight, GifFileIn -> IInterlace, GifFileIn -> IBitsPerPixel, GifFileIn -> IColorMap) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* Now read image itself in decoded form as we dont */ /* dont care what is there, and this is much faster. */ if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR || EGifPutCode(GifFileOut, CodeSize, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); while (CodeBlock != NULL) if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR || EGifPutCodeNext(GifFileOut, CodeBlock) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); break; case EXTENSION_RECORD_TYPE: /* Skip any extension blocks in file: */ if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); if (EGifPutExtension(GifFileOut, ExtCode, Extension[0], Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); /* No support to more than one extension blocks, discard.*/ while (Extension != NULL) if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); if (DGifCloseFile(GifFileIn) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); } if (EGifCloseFile(GifFileOut) == GIF_ERROR) QuitGifError(GifFileIn, GifFileOut); }