1
0
Fork 0
mirror of https://github.com/Yetangitu/ampache synced 2025-10-05 10:49:37 +02:00
ampache/modules/getid3/module.graphic.bmp.php

319 lines
No EOL
14 KiB
PHP

<?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
}
}
?>