mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Support TGA reading
We add PHP bindings for libgd's features to read TGA files, which are available as of libgd 2.1.0. As PHP's bundled libgd doesn't yet include the respective features of the external libgd, we add these. Since TGA has no easily recognizable file signature, we don't add TGA support for imagecreatefromstring() or getimagesize() and friends.
This commit is contained in:
parent
2b4fc9eb9c
commit
81fd113506
3
NEWS
3
NEWS
@ -12,6 +12,9 @@ PHP NEWS
|
||||
- Date:
|
||||
. Fixed #69044 (discrepency between time and microtime). (krakjoe)
|
||||
|
||||
- GD:
|
||||
. Added TGA read support. (cmb)
|
||||
|
||||
- Opcache:
|
||||
. Fixed bug #78106 (Path resolution fails if opcache disabled during request).
|
||||
(Nikita)
|
||||
|
@ -354,6 +354,12 @@ PHP 7.4 UPGRADE NOTES
|
||||
exception that it ignores overloaded array casts, such as used by
|
||||
ArrayObject.
|
||||
|
||||
- GD:
|
||||
. Added imagecreatefromtga() function, which allows to read images in TGA
|
||||
format. TGA support is now also indicated by gd_info() and imagetypes().
|
||||
Note that TGA images are not recognized by imagecreatefromstring() and
|
||||
getimagesize().
|
||||
|
||||
- OpenSSL:
|
||||
. Added openssl_x509_verify(mixed cert, mixed key) function that verifies the
|
||||
signature of the certificate using a public key. A wrapper around the
|
||||
|
@ -126,6 +126,7 @@ AC_DEFUN([PHP_GD_CHECK_VERSION],[
|
||||
PHP_CHECK_LIBRARY(gd, gdImageCreateFromJpeg, [AC_DEFINE(HAVE_GD_JPG, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
|
||||
PHP_CHECK_LIBRARY(gd, gdImageCreateFromXpm, [AC_DEFINE(HAVE_GD_XPM, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
|
||||
PHP_CHECK_LIBRARY(gd, gdImageCreateFromBmp, [AC_DEFINE(HAVE_GD_BMP, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
|
||||
PHP_CHECK_LIBRARY(gd, gdImageCreateFromTga, [AC_DEFINE(HAVE_GD_TGA, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
|
||||
PHP_CHECK_LIBRARY(gd, gdImageStringFT, [AC_DEFINE(HAVE_GD_FREETYPE, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
|
||||
PHP_CHECK_LIBRARY(gd, gdVersionString, [AC_DEFINE(HAVE_GD_LIBVERSION, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
|
||||
])
|
||||
@ -146,7 +147,7 @@ if test "$PHP_GD" != "no"; then
|
||||
libgd/gd_topal.c libgd/gd_gif_in.c libgd/gd_xbm.c libgd/gd_gif_out.c libgd/gd_security.c \
|
||||
libgd/gd_filter.c libgd/gd_pixelate.c libgd/gd_rotate.c libgd/gd_color_match.c \
|
||||
libgd/gd_transform.c libgd/gd_crop.c libgd/gd_interpolation.c libgd/gd_matrix.c \
|
||||
libgd/gd_bmp.c"
|
||||
libgd/gd_bmp.c libgd/gd_tga.c"
|
||||
|
||||
dnl check for fabsf and floorf which are available since C99
|
||||
AC_CHECK_FUNCS(fabsf floorf)
|
||||
@ -155,6 +156,7 @@ dnl These are always available with bundled library
|
||||
AC_DEFINE(HAVE_GD_BUNDLED, 1, [ ])
|
||||
AC_DEFINE(HAVE_GD_PNG, 1, [ ])
|
||||
AC_DEFINE(HAVE_GD_BMP, 1, [ ])
|
||||
AC_DEFINE(HAVE_GD_TGA, 1, [ ])
|
||||
|
||||
dnl Various checks for GD features
|
||||
PHP_GD_ZLIB
|
||||
|
@ -40,7 +40,7 @@ if (PHP_GD != "no") {
|
||||
gd_io_file.c gd_io_ss.c gd_jpeg.c gdkanji.c gd_png.c gd_ss.c \
|
||||
gdtables.c gd_topal.c gd_wbmp.c gdxpm.c wbmp.c gd_xbm.c gd_security.c gd_transform.c \
|
||||
gd_filter.c gd_pixelate.c gd_rotate.c gd_color_match.c gd_webp.c \
|
||||
gd_crop.c gd_interpolation.c gd_matrix.c gd_bmp.c", "gd");
|
||||
gd_crop.c gd_interpolation.c gd_matrix.c gd_bmp.c gd_tga.c", "gd");
|
||||
AC_DEFINE('HAVE_LIBGD', 1, 'GD support');
|
||||
ADD_FLAG("CFLAGS_GD", " \
|
||||
/D HAVE_GD_DYNAMIC_CTX_EX=1 \
|
||||
@ -63,6 +63,7 @@ if (PHP_GD != "no") {
|
||||
/D HAVE_GD_XPM \
|
||||
/D HAVE_GD_FREETYPE=1 \
|
||||
/D HAVE_GD_BMP \
|
||||
/D HAVE_GD_TGA \
|
||||
/D HAVE_LIBGD13=1 \
|
||||
/D HAVE_LIBGD15=1 \
|
||||
/D HAVE_LIBGD20=1 \
|
||||
|
31
ext/gd/gd.c
31
ext/gd/gd.c
@ -356,6 +356,12 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefrombmp, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GD_TGA)
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromtga, 0)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_imagexbm, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, im)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
@ -942,6 +948,9 @@ static const zend_function_entry gd_functions[] = {
|
||||
#ifdef HAVE_GD_BMP
|
||||
PHP_FE(imagecreatefrombmp, arginfo_imagecreatefrombmp)
|
||||
#endif
|
||||
#ifdef HAVE_GD_TGA
|
||||
PHP_FE(imagecreatefromtga, arginfo_imagecreatefromtga)
|
||||
#endif
|
||||
#ifdef HAVE_GD_PNG
|
||||
PHP_FE(imagepng, arginfo_imagepng)
|
||||
#endif
|
||||
@ -1109,6 +1118,7 @@ PHP_MINIT_FUNCTION(gd)
|
||||
REGISTER_LONG_CONSTANT("IMG_XPM", PHP_IMG_XPM, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMG_WEBP", PHP_IMG_WEBP, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMG_BMP", PHP_IMG_BMP, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("IMG_TGA", PHP_IMG_TGA, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
/* special colours for gd */
|
||||
REGISTER_LONG_CONSTANT("IMG_COLOR_TILED", gdTiled, CONST_CS | CONST_PERSISTENT);
|
||||
@ -1316,6 +1326,9 @@ PHP_MINFO_FUNCTION(gd)
|
||||
#endif
|
||||
#ifdef HAVE_GD_BMP
|
||||
php_info_print_table_row(2, "BMP Support", "enabled");
|
||||
#endif
|
||||
#ifdef HAVE_GD_TGA
|
||||
php_info_print_table_row(2, "TGA Read Support", "enabled");
|
||||
#endif
|
||||
php_info_print_table_end();
|
||||
DISPLAY_INI_ENTRIES();
|
||||
@ -1373,6 +1386,11 @@ PHP_FUNCTION(gd_info)
|
||||
#else
|
||||
add_assoc_bool(return_value, "BMP Support", 0);
|
||||
#endif
|
||||
#ifdef HAVE_GD_TGA
|
||||
add_assoc_bool(return_value, "TGA Read Support", 1);
|
||||
#else
|
||||
add_assoc_bool(return_value, "TGA Read Support", 0);
|
||||
#endif
|
||||
#if defined(USE_GD_JISX0208)
|
||||
add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 1);
|
||||
#else
|
||||
@ -2203,6 +2221,9 @@ PHP_FUNCTION(imagetypes)
|
||||
#ifdef HAVE_GD_BMP
|
||||
ret |= PHP_IMG_BMP;
|
||||
#endif
|
||||
#ifdef HAVE_GD_TGA
|
||||
ret |= PHP_IMG_TGA;
|
||||
#endif
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
@ -2599,6 +2620,16 @@ PHP_FUNCTION(imagecreatefrombmp)
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GD_TGA)
|
||||
/* {{{ proto resource imagecreatefromtga(string filename)
|
||||
Create a new image from TGA file or URL */
|
||||
PHP_FUNCTION(imagecreatefromtga)
|
||||
{
|
||||
_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_TGA, "TGA", gdImageCreateFromTga, gdImageCreateFromTgaCtx);
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
/* {{{ _php_image_output
|
||||
*/
|
||||
static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
|
||||
|
@ -364,6 +364,10 @@ gdImagePtr gdImageCreateFromWebp(FILE *fd);
|
||||
gdImagePtr gdImageCreateFromWebpCtx(gdIOCtxPtr in);
|
||||
gdImagePtr gdImageCreateFromWebpPtr (int size, void *data);
|
||||
|
||||
gdImagePtr gdImageCreateFromTga( FILE * fp );
|
||||
gdImagePtr gdImageCreateFromTgaCtx(gdIOCtx* ctx);
|
||||
gdImagePtr gdImageCreateFromTgaPtr(int size, void *data);
|
||||
|
||||
gdImagePtr gdImageCreateFromBmp (FILE * inFile);
|
||||
gdImagePtr gdImageCreateFromBmpPtr (int size, void *data);
|
||||
gdImagePtr gdImageCreateFromBmpCtx (gdIOCtxPtr infile);
|
||||
|
360
ext/gd/libgd/gd_tga.c
Normal file
360
ext/gd/libgd/gd_tga.c
Normal file
@ -0,0 +1,360 @@
|
||||
/**
|
||||
* File: TGA Input
|
||||
*
|
||||
* Read TGA images.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gd_tga.h"
|
||||
#include "gd.h"
|
||||
#include "gd_errors.h"
|
||||
#include "gdhelpers.h"
|
||||
|
||||
/*
|
||||
Function: gdImageCreateFromTga
|
||||
|
||||
Creates a gdImage from a TGA file
|
||||
|
||||
Parameters:
|
||||
|
||||
infile - Pointer to TGA binary file
|
||||
*/
|
||||
gdImagePtr gdImageCreateFromTga(FILE *fp)
|
||||
{
|
||||
gdImagePtr image;
|
||||
gdIOCtx* in = gdNewFileCtx(fp);
|
||||
if (in == NULL) return NULL;
|
||||
image = gdImageCreateFromTgaCtx(in);
|
||||
in->gd_free( in );
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: gdImageCreateFromTgaPtr
|
||||
*/
|
||||
gdImagePtr gdImageCreateFromTgaPtr(int size, void *data)
|
||||
{
|
||||
gdImagePtr im;
|
||||
gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
|
||||
if (in == NULL) return NULL;
|
||||
im = gdImageCreateFromTgaCtx(in);
|
||||
in->gd_free(in);
|
||||
return im;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Function: gdImageCreateFromTgaCtx
|
||||
|
||||
Creates a gdImage from a gdIOCtx referencing a TGA binary file.
|
||||
|
||||
Parameters:
|
||||
ctx - Pointer to a gdIOCtx structure
|
||||
*/
|
||||
gdImagePtr gdImageCreateFromTgaCtx(gdIOCtx* ctx)
|
||||
{
|
||||
int bitmap_caret = 0;
|
||||
oTga *tga = NULL;
|
||||
/* int pixel_block_size = 0;
|
||||
int image_block_size = 0; */
|
||||
volatile gdImagePtr image = NULL;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
tga = (oTga *) gdMalloc(sizeof(oTga));
|
||||
if (!tga) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tga->bitmap = NULL;
|
||||
tga->ident = NULL;
|
||||
|
||||
if (read_header_tga(ctx, tga) < 0) {
|
||||
free_tga(tga);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*TODO: Will this be used?
|
||||
pixel_block_size = tga->bits / 8;
|
||||
image_block_size = (tga->width * tga->height) * pixel_block_size;
|
||||
*/
|
||||
|
||||
if (read_image_tga(ctx, tga) < 0) {
|
||||
free_tga(tga);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = gdImageCreateTrueColor((int)tga->width, (int)tga->height );
|
||||
|
||||
if (image == 0) {
|
||||
free_tga( tga );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! \brief Populate GD image object
|
||||
* Copy the pixel data from our tga bitmap buffer into the GD image
|
||||
* Disable blending and save the alpha channel per default
|
||||
*/
|
||||
if (tga->alphabits) {
|
||||
gdImageAlphaBlending(image, 0);
|
||||
gdImageSaveAlpha(image, 1);
|
||||
}
|
||||
|
||||
/* TODO: use alphabits as soon as we support 24bit and other alpha bps (ie != 8bits) */
|
||||
for (y = 0; y < tga->height; y++) {
|
||||
register int *tpix = image->tpixels[y];
|
||||
for ( x = 0; x < tga->width; x++, tpix++) {
|
||||
if (tga->bits == TGA_BPP_24) {
|
||||
*tpix = gdTrueColor(tga->bitmap[bitmap_caret + 2], tga->bitmap[bitmap_caret + 1], tga->bitmap[bitmap_caret]);
|
||||
bitmap_caret += 3;
|
||||
} else if (tga->bits == TGA_BPP_32 && tga->alphabits) {
|
||||
register int a = tga->bitmap[bitmap_caret + 3];
|
||||
|
||||
*tpix = gdTrueColorAlpha(tga->bitmap[bitmap_caret + 2], tga->bitmap[bitmap_caret + 1], tga->bitmap[bitmap_caret], gdAlphaMax - (a >> 1));
|
||||
bitmap_caret += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tga->flipv && tga->fliph) {
|
||||
gdImageFlipBoth(image);
|
||||
} else if (tga->flipv) {
|
||||
gdImageFlipVertical(image);
|
||||
} else if (tga->fliph) {
|
||||
gdImageFlipHorizontal(image);
|
||||
}
|
||||
|
||||
free_tga(tga);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/*! \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;
|
||||
}
|
||||
|
||||
/*! \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;
|
||||
int* decompression_buffer = NULL;
|
||||
unsigned char* conversion_buffer = NULL;
|
||||
int buffer_caret = 0;
|
||||
int bitmap_caret = 0;
|
||||
int i = 0;
|
||||
int encoded_pixels;
|
||||
int rle_size;
|
||||
|
||||
if(overflow2(tga->width, tga->height)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(overflow2(tga->width * tga->height, pixel_block_size)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
image_block_size = (tga->width * tga->height) * pixel_block_size;
|
||||
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 = (int*) gdMalloc(image_block_size * sizeof(int));
|
||||
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;
|
||||
}
|
||||
|
||||
rle_size = gdGetBuf(conversion_buffer, image_block_size, ctx);
|
||||
if (rle_size <= 0) {
|
||||
gdFree(conversion_buffer);
|
||||
gdFree(decompression_buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_caret = 0;
|
||||
|
||||
while( buffer_caret < rle_size) {
|
||||
decompression_buffer[buffer_caret] = (int)conversion_buffer[buffer_caret];
|
||||
buffer_caret++;
|
||||
}
|
||||
|
||||
buffer_caret = 0;
|
||||
|
||||
while( bitmap_caret < image_block_size ) {
|
||||
|
||||
if (buffer_caret + pixel_block_size > rle_size) {
|
||||
gdFree( decompression_buffer );
|
||||
gdFree( conversion_buffer );
|
||||
return -1;
|
||||
}
|
||||
|
||||
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
|
||||
|| buffer_caret + pixel_block_size > rle_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 * sizeof(int));
|
||||
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
|
||||
|| buffer_caret + (encoded_pixels * pixel_block_size) > rle_size) {
|
||||
gdFree( decompression_buffer );
|
||||
gdFree( conversion_buffer );
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(tga->bitmap + bitmap_caret, decompression_buffer + buffer_caret, encoded_pixels * pixel_block_size * sizeof(int));
|
||||
bitmap_caret += (encoded_pixels * pixel_block_size);
|
||||
buffer_caret += (encoded_pixels * pixel_block_size);
|
||||
}
|
||||
}
|
||||
gdFree( decompression_buffer );
|
||||
gdFree( conversion_buffer );
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*! \brief Cleans up a TGA structure.
|
||||
* Dereferences the bitmap referenced in a TGA structure, then the structure itself
|
||||
* \param tga Pointer to TGA structure
|
||||
*/
|
||||
void free_tga(oTga * tga)
|
||||
{
|
||||
if (tga) {
|
||||
if (tga->ident)
|
||||
gdFree(tga->ident);
|
||||
if (tga->bitmap)
|
||||
gdFree(tga->bitmap);
|
||||
gdFree(tga);
|
||||
}
|
||||
}
|
52
ext/gd/libgd/gd_tga.h
Normal file
52
ext/gd/libgd/gd_tga.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef __TGA_H
|
||||
#define __TGA_H 1
|
||||
|
||||
#include "gd.h"
|
||||
#include "gdhelpers.h"
|
||||
|
||||
#include "gd_intern.h"
|
||||
|
||||
typedef struct oTga_ {
|
||||
uint8_t identsize; // size of ID field that follows 18 uint8_t header (0 usually)
|
||||
uint8_t colormaptype; // type of colour map 0=none, 1=has palette [IGNORED] Adrian requested no support
|
||||
uint8_t imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
|
||||
|
||||
int colormapstart; // first colour map entry in palette [IGNORED] Adrian requested no support
|
||||
int colormaplength; // number of colours in palette [IGNORED] Adrian requested no support
|
||||
uint8_t colormapbits; // number of bits per palette entry 15,16,24,32 [IGNORED] Adrian requested no support
|
||||
|
||||
int xstart; // image x origin
|
||||
int ystart; // image y origin
|
||||
int width; // image width in pixels
|
||||
int height; // image height in pixels
|
||||
uint8_t bits; // image bits per pixel 8,16,24,32
|
||||
uint8_t alphabits; // alpha bits (low 4bits of header 17)
|
||||
uint8_t fliph; // horizontal or vertical
|
||||
uint8_t flipv; // flip
|
||||
char *ident; // identifcation tag string
|
||||
int *bitmap; // bitmap data
|
||||
|
||||
} oTga;
|
||||
|
||||
#define TGA_TYPE_NO_IMAGE 0
|
||||
#define TGA_TYPE_INDEXED 1
|
||||
#define TGA_TYPE_RGB 2
|
||||
#define TGA_TYPE_GREYSCALE 3
|
||||
#define TGA_TYPE_INDEXED_RLE 9
|
||||
#define TGA_TYPE_RGB_RLE 10
|
||||
#define TGA_TYPE_GREYSCALE_RLE 11
|
||||
#define TGA_TYPE_INDEXED_HUFFMAN_DELTA_RLE 32
|
||||
#define TGA_TYPE_RGB_HUFFMAN_DELTA_QUADTREE_RLE 33
|
||||
|
||||
#define TGA_BPP_8 8
|
||||
#define TGA_BPP_16 16
|
||||
#define TGA_BPP_24 24
|
||||
#define TGA_BPP_32 32
|
||||
|
||||
#define TGA_RLE_FLAG 128
|
||||
|
||||
int read_header_tga(gdIOCtx *ctx, oTga *tga);
|
||||
int read_image_tga(gdIOCtx *ctx, oTga *tga);
|
||||
void free_tga(oTga *tga);
|
||||
|
||||
#endif //__TGA_H
|
@ -47,6 +47,7 @@
|
||||
#define PHP_GDIMG_TYPE_GD2PART 10
|
||||
#define PHP_GDIMG_TYPE_WEBP 11
|
||||
#define PHP_GDIMG_TYPE_BMP 12
|
||||
#define PHP_GDIMG_TYPE_TGA 13
|
||||
|
||||
#define PHP_IMG_GIF 1
|
||||
#define PHP_IMG_JPG 2
|
||||
@ -56,6 +57,7 @@
|
||||
#define PHP_IMG_XPM 16
|
||||
#define PHP_IMG_WEBP 32
|
||||
#define PHP_IMG_BMP 64
|
||||
#define PHP_IMG_TGA 128
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# define PHP_GD_API __declspec(dllexport)
|
||||
@ -163,6 +165,9 @@ PHP_FUNCTION(imagecreatefromgd2part);
|
||||
#if defined(HAVE_GD_BMP)
|
||||
PHP_FUNCTION(imagecreatefrombmp);
|
||||
#endif
|
||||
#if defined(HAVE_GD_TGA)
|
||||
PHP_FUNCTION(imagecreatefromtga);
|
||||
#endif
|
||||
#if defined(HAVE_GD_XPM)
|
||||
PHP_FUNCTION(imagecreatefromxpm);
|
||||
#endif
|
||||
|
BIN
ext/gd/tests/imagecreatefromtga.png
Normal file
BIN
ext/gd/tests/imagecreatefromtga.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
17
ext/gd/tests/imagecreatefromtga_basic.phpt
Normal file
17
ext/gd/tests/imagecreatefromtga_basic.phpt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
imagecreatefromtga() - basic functionality
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('gd')) die('skip ext/gd required');
|
||||
if (!(imagetypes() & IMG_TGA)) die('skip TGA support required');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
// create an image from a TGA file
|
||||
$im = imagecreatefromtga(__DIR__ . '/imagecreatefromtga_basic.tga');
|
||||
|
||||
include_once __DIR__ . '/func.inc';
|
||||
test_image_equals_file(__DIR__ . '/imagecreatefromtga.png', $im);
|
||||
?>
|
||||
--EXPECT--
|
||||
The images are equal.
|
BIN
ext/gd/tests/imagecreatefromtga_basic.tga
Normal file
BIN
ext/gd/tests/imagecreatefromtga_basic.tga
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
17
ext/gd/tests/imagecreatefromtga_variation.phpt
Normal file
17
ext/gd/tests/imagecreatefromtga_variation.phpt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
imagecreatefromtga() - RLE file reading
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('gd')) die('skip ext/gd required');
|
||||
if (!(imagetypes() & IMG_TGA)) die('skip TGA support required');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
// create an image from a TGA file
|
||||
$im = imagecreatefromtga(__DIR__ . '/imagecreatefromtga_variation.tga');
|
||||
|
||||
include_once __DIR__ . '/func.inc';
|
||||
test_image_equals_file(__DIR__ . '/imagecreatefromtga.png', $im);
|
||||
?>
|
||||
--EXPECT--
|
||||
The images are equal.
|
BIN
ext/gd/tests/imagecreatefromtga_variation.tga
Normal file
BIN
ext/gd/tests/imagecreatefromtga_variation.tga
Normal file
Binary file not shown.
12
ext/gd/tests/imagetypes_tga.phpt
Normal file
12
ext/gd/tests/imagetypes_tga.phpt
Normal file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
imagetypes() - TGA support
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('gd')) die('skip ext/gd required');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump((imagetypes() & IMG_TGA) == function_exists('imagecreatefromtga'));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
Loading…
Reference in New Issue
Block a user