20 function getid3_bmp(&$fd, &$ThisFileInfo, $ExtractPalette=
false, $ExtractData=
false) {
23 $ThisFileInfo[
'bmp'][
'header'][
'raw'] = array();
24 $thisfile_bmp = &$ThisFileInfo[
'bmp'];
25 $thisfile_bmp_header = &$thisfile_bmp[
'header'];
26 $thisfile_bmp_header_raw = &$thisfile_bmp_header[
'raw'];
36 fseek($fd, $ThisFileInfo[
'avdataoffset'], SEEK_SET);
38 $BMPheader = fread($fd, 14 + 40);
40 $thisfile_bmp_header_raw[
'identifier'] = substr($BMPheader, $offset, 2);
43 if ($thisfile_bmp_header_raw[
'identifier'] !=
'BM') {
44 $ThisFileInfo[
'error'][] =
'Expecting "BM" at offset '.$ThisFileInfo[
'avdataoffset'].
', found "'.$thisfile_bmp_header_raw[
'identifier'].
'"';
45 unset($ThisFileInfo[
'fileformat']);
46 unset($ThisFileInfo[
'bmp']);
65 if (($planes22 == 1) && ($planes26 != 1)) {
66 $thisfile_bmp[
'type_os'] =
'OS/2';
67 $thisfile_bmp[
'type_version'] = 1;
68 } elseif (($planes26 == 1) && ($planes22 != 1)) {
69 $thisfile_bmp[
'type_os'] =
'Windows';
70 $thisfile_bmp[
'type_version'] = 1;
71 } elseif ($thisfile_bmp_header_raw[
'header_size'] == 12) {
72 $thisfile_bmp[
'type_os'] =
'OS/2';
73 $thisfile_bmp[
'type_version'] = 1;
74 } elseif ($thisfile_bmp_header_raw[
'header_size'] == 40) {
75 $thisfile_bmp[
'type_os'] =
'Windows';
76 $thisfile_bmp[
'type_version'] = 1;
77 } elseif ($thisfile_bmp_header_raw[
'header_size'] == 84) {
78 $thisfile_bmp[
'type_os'] =
'Windows';
79 $thisfile_bmp[
'type_version'] = 4;
80 } elseif ($thisfile_bmp_header_raw[
'header_size'] == 100) {
81 $thisfile_bmp[
'type_os'] =
'Windows';
82 $thisfile_bmp[
'type_version'] = 5;
84 $ThisFileInfo[
'error'][] =
'Unknown BMP subtype (or not a BMP file)';
85 unset($ThisFileInfo[
'fileformat']);
86 unset($ThisFileInfo[
'bmp']);
90 $ThisFileInfo[
'fileformat'] =
'bmp';
91 $ThisFileInfo[
'video'][
'dataformat'] =
'bmp';
92 $ThisFileInfo[
'video'][
'lossless'] =
true;
93 $ThisFileInfo[
'video'][
'pixel_aspect_ratio'] = (float) 1;
95 if ($thisfile_bmp[
'type_os'] ==
'OS/2') {
115 $ThisFileInfo[
'video'][
'resolution_x'] = $thisfile_bmp_header_raw[
'width'];
116 $ThisFileInfo[
'video'][
'resolution_y'] = $thisfile_bmp_header_raw[
'height'];
117 $ThisFileInfo[
'video'][
'codec'] =
'BI_RGB '.$thisfile_bmp_header_raw[
'bits_per_pixel'].
'-bit';
118 $ThisFileInfo[
'video'][
'bits_per_sample'] = $thisfile_bmp_header_raw[
'bits_per_pixel'];
120 if ($thisfile_bmp[
'type_version'] >= 2) {
167 $ThisFileInfo[
'video'][
'codec'] = $thisfile_bmp_header[
'compression'].
' '.$thisfile_bmp_header_raw[
'bits_per_pixel'].
'-bit';
170 } elseif ($thisfile_bmp[
'type_os'] ==
'Windows') {
210 $ThisFileInfo[
'video'][
'resolution_x'] = $thisfile_bmp_header_raw[
'width'];
211 $ThisFileInfo[
'video'][
'resolution_y'] = $thisfile_bmp_header_raw[
'height'];
212 $ThisFileInfo[
'video'][
'codec'] = $thisfile_bmp_header[
'compression'].
' '.$thisfile_bmp_header_raw[
'bits_per_pixel'].
'-bit';
213 $ThisFileInfo[
'video'][
'bits_per_sample'] = $thisfile_bmp_header_raw[
'bits_per_pixel'];
215 if (($thisfile_bmp[
'type_version'] >= 4) || ($thisfile_bmp_header_raw[
'compression'] == 3)) {
217 $BMPheader .= fread($fd, 44);
240 $thisfile_bmp_header_raw[
'ciexyz_red'] = substr($BMPheader, $offset, 4);
242 $thisfile_bmp_header_raw[
'ciexyz_green'] = substr($BMPheader, $offset, 4);
244 $thisfile_bmp_header_raw[
'ciexyz_blue'] = substr($BMPheader, $offset, 4);
258 if ($thisfile_bmp[
'type_version'] >= 5) {
259 $BMPheader .= fread($fd, 16);
279 $ThisFileInfo[
'error'][] =
'Unknown BMP format in header.';
285 if ($ExtractPalette || $ExtractData) {
287 if ($thisfile_bmp_header_raw[
'bits_per_pixel'] < 16) {
288 $PaletteEntries = pow(2, $thisfile_bmp_header_raw[
'bits_per_pixel']);
289 } elseif (isset($thisfile_bmp_header_raw[
'colors_used']) && ($thisfile_bmp_header_raw[
'colors_used'] > 0) && ($thisfile_bmp_header_raw[
'colors_used'] <= 256)) {
290 $PaletteEntries = $thisfile_bmp_header_raw[
'colors_used'];
292 if ($PaletteEntries > 0) {
293 $BMPpalette = fread($fd, 4 * $PaletteEntries);
295 for ($i = 0; $i < $PaletteEntries; $i++) {
304 if (($thisfile_bmp[
'type_os'] ==
'OS/2') && ($thisfile_bmp[
'type_version'] == 1)) {
309 $thisfile_bmp[
'palette'][$i] = (($red << 16) | ($green << 8) | $blue);
315 fseek($fd, $thisfile_bmp_header_raw[
'data_offset'], SEEK_SET);
316 $RowByteLength = ceil(($thisfile_bmp_header_raw[
'width'] * ($thisfile_bmp_header_raw[
'bits_per_pixel'] / 8)) / 4) * 4;
317 $BMPpixelData = fread($fd, $thisfile_bmp_header_raw[
'height'] * $RowByteLength);
318 $pixeldataoffset = 0;
319 switch (@$thisfile_bmp_header_raw[
'compression']) {
322 switch ($thisfile_bmp_header_raw[
'bits_per_pixel']) {
324 for (
$row = ($thisfile_bmp_header_raw[
'height'] - 1);
$row >= 0;
$row--) {
325 for ($col = 0; $col < $thisfile_bmp_header_raw[
'width']; $col = $col) {
326 $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++});
327 for ($i = 7; $i >= 0; $i--) {
328 $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i;
329 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$paletteindex];
333 while (($pixeldataoffset % 4) != 0) {
341 for (
$row = ($thisfile_bmp_header_raw[
'height'] - 1);
$row >= 0;
$row--) {
342 for ($col = 0; $col < $thisfile_bmp_header_raw[
'width']; $col = $col) {
343 $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++});
344 for ($i = 1; $i >= 0; $i--) {
345 $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i);
346 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$paletteindex];
350 while (($pixeldataoffset % 4) != 0) {
358 for (
$row = ($thisfile_bmp_header_raw[
'height'] - 1);
$row >= 0;
$row--) {
359 for ($col = 0; $col < $thisfile_bmp_header_raw[
'width']; $col++) {
360 $paletteindex = ord($BMPpixelData{$pixeldataoffset++});
361 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$paletteindex];
363 while (($pixeldataoffset % 4) != 0) {
371 for (
$row = ($thisfile_bmp_header_raw[
'height'] - 1);
$row >= 0;
$row--) {
372 for ($col = 0; $col < $thisfile_bmp_header_raw[
'width']; $col++) {
373 $thisfile_bmp[
'data'][
$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset});
374 $pixeldataoffset += 3;
376 while (($pixeldataoffset % 4) != 0) {
384 for (
$row = ($thisfile_bmp_header_raw[
'height'] - 1);
$row >= 0;
$row--) {
385 for ($col = 0; $col < $thisfile_bmp_header_raw[
'width']; $col++) {
386 $thisfile_bmp[
'data'][
$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset});
387 $pixeldataoffset += 4;
389 while (($pixeldataoffset % 4) != 0) {
401 $ThisFileInfo[
'error'][] =
'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw[
'bits_per_pixel'].
') - cannot read pixel data';
408 switch ($thisfile_bmp_header_raw[
'bits_per_pixel']) {
411 while ($pixeldataoffset < strlen($BMPpixelData)) {
414 if ($firstbyte == 0) {
419 switch ($secondbyte) {
427 $pixeldataoffset = strlen($BMPpixelData);
436 $col = ($pixelcounter % $thisfile_bmp_header_raw[
'width']) + $colincrement;
437 $row = ($thisfile_bmp_header_raw[
'height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw[
'width'])) - $rowincrement;
438 $pixelcounter = (
$row * $thisfile_bmp_header_raw[
'width']) + $col;
446 for ($i = 0; $i < $secondbyte; $i++) {
448 $col = $pixelcounter % $thisfile_bmp_header_raw[
'width'];
449 $row = $thisfile_bmp_header_raw[
'height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw[
'width']);
450 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$paletteindex];
453 while (($pixeldataoffset % 2) != 0) {
464 for ($i = 0; $i < $firstbyte; $i++) {
465 $col = $pixelcounter % $thisfile_bmp_header_raw[
'width'];
466 $row = $thisfile_bmp_header_raw[
'height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw[
'width']);
467 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$secondbyte];
476 $ThisFileInfo[
'error'][] =
'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw[
'bits_per_pixel'].
') - cannot read pixel data';
484 switch ($thisfile_bmp_header_raw[
'bits_per_pixel']) {
487 while ($pixeldataoffset < strlen($BMPpixelData)) {
490 if ($firstbyte == 0) {
495 switch ($secondbyte) {
503 $pixeldataoffset = strlen($BMPpixelData);
512 $col = ($pixelcounter % $thisfile_bmp_header_raw[
'width']) + $colincrement;
513 $row = ($thisfile_bmp_header_raw[
'height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw[
'width'])) - $rowincrement;
514 $pixelcounter = (
$row * $thisfile_bmp_header_raw[
'width']) + $col;
522 unset($paletteindexes);
523 for ($i = 0; $i < ceil($secondbyte / 2); $i++) {
525 $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4;
526 $paletteindexes[] = ($paletteindexbyte & 0x0F);
528 while (($pixeldataoffset % 2) != 0) {
533 foreach ($paletteindexes as $paletteindex) {
534 $col = $pixelcounter % $thisfile_bmp_header_raw[
'width'];
535 $row = $thisfile_bmp_header_raw[
'height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw[
'width']);
536 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$paletteindex];
551 $paletteindexes[0] = ($secondbyte & 0xF0) >> 4;
552 $paletteindexes[1] = ($secondbyte & 0x0F);
553 for ($i = 0; $i < $firstbyte; $i++) {
554 $col = $pixelcounter % $thisfile_bmp_header_raw[
'width'];
555 $row = $thisfile_bmp_header_raw[
'height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw[
'width']);
556 $thisfile_bmp[
'data'][
$row][$col] = $thisfile_bmp[
'palette'][$paletteindexes[($i % 2)]];
565 $ThisFileInfo[
'error'][] =
'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw[
'bits_per_pixel'].
') - cannot read pixel data';
572 switch ($thisfile_bmp_header_raw[
'bits_per_pixel']) {
578 while ((($thisfile_bmp_header_raw[
'red_mask'] >> $redshift) & 0x01) == 0) {
581 while ((($thisfile_bmp_header_raw[
'green_mask'] >> $greenshift) & 0x01) == 0) {
584 while ((($thisfile_bmp_header_raw[
'blue_mask'] >> $blueshift) & 0x01) == 0) {
587 for (
$row = ($thisfile_bmp_header_raw[
'height'] - 1);
$row >= 0;
$row--) {
588 for ($col = 0; $col < $thisfile_bmp_header_raw[
'width']; $col++) {
590 $pixeldataoffset += $thisfile_bmp_header_raw[
'bits_per_pixel'] / 8;
592 $red = intval(round(((($pixelvalue & $thisfile_bmp_header_raw[
'red_mask']) >> $redshift) / ($thisfile_bmp_header_raw[
'red_mask'] >> $redshift)) * 255));
593 $green = intval(round(((($pixelvalue & $thisfile_bmp_header_raw[
'green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw[
'green_mask'] >> $greenshift)) * 255));
594 $blue = intval(round(((($pixelvalue & $thisfile_bmp_header_raw[
'blue_mask']) >> $blueshift) / ($thisfile_bmp_header_raw[
'blue_mask'] >> $blueshift)) * 255));
595 $thisfile_bmp[
'data'][
$row][$col] = (($red << 16) | ($green << 8) | ($blue));
597 while (($pixeldataoffset % 4) != 0) {
605 $ThisFileInfo[
'error'][] =
'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw[
'bits_per_pixel'].
') - cannot read pixel data';
612 $ThisFileInfo[
'error'][] =
'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw[
'compression'].
') - cannot decompress pixel data';
623 if (!isset($BMPinfo[
'bmp'][
'data']) || !is_array($BMPinfo[
'bmp'][
'data'])) {
624 echo
'ERROR: no pixel data<BR>';
627 set_time_limit(intval(round($BMPinfo[
'resolution_x'] * $BMPinfo[
'resolution_y'] / 10000)));
628 if ($im = ImageCreateTrueColor($BMPinfo[
'resolution_x'], $BMPinfo[
'resolution_y'])) {
629 for (
$row = 0;
$row < $BMPinfo[
'resolution_y'];
$row++) {
630 for ($col = 0; $col < $BMPinfo[
'resolution_x']; $col++) {
631 if (isset($BMPinfo[
'bmp'][
'data'][
$row][$col])) {
632 $red = ($BMPinfo[
'bmp'][
'data'][
$row][$col] & 0x00FF0000) >> 16;
633 $green = ($BMPinfo[
'bmp'][
'data'][
$row][$col] & 0x0000FF00) >> 8;
634 $blue = ($BMPinfo[
'bmp'][
'data'][
$row][$col] & 0x000000FF);
635 $pixelcolor = ImageColorAllocate($im, $red, $green, $blue);
636 ImageSetPixel($im, $col,
$row, $pixelcolor);
643 if (headers_sent()) {
644 echo
'plotted '.($BMPinfo[
'resolution_x'] * $BMPinfo[
'resolution_y']).
' pixels in '.(time() - $starttime).
' seconds<BR>';
648 header(
'Content-type: image/png');
658 static $BMPcompressionWindowsLookup = array(
666 return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] :
'invalid');
670 static $BMPcompressionOS2Lookup = array(
677 return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] :
'invalid');