| |
BMP
Informations
Author: Valentin Schmidt
License: Freeware
Version: 1.1
Description
This script adds support for windows bitmaps (*.bmp, *.rle) to FPDF.
Source
<?php
//*************************************************************************
// Script: PDF_BMP
// Version: 1.1
//
// This extension adds support for windows bitmaps (*.bmp, *.rle)
//
//**************************************************************************
require('../fpdf.php');
class PDF_BMP extends FPDF
{
function _parsebmp ($file){
$fsize = filesize($file);
$f = fopen($file, 'rb');
# bmpfileheader (0..13)
$bfOffBits = $this->_fread_long_le_at($f, 10);
# bmpinfoheader (14..53)
$width = $this->_fread_long_le_at($f, 18);
$height = $this->_fread_long_le_at($f, 22);
$flip = ($height<0);
if ($flip) $height =-$height;
$biBitCount = $this->_fread_short_le_at($f, 28);
$biCompression = $this->_fread_long_le_at($f, 30); # BI_RGB = 0, BI_RLE8 = 1, BI_RLE4 = 2
$info = array('w'=>$width, 'h'=>$height);
fseek($f, 54);
if ($biBitCount<16){
$info['cs'] = 'Indexed';
$info['bpc'] = $biBitCount;
$palStr = fread($f, $bfOffBits-54); # palette
$pal = '';
$cnt = strlen($palStr)/4;
for ($i=0;$i<$cnt;$i++){
$n = 4*$i;
$pal .= $palStr{$n+2}.$palStr{$n+1}.$palStr{$n};
}
$info['pal'] = $pal;
}else{
$info['cs'] = 'DeviceRGB';
$info['bpc'] = 8;
}
# image data
switch ($biCompression){
case 0:
$str = fread($f, $fsize-$bfOffBits);
break;
case 1: # BI_RLE8
$str = $this->rle8_decode(fread($f, $fsize-$bfOffBits), $width);
break;
case 2: # BI_RLE4
$str = $this->rle4_decode(fread($f, $fsize-$bfOffBits), $width);
break;
}
$data = '';
$padCnt = (4-ceil(($width/(8/$biBitCount)))%4)%4;
switch ($biBitCount){
case 1:
case 4:
case 8:
$w = floor($width/(8/$biBitCount)) + ($width%(8/$biBitCount)?1:0);
$w_row = $w + $padCnt;
if ($flip){
for ($y=0;$y<$height;$y++){
$y0 = $y*$w_row;
for ($x=0;$x<$w;$x++)
$data .= $str{$y0+$x};
}
}else{
for ($y=$height-1;$y>=0;$y--){
$y0 = $y*$w_row;
for ($x=0;$x<$w;$x++)
$data .= $str{$y0+$x};
}
}
break;
case 16:
$w_row = $width*2 + $padCnt;
if ($flip){
for ($y=0;$y<$height;$y++){
$y0 = $y*$w_row;
for ($x=0;$x<$width;$x++){
$n = (ord( $str{$y0 + 2*$x + 1})*256 + ord( $str{$y0 + 2*$x}));
$b = ($n & 31)<<3; $g = ($n & 992)>>2; $r = ($n & 31744)>>7128;
$data .= chr($r) . chr($g) . chr($b);
}
}
}else{
for ($y=$height-1;$y>=0;$y--){
$y0 = $y*$w_row;
for ($x=0;$x<$width;$x++){
$n = (ord( $str{$y0 + 2*$x + 1})*256 + ord( $str{$y0 + 2*$x}));
$b = ($n & 31)<<3; $g = ($n & 992)>>2; $r = ($n & 31744)>>7;
$data .= chr($r) . chr($g) . chr($b);
}
}
}
break;
case 24:
case 32:
##$padCnt = $width % 4;
$byteCnt = $biBitCount/8;
$w_row = $width*$byteCnt + $padCnt;
if ($flip){
for ($y=0;$y<$height;$y++){
$y0 = $y*$w_row;
for ($x=0;$x<$width;$x++){
$i = $y0 + $x*$byteCnt ; # + 1
$data .= $str{$i+2}.$str{$i+1}.$str{$i};
}
}
}else{
for ($y=$height-1;$y>=0;$y--){
$y0 = $y*$w_row;
for ($x=0;$x<$width;$x++){
$i = $y0 + $x*$byteCnt ; # + 1
$data .= $str{$i+2}.$str{$i+1}.$str{$i};
}
}
}
break;
default:
$this->Error('Unsupported image biBitCount: '.$file);
}
# compress data
$info['f'] = 'FlateDecode';
$info['data'] = gzcompress($data);
return $info;
}
function _fread_long_le_at($f, $pos){
fseek($f, $pos);
$a=unpack('Vi', fread($f, 4));
return $a['i'];
}
function _fread_short_le_at($f, $pos){
fseek($f, $pos);
$a=unpack('vi', fread($f, 2));
return $a['i'];
}
# Decoder for RLE8 compression in windows bitmaps
# see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
function rle8_decode ($str, $width){
$lineWidth = $width + (3 - ($width-1) % 4);
$out = '';
$cnt = strlen($str);
for ($i=0;$i<$cnt;$i++){
$o = ord($str{$i});
switch ($o){
case 0: # ESCAPE
$i++;
switch (ord($str{$i})){
case 0: # NEW LINE
$padCnt = $lineWidth - strlen($out)%$lineWidth;
if ($padCnt<$lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
break;
case 1: # END OF FILE
$padCnt = $lineWidth - strlen($out)%$lineWidth;
if ($padCnt<$lineWidth) $out .= str_repeat(chr(0), $padCnt); # pad line
break 3;
case 2: # DELTA
$i += 2;
break;
default: # ABSOLUTE MODE
$num = ord($str{$i});
for ($j=0;$j<$num;$j++)
$out .= $str{++$i};
if ($num % 2) $i++;
}
break;
default:
$out .= str_repeat($str{++$i}, $o);
}
}
return $out;
}
# Decoder for RLE4 compression in windows bitmaps
# see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_6x0u.asp
function rle4_decode ($str, $width){
$w = floor($width/2) + ($width % 2);
$lineWidth = $w + (3 - ( ($width-1) / 2) % 4);
$pixels = array();
$cnt = strlen($str);
for ($i=0;$i<$cnt;$i++){
$o = ord($str{$i});
switch ($o){
case 0: # ESCAPE
$i++;
switch (ord($str{$i})){
case 0: # NEW LINE
while (count($pixels)%$lineWidth!=0)
$pixels[]=0;
break;
case 1: # END OF FILE
while (count($pixels)%$lineWidth!=0)
$pixels[]=0;
break 3;
case 2: # DELTA
$i += 2;
break;
default: # ABSOLUTE MODE
$num = ord($str{$i});
for ($j=0;$j<$num;$j++){
if ($j%2==0){
$c = ord($str{++$i});
$pixels[] = ($c & 240)>>4;
} else
$pixels[] = $c & 15;
}
if ($num % 2) $i++;
}
break;
default:
$c = ord($str{++$i});
for ($j=0;$j<$o;$j++)
$pixels[] = ($j%2==0 ? ($c & 240)>>4 : $c & 15);
}
}
$out = '';
if (count($pixels)%2) $pixels[]=0;
$cnt = count($pixels)/2;
for ($i=0;$i<$cnt;$i++)
$out .= chr(16*$pixels[2*$i] + $pixels[2*$i+1]);
return $out;
}
} # END CLASS
?>
|
Example
<?php
require('fpdf_bmp.php');
$pdf = new PDF_BMP();
$pdf->AddPage();
$pdf->Image('test_32bit.bmp', 20, 10, 60);
$pdf->Image('test_24bit.bmp', 20, 80, 60);
$pdf->Image('test_24bit_flip.bmp', 20, 150, 60);
$pdf->Image('test_16bit.bmp', 20, 220, 60);
$pdf->Image('test_8bit.bmp', 130, 10, 60);
$pdf->Image('test_8bit_rle.bmp', 130, 80, 60);
$pdf->Image('test_4bit_rle.bmp', 130, 150, 60);
$pdf->Image('test_1bit.bmp', 130, 220, 60);
$pdf->Output();
?>
|
View the result here.
DownloadZIP
|