📄 image.c
字号:
length -= 2; /* length includes itself */ buffer = emalloc(length); if (php_stream_read(stream, buffer, (long) length) <= 0) { efree(buffer); return 0; } sprintf(markername, "APP%d", marker - M_APP0); if (zend_hash_find(Z_ARRVAL_P(info), markername, strlen(markername)+1, (void **) &tmp) == FAILURE) { /* XXX we onyl catch the 1st tag of it's kind! */ add_assoc_stringl(info, markername, buffer, length, 1); } efree(buffer); return 1;}/* }}} *//* {{{ php_handle_jpeg main loop to parse JPEG structure */static struct gfxinfo *php_handle_jpeg (php_stream * stream, pval *info TSRMLS_DC) { struct gfxinfo *result = NULL; unsigned int marker = M_PSEUDO; unsigned short length, ff_read=1; for (;;) { marker = php_next_marker(stream, marker, 1, ff_read TSRMLS_CC); ff_read = 0; switch (marker) { case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: if (result == NULL) { /* handle SOFn block */ result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); length = php_read2(stream TSRMLS_CC); result->bits = php_stream_getc(stream); result->height = php_read2(stream TSRMLS_CC); result->width = php_read2(stream TSRMLS_CC); result->channels = php_stream_getc(stream); if (!info || length < 8) { /* if we don't want an extanded info -> return */ return result; } if (php_stream_seek(stream, length - 8, SEEK_CUR)) { /* file error after info */ return result; } } else { if (!php_skip_variable(stream TSRMLS_CC)) { return result; } } break; case M_APP0: case M_APP1: case M_APP2: case M_APP3: case M_APP4: case M_APP5: case M_APP6: case M_APP7: case M_APP8: case M_APP9: case M_APP10: case M_APP11: case M_APP12: case M_APP13: case M_APP14: case M_APP15: if (info) { if (!php_read_APP(stream, marker, info TSRMLS_CC)) { /* read all the app markes... */ return result; } } else { if (!php_skip_variable(stream TSRMLS_CC)) { return result; } } break; case M_SOS: case M_EOI: return result; /* we're about to hit image data, or are at EOF. stop processing. */ default: if (!php_skip_variable(stream TSRMLS_CC)) { /* anything else isn't interesting */ return result; } break; } } return result; /* perhaps image broken -> no info but size */}/* }}} *//* {{{ php_read4 */static unsigned int php_read4(php_stream * stream TSRMLS_DC){ unsigned char a[4]; /* just return 0 if we hit the end-of-file */ if ((php_stream_read(stream, a, sizeof(a))) != sizeof(a)) return 0; return (((unsigned int)a[0]) << 24) + (((unsigned int)a[1]) << 16) + (((unsigned int)a[2]) << 8) + (((unsigned int)a[3]));}/* }}} *//* {{{ JPEG 2000 Marker Codes */#define JPEG2000_MARKER_PREFIX 0xFF /* All marker codes start with this */#define JPEG2000_MARKER_SOC 0x4F /* Start of Codestream */#define JPEG2000_MARKER_SOT 0x90 /* Start of Tile part */#define JPEG2000_MARKER_SOD 0x93 /* Start of Data */#define JPEG2000_MARKER_EOC 0xD9 /* End of Codestream */#define JPEG2000_MARKER_SIZ 0x51 /* Image and tile size */#define JPEG2000_MARKER_COD 0x52 /* Coding style default */ #define JPEG2000_MARKER_COC 0x53 /* Coding style component */#define JPEG2000_MARKER_RGN 0x5E /* Region of interest */#define JPEG2000_MARKER_QCD 0x5C /* Quantization default */#define JPEG2000_MARKER_QCC 0x5D /* Quantization component */#define JPEG2000_MARKER_POC 0x5F /* Progression order change */#define JPEG2000_MARKER_TLM 0x55 /* Tile-part lengths */#define JPEG2000_MARKER_PLM 0x57 /* Packet length, main header */#define JPEG2000_MARKER_PLT 0x58 /* Packet length, tile-part header */#define JPEG2000_MARKER_PPM 0x60 /* Packed packet headers, main header */#define JPEG2000_MARKER_PPT 0x61 /* Packed packet headers, tile part header */#define JPEG2000_MARKER_SOP 0x91 /* Start of packet */#define JPEG2000_MARKER_EPH 0x92 /* End of packet header */#define JPEG2000_MARKER_CRG 0x63 /* Component registration */#define JPEG2000_MARKER_COM 0x64 /* Comment *//* }}} *//* {{{ php_handle_jpc Main loop to parse JPEG2000 raw codestream structure */static struct gfxinfo *php_handle_jpc(php_stream * stream TSRMLS_DC){ struct gfxinfo *result = NULL; unsigned short dummy_short; int dummy_int, highest_bit_depth, bit_depth; unsigned char first_marker_id; unsigned int i; /* JPEG 2000 components can be vastly different from one another. Each component can be sampled at a different resolution, use a different colour space, have a seperate colour depth, and be compressed totally differently! This makes giving a single "bit depth" answer somewhat problematic. For this implementation we'll use the highest depth encountered. */ /* Get the single byte that remains after the file type indentification */ first_marker_id = php_stream_getc(stream); /* Ensure that this marker is SIZ (as is mandated by the standard) */ if (first_marker_id != JPEG2000_MARKER_SIZ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "JPEG2000 codestream corrupt(Expected SIZ marker not found after SOC)"); return NULL; } result = (struct gfxinfo *)ecalloc(1, sizeof(struct gfxinfo)); dummy_short = php_read2(stream TSRMLS_CC); /* Lsiz */ dummy_short = php_read2(stream TSRMLS_CC); /* Rsiz */ result->width = php_read4(stream TSRMLS_CC); /* Ysiz */ result->height = php_read4(stream TSRMLS_CC); /* Xsiz */#if MBO_0 dummy_int = php_read4(stream TSRMLS_CC); /* XOsiz */ dummy_int = php_read4(stream TSRMLS_CC); /* YOsiz */ dummy_int = php_read4(stream TSRMLS_CC); /* XTsiz */ dummy_int = php_read4(stream TSRMLS_CC); /* YTsiz */ dummy_int = php_read4(stream TSRMLS_CC); /* XTOsiz */ dummy_int = php_read4(stream TSRMLS_CC); /* YTOsiz */#else if (php_stream_seek(stream, 24, SEEK_CUR)) { efree(result); return NULL; }#endif result->channels = php_read2(stream TSRMLS_CC); /* Csiz */ if (result->channels < 0 || result->channels > 256) { efree(result); return NULL; } /* Collect bit depth info */ highest_bit_depth = bit_depth = 0; for (i = 0; i < result->channels; i++) { bit_depth = php_stream_getc(stream); /* Ssiz[i] */ bit_depth++; if (bit_depth > highest_bit_depth) { highest_bit_depth = bit_depth; } php_stream_getc(stream); /* XRsiz[i] */ php_stream_getc(stream); /* YRsiz[i] */ } result->bits = highest_bit_depth; return result;}/* }}} *//* {{{ php_handle_jp2 main loop to parse JPEG 2000 JP2 wrapper format structure */static struct gfxinfo *php_handle_jp2(php_stream *stream TSRMLS_DC){ struct gfxinfo *result = NULL; unsigned int box_length; unsigned int box_type; char jp2c_box_id[] = {(char)0x6a, (char)0x70, (char)0x32, (char)0x63}; /* JP2 is a wrapper format for JPEG 2000. Data is contained within "boxes". Boxes themselves can be contained within "super-boxes". Super-Boxes can contain super-boxes which provides us with a hierarchical storage system. It is valid for a JP2 file to contain multiple individual codestreams. We'll just look for the first codestream at the root of the box structure and handle that. */ for (;;) { box_length = php_read4(stream TSRMLS_CC); /* LBox */ /* TBox */ if (php_stream_read(stream, (void *)&box_type, sizeof(box_type)) != sizeof(box_type)) { /* Use this as a general "out of stream" error */ break; } if (box_length == 1) { /* We won't handle XLBoxes */ return NULL; } if (!memcmp(&box_type, jp2c_box_id, 4)) { /* Skip the first 3 bytes to emulate the file type examination */ php_stream_seek(stream, 3, SEEK_CUR); result = php_handle_jpc(stream TSRMLS_CC); break; } /* Stop if this was the last box */ if ((int)box_length <= 0) { break; } /* Skip over LBox (Which includes both TBox and LBox itself */ if (php_stream_seek(stream, box_length - 8, SEEK_CUR)) { break; } } if (result == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "JP2 file has no codestreams at root level"); } return result;}/* }}} *//* {{{ 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/* }}} *//* {{{ 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 (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1]; } else { return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)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) | (((unsigned char *)Long)[1] << 16) | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 ); } else { return ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16) | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)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 (php_stream * stream, pval *info, int motorola_intel TSRMLS_DC){ struct gfxinfo *result = NULL; int i, num_entries; unsigned char *dir_entry; size_t ifd_size, dir_size, entry_value, width=0, height=0, ifd_addr; int entry_tag , entry_type; char *ifd_data, ifd_ptr[4]; if (php_stream_read(stream, ifd_ptr, 4) != 4) return NULL; ifd_addr = php_ifd_get32u(ifd_ptr, motorola_intel); if (php_stream_seek(stream, ifd_addr-8, SEEK_CUR)) return NULL; ifd_size = 2; ifd_data = emalloc(ifd_size); if (php_stream_read(stream, ifd_data, 2) != 2) { efree(ifd_data); return NULL; } 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); if (php_stream_read(stream, ifd_data+2, dir_size-2) != dir_size-2) { efree(ifd_data); return NULL; } /* 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); switch(entry_type) { case TAG_FMT_BYTE: case TAG_FMT_SBYTE: entry_value = (size_t)(dir_entry[8]); break; 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; } } efree(ifd_data); if ( width && height) { /* not the same when in for-loop */ result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); result->height = height; result->width = width; result->bits = 0; result->channels = 0; return result; } return NULL;}/* }}} *//* {{{ php_handle_psd */static struct gfxinfo *php_handle_iff(php_stream * stream TSRMLS_DC){ struct gfxinfo * result; unsigned char a[10]; int chunkId; int size; short width, height, bits; if (php_stream_read(stream, a, 8) != 8) { return NULL; } if (strncmp(a+4, "ILBM", 4) && strncmp(a+4, "PBM ", 4)) { return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -