📄 image.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Rasmus Lerdorf <rasmus@php.net> | | Marcus Boerger <helly@php.net> | +----------------------------------------------------------------------+ *//* $Id: image.c,v 1.72.2.19.2.3 2007/01/01 09:46:48 sebastian Exp $ */#include "php.h"#include <stdio.h>#if HAVE_FCNTL_H#include <fcntl.h>#endif#include "fopen_wrappers.h"#include "ext/standard/fsock.h"#if HAVE_UNISTD_H#include <unistd.h>#endif#include "php_image.h"#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)#include "zlib.h"#endif/* file type markers */PHPAPI const char php_sig_gif[3] = {'G', 'I', 'F'};PHPAPI const char php_sig_psd[4] = {'8', 'B', 'P', 'S'};PHPAPI const char php_sig_bmp[2] = {'B', 'M'};PHPAPI const char php_sig_swf[3] = {'F', 'W', 'S'};PHPAPI const char php_sig_swc[3] = {'C', 'W', 'S'};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, (char) 0x0d, (char) 0x0a, (char) 0x1a, (char) 0x0a};PHPAPI const char php_sig_tif_ii[4] = {'I','I', (char)0x2A, (char)0x00};PHPAPI const char php_sig_tif_mm[4] = {'M','M', (char)0x00, (char)0x2A};PHPAPI const char php_sig_jpc[3] = {(char)0xff, (char)0x4f, (char)0xff};PHPAPI const char php_sig_jp2[12] = {(char)0x00, (char)0x00, (char)0x00, (char)0x0c, (char)0x6a, (char)0x50, (char)0x20, (char)0x20, (char)0x0d, (char)0x0a, (char)0x87, (char)0x0a};PHPAPI const char php_sig_iff[4] = {'F','O','R','M'};/* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type *//* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 *//* return info as a struct, to make expansion easier */struct gfxinfo { unsigned int width; unsigned int height; unsigned int bits; unsigned int channels;};/* {{{ PHP_MINIT_FUNCTION(imagetypes) * Register IMAGETYPE_<xxx> constants used by GetImageSize(), image_type_to_mime_type, ext/exif */PHP_MINIT_FUNCTION(imagetypes){ REGISTER_LONG_CONSTANT("IMAGETYPE_GIF", IMAGE_FILETYPE_GIF, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG", IMAGE_FILETYPE_JPEG, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_PNG", IMAGE_FILETYPE_PNG, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_SWF", IMAGE_FILETYPE_SWF, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_PSD", IMAGE_FILETYPE_PSD, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_BMP", IMAGE_FILETYPE_BMP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_TIFF_II", IMAGE_FILETYPE_TIFF_II, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_TIFF_MM", IMAGE_FILETYPE_TIFF_MM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_JPC", IMAGE_FILETYPE_JPC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_JP2", IMAGE_FILETYPE_JP2, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_JPX", IMAGE_FILETYPE_JPX, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_JB2", IMAGE_FILETYPE_JB2, CONST_CS | CONST_PERSISTENT);#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) REGISTER_LONG_CONSTANT("IMAGETYPE_SWC", IMAGE_FILETYPE_SWC, CONST_CS | CONST_PERSISTENT);#endif REGISTER_LONG_CONSTANT("IMAGETYPE_IFF", IMAGE_FILETYPE_IFF, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_WBMP", IMAGE_FILETYPE_WBMP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG2000",IMAGE_FILETYPE_JPC, CONST_CS | CONST_PERSISTENT); /* keep alias */ REGISTER_LONG_CONSTANT("IMAGETYPE_XBM", IMAGE_FILETYPE_XBM, CONST_CS | CONST_PERSISTENT); return SUCCESS;}/* }}} *//* {{{ php_handle_gif * routine to handle GIF files. If only everything were that easy... ;} */static struct gfxinfo *php_handle_gif (php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; unsigned char dim[5]; if (php_stream_seek(stream, 3, SEEK_CUR)) return NULL; if (php_stream_read(stream, dim, sizeof(dim)) != sizeof(dim)) return NULL; result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); result->width = (unsigned int)dim[0] | (((unsigned int)dim[1])<<8); result->height = (unsigned int)dim[2] | (((unsigned int)dim[3])<<8); result->bits = dim[4]&0x80 ? ((((unsigned int)dim[4])&0x07) + 1) : 0; result->channels = 3; /* allways */ return result;}/* }}} *//* {{{ php_handle_psd */static struct gfxinfo *php_handle_psd (php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; unsigned char dim[8]; if (php_stream_seek(stream, 11, SEEK_CUR)) return NULL; if (php_stream_read(stream, dim, sizeof(dim)) != sizeof(dim)) return NULL; result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); result->height = (((unsigned int)dim[0]) << 24) + (((unsigned int)dim[1]) << 16) + (((unsigned int)dim[2]) << 8) + ((unsigned int)dim[3]); result->width = (((unsigned int)dim[4]) << 24) + (((unsigned int)dim[5]) << 16) + (((unsigned int)dim[6]) << 8) + ((unsigned int)dim[7]); return result;}/* }}} *//* {{{ php_handle_bmp */static struct gfxinfo *php_handle_bmp (php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; unsigned char dim[16]; int size; if (php_stream_seek(stream, 11, SEEK_CUR)) return NULL; if (php_stream_read(stream, dim, sizeof(dim)) != sizeof(dim)) return NULL; size = (((unsigned int)dim[ 3]) << 24) + (((unsigned int)dim[ 2]) << 16) + (((unsigned int)dim[ 1]) << 8) + ((unsigned int) dim[ 0]); if (size == 12) { result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo)); result->width = (((unsigned int)dim[ 5]) << 8) + ((unsigned int) dim[ 4]); result->height = (((unsigned int)dim[ 7]) << 8) + ((unsigned int) dim[ 6]); result->bits = ((unsigned int)dim[11]); } else if (size > 12 && (size <= 64 || size == 108)) { result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo)); result->width = (((unsigned int)dim[ 7]) << 24) + (((unsigned int)dim[ 6]) << 16) + (((unsigned int)dim[ 5]) << 8) + ((unsigned int) dim[ 4]); result->height = (((unsigned int)dim[11]) << 24) + (((unsigned int)dim[10]) << 16) + (((unsigned int)dim[ 9]) << 8) + ((unsigned int) dim[ 8]); result->bits = (((unsigned int)dim[15]) << 8) + ((unsigned int)dim[14]); } else { return NULL; } return result;}/* }}} *//* {{{ php_swf_get_bits * routines to handle SWF files. */static unsigned long int php_swf_get_bits (unsigned char* buffer, unsigned int pos, unsigned int count){ unsigned int loop; unsigned long int result = 0; for (loop = pos; loop < pos + count; loop++) { result = result + ((((buffer[loop / 8]) >> (7 - (loop % 8))) & 0x01) << (count - (loop - pos) - 1)); } return result;}/* }}} */#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB)/* {{{ php_handle_swc */static struct gfxinfo *php_handle_swc(php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; long bits; unsigned char a[64]; unsigned long len=64, szlength; int factor=1,maxfactor=16; int slength, status=0; char *b, *buf=NULL, *bufz=NULL; b = ecalloc (1, len + 1); if (php_stream_seek(stream, 5, SEEK_CUR)) return NULL; if (php_stream_read(stream, a, sizeof(a)) != sizeof(a)) return NULL; if (uncompress(b, &len, a, sizeof(a)) != Z_OK) { /* failed to decompress the file, will try reading the rest of the file */ if (php_stream_seek(stream, 8, SEEK_SET)) return NULL; slength = php_stream_copy_to_mem(stream, &bufz, PHP_STREAM_COPY_ALL, 0); /* * zlib::uncompress() wants to know the output data length * if none was given as a parameter * we try from input length * 2 up to input length * 2^8 * doubling it whenever it wasn't big enough * that should be eneugh for all real life cases */ do { szlength=slength*(1<<factor++); buf = (char *) erealloc(buf,szlength); status = uncompress(buf, &szlength, bufz, slength); } while ((status==Z_BUF_ERROR)&&(factor<maxfactor)); if (bufz) { pefree(bufz, 0); } if (status == Z_OK) { memcpy(b, buf, len); } if (buf) { efree(buf); } } if (!status) { result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo)); bits = php_swf_get_bits (b, 0, 5); result->width = (php_swf_get_bits (b, 5 + bits, bits) - php_swf_get_bits (b, 5, bits)) / 20; result->height = (php_swf_get_bits (b, 5 + (3 * bits), bits) - php_swf_get_bits (b, 5 + (2 * bits), bits)) / 20; } else { result = NULL; } efree (b); return result;}/* }}} */#endif/* {{{ php_handle_swf */static struct gfxinfo *php_handle_swf (php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; long bits; unsigned char a[32]; if (php_stream_seek(stream, 5, SEEK_CUR)) return NULL; if (php_stream_read(stream, a, sizeof(a)) != sizeof(a)) return NULL; result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo)); bits = php_swf_get_bits (a, 0, 5); result->width = (php_swf_get_bits (a, 5 + bits, bits) - php_swf_get_bits (a, 5, bits)) / 20; result->height = (php_swf_get_bits (a, 5 + (3 * bits), bits) - php_swf_get_bits (a, 5 + (2 * bits), bits)) / 20; result->bits = 0; result->channels = 0; return result;}/* }}} *//* {{{ php_handle_png * routine to handle PNG files */static struct gfxinfo *php_handle_png (php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; unsigned char dim[9];/* Width: 4 bytes * Height: 4 bytes * Bit depth: 1 byte * Color type: 1 byte * Compression method: 1 byte * Filter method: 1 byte * Interlace method: 1 byte */ if (php_stream_seek(stream, 8, SEEK_CUR)) return NULL; if((php_stream_read(stream, dim, sizeof(dim))) < sizeof(dim)) return NULL; result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); result->width = (((unsigned int)dim[0]) << 24) + (((unsigned int)dim[1]) << 16) + (((unsigned int)dim[2]) << 8) + ((unsigned int)dim[3]); result->height = (((unsigned int)dim[4]) << 24) + (((unsigned int)dim[5]) << 16) + (((unsigned int)dim[6]) << 8) + ((unsigned int)dim[7]); result->bits = (unsigned int)dim[8]; return result;}/* }}} *//* routines to handle JPEG data *//* some defines for the different JPEG block types */#define M_SOF0 0xC0 /* Start Of Frame N */#define M_SOF1 0xC1 /* N indicates which compression process */#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */#define M_SOF3 0xC3#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */#define M_SOF6 0xC6#define M_SOF7 0xC7#define M_SOF9 0xC9#define M_SOF10 0xCA#define M_SOF11 0xCB#define M_SOF13 0xCD#define M_SOF14 0xCE#define M_SOF15 0xCF#define M_SOI 0xD8#define M_EOI 0xD9 /* End Of Image (end of datastream) */#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */#define M_APP0 0xe0#define M_APP1 0xe1#define M_APP2 0xe2#define M_APP3 0xe3#define M_APP4 0xe4#define M_APP5 0xe5#define M_APP6 0xe6#define M_APP7 0xe7#define M_APP8 0xe8#define M_APP9 0xe9#define M_APP10 0xea#define M_APP11 0xeb#define M_APP12 0xec#define M_APP13 0xed#define M_APP14 0xee#define M_APP15 0xef#define M_COM 0xFE /* COMment */#define M_PSEUDO 0xFFD8 /* pseudo marker for start of image(byte 0) *//* {{{ php_read2 */static unsigned short php_read2(php_stream * stream TSRMLS_DC){ unsigned char a[2]; /* just return 0 if we hit the end-of-file */ if((php_stream_read(stream, a, sizeof(a))) <= 0) return 0; return (((unsigned short)a[0]) << 8) + ((unsigned short)a[1]);}/* }}} *//* {{{ php_next_marker * get next marker byte from file */static unsigned int php_next_marker(php_stream * stream, int last_marker, int comment_correction, int ff_read TSRMLS_DC){ int a=0, marker; /* get marker byte, swallowing possible padding */ if (last_marker==M_COM && comment_correction) { /* some software does not count the length bytes of COM section */ /* one company doing so is very much envolved in JPEG... so we accept too */ /* by the way: some of those companies changed their code now... */ comment_correction = 2; } else { last_marker = 0; comment_correction = 0; } if (ff_read) { a = 1; /* already read 0xff in filetype detection */ } do { if ((marker = php_stream_getc(stream)) == EOF) { return M_EOI;/* we hit EOF */ } if (last_marker==M_COM && comment_correction>0) { if (marker != 0xFF) { marker = 0xff; comment_correction--; } else { last_marker = M_PSEUDO; /* stop skipping non 0xff for M_COM */ } } if (++a > 25) { /* who knows the maxim amount of 0xff? though 7 */ /* but found other implementations */ return M_EOI; } } while (marker == 0xff); if (a < 2) { return M_EOI; /* at least one 0xff is needed before marker code */ } if ( last_marker==M_COM && comment_correction) { return M_EOI; /* ah illegal: char after COM section not 0xFF */ } return (unsigned int)marker;}/* }}} *//* {{{ php_skip_variable * skip over a variable-length block; assumes proper length marker */static int php_skip_variable(php_stream * stream TSRMLS_DC){ off_t length = ((unsigned int)php_read2(stream TSRMLS_CC)); if (length < 2) { return 0; } length = length - 2; php_stream_seek(stream, (long)length, SEEK_CUR); return 1;}/* }}} *//* {{{ php_read_APP */static int php_read_APP(php_stream * stream, unsigned int marker, zval *info TSRMLS_DC){ unsigned short length; unsigned char *buffer; unsigned char markername[16]; zval *tmp; length = php_read2(stream TSRMLS_CC); if (length < 2) { return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -