- TIFF support for GetImageSize

@ TIFF support for GetImageSize (Marcus)
This commit is contained in:
Marcus Boerger 2002-03-04 17:17:41 +00:00
parent a7403576e1
commit d95f691e3f

View file

@ -12,7 +12,8 @@
| obtain it through the world-wide-web, please send a note to | | obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. | | license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
| Author: Rasmus Lerdorf <rasmus@php.net> | | Authors: Rasmus Lerdorf <rasmus@php.net> |
| Marcus Boerger <helly@php.net> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
*/ */
/* $Id$ */ /* $Id$ */
@ -56,6 +57,9 @@ PHPAPI const char php_sig_swf[3] = {'F', 'W', 'S'};
PHPAPI const char php_sig_jpg[3] = {(char) 0xff, (char) 0xd8, (char) 0xff}; PHPAPI const char php_sig_jpg[3] = {(char) 0xff, (char) 0xd8, (char) 0xff};
PHPAPI const char php_sig_png[8] = {(char) 0x89, (char) 0x50, (char) 0x4e, (char) 0x47, PHPAPI const char php_sig_png[8] = {(char) 0x89, (char) 0x50, (char) 0x4e, (char) 0x47,
(char) 0x0d, (char) 0x0a, (char) 0x1a, (char) 0x0a}; (char) 0x0d, (char) 0x0a, (char) 0x1a, (char) 0x0a};
PHPAPI const char php_sig_tif_ii[8] = {'I','I', (char)0x2A, (char)0x00, (char)0x08, (char)0x00, (char)0x00, (char)0x00};
PHPAPI const char php_sig_tif_mm[8] = {'M','M', (char)0x00, (char)0x2A, (char)0x00, (char)0x00, (char)0x00, (char)0x08};
/* return info as a struct, to make expansion easier */ /* return info as a struct, to make expansion easier */
@ -395,7 +399,139 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval
} }
/* }}} */ /* }}} */
/* main function */ /* {{{ tiff constants
*/
PHPAPI const int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
/* uncompressed only */
#define TAG_IMAGEWIDTH 0x0100
#define TAG_IMAGEHEIGHT 0x0101
/* compressed images only */
#define TAG_COMP_IMAGEWIDTH 0xA002
#define TAG_COMP_IMAGEHEIGHT 0xA003
#define TAG_FMT_BYTE 1
#define TAG_FMT_STRING 2
#define TAG_FMT_USHORT 3
#define TAG_FMT_ULONG 4
#define TAG_FMT_URATIONAL 5
#define TAG_FMT_SBYTE 6
#define TAG_FMT_UNDEFINED 7
#define TAG_FMT_SSHORT 8
#define TAG_FMT_SLONG 9
#define TAG_FMT_SRATIONAL 10
#define TAG_FMT_SINGLE 11
#define TAG_FMT_DOUBLE 12
typedef unsigned char uchar;
/* }}} */
/* {{{ php_ifd_get16u
* Convert a 16 bit unsigned value from file's native byte order */
static int php_ifd_get16u(void *Short, int motorola_intel)
{
if (motorola_intel) {
return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
} else {
return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0];
}
}
/* }}} */
/* {{{ php_ifd_get16s
* Convert a 16 bit signed value from file's native byte order */
static signed short php_ifd_get16s(void *Short, int motorola_intel)
{
return (signed short)php_ifd_get16u(Short, motorola_intel);
}
/* }}} */
/* {{{ php_ifd_get32s
* Convert a 32 bit signed value from file's native byte order */
static int php_ifd_get32s(void *Long, int motorola_intel)
{
if (motorola_intel) {
return ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16)
| (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 );
} else {
return ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16)
| (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 );
}
}
/* }}} */
/* {{{ php_ifd_get32u
* Convert a 32 bit unsigned value from file's native byte order */
static unsigned php_ifd_get32u(void *Long, int motorola_intel)
{
return (unsigned)php_ifd_get32s(Long, motorola_intel) & 0xffffffff;
}
/* }}} */
/* {{{ php_handle_tiff
main loop to parse TIFF structure */
static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval *info, int motorola_intel)
{
struct gfxinfo *result = NULL;
int i, sn, num_entries;
unsigned char *dir_entry;
size_t ifd_size, dir_size, entry_value, entry_length, width, height;
int entry_tag , entry_type;
char *ifd_data;
ifd_size = 2;
ifd_data = emalloc(ifd_size);
FP_FREAD(ifd_data, 2, socketd, fp, issock);
num_entries = php_ifd_get16u(ifd_data, motorola_intel);
dir_size = 2/*num dir entries*/ +12/*length of entry*/*num_entries +4/* offset to next ifd (points to thumbnail or NULL)*/;
ifd_size = dir_size;
ifd_data = erealloc(ifd_data,ifd_size);
FP_FREAD(ifd_data+2, dir_size-2, socketd, fp, issock);
/* now we have the directory we can look how long it should be */
ifd_size = dir_size;
for(i=0;i<num_entries;i++) {
dir_entry = ifd_data+2+i*12;
entry_tag = php_ifd_get16u(dir_entry+0, motorola_intel);
entry_type = php_ifd_get16u(dir_entry+2, motorola_intel);
entry_length = php_ifd_get32u(dir_entry+4, motorola_intel) * php_tiff_bytes_per_format[entry_type];
switch(entry_type) {
case TAG_FMT_USHORT:
entry_value = php_ifd_get16u(dir_entry+8, motorola_intel);
break;
case TAG_FMT_SSHORT:
entry_value = php_ifd_get16s(dir_entry+8, motorola_intel);
break;
case TAG_FMT_ULONG:
entry_value = php_ifd_get32u(dir_entry+8, motorola_intel);
break;
case TAG_FMT_SLONG:
entry_value = php_ifd_get32s(dir_entry+8, motorola_intel);
break;
default:
continue;
}
switch(entry_tag) {
case TAG_IMAGEWIDTH:
case TAG_COMP_IMAGEWIDTH:
width = entry_value;
break;
case TAG_IMAGEHEIGHT:
case TAG_COMP_IMAGEHEIGHT:
height = entry_value;
break;
}
}
if ( width && height) {
/* not the same when in for-loop */
result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo));
result->height = height;
result->width = width;
return result;
}
return NULL;
}
/* }}} */
/* {{{ proto array getimagesize(string imagefile [, array info]) /* {{{ proto array getimagesize(string imagefile [, array info])
Get the size of an image as 4-element array */ Get the size of an image as 4-element array */
@ -463,31 +599,41 @@ PHP_FUNCTION(getimagesize)
if (!memcmp(filetype, php_sig_gif, 3)) { if (!memcmp(filetype, php_sig_gif, 3)) {
result = php_handle_gif (socketd, fp, issock); result = php_handle_gif (socketd, fp, issock);
itype = 1; itype = IMAGE_FILETYPE_GIF;
} else if (!memcmp(filetype, php_sig_jpg, 3)) { } else if (!memcmp(filetype, php_sig_jpg, 3)) {
if (info) { if (info) {
result = php_handle_jpeg(socketd, fp, issock, *info); result = php_handle_jpeg(socketd, fp, issock, *info);
} else { } else {
result = php_handle_jpeg(socketd, fp, issock, NULL); result = php_handle_jpeg(socketd, fp, issock, NULL);
} }
itype = 2; itype = IMAGE_FILETYPE_JPEG;
} else if (!memcmp(filetype, php_sig_png, 3)) { } else if (!memcmp(filetype, php_sig_png, 3)) {
FP_FREAD(filetype+3, 5, socketd, fp, issock); FP_FREAD(filetype+3, 5, socketd, fp, issock);
if (!memcmp(filetype, php_sig_png, 8)) { if (!memcmp(filetype, php_sig_png, 8)) {
result = php_handle_png(socketd, fp, issock); result = php_handle_png(socketd, fp, issock);
itype = 3; itype = IMAGE_FILETYPE_PNG;
} else { } else {
php_error(E_WARNING, "PNG file corrupted by ASCII conversion"); php_error(E_WARNING, "PNG file corrupted by ASCII conversion");
} }
} else if (!memcmp(filetype, php_sig_swf, 3)) { } else if (!memcmp(filetype, php_sig_swf, 3)) {
result = php_handle_swf(socketd, fp, issock); result = php_handle_swf(socketd, fp, issock);
itype = 4; itype = IMAGE_FILETYPE_SWF;
} else if (!memcmp(filetype, php_sig_psd, 3)) { } else if (!memcmp(filetype, php_sig_psd, 3)) {
result = php_handle_psd(socketd, fp, issock); result = php_handle_psd(socketd, fp, issock);
itype = 5; itype = IMAGE_FILETYPE_PSD;
} else if (!memcmp(filetype, php_sig_bmp, 2)) { } else if (!memcmp(filetype, php_sig_bmp, 2)) {
result = php_handle_bmp(socketd, fp, issock); result = php_handle_bmp(socketd, fp, issock);
itype = 6; itype = IMAGE_FILETYPE_BMP;
} else {
FP_FREAD(filetype+3, 5, socketd, fp, issock);
if (!memcmp(filetype, php_sig_tif_ii, 8)) {
result = php_handle_tiff(socketd, fp, issock, NULL, 0);
itype = IMAGE_FILETYPE_TIFF;
} else
if (!memcmp(filetype, php_sig_tif_mm, 8)) {
result = php_handle_tiff(socketd, fp, issock, NULL, 1);
itype = IMAGE_FILETYPE_TIFF;
}
} }
zend_list_delete(rsrc_id); zend_list_delete(rsrc_id);