diff options
Diffstat (limited to 'modules/getid3/module.graphic.bmp.php')
-rw-r--r-- | modules/getid3/module.graphic.bmp.php | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/modules/getid3/module.graphic.bmp.php b/modules/getid3/module.graphic.bmp.php new file mode 100644 index 00000000..ca1ce87f --- /dev/null +++ b/modules/getid3/module.graphic.bmp.php @@ -0,0 +1,319 @@ +<?php +// +----------------------------------------------------------------------+ +// | PHP version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2 of the GPL license, | +// | that is bundled with this package in the file license.txt and is | +// | available through the world-wide-web at the following url: | +// | http://www.gnu.org/copyleft/gpl.html | +// +----------------------------------------------------------------------+ +// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | +// +----------------------------------------------------------------------+ +// | Authors: James Heinrich <infoØgetid3*org> | +// | Allan Hansen <ahØartemis*dk> | +// +----------------------------------------------------------------------+ +// | module.graphic.bmp.php | +// | Module for analyzing BMP graphic files. | +// | dependencies: NONE | +// +----------------------------------------------------------------------+ +// +// $Id: module.graphic.bmp.php,v 1.4 2006/11/02 10:48:02 ah Exp $ + + + +class getid3_bmp extends getid3_handler +{ + + + public function Analyze() { + + $getid3 = $this->getid3; + + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + // all versions + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + + // shortcuts + $getid3->info['bmp']['header']['raw'] = array (); + $info_bmp = &$getid3->info['bmp']; + $info_bmp_header = &$info_bmp['header']; + $info_bmp_header_raw = &$info_bmp_header['raw']; + + fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET); + $bmp_header = fread($getid3->fp, 14 + 40); + + // Magic bytes + $info_bmp_header_raw['identifier'] = 'BM'; + + getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 2, + array ( + 'filesize' => 4, + 'reserved1' => 2, + 'reserved2' => 2, + 'data_offset' => 4, + 'header_size' => 4 + ) + ); + + // Check if the hardcoded-to-1 "planes" is at offset 22 or 26 + $planes22 = getid3_lib::LittleEndian2Int(substr($bmp_header, 22, 2)); + $planes26 = getid3_lib::LittleEndian2Int(substr($bmp_header, 26, 2)); + if (($planes22 == 1) && ($planes26 != 1)) { + $info_bmp['type_os'] = 'OS/2'; + $info_bmp['type_version'] = 1; + } + elseif (($planes26 == 1) && ($planes22 != 1)) { + $info_bmp['type_os'] = 'Windows'; + $info_bmp['type_version'] = 1; + } + elseif ($info_bmp_header_raw['header_size'] == 12) { + $info_bmp['type_os'] = 'OS/2'; + $info_bmp['type_version'] = 1; + } + elseif ($info_bmp_header_raw['header_size'] == 40) { + $info_bmp['type_os'] = 'Windows'; + $info_bmp['type_version'] = 1; + } + elseif ($info_bmp_header_raw['header_size'] == 84) { + $info_bmp['type_os'] = 'Windows'; + $info_bmp['type_version'] = 4; + } + elseif ($info_bmp_header_raw['header_size'] == 100) { + $info_bmp['type_os'] = 'Windows'; + $info_bmp['type_version'] = 5; + } + else { + throw new getid3_exception('Unknown BMP subtype (or not a BMP file)'); + } + + $getid3->info['fileformat'] = 'bmp'; + $getid3->info['video']['dataformat'] = 'bmp'; + $getid3->info['video']['lossless'] = true; + $getid3->info['video']['pixel_aspect_ratio'] = (float)1; + + if ($info_bmp['type_os'] == 'OS/2') { + + // OS/2-format BMP + // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm + + // DWORD Size; /* Size of this structure in bytes */ + // DWORD Width; /* Bitmap width in pixels */ + // DWORD Height; /* Bitmap height in pixel */ + // WORD NumPlanes; /* Number of bit planes (color depth) */ + // WORD BitsPerPixel; /* Number of bits per pixel per plane */ + + getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 18, + array ( + 'width' => 2, + 'height' => 2, + 'planes' => 2, + 'bits_per_pixel' => 2 + ) + ); + + $getid3->info['video']['resolution_x'] = $info_bmp_header_raw['width']; + $getid3->info['video']['resolution_y'] = $info_bmp_header_raw['height']; + $getid3->info['video']['codec'] = 'BI_RGB '.$info_bmp_header_raw['bits_per_pixel'].'-bit'; + $getid3->info['video']['bits_per_sample'] = $info_bmp_header_raw['bits_per_pixel']; + + if ($info_bmp['type_version'] >= 2) { + // DWORD Compression; /* Bitmap compression scheme */ + // DWORD ImageDataSize; /* Size of bitmap data in bytes */ + // DWORD XResolution; /* X resolution of display device */ + // DWORD YResolution; /* Y resolution of display device */ + // DWORD ColorsUsed; /* Number of color table indices used */ + // DWORD ColorsImportant; /* Number of important color indices */ + // WORD Units; /* Type of units used to measure resolution */ + // WORD Reserved; /* Pad structure to 4-byte boundary */ + // WORD Recording; /* Recording algorithm */ + // WORD Rendering; /* Halftoning algorithm used */ + // DWORD Size1; /* Reserved for halftoning algorithm use */ + // DWORD Size2; /* Reserved for halftoning algorithm use */ + // DWORD ColorEncoding; /* Color model used in bitmap */ + // DWORD Identifier; /* Reserved for application use */ + + getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 26, + array ( + 'compression' => 4, + 'bmp_data_size' => 4, + 'resolution_h' => 4, + 'resolution_v' => 4, + 'colors_used' => 4, + 'colors_important' => 4, + 'resolution_units' => 2, + 'reserved1' => 2, + 'recording' => 2, + 'rendering' => 2, + 'size1' => 4, + 'size2' => 4, + 'color_encoding' => 4, + 'identifier' => 4 + ) + ); + + $info_bmp_header['compression'] = getid3_bmp::BMPcompressionOS2Lookup($info_bmp_header_raw['compression']); + $getid3->info['video']['codec'] = $info_bmp_header['compression'].' '.$info_bmp_header_raw['bits_per_pixel'].'-bit'; + } + + return true; + } + + + if ($info_bmp['type_os'] == 'Windows') { + + // Windows-format BMP + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + // all versions + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + + getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 18, + array ( + 'width' => -4, //signed + 'height' => -4, //signed + 'planes' => 2, + 'bits_per_pixel' => 2, + 'compression' => 4, + 'bmp_data_size' => 4, + 'resolution_h' => -4, //signed + 'resolution_v' => -4, //signed + 'colors_used' => 4, + 'colors_important' => 4 + ) + ); + foreach (array ('width', 'height', 'resolution_h', 'resolution_v') as $key) { + $info_bmp_header_raw[$key] = getid3_lib::LittleEndian2Int($info_bmp_header_raw[$key], true); + } + + $info_bmp_header['compression'] = getid3_bmp::BMPcompressionWindowsLookup($info_bmp_header_raw['compression']); + $getid3->info['video']['resolution_x'] = $info_bmp_header_raw['width']; + $getid3->info['video']['resolution_y'] = $info_bmp_header_raw['height']; + $getid3->info['video']['codec'] = $info_bmp_header['compression'].' '.$info_bmp_header_raw['bits_per_pixel'].'-bit'; + $getid3->info['video']['bits_per_sample'] = $info_bmp_header_raw['bits_per_pixel']; + + // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen + if (($info_bmp['type_version'] >= 4) || ($info_bmp_header_raw['compression'] == 3)) { + + + $bmp_header .= fread($getid3->fp, 44); + + // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp + // Win95+, WinNT4.0+ + // DWORD bV4RedMask; + // DWORD bV4GreenMask; + // DWORD bV4BlueMask; + // DWORD bV4AlphaMask; + // DWORD bV4CSType; + // CIEXYZTRIPLE bV4Endpoints; + // DWORD bV4GammaRed; + // DWORD bV4GammaGreen; + // DWORD bV4GammaBlue; + + getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 54, + array ( + 'red_mask' => 4, + 'green_mask' => 4, + 'blue_mask' => 4, + 'alpha_mask' => 4, + 'cs_type' => 4, + 'ciexyz_red' => -4, //string + 'ciexyz_green' => -4, //string + 'ciexyz_blue' => -4, //string + 'gamma_red' => 4, + 'gamma_green' => 4, + 'gamma_blue' => 4 + ) + ); + + $info_bmp_header['ciexyz_red'] = getid3_bmp::FixedPoint2_30(strrev($info_bmp_header_raw['ciexyz_red'])); + $info_bmp_header['ciexyz_green'] = getid3_bmp::FixedPoint2_30(strrev($info_bmp_header_raw['ciexyz_green'])); + $info_bmp_header['ciexyz_blue'] = getid3_bmp::FixedPoint2_30(strrev($info_bmp_header_raw['ciexyz_blue'])); + + + if ($info_bmp['type_version'] >= 5) { + $bmp_header .= fread($getid3->fp, 16); + + // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp + // Win98+, Win2000+ + // DWORD bV5Intent; + // DWORD bV5ProfileData; + // DWORD bV5ProfileSize; + // DWORD bV5Reserved; + + getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 98, + array ( + 'intent' => 4, + 'profile_data_offset' => 4, + 'profile_data_size' => 4, + 'reserved3' => 4 + ) + ); + + } + } + + return true; + } + + + throw new getid3_exception('Unknown BMP format in header.'); + + } + + + + public static function BMPcompressionWindowsLookup($compression_id) { + + static $lookup = array ( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'BI_BITFIELDS', + 4 => 'BI_JPEG', + 5 => 'BI_PNG' + ); + return (isset($lookup[$compression_id]) ? $lookup[$compression_id] : 'invalid'); + } + + + + public static function BMPcompressionOS2Lookup($compression_id) { + + static $lookup = array ( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'Huffman 1D', + 4 => 'BI_RLE24', + ); + return (isset($lookup[$compression_id]) ? $lookup[$compression_id] : 'invalid'); + } + + + public static function FixedPoint2_30($raw_data) { + + $binary_string = getid3_lib::BigEndian2Bin($raw_data); + return bindec(substr($binary_string, 0, 2)) + (float)(bindec(substr($binary_string, 2, 30)) / 1073741824); // pow(2, 30) = 1073741824 + } + + +} + + +?>
\ No newline at end of file |