Exemple #1
0
/*!	\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;
}
Exemple #2
0
/*!	\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;
}
Exemple #3
0
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;
}
Exemple #4
0
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");
  }
}
Exemple #5
0
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;
}
Exemple #8
0
/*!	\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;
}
Exemple #9
0
/* 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 {
Exemple #10
0
static void gdPngReadData(png_structp png_ptr,
	png_bytep data, png_size_t length)
{
	gdGetBuf(data, length, (gdIOCtx *)
		png_get_io_ptr(png_ptr));
}
Exemple #11
0
/* 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.)
         */
      }
Exemple #12
0
/*!	\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;
}