From 289761adddd30fc486b2db2e3fae00eacdfc1e3a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 4 Feb 2006 22:26:04 +0000 Subject: [PATCH] If there's an error loading an image, seek back to the start of the image. --- IMG_bmp.c | 3 +++ IMG_gif.c | 8 +++++++- IMG_jpg.c | 15 ++++++++++----- IMG_lbm.c | 10 ++++++++-- IMG_pcx.c | 10 ++++++++-- IMG_png.c | 29 +++++++++++++++++++++-------- IMG_pnm.c | 9 +++++++-- IMG_tga.c | 30 +++++++++++++++++++----------- IMG_tif.c | 15 ++++++++++++--- IMG_xcf.c | 28 +++++++++++++++++----------- IMG_xpm.c | 10 ++++++++-- IMG_xxx.c | 21 ++++++++++++++++++++- 12 files changed, 140 insertions(+), 48 deletions(-) diff --git a/IMG_bmp.c b/IMG_bmp.c index e70a532b..e5892b91 100644 --- a/IMG_bmp.c +++ b/IMG_bmp.c @@ -422,6 +422,9 @@ static SDL_Surface *LoadBMP_RW (SDL_RWops *src, int freesrc) } done: if ( was_error ) { + if ( src ) { + SDL_RWseek(src, fp_offset, SEEK_SET); + } if ( surface ) { SDL_FreeSurface(surface); } diff --git a/IMG_gif.c b/IMG_gif.c index 5e30b6cf..8bceb4f4 100644 --- a/IMG_gif.c +++ b/IMG_gif.c @@ -151,6 +151,7 @@ static Image *ReadImage(SDL_RWops * src, int len, int height, int, Image * IMG_LoadGIF_RW(SDL_RWops *src) { + int start; unsigned char buf[16]; unsigned char c; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; @@ -163,8 +164,10 @@ IMG_LoadGIF_RW(SDL_RWops *src) Image *image = NULL; if ( src == NULL ) { - goto done; + return NULL; } + start = SDL_RWtell(src); + if (!ReadOK(src, buf, 6)) { RWSetMsg("error reading magic number"); goto done; @@ -262,6 +265,9 @@ IMG_LoadGIF_RW(SDL_RWops *src) #endif done: + if ( image == NULL ) { + SDL_RWseek(src, start, SEEK_SET); + } return image; } diff --git a/IMG_jpg.c b/IMG_jpg.c index 4916ac53..80325b71 100644 --- a/IMG_jpg.c +++ b/IMG_jpg.c @@ -202,6 +202,7 @@ static void output_no_message(j_common_ptr cinfo) /* Load a JPEG type image from an SDL datasource */ SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) { + int start; struct jpeg_decompress_struct cinfo; JSAMPROW rowptr[1]; SDL_Surface *volatile surface = NULL; @@ -211,6 +212,7 @@ SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); /* Create a decompression structure and load the JPEG header */ cinfo.err = jpeg_std_error(&jerr.errmgr); @@ -219,8 +221,11 @@ SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) if(setjmp(jerr.escape)) { /* If we get here, libjpeg found an error */ jpeg_destroy_decompress(&cinfo); + if ( surface != NULL ) { + SDL_FreeSurface(surface); + } + SDL_RWseek(src, start, SEEK_SET); IMG_SetError("JPEG loading error"); - SDL_FreeSurface(surface); return NULL; } @@ -249,8 +254,10 @@ SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) #endif 0); if ( surface == NULL ) { + jpeg_destroy_decompress(&cinfo); + SDL_RWseek(src, start, SEEK_SET); IMG_SetError("Out of memory"); - goto done; + return NULL; } /* Decompress the image */ @@ -261,10 +268,8 @@ SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src) jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1); } jpeg_finish_decompress(&cinfo); - - /* Clean up and return */ -done: jpeg_destroy_decompress(&cinfo); + return(surface); } diff --git a/IMG_lbm.c b/IMG_lbm.c index 578f6c7c..3a710460 100644 --- a/IMG_lbm.c +++ b/IMG_lbm.c @@ -84,6 +84,7 @@ int IMG_isLBM( SDL_RWops *src ) SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src ) { + int start; SDL_Surface *Image; Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk; Uint32 size, bytesloaded, nbcolors; @@ -102,6 +103,8 @@ SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src ) /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); + if ( !SDL_RWread( src, id, 4, 1 ) ) { error="error reading IFF chunk"; @@ -469,9 +472,12 @@ SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src ) if ( error ) { + SDL_RWseek(src, start, SEEK_SET); + if ( Image ) { + SDL_FreeSurface( Image ); + Image = NULL; + } IMG_SetError( error ); - SDL_FreeSurface( Image ); - Image = NULL; } return( Image ); diff --git a/IMG_pcx.c b/IMG_pcx.c index 52ba3d4c..25b7bc95 100644 --- a/IMG_pcx.c +++ b/IMG_pcx.c @@ -87,6 +87,7 @@ int IMG_isPCX(SDL_RWops *src) /* Load a PCX type image from an SDL datasource */ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) { + int start; struct PCXheader pcxh; Uint32 Rmask; Uint32 Gmask; @@ -103,6 +104,8 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); + if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) { error = "file truncated"; goto done; @@ -235,9 +238,12 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) done: free(buf); if ( error ) { - SDL_FreeSurface(surface); + SDL_RWseek(src, start, SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } IMG_SetError(error); - surface = NULL; } return(surface); } diff --git a/IMG_png.c b/IMG_png.c index ed763ceb..ab81fba1 100644 --- a/IMG_png.c +++ b/IMG_png.c @@ -99,6 +99,8 @@ static void png_read_data(png_structp ctx, png_bytep area, png_size_t size) } SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) { + int start; + const char *error; SDL_Surface *volatile surface; png_structp png_ptr; png_infop info_ptr; @@ -118,22 +120,24 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); /* Initialize the data we will clean up when we're done */ + error = NULL; png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL; /* Create the PNG loading context structure */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (png_ptr == NULL){ - IMG_SetError("Couldn't allocate memory for PNG file or incompatible PNG dll"); + error = "Couldn't allocate memory for PNG file or incompatible PNG dll"; goto done; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { - IMG_SetError("Couldn't create image information for PNG file"); + error = "Couldn't create image information for PNG file"; goto done; } @@ -142,7 +146,7 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) * set up your own error handlers in png_create_read_struct() earlier. */ if ( setjmp(png_ptr->jmpbuf) ) { - IMG_SetError("Error reading the PNG file."); + error = "Error reading the PNG file."; goto done; } @@ -222,7 +226,7 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, bit_depth*info_ptr->channels, Rmask,Gmask,Bmask,Amask); if ( surface == NULL ) { - IMG_SetError("Out of memory"); + error = "Out of memory"; goto done; } @@ -239,9 +243,7 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) /* Create the array of pointers to image data */ row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height); if ( (row_pointers == NULL) ) { - IMG_SetError("Out of memory"); - SDL_FreeSurface(surface); - surface = NULL; + error = "Out of memory"; goto done; } for (row = 0; row < (int)height; row++) { @@ -281,11 +283,22 @@ SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) } done: /* Clean up and return */ - png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : (png_infopp)0, + if ( png_ptr ) { + png_destroy_read_struct(&png_ptr, + info_ptr ? &info_ptr : (png_infopp)0, (png_infopp)0); + } if ( row_pointers ) { free(row_pointers); } + if ( error ) { + SDL_RWseek(src, start, SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } return(surface); } diff --git a/IMG_pnm.c b/IMG_pnm.c index bcef664c..671eb252 100644 --- a/IMG_pnm.c +++ b/IMG_pnm.c @@ -105,6 +105,7 @@ static int ReadNumber(SDL_RWops *src) SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) { + int start; SDL_Surface *surface = NULL; int width, height; int maxval, y, bpl; @@ -121,6 +122,7 @@ SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); SDL_RWread(src, magic, 2, 1); kind = magic[1] - '1'; @@ -229,9 +231,12 @@ SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) done: free(buf); if(error) { - SDL_FreeSurface(surface); + SDL_RWseek(src, start, SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } IMG_SetError(error); - surface = NULL; } return(surface); } diff --git a/IMG_tga.c b/IMG_tga.c index 6481bccb..b83b2ee1 100644 --- a/IMG_tga.c +++ b/IMG_tga.c @@ -87,6 +87,7 @@ enum tga_type { SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) { int start; + const char *error = NULL; struct TGAheader hdr; int rle = 0; int alpha = 0; @@ -94,7 +95,7 @@ SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) int grey = 0; int ckey = -1; int ncols, w, h; - SDL_Surface *img; + SDL_Surface *img = NULL; Uint32 rmask, gmask, bmask, amask; Uint8 *dst; int i; @@ -107,10 +108,12 @@ SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) /* The error message has been set in SDL_RWFromFile */ return NULL; } - start = SDL_RWtell(src); - if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) + + if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) { + error = "Error reading TGA data"; goto error; + } ncols = LE16(hdr.cmap_len); switch(hdr.type) { case TGA_TYPE_RLE_INDEXED: @@ -118,7 +121,7 @@ SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) /* fallthrough */ case TGA_TYPE_INDEXED: if(!hdr.has_cmap || hdr.pixel_bits != 8 || ncols > 256) - goto error; + goto unsupported; indexed = 1; break; @@ -134,7 +137,7 @@ SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) /* fallthrough */ case TGA_TYPE_BW: if(hdr.pixel_bits != 8) - goto error; + goto unsupported; /* Treat greyscale as 8bpp indexed images */ indexed = grey = 1; break; @@ -195,6 +198,10 @@ SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp * 8, rmask, gmask, bmask, amask); + if(img == NULL) { + error = "Out of memory"; + goto error; + } if(hdr.has_cmap) { int palsiz = ncols * ((hdr.cmap_bits + 7) >> 3); @@ -303,14 +310,15 @@ SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src) } return img; -error: - SDL_RWseek(src, start, SEEK_SET); - IMG_SetError("Error reading TGA data"); - return NULL; - unsupported: + error = "Unsupported TGA format"; + +error: SDL_RWseek(src, start, SEEK_SET); - IMG_SetError("unsupported TGA format"); + if ( img ) { + SDL_FreeSurface(img); + } + IMG_SetError(error); return NULL; } diff --git a/IMG_tif.c b/IMG_tif.c index a4f58d79..b12a86a5 100644 --- a/IMG_tif.c +++ b/IMG_tif.c @@ -109,6 +109,7 @@ int IMG_isTIF(SDL_RWops* src) SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src) { + int start; TIFF* tiff; SDL_Surface* surface = NULL; Uint32 img_width, img_height; @@ -120,12 +121,13 @@ SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src) /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); /* turn off memory mapped access with the m flag */ tiff = TIFFClientOpen("SDL_image", "rm", (thandle_t)src, tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, NULL, NULL); if(!tiff) - return NULL; + goto error; /* Retrieve the dimensions of the image from the TIFF tags */ TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width); @@ -138,10 +140,10 @@ SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src) surface = SDL_AllocSurface(SDL_SWSURFACE, img_width, img_height, 32, Rmask, Gmask, Bmask, Amask); if(!surface) - return NULL; + goto error; if(!TIFFReadRGBAImage(tiff, img_width, img_height, surface->pixels, 0)) - return NULL; + goto error; /* libtiff loads the image upside-down, flip it back */ half = img_height / 2; @@ -160,6 +162,13 @@ SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src) TIFFClose(tiff); return surface; + +error: + SDL_RWseek(src, start, SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + } + return NULL; } #else diff --git a/IMG_xcf.c b/IMG_xcf.c index 73433bc9..2adc8202 100644 --- a/IMG_xcf.c +++ b/IMG_xcf.c @@ -671,12 +671,15 @@ int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, return 0; } -SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { +SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) +{ + int start; + const char *error = NULL; SDL_Surface *surface, *lays; xcf_header * head; xcf_layer * layer; xcf_channel ** channel; - int read_error, chnls, i, offsets; + int chnls, i, offsets; Uint32 offset, fp; unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int); @@ -685,10 +688,10 @@ SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { /* The error message has been set in SDL_RWFromFile */ return NULL; } + start = SDL_RWtell(src); /* Initialize the data we will clean up when we're done */ surface = NULL; - read_error = 0; head = read_xcf_header (src); @@ -710,7 +713,7 @@ SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); if ( surface == NULL ) { - IMG_SetError("Out of memory"); + error = "Out of memory"; goto done; } @@ -728,7 +731,7 @@ SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); if ( lays == NULL ) { - IMG_SetError("Out of memory"); + error = "Out of memory"; goto done; } @@ -775,7 +778,7 @@ SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { 0x00FF0000,0x0000FF00,0x000000FF,0xFF000000); if (chs == NULL) { - IMG_SetError("Out of memory"); + error = "Out of memory"; goto done; } for (i = 0; i < chnls; i++) { @@ -790,12 +793,15 @@ SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src) { SDL_FreeSurface (chs); } - done: +done: free_xcf_header (head); - if ( read_error ) { - SDL_FreeSurface(surface); - IMG_SetError("Error reading XCF data"); - surface = NULL; + if ( error ) { + SDL_RWseek(src, start, SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); } return(surface); diff --git a/IMG_xpm.c b/IMG_xpm.c index 79a3c8f0..f7cd1ec7 100644 --- a/IMG_xpm.c +++ b/IMG_xpm.c @@ -310,6 +310,7 @@ do { \ /* read XPM from either array or RWops */ static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) { + int start; SDL_Surface *image = NULL; int index; int x, y; @@ -327,6 +328,8 @@ static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) linebuf = NULL; buflen = 0; + start = SDL_RWtell(src); + if(xpm) xpmlines = &xpm; @@ -452,8 +455,11 @@ static SDL_Surface *load_xpm(char **xpm, SDL_RWops *src) done: if(error) { - SDL_FreeSurface(image); - image = NULL; + SDL_RWseek(src, start, SEEK_SET); + if ( image ) { + SDL_FreeSurface(image); + image = NULL; + } IMG_SetError(error); } free(keystrings); diff --git a/IMG_xxx.c b/IMG_xxx.c index 590af52b..38f82f52 100644 --- a/IMG_xxx.c +++ b/IMG_xxx.c @@ -38,6 +38,9 @@ int IMG_isXXX(SDL_RWops *src) start = SDL_RWtell(src); is_XXX = 0; + + /* Detect the image here */ + SDL_RWseek(src, start, SEEK_SET); return(is_XXX); } @@ -45,11 +48,27 @@ int IMG_isXXX(SDL_RWops *src) /* Load a XXX type image from an SDL datasource */ SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src) { + int start; + const char *error = NULL; + SDL_Surface *surface = NULL; + if ( !src ) { /* The error message has been set in SDL_RWFromFile */ return NULL; } - return(NULL); + start = SDL_RWtell(src); + + /* Load the image here */ + + if ( error ) { + SDL_RWseek(src, start, SEEK_SET); + if ( surface ) { + SDL_FreeSurface(surface); + surface = NULL; + } + IMG_SetError(error); + } + return surface; } #else