| [ Index ] |
PHP Cross Reference of Limb3 |
[Summary view] [Print] [Text view]
1 <?php 2 ///////////////////////////////////////////////////////////////// 3 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 ///////////////////////////////////////////////////////////////// 7 // See readme.txt for more details // 8 ///////////////////////////////////////////////////////////////// 9 // // 10 // module.graphic.bmp.php // 11 // module for analyzing BMP Image files // 12 // dependencies: NONE // 13 // /// 14 ///////////////////////////////////////////////////////////////// 15 // // 16 // Modified for use in phpThumb() - James Heinrich 2004.07.27 // 17 // // 18 ///////////////////////////////////////////////////////////////// 19 20 21 class phpthumb_bmp { 22 23 function phpthumb_bmp() { 24 return true; 25 } 26 27 function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) { 28 $ThisFileInfo = array(); 29 if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) { 30 $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor); 31 return $gd; 32 } 33 return false; 34 } 35 36 function phpthumb_bmpfile2gd($filename, $truecolor=true) { 37 if ($fp = @fopen($filename, 'rb')) { 38 $BMPdata = fread($fp, filesize($filename)); 39 fclose($fp); 40 return $this->phpthumb_bmp2gd($BMPdata, $truecolor); 41 } 42 return false; 43 } 44 45 function GD2BMPstring(&$gd_image) { 46 $imageX = ImageSX($gd_image); 47 $imageY = ImageSY($gd_image); 48 49 $BMP = ''; 50 for ($y = ($imageY - 1); $y >= 0; $y--) { 51 $thisline = ''; 52 for ($x = 0; $x < $imageX; $x++) { 53 $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); 54 $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']); 55 } 56 while (strlen($thisline) % 4) { 57 $thisline .= "\x00"; 58 } 59 $BMP .= $thisline; 60 } 61 62 $bmpSize = strlen($BMP) + 14 + 40; 63 // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp 64 $BITMAPFILEHEADER = 'BM'; // WORD bfType; 65 $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD bfSize; 66 $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved1; 67 $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved2; 68 $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 54, 4); // DWORD bfOffBits; 69 70 // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp 71 $BITMAPINFOHEADER = phpthumb_functions::LittleEndian2String( 40, 4); // DWORD biSize; 72 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG biWidth; 73 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG biHeight; 74 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 1, 2); // WORD biPlanes; 75 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 24, 2); // WORD biBitCount; 76 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biCompression; 77 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biSizeImage; 78 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter; 79 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter; 80 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrUsed; 81 $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrImportant; 82 83 return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP; 84 } 85 86 function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) { 87 88 // shortcuts 89 $ThisFileInfo['bmp']['header']['raw'] = array(); 90 $thisfile_bmp = &$ThisFileInfo['bmp']; 91 $thisfile_bmp_header = &$thisfile_bmp['header']; 92 $thisfile_bmp_header_raw = &$thisfile_bmp_header['raw']; 93 94 // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp 95 // all versions 96 // WORD bfType; 97 // DWORD bfSize; 98 // WORD bfReserved1; 99 // WORD bfReserved2; 100 // DWORD bfOffBits; 101 102 $offset = 0; 103 $overalloffset = 0; 104 $BMPheader = substr($BMPdata, $overalloffset, 14 + 40); 105 $overalloffset += (14 + 40); 106 107 $thisfile_bmp_header_raw['identifier'] = substr($BMPheader, $offset, 2); 108 $offset += 2; 109 110 if ($thisfile_bmp_header_raw['identifier'] != 'BM') { 111 $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.intval(@$ThisFileInfo['avdataoffset']).', found "'.$thisfile_bmp_header_raw['identifier'].'"'; 112 unset($ThisFileInfo['fileformat']); 113 unset($ThisFileInfo['bmp']); 114 return false; 115 } 116 117 $thisfile_bmp_header_raw['filesize'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 118 $offset += 4; 119 $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 120 $offset += 2; 121 $thisfile_bmp_header_raw['reserved2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 122 $offset += 2; 123 $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 124 $offset += 4; 125 $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 126 $offset += 4; 127 128 129 // check if the hardcoded-to-1 "planes" is at offset 22 or 26 130 $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2)); 131 $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2)); 132 if (($planes22 == 1) && ($planes26 != 1)) { 133 $thisfile_bmp['type_os'] = 'OS/2'; 134 $thisfile_bmp['type_version'] = 1; 135 } elseif (($planes26 == 1) && ($planes22 != 1)) { 136 $thisfile_bmp['type_os'] = 'Windows'; 137 $thisfile_bmp['type_version'] = 1; 138 } elseif ($thisfile_bmp_header_raw['header_size'] == 12) { 139 $thisfile_bmp['type_os'] = 'OS/2'; 140 $thisfile_bmp['type_version'] = 1; 141 } elseif ($thisfile_bmp_header_raw['header_size'] == 40) { 142 $thisfile_bmp['type_os'] = 'Windows'; 143 $thisfile_bmp['type_version'] = 1; 144 } elseif ($thisfile_bmp_header_raw['header_size'] == 84) { 145 $thisfile_bmp['type_os'] = 'Windows'; 146 $thisfile_bmp['type_version'] = 4; 147 } elseif ($thisfile_bmp_header_raw['header_size'] == 100) { 148 $thisfile_bmp['type_os'] = 'Windows'; 149 $thisfile_bmp['type_version'] = 5; 150 } else { 151 $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)'; 152 unset($ThisFileInfo['fileformat']); 153 unset($ThisFileInfo['bmp']); 154 return false; 155 } 156 157 $ThisFileInfo['fileformat'] = 'bmp'; 158 $ThisFileInfo['video']['dataformat'] = 'bmp'; 159 $ThisFileInfo['video']['lossless'] = true; 160 $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1; 161 162 if ($thisfile_bmp['type_os'] == 'OS/2') { 163 164 // OS/2-format BMP 165 // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm 166 167 // DWORD Size; /* Size of this structure in bytes */ 168 // DWORD Width; /* Bitmap width in pixels */ 169 // DWORD Height; /* Bitmap height in pixel */ 170 // WORD NumPlanes; /* Number of bit planes (color depth) */ 171 // WORD BitsPerPixel; /* Number of bits per pixel per plane */ 172 173 $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 174 $offset += 2; 175 $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 176 $offset += 2; 177 $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 178 $offset += 2; 179 $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 180 $offset += 2; 181 182 $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; 183 $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; 184 $ThisFileInfo['video']['codec'] = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; 185 $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; 186 187 if ($thisfile_bmp['type_version'] >= 2) { 188 // DWORD Compression; /* Bitmap compression scheme */ 189 // DWORD ImageDataSize; /* Size of bitmap data in bytes */ 190 // DWORD XResolution; /* X resolution of display device */ 191 // DWORD YResolution; /* Y resolution of display device */ 192 // DWORD ColorsUsed; /* Number of color table indices used */ 193 // DWORD ColorsImportant; /* Number of important color indices */ 194 // WORD Units; /* Type of units used to measure resolution */ 195 // WORD Reserved; /* Pad structure to 4-byte boundary */ 196 // WORD Recording; /* Recording algorithm */ 197 // WORD Rendering; /* Halftoning algorithm used */ 198 // DWORD Size1; /* Reserved for halftoning algorithm use */ 199 // DWORD Size2; /* Reserved for halftoning algorithm use */ 200 // DWORD ColorEncoding; /* Color model used in bitmap */ 201 // DWORD Identifier; /* Reserved for application use */ 202 203 $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 204 $offset += 4; 205 $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 206 $offset += 4; 207 $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 208 $offset += 4; 209 $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 210 $offset += 4; 211 $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 212 $offset += 4; 213 $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 214 $offset += 4; 215 $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 216 $offset += 2; 217 $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 218 $offset += 2; 219 $thisfile_bmp_header_raw['recording'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 220 $offset += 2; 221 $thisfile_bmp_header_raw['rendering'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 222 $offset += 2; 223 $thisfile_bmp_header_raw['size1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 224 $offset += 4; 225 $thisfile_bmp_header_raw['size2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 226 $offset += 4; 227 $thisfile_bmp_header_raw['color_encoding'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 228 $offset += 4; 229 $thisfile_bmp_header_raw['identifier'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 230 $offset += 4; 231 232 $thisfile_bmp_header['compression'] = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']); 233 234 $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; 235 } 236 237 } elseif ($thisfile_bmp['type_os'] == 'Windows') { 238 239 // Windows-format BMP 240 241 // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp 242 // all versions 243 // DWORD biSize; 244 // LONG biWidth; 245 // LONG biHeight; 246 // WORD biPlanes; 247 // WORD biBitCount; 248 // DWORD biCompression; 249 // DWORD biSizeImage; 250 // LONG biXPelsPerMeter; 251 // LONG biYPelsPerMeter; 252 // DWORD biClrUsed; 253 // DWORD biClrImportant; 254 255 $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); 256 $offset += 4; 257 $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); 258 $offset += 4; 259 $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 260 $offset += 2; 261 $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); 262 $offset += 2; 263 $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 264 $offset += 4; 265 $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 266 $offset += 4; 267 $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); 268 $offset += 4; 269 $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); 270 $offset += 4; 271 $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 272 $offset += 4; 273 $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 274 $offset += 4; 275 276 $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']); 277 $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; 278 $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; 279 $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; 280 $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; 281 282 if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) { 283 // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen 284 $BMPheader .= substr($BMPdata, $overalloffset, 44); 285 $overalloffset += 44; 286 287 // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp 288 // Win95+, WinNT4.0+ 289 // DWORD bV4RedMask; 290 // DWORD bV4GreenMask; 291 // DWORD bV4BlueMask; 292 // DWORD bV4AlphaMask; 293 // DWORD bV4CSType; 294 // CIEXYZTRIPLE bV4Endpoints; 295 // DWORD bV4GammaRed; 296 // DWORD bV4GammaGreen; 297 // DWORD bV4GammaBlue; 298 $thisfile_bmp_header_raw['red_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 299 $offset += 4; 300 $thisfile_bmp_header_raw['green_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 301 $offset += 4; 302 $thisfile_bmp_header_raw['blue_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 303 $offset += 4; 304 $thisfile_bmp_header_raw['alpha_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 305 $offset += 4; 306 $thisfile_bmp_header_raw['cs_type'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 307 $offset += 4; 308 $thisfile_bmp_header_raw['ciexyz_red'] = substr($BMPheader, $offset, 4); 309 $offset += 4; 310 $thisfile_bmp_header_raw['ciexyz_green'] = substr($BMPheader, $offset, 4); 311 $offset += 4; 312 $thisfile_bmp_header_raw['ciexyz_blue'] = substr($BMPheader, $offset, 4); 313 $offset += 4; 314 $thisfile_bmp_header_raw['gamma_red'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 315 $offset += 4; 316 $thisfile_bmp_header_raw['gamma_green'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); 317 $offset += 4; 318 $thisfile_bmp_header_raw['gamma_blue'] = $this->LittleEndian2Int(substr($BMPheader,