source: extensions/charlies_content/getid3/getid3/module.graphic.bmp.php @ 3318

Revision 3318, 13.7 KB checked in by vdigital, 11 years ago (diff)

+ Add Charlies' content to depository

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2// +----------------------------------------------------------------------+
3// | PHP version 5                                                        |
4// +----------------------------------------------------------------------+
5// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
6// +----------------------------------------------------------------------+
7// | This source file is subject to version 2 of the GPL license,         |
8// | that is bundled with this package in the file license.txt and is     |
9// | available through the world-wide-web at the following url:           |
10// | http://www.gnu.org/copyleft/gpl.html                                 |
11// +----------------------------------------------------------------------+
12// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
13// +----------------------------------------------------------------------+
14// | Authors: James Heinrich <infoØgetid3*org>                            |
15// |          Allan Hansen <ahØartemis*dk>                                |
16// +----------------------------------------------------------------------+
17// | module.graphic.bmp.php                                               |
18// | Module for analyzing BMP graphic files.                              |
19// | dependencies: NONE                                                   |
20// +----------------------------------------------------------------------+
21//
22// $Id$
23
24       
25       
26class getid3_bmp extends getid3_handler
27{
28
29
30    public function Analyze() {
31
32        $getid3 = $this->getid3;
33
34        // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
35        // all versions
36        // WORD    bfType;
37        // DWORD   bfSize;
38        // WORD    bfReserved1;
39        // WORD    bfReserved2;
40        // DWORD   bfOffBits;
41       
42        // shortcuts
43        $getid3->info['bmp']['header']['raw'] = array ();
44        $info_bmp            = &$getid3->info['bmp'];
45        $info_bmp_header     = &$info_bmp['header'];
46        $info_bmp_header_raw = &$info_bmp_header['raw'];
47
48        fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);
49        $bmp_header = fread($getid3->fp, 14 + 40);
50
51        // Magic bytes
52        $info_bmp_header_raw['identifier'] = 'BM';
53       
54        getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 2,
55            array (
56                'filesize'    => 4,
57                'reserved1'   => 2,
58                'reserved2'   => 2,
59                'data_offset' => 4,
60                'header_size' => 4
61            )
62        );
63       
64        // Check if the hardcoded-to-1 "planes" is at offset 22 or 26
65        $planes22 = getid3_lib::LittleEndian2Int(substr($bmp_header, 22, 2));
66        $planes26 = getid3_lib::LittleEndian2Int(substr($bmp_header, 26, 2));
67        if (($planes22 == 1) && ($planes26 != 1)) {
68            $info_bmp['type_os']      = 'OS/2';
69            $info_bmp['type_version'] = 1;
70        } 
71        elseif (($planes26 == 1) && ($planes22 != 1)) {
72            $info_bmp['type_os']      = 'Windows';
73            $info_bmp['type_version'] = 1;
74        } 
75        elseif ($info_bmp_header_raw['header_size'] == 12) {
76            $info_bmp['type_os']      = 'OS/2';
77            $info_bmp['type_version'] = 1;
78        } 
79        elseif ($info_bmp_header_raw['header_size'] == 40) {
80            $info_bmp['type_os']      = 'Windows';
81            $info_bmp['type_version'] = 1;
82        } 
83        elseif ($info_bmp_header_raw['header_size'] == 84) {
84            $info_bmp['type_os']      = 'Windows';
85            $info_bmp['type_version'] = 4;
86        } 
87        elseif ($info_bmp_header_raw['header_size'] == 100) {
88            $info_bmp['type_os']      = 'Windows';
89            $info_bmp['type_version'] = 5;
90        } 
91        else {
92            throw new getid3_exception('Unknown BMP subtype (or not a BMP file)');
93        }
94
95        $getid3->info['fileformat']                  = 'bmp';
96        $getid3->info['video']['dataformat']         = 'bmp';
97        $getid3->info['video']['lossless']           = true;
98        $getid3->info['video']['pixel_aspect_ratio'] = (float)1;
99
100        if ($info_bmp['type_os'] == 'OS/2') {
101
102            // OS/2-format BMP
103            // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm
104
105            // DWORD  Size;             /* Size of this structure in bytes */
106            // DWORD  Width;            /* Bitmap width in pixels */
107            // DWORD  Height;           /* Bitmap height in pixel */
108            // WORD   NumPlanes;        /* Number of bit planes (color depth) */
109            // WORD   BitsPerPixel;     /* Number of bits per pixel per plane */
110           
111            getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 18,
112                array (
113                    'width'          => 2,
114                    'height'         => 2,
115                    'planes'         => 2,
116                    'bits_per_pixel' => 2
117                )
118            );
119           
120            $getid3->info['video']['resolution_x']    = $info_bmp_header_raw['width'];
121            $getid3->info['video']['resolution_y']    = $info_bmp_header_raw['height'];
122            $getid3->info['video']['codec']           = 'BI_RGB '.$info_bmp_header_raw['bits_per_pixel'].'-bit';
123            $getid3->info['video']['bits_per_sample'] = $info_bmp_header_raw['bits_per_pixel'];
124           
125            if ($info_bmp['type_version'] >= 2) {
126                // DWORD  Compression;      /* Bitmap compression scheme */
127                // DWORD  ImageDataSize;    /* Size of bitmap data in bytes */
128                // DWORD  XResolution;      /* X resolution of display device */
129                // DWORD  YResolution;      /* Y resolution of display device */
130                // DWORD  ColorsUsed;       /* Number of color table indices used */
131                // DWORD  ColorsImportant;  /* Number of important color indices */
132                // WORD   Units;            /* Type of units used to measure resolution */
133                // WORD   Reserved;         /* Pad structure to 4-byte boundary */
134                // WORD   Recording;        /* Recording algorithm */
135                // WORD   Rendering;        /* Halftoning algorithm used */
136                // DWORD  Size1;            /* Reserved for halftoning algorithm use */
137                // DWORD  Size2;            /* Reserved for halftoning algorithm use */
138                // DWORD  ColorEncoding;    /* Color model used in bitmap */
139                // DWORD  Identifier;       /* Reserved for application use */
140               
141                getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 26,
142                    array (
143                        'compression'      => 4,
144                        'bmp_data_size'    => 4,
145                        'resolution_h'     => 4,
146                        'resolution_v'     => 4,
147                        'colors_used'      => 4,
148                        'colors_important' => 4,
149                        'resolution_units' => 2,
150                        'reserved1'        => 2,
151                        'recording'        => 2,
152                        'rendering'        => 2,
153                        'size1'            => 4,
154                        'size2'            => 4,
155                        'color_encoding'   => 4,
156                        'identifier'       => 4
157                    )
158                );
159
160                $info_bmp_header['compression'] = getid3_bmp::BMPcompressionOS2Lookup($info_bmp_header_raw['compression']);
161                $getid3->info['video']['codec'] = $info_bmp_header['compression'].' '.$info_bmp_header_raw['bits_per_pixel'].'-bit';
162            }
163           
164            return true;
165        } 
166   
167       
168        if ($info_bmp['type_os'] == 'Windows') {
169
170            // Windows-format BMP
171
172            // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
173            // all versions
174            // DWORD  biSize;
175            // LONG   biWidth;
176            // LONG   biHeight;
177            // WORD   biPlanes;
178            // WORD   biBitCount;
179            // DWORD  biCompression;
180            // DWORD  biSizeImage;
181            // LONG   biXPelsPerMeter;
182            // LONG   biYPelsPerMeter;
183            // DWORD  biClrUsed;
184            // DWORD  biClrImportant;
185
186            getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 18,
187                array (
188                    'width'            => -4,        //signed
189                    'height'           => -4,        //signed
190                    'planes'           => 2,
191                    'bits_per_pixel'   => 2,
192                    'compression'      => 4,
193                    'bmp_data_size'    => 4,
194                    'resolution_h'     => -4,        //signed
195                    'resolution_v'     => -4,        //signed
196                    'colors_used'      => 4,
197                    'colors_important' => 4
198                )
199            );
200            foreach (array ('width', 'height', 'resolution_h', 'resolution_v') as $key) {
201                $info_bmp_header_raw[$key] = getid3_lib::LittleEndian2Int($info_bmp_header_raw[$key], true);
202            }
203           
204            $info_bmp_header['compression']           = getid3_bmp::BMPcompressionWindowsLookup($info_bmp_header_raw['compression']);
205            $getid3->info['video']['resolution_x']    = $info_bmp_header_raw['width'];
206            $getid3->info['video']['resolution_y']    = $info_bmp_header_raw['height'];
207            $getid3->info['video']['codec']           = $info_bmp_header['compression'].' '.$info_bmp_header_raw['bits_per_pixel'].'-bit';
208            $getid3->info['video']['bits_per_sample'] = $info_bmp_header_raw['bits_per_pixel'];
209
210            // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen
211            if (($info_bmp['type_version'] >= 4) || ($info_bmp_header_raw['compression'] == 3)) {
212                   
213               
214                $bmp_header .= fread($getid3->fp, 44);
215
216                // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp
217                // Win95+, WinNT4.0+
218                // DWORD        bV4RedMask;
219                // DWORD        bV4GreenMask;
220                // DWORD        bV4BlueMask;
221                // DWORD        bV4AlphaMask;
222                // DWORD        bV4CSType;
223                // CIEXYZTRIPLE bV4Endpoints;
224                // DWORD        bV4GammaRed;
225                // DWORD        bV4GammaGreen;
226                // DWORD        bV4GammaBlue;
227               
228                getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 54,
229                    array (
230                        'red_mask'     => 4,
231                        'green_mask'   => 4,
232                        'blue_mask'    => 4,
233                        'alpha_mask'   => 4,
234                        'cs_type'      => 4,
235                        'ciexyz_red'   => -4,       //string
236                        'ciexyz_green' => -4,       //string
237                        'ciexyz_blue'  => -4,       //string
238                        'gamma_red'    => 4,
239                        'gamma_green'  => 4,
240                        'gamma_blue'   => 4
241                    )
242                );
243               
244                $info_bmp_header['ciexyz_red']   = getid3_bmp::FixedPoint2_30(strrev($info_bmp_header_raw['ciexyz_red']));
245                $info_bmp_header['ciexyz_green'] = getid3_bmp::FixedPoint2_30(strrev($info_bmp_header_raw['ciexyz_green']));
246                $info_bmp_header['ciexyz_blue']  = getid3_bmp::FixedPoint2_30(strrev($info_bmp_header_raw['ciexyz_blue']));
247           
248
249                if ($info_bmp['type_version'] >= 5) {
250                    $bmp_header .= fread($getid3->fp, 16);
251   
252                    // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp
253                    // Win98+, Win2000+
254                    // DWORD        bV5Intent;
255                    // DWORD        bV5ProfileData;
256                    // DWORD        bV5ProfileSize;
257                    // DWORD        bV5Reserved;
258                   
259                    getid3_lib::ReadSequence('LittleEndian2Int', $info_bmp_header_raw, $bmp_header, 98,
260                        array (
261                            'intent'              => 4,
262                            'profile_data_offset' => 4,
263                            'profile_data_size'   => 4,
264                            'reserved3'           => 4
265                        )
266                    );
267                   
268                }
269            }
270           
271            return true;
272        }
273
274
275        throw new getid3_exception('Unknown BMP format in header.');
276       
277    }
278
279
280
281    public static function BMPcompressionWindowsLookup($compression_id) {
282
283        static $lookup = array (
284            0 => 'BI_RGB',
285            1 => 'BI_RLE8',
286            2 => 'BI_RLE4',
287            3 => 'BI_BITFIELDS',
288            4 => 'BI_JPEG',
289            5 => 'BI_PNG'
290        );
291        return (isset($lookup[$compression_id]) ? $lookup[$compression_id] : 'invalid');
292    }
293
294
295
296    public static function BMPcompressionOS2Lookup($compression_id) {
297       
298        static $lookup = array (
299            0 => 'BI_RGB',
300            1 => 'BI_RLE8',
301            2 => 'BI_RLE4',
302            3 => 'Huffman 1D',
303            4 => 'BI_RLE24',
304        );
305        return (isset($lookup[$compression_id]) ? $lookup[$compression_id] : 'invalid');
306    }
307   
308   
309    public static function FixedPoint2_30($raw_data) {
310       
311        $binary_string = getid3_lib::BigEndian2Bin($raw_data);
312        return bindec(substr($binary_string, 0, 2)) + (float)(bindec(substr($binary_string, 2, 30)) / 1073741824);        // pow(2, 30) = 1073741824
313    }
314
315
316}
317
318
319?>
Note: See TracBrowser for help on using the repository browser.