/*! \brief Reads a TGA header. * Reads the header block from a binary TGA file populating the referenced TGA structure. * \param ctx Pointer to TGA binary file * \param tga Pointer to TGA structure * \return int 1 on sucess, -1 on failure */ int read_header_tga(gdIOCtx *ctx, oTga *tga) { unsigned char header[18]; if (gdGetBuf(header, sizeof(header), ctx) < 18) { fprintf(stderr, "fail to read header"); return -1; } tga->identsize = header[0]; tga->colormaptype = header[1]; tga->imagetype = header[2]; tga->colormapstart = header[3] + (header[4] << 8); tga->colormaplength = header[5] + (header[6] << 8); tga->colormapbits = header[7]; tga->xstart = header[8] + (header[9] << 8); tga->ystart = header[10] + (header[11] << 8); tga->width = header[12] + (header[13] << 8); tga->height = header[14] + (header[15] << 8); tga->bits = header[16]; tga->alphabits = header[17] & 0x0f; tga->fliph = (header[17] & 0x10) ? 1 : 0; tga->flipv = (header[17] & 0x20) ? 0 : 1; #if DEBUG printf("format bps: %i\n", tga->bits); printf("flip h/v: %i / %i\n", tga->fliph, tga->flipv); printf("alpha: %i\n", tga->alphabits); printf("wxh: %i %i\n", tga->width, tga->height); #endif switch(tga->bits) { case 8: case 16: case 24: case 32: break; default: fprintf(stderr, "bps %i not supported", tga->bits); return -1; break; } tga->ident = NULL; if (tga->identsize > 0) { tga->ident = (char *) gdMalloc(tga->identsize * sizeof(char)); if(tga->ident == NULL) { return -1; } gdGetBuf( &( tga->ident ), tga->identsize, ctx ); } return 1; }
/*! \brief Reads a TGA header. * Reads the header block from a binary TGA file populating the referenced TGA structure. * \param ctx Pointer to TGA binary file * \param tga Pointer to TGA structure * \return int 1 on sucess, -1 on failure */ int read_header_tga(gdIOCtx *ctx, oTga *tga) { unsigned char header[18]; if (gdGetBuf(header, sizeof(header), ctx) < 18) { gd_error("fail to read header"); return -1; } tga->identsize = header[0]; tga->colormaptype = header[1]; tga->imagetype = header[2]; tga->colormapstart = header[3] + (header[4] << 8); tga->colormaplength = header[5] + (header[6] << 8); tga->colormapbits = header[7]; tga->xstart = header[8] + (header[9] << 8); tga->ystart = header[10] + (header[11] << 8); tga->width = header[12] + (header[13] << 8); tga->height = header[14] + (header[15] << 8); tga->bits = header[16]; tga->alphabits = header[17] & 0x0f; tga->fliph = (header[17] & 0x10) ? 1 : 0; tga->flipv = (header[17] & 0x20) ? 0 : 1; #if DEBUG printf("format bps: %i\n", tga->bits); printf("flip h/v: %i / %i\n", tga->fliph, tga->flipv); printf("alpha: %i\n", tga->alphabits); printf("wxh: %i %i\n", tga->width, tga->height); #endif if (!((tga->bits == TGA_BPP_24 && tga->alphabits == 0) || (tga->bits == TGA_BPP_32 && tga->alphabits == 8))) { gd_error_ex(GD_WARNING, "gd-tga: %u bits per pixel with %u alpha bits not supported\n", tga->bits, tga->alphabits); return -1; } tga->ident = NULL; if (tga->identsize > 0) { tga->ident = (char *) gdMalloc(tga->identsize * sizeof(char)); if(tga->ident == NULL) { return -1; } gdGetBuf(tga->ident, tga->identsize, ctx); } return 1; }
static int _gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf * chunkLen, gdIOCtx * in) { int zerr; if (gdTell (in) != offset) { GD2_DBG (printf ("Positioning in file to %d\n", offset)); gdSeek (in, offset); } else { GD2_DBG (printf ("Already Positioned in file to %d\n", offset)); }; /* Read and uncompress an entire chunk. */ GD2_DBG (printf ("Reading file\n")); if (gdGetBuf (compBuf, compSize, in) != compSize) { return FALSE; }; GD2_DBG (printf ("Got %d bytes. Uncompressing into buffer of %d bytes\n", compSize, *chunkLen)); zerr = uncompress ((unsigned char *) chunkBuf, chunkLen, (unsigned char *) compBuf, compSize); if (zerr != Z_OK) { GD2_DBG (printf ("Error %d from uncompress\n", zerr)); return FALSE; }; GD2_DBG (printf ("Got chunk\n")); return TRUE; }
static void gdPngReadData (png_structp png_ptr, png_bytep data, png_size_t length) { int check; check = gdGetBuf(data, length, (gdIOCtx *) png_get_io_ptr(png_ptr)); if (check != length) { png_error(png_ptr, "Read Error: truncated data"); } }
safeboolean fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; /* 2.0.12: signed size. Thanks to Geert Jansen */ /* 2.0.14: some platforms (mingw-msys) don't have ssize_t. Call an int an int. */ int nbytes = 0; memset (src->buffer, 0, INPUT_BUF_SIZE); while (nbytes < INPUT_BUF_SIZE) { int got = gdGetBuf (src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile); if ((got == EOF) || (got == 0)) { /* EOF or error. If we got any data, don't worry about it. If we didn't, then this is unexpected. */ if (!nbytes) { nbytes = -1; } break; } nbytes += got; } if (nbytes <= 0) { if (src->start_of_file) /* Treat empty input file as fatal error */ ERREXIT (cinfo, JERR_INPUT_EMPTY); WARNMS (cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (unsigned char) 0xFF; src->buffer[1] = (unsigned char) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; src->start_of_file = FALSE; return TRUE; }
/** * int gdreadMRCHeader(gdIOCtx *io_ctx, MRCHeader *pMRCHeader) */ int gdreadMRCHeader(gdIOCtx *io_ctx, MRCHeader *pMRCHeader) { gdGetBuf(pMRCHeader, MRC_HEADER_SIZE, io_ctx); if( (pMRCHeader->nx < 0) || (pMRCHeader->ny < 0) || (pMRCHeader->nz < 0) || (pMRCHeader->mode < 0) || (pMRCHeader->mode > 4) || (pMRCHeader->x_length < 0) || (pMRCHeader->y_length < 0) || (pMRCHeader->z_length < 0) || (pMRCHeader->x_length > pMRCHeader->nx ) || (pMRCHeader->y_length > pMRCHeader->ny ) || (pMRCHeader->z_length > pMRCHeader->nz ) ) return -1; /* This is not a valid pMRCHeader header */ return 1 ; }
/** * int gdloadMRC(gdIOCtx *io_ctx, int in_length, MRC *pMRC) */ int gdloadMRC(gdIOCtx *io_ctx, int in_length, MRC *pMRC) { unsigned int uElementSize = 0; unsigned int uElements = 0; if (gdreadMRCHeader(io_ctx, &(pMRC->header))==-1) return -1; uElements = pMRC->header.nx * pMRC->header.ny * pMRC->header.nz; switch(pMRC->header.mode) { case MRC_MODE_BYTE: uElementSize = sizeof(char); break; case MRC_MODE_SHORT: uElementSize = sizeof(short); break; case MRC_MODE_UNSIGNED_SHORT: uElementSize = sizeof(short); break; case MRC_MODE_FLOAT: uElementSize = sizeof(float); break; case MRC_MODE_SHORT_COMPLEX: uElementSize = sizeof(short); uElements *= 2; break; case MRC_MODE_FLOAT_COMPLEX: uElementSize = sizeof(float); uElements *= 2; break; default: return -1; } if (in_length != (uElements*uElementSize+MRC_HEADER_SIZE)) return -1; if((pMRC->pbyData = malloc(uElements*uElementSize)) == NULL) pMRC->pbyData = malloc(uElements*uElementSize); if(!gdGetBuf(pMRC->pbyData, (uElements*uElementSize), io_ctx)) return -1; return 1; }
/*! \brief Reads a TGA image data into buffer. * Reads the image data block from a binary TGA file populating the referenced TGA structure. * \param ctx Pointer to TGA binary file * \param tga Pointer to TGA structure * \return int 0 on sucess, -1 on failure */ int read_image_tga( gdIOCtx *ctx, oTga *tga ) { int pixel_block_size = (tga->bits / 8); int image_block_size = (tga->width * tga->height) * pixel_block_size; uint8_t* decompression_buffer = NULL; unsigned char* conversion_buffer = NULL; int buffer_caret = 0; int bitmap_caret = 0; int i = 0; int encoded_pixels; if(overflow2(tga->width, tga->height)) { return -1; } if(overflow2(tga->width * tga->height, pixel_block_size)) { return -1; } if(overflow2(image_block_size, sizeof(int))) { return -1; } /*! \todo Add more image type support. */ if (tga->imagetype != TGA_TYPE_RGB && tga->imagetype != TGA_TYPE_RGB_RLE) return -1; /*! \brief Allocate memmory for image block * Allocate a chunk of memory for the image block to be passed into. */ tga->bitmap = (int *) gdMalloc(image_block_size * sizeof(int)); if (tga->bitmap == NULL) return -1; switch (tga->imagetype) { case TGA_TYPE_RGB: /*! \brief Read in uncompressed RGB TGA * Chunk load the pixel data from an uncompressed RGB type TGA. */ conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char)); if (conversion_buffer == NULL) { return -1; } if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) { gd_error("gd-tga: premature end of image data\n"); gdFree(conversion_buffer); return -1; } while (buffer_caret < image_block_size) { tga->bitmap[buffer_caret] = (int) conversion_buffer[buffer_caret]; buffer_caret++; } gdFree(conversion_buffer); break; case TGA_TYPE_RGB_RLE: /*! \brief Read in RLE compressed RGB TGA * Chunk load the pixel data from an RLE compressed RGB type TGA. */ decompression_buffer = (uint8_t*) gdMalloc(image_block_size * sizeof(uint8_t)); if (decompression_buffer == NULL) { return -1; } conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char)); if (conversion_buffer == NULL) { gd_error("gd-tga: premature end of image data\n"); gdFree( decompression_buffer ); return -1; } if (gdGetBuf(conversion_buffer, image_block_size, ctx) != image_block_size) { gdFree(conversion_buffer); gdFree(decompression_buffer); return -1; } buffer_caret = 0; while( buffer_caret < image_block_size) { decompression_buffer[buffer_caret] = (int)conversion_buffer[buffer_caret]; buffer_caret++; } buffer_caret = 0; while( bitmap_caret < image_block_size ) { if ((decompression_buffer[buffer_caret] & TGA_RLE_FLAG) == TGA_RLE_FLAG) { encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & ~TGA_RLE_FLAG ) + 1 ); buffer_caret++; if ((bitmap_caret + (encoded_pixels * pixel_block_size)) >= image_block_size) { gdFree( decompression_buffer ); gdFree( conversion_buffer ); return -1; } for (i = 0; i < encoded_pixels; i++) { memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, pixel_block_size); bitmap_caret += pixel_block_size; } buffer_caret += pixel_block_size; } else { encoded_pixels = decompression_buffer[ buffer_caret ] + 1; buffer_caret++; if ((bitmap_caret + (encoded_pixels * pixel_block_size)) >= image_block_size) { gdFree( decompression_buffer ); gdFree( conversion_buffer ); return -1; } memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size); bitmap_caret += (encoded_pixels * pixel_block_size); buffer_caret += (encoded_pixels * pixel_block_size); } } gdFree( decompression_buffer ); gdFree( conversion_buffer ); break; } return 1; }
/* This routine is based in part on the Chapter 13 demo code in "PNG: The * Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html). */ gdImagePtr gdImageCreateFromPngCtx(gdIOCtx *infile) { png_byte sig[8]; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height, rowbytes; int bit_depth, color_type, interlace_type; int num_palette, num_trans; png_colorp palette; png_color_16p trans_gray_rgb; png_bytep trans; png_bytep image_data = NULL; png_bytepp row_pointers = NULL; gdImagePtr im = NULL; int i, j, *open; volatile int transparent = -1; volatile int palette_allocated = FALSE; /* Make sure the signature can't match by dumb luck -- TBB */ /* GRR: isn't sizeof(infile) equal to the size of the pointer? */ memset(infile, 0, sizeof(infile)); /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ gdGetBuf(sig, 8, infile); if (!png_check_sig(sig, 8)) return NULL; /* bad signature */ #ifndef PNG_SETJMP_NOT_SUPPORTED png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct, gdPngErrorHandler, NULL); #else png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif if (png_ptr == NULL) { fprintf(stderr, "gd-png error: cannot allocate libpng main struct\n"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "gd-png error: cannot allocate libpng info struct\n"); png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every non-callback function that calls a * PNG-reading libpng function */ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp(gdPngJmpbufStruct.jmpbuf)) { fprintf(stderr, "gd-png error: setjmp returns error condition\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } #endif png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_set_read_fn(png_ptr, (void *)infile, gdPngReadData); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (bit_depth == 16) png_set_strip_16(png_ptr); else if (bit_depth < 8) png_set_packing(png_ptr); /* expand to 1 byte per pixel */ if (color_type & PNG_COLOR_MASK_ALPHA) { fprintf(stderr, "gd-png warning: alpha channel not supported\n"); png_set_strip_alpha(png_ptr); } switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); #ifdef DEBUG fprintf(stderr, "gd-png color_type is palette, colors: %d\n", num_palette); #endif /* DEBUG */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { int real_num_trans = 0, idx_first_trans = -1; int min_trans = 256, idx_min_trans = -1; png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); for (i = 0; i < num_trans; ++i) { if (trans[i] < 255) { ++real_num_trans; if (idx_first_trans < 0) idx_first_trans = i; if (trans[i] < min_trans) { min_trans = trans[i]; idx_min_trans = i; } } } if (real_num_trans > 0) { if (real_num_trans > 1 || trans[idx_first_trans] != 0) { fprintf(stderr, "gd-png warning: only single-color, " "100%% transparency supported\n"); transparent = idx_min_trans; } else { transparent = idx_first_trans; } } } break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: /* create a fake palette and check for single-shade transparency */ if ((palette = (png_colorp)gdMalloc(256*sizeof(png_color))) == NULL) { fprintf(stderr, "gd-png error: cannot allocate gray palette\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } palette_allocated = TRUE; if (bit_depth < 8) { num_palette = 1<<bit_depth; for (i = 0; i < 256; ++i) { j = (255*i)/(num_palette-1); palette[i].red = palette[i].green = palette[i].blue = j; } } else { num_palette = 256; for (i = 0; i < 256; ++i) { palette[i].red = palette[i].green = palette[i].blue = i; } } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb); if (bit_depth == 16) /* png_set_strip_16() not yet in effect */ transparent = trans_gray_rgb->gray >> 8; else transparent = trans_gray_rgb->gray; /* Note slight error in 16-bit case: up to 256 16-bit shades * may get mapped to a single 8-bit shade, and only one of them * is supposed to be transparent. IOW, both opaque pixels and * transparent pixels will be mapped into the transparent entry. * There is no particularly good way around this in the case * that all 256 8-bit shades are used, but one could write some * custom 16-bit code to handle the case where there are gdFree * palette entries. This error will be extremely rare in * general, though. (Quite possibly there is only one such * image in existence.) */ } break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: /* allocate a palette and check for single-shade transparency */ if ((palette = (png_colorp)gdMalloc(256*sizeof(png_color))) == NULL) { fprintf(stderr, "gd-png error: cannot allocate RGB palette\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } palette_allocated = TRUE; num_palette = 256; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb); if (bit_depth == 16) { /* png_set_strip_16() not yet active */ palette[0].red = trans_gray_rgb->red >> 8; palette[0].green = trans_gray_rgb->green >> 8; palette[0].blue = trans_gray_rgb->blue >> 8; } else {
static void gdPngReadData(png_structp png_ptr, png_bytep data, png_size_t length) { gdGetBuf(data, length, (gdIOCtx *) png_get_io_ptr(png_ptr)); }
/* This routine is based in part on the Chapter 13 demo code in "PNG: The * Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html). */ gdImagePtr gdImageCreateFromPngCtx (gdIOCtx * infile) { png_byte sig[8]; #ifdef PNG_SETJMP_SUPPORTED jmpbuf_wrapper jbw; #endif png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height, rowbytes, w, h; int bit_depth, color_type, interlace_type; int num_palette, num_trans; png_colorp palette; png_color_16p trans_gray_rgb; png_color_16p trans_color_rgb; png_bytep trans; volatile png_bytep image_data = NULL; volatile png_bytepp row_pointers = NULL; gdImagePtr im = NULL; int i, j, *open = NULL; volatile int transparent = -1; volatile int palette_allocated = FALSE; /* Make sure the signature can't match by dumb luck -- TBB */ /* GRR: isn't sizeof(infile) equal to the size of the pointer? */ memset (sig, 0, sizeof(sig)); /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ if (gdGetBuf(sig, 8, infile) < 8) { return NULL; } if (png_sig_cmp(sig, 0, 8) != 0) { /* bad signature */ return NULL; } #ifdef PNG_SETJMP_SUPPORTED png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, &jbw, gdPngErrorHandler, NULL); #else png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif if (png_ptr == NULL) { php_gd_error("gd-png error: cannot allocate libpng main struct"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { php_gd_error("gd-png error: cannot allocate libpng info struct"); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every non-callback function that calls a * PNG-reading libpng function */ #ifdef PNG_SETJMP_SUPPORTED if (setjmp(jbw.jmpbuf)) { php_gd_error("gd-png error: setjmp returns error condition"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } #endif png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_set_read_fn(png_ptr, (void *) infile, gdPngReadData); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA) || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { im = gdImageCreateTrueColor((int) width, (int) height); } else { im = gdImageCreate((int) width, (int) height); } if (im == NULL) { php_gd_error("gd-png error: cannot allocate gdImage struct"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } if (bit_depth == 16) { png_set_strip_16(png_ptr); } else if (bit_depth < 8) { png_set_packing (png_ptr); /* expand to 1 byte per pixel */ } /* setjmp() must be called in every non-callback function that calls a * PNG-reading libpng function */ #ifdef PNG_SETJMP_SUPPORTED if (setjmp(jbw.jmpbuf)) { php_gd_error("gd-png error: setjmp returns error condition"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); gdFree(image_data); gdFree(row_pointers); if (im) { gdImageDestroy(im); } return NULL; } #endif switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { /* gd 2.0: we support this rather thoroughly now. Grab the * first fully transparent entry, if any, as the value of * the simple-transparency index, mostly for backwards * binary compatibility. The alpha channel is where it's * really at these days. */ int firstZero = 1; png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); for (i = 0; i < num_trans; ++i) { im->alpha[i] = gdAlphaMax - (trans[i] >> 1); if ((trans[i] == 0) && (firstZero)) { transparent = i; firstZero = 0; } } } break; case PNG_COLOR_TYPE_GRAY: /* create a fake palette and check for single-shade transparency */ if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) { php_gd_error("gd-png error: cannot allocate gray palette"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } palette_allocated = TRUE; if (bit_depth < 8) { num_palette = 1 << bit_depth; for (i = 0; i < 256; ++i) { j = (255 * i) / (num_palette - 1); palette[i].red = palette[i].green = palette[i].blue = j; } } else { num_palette = 256; for (i = 0; i < 256; ++i) { palette[i].red = palette[i].green = palette[i].blue = i; } } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb); if (bit_depth == 16) { /* png_set_strip_16() not yet in effect */ transparent = trans_gray_rgb->gray >> 8; } else { transparent = trans_gray_rgb->gray; } /* Note slight error in 16-bit case: up to 256 16-bit shades * may get mapped to a single 8-bit shade, and only one of them * is supposed to be transparent. IOW, both opaque pixels and * transparent pixels will be mapped into the transparent entry. * There is no particularly good way around this in the case * that all 256 8-bit shades are used, but one could write some * custom 16-bit code to handle the case where there are gdFree * palette entries. This error will be extremely rare in * general, though. (Quite possibly there is only one such * image in existence.) */ }
/*! \brief Reads a TGA image data into buffer. * Reads the image data block from a binary TGA file populating the referenced TGA structure. * \param ctx Pointer to TGA binary file * \param tga Pointer to TGA structure * \return int 0 on sucess, -1 on failure */ int read_image_tga( gdIOCtx *ctx, oTga *tga ) { int pixel_block_size = (tga->bits / 8); int image_block_size = (tga->width * tga->height) * pixel_block_size; byte* decompression_buffer = NULL; unsigned char* conversion_buffer = NULL; int buffer_caret = 0; int bitmap_caret = 0; int i = 0; int j = 0; byte encoded_pixels; if(overflow2(tga->width, tga->height)) { return -1; } if(overflow2(tga->width * tga->height, pixel_block_size)) { return -1; } if(overflow2(image_block_size, sizeof(byte))) { return -1; } /*! \brief Allocate memmory for image block * Allocate a chunk of memory for the image block to be passed into. */ tga->bitmap = (int *) gdMalloc(image_block_size * sizeof(byte)); if (tga->bitmap == NULL) { return -1; } /*! \todo Add image type support * Add support for this image type. */ if (tga->imagetype == TGA_TYPE_INDEXED) { return -1; } /*! \todo Add image type support * Add support for this image type. */ if (tga->imagetype == TGA_TYPE_INDEXED_RLE) { return -1; } /*! \brief Read in uncompressed RGB TGA * Chunk load the pixel data from an uncompressed RGB type TGA. */ if (tga->imagetype == TGA_TYPE_RGB) { conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char)); if (conversion_buffer == NULL) { gdFree(conversion_buffer); return -1; } gdGetBuf(conversion_buffer, image_block_size, ctx); while (buffer_caret < image_block_size) { tga->bitmap[buffer_caret] = (int) conversion_buffer[buffer_caret]; buffer_caret++; } gdFree( conversion_buffer ); } /*! \brief Read in RLE compressed RGB TGA * Chunk load the pixel data from an RLE compressed RGB type TGA. */ if (tga->imagetype == TGA_TYPE_RGB_RLE) { decompression_buffer = (byte*) gdMalloc(image_block_size * sizeof(byte)); if (decompression_buffer == NULL) { gdFree( decompression_buffer ); return -1; } conversion_buffer = (unsigned char *) gdMalloc(image_block_size * sizeof(unsigned char)); if (conversion_buffer == NULL) { gdFree( decompression_buffer ); gdFree( conversion_buffer ); return -1; } gdGetBuf( conversion_buffer, image_block_size, ctx ); buffer_caret = 0; while( buffer_caret < image_block_size ) { decompression_buffer[buffer_caret] = (int)conversion_buffer[buffer_caret]; buffer_caret++; } buffer_caret = 0; while( bitmap_caret < image_block_size ) { if ((decompression_buffer[buffer_caret] & TGA_RLE_FLAG) == TGA_RLE_FLAG) { encoded_pixels = ( ( decompression_buffer[ buffer_caret ] & 127 ) + 1 ); buffer_caret++; for (i = 0; i < encoded_pixels; i++) { for (j = 0; j < pixel_block_size; j++, bitmap_caret++) { tga->bitmap[ bitmap_caret ] = decompression_buffer[ buffer_caret + j ]; } } buffer_caret += pixel_block_size; } else { encoded_pixels = decompression_buffer[ buffer_caret ] + 1; buffer_caret++; for (i = 0; i < encoded_pixels; i++) { for( j = 0; j < pixel_block_size; j++, bitmap_caret++ ) { tga->bitmap[ bitmap_caret ] = decompression_buffer[ buffer_caret + j ]; } buffer_caret += pixel_block_size; } } } gdFree( decompression_buffer ); gdFree( conversion_buffer ); } /*! \todo Add image type support * Add support for this image type. */ if( tga->imagetype == TGA_TYPE_GREYSCALE ) { return -1; } /*! \todo Add image type support * Add support for this image type. */ if( tga->imagetype == TGA_TYPE_GREYSCALE_RLE ) { return -1; } return 0; }