Artykuły na każdy temat
[PHP] Masowa konwersja windowsowskich plików BMP na inny format
<?php
$config['path']['new'] = './new/';
$list['old'] = glob('./old/*.bmp');
$list['new'] = glob($config['path']['new'].'*.png');
if(!empty($list['old']))
{
header('Content-Type: text/plain; charset=windows-1250');
$counter = (empty($list['new']) ? 1 : count($list['new']) + 1);
foreach($list['old'] as $object)
{
$handle = convert_bmp2gd($object);
if($handle)
{
$info = stream_get_meta_data($handle);
$img = imagecreatefromgd($info['uri']);
if($img)
{
fclose($handle);
echo '[';
if(imagepng($img, $config['path']['new'].$counter.'.png', 9) && unlink($object))
{
++$counter;
echo 't';
}
else
{
echo 'f';
}
echo '] '.$object."\n";
}
}
}
// Or option number two
foreach($list['old'] as $object)
{
$img = convert_bmp2gd_v2($object);
if($img)
{
echo '[';
if(imagepng($img, $config['path']['new'].$counter.'.png', 9) && unlink($object))
{
++$counter;
echo 't';
}
else
{
echo 'f';
}
echo '] '.$object."\n";
}
break;
}
}
function convert_bmp2gd($source)
{
$handle['source'] = fopen($source, 'rb');
$handle['temporary'] = tmpfile();
if(!$handle['source'] || !$handle['temporary'])
{
return false;
}
// Grab necessary information
$header = unpack('vtype/Vsize/v2reserved/Voffset', fread($handle['source'], 14));
$info = unpack('Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vimportant', fread($handle['source'], 40));
extract($info);
extract($header);
// Check the file header
if($type != 0x4D42)
{
return false;
}
// Set the pallete
$palette_size = $offset - 54;
$ncolor = $palette_size / 4;
// True color or palette?
$gd_header .= ($palette_size == 0) ? "\xFF\xFE" : "\xFF\xFF";
$gd_header .= pack('n2', $width, $height);
$gd_header .= ($palette_size == 0) ? "\x01" : "\x00";
if($palette_size)
{
$gd_header .= pack('n', $ncolor);
}
$gd_header .= "\xFF\xFF\xFF\xFF";
fwrite($handle['temporary'], $gd_header);
if($palette_size)
{
$palette = fread($handle['source'], $palette_size);
while($j < $palette_size)
{
$b = $palette[$j++];
$g = $palette[$j++];
$r = $palette[$j++];
$a = $palette[$j++];
$gd_palette .= "$r$g$b$a";
}
$gd_palette .= str_repeat("\x00\x00\x00\x00", 256 - $ncolor);
fwrite($handle['temporary'], $gd_palette);
}
$scan_line_size = ($bits * $width + 7) >> 3;
$scan_line_align = ($scan_line_size & 0x03 ? 4 - ($scan_line_size & 0x03) : 0);
for($h = 0, $i = $height - 1; $h < $height; ++$h, --$i)
{
fseek($handle['source'], ($scan_line_size + $scan_line_align) * $i + $offset);
$scan_line = fread($handle['source'], $scan_line_size);
if($bits == 8)
{
$gd_scan_line = $scan_line;
}
else
{
$gd_scan_line = '';
$j = 0;
if($bits == 24)
{
while($j < $scan_line_size)
{
$b = $scan_line[$j++];
$g = $scan_line[$j++];
$r = $scan_line[$j++];
$gd_scan_line .= "\x00$r$g$b";
}
}
else
{
if($bits == 4)
{
while($j < $scan_line_size)
{
$byte = ord($scan_line[$j++]);
$p1 = chr($byte >> 4);
$p2 = chr($byte & 0x0F);
$gd_scan_line .= "$p1$p2";
}
}
else if($bits == 1)
{
while($j < $scan_line_size)
{
$byte = ord($scan_line[$j++]);
$p1 = chr((int)($byte & 0x80) != 0);
$p2 = chr((int)($byte & 0x40) != 0);
$p3 = chr((int)($byte & 0x20) != 0);
$p4 = chr((int)($byte & 0x10) != 0);
$p5 = chr((int)($byte & 0x08) != 0);
$p6 = chr((int)($byte & 0x04) != 0);
$p7 = chr((int)($byte & 0x02) != 0);
$p8 = chr((int)($byte & 0x01) != 0);
$gd_scan_line .= "$p1$p2$p3$p4$p5$p6$p7$p8";
}
}
$gd_scan_line = substr($gd_scan_line, 0, $width);
}
}
fwrite($handle['temporary'], $gd_scan_line);
}
fclose($handle['source']);
return $handle['temporary'];
}
function convert_bmp2gd_v2($source)
{
$handle['source'] = fopen($source, 'rb');
if(!$handle['source'])
{
return false;
}
// Grab necessary information
$header = unpack('vtype/Vsize/v2reserved/Voffset', fread($handle['source'], 14));
$info = unpack('Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vncolor/Vimportant', fread($handle['source'], 40));
extract($info);
extract($header);
// Check the file header
if($type != 19778)
{
return false;
}
$resource = imagecreatetruecolor($width, $height);
if(!$resource)
{
return false;
}
$colors = pow(2, $bits);
if($imagesize == 0)
{
$imagesize = $size - $offset;
}
$bytes_per_pixel = $bits / 8;
$decal = $width * $bytes_per_pixel / 4;
$decal -= floor($width * $bytes_per_pixel / 4);
$decal = 4 - ($decal * 4);
if($decal == 4)
{
$decal = 0;
}
$palette = array();
if($colors < 16777216)
{
$palette = unpack('V'.$colors, fread($handle['source'], $colors * 4));
}
$img = fread($handle['source'], $imagesize);
$vide = chr(0);
$p = 0;
$y = $height - 1;
while($y >= 0)
{
$x = 0;
while($x < $width)
{
switch($bits)
{
case 32:
$color = unpack('V', substr($img, $p, 4));
break;
case 24:
$color = unpack('V', substr($img, $p, 3).$vide);
break;
case 16:
$color = unpack('n', substr($img, $p, 2));
$color[1] = $palette[$color[1] + 1];
break;
case 8:
$color = unpack('n', $vide.substr($img, $p, 1));
$color[1] = $palette[$color[1] + 1];
break;
case 4:
$color = unpack('n', $vide.substr($img, floor($p), 1));
$color[1] = $palette[(($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F) + 1];
break;
case 1:
$color = unpack('n', $vide.substr($img, floor($p), 1));
switch(($p * 8) % 8)
{
case 0:
$color[1] = $color[1] >> 7;
break;
case 1:
$color[1] = ($color[1] & 0x40) >> 6;
break;
case 2:
$color[1] = ($color[1] & 0x20) >> 5;
break;
case 3:
$color[1] = ($color[1] & 0x10) >> 4;
break;
case 4:
$color[1] = ($color[1] & 0x8) >> 3;
break;
case 5:
$color[1] = ($color[1] & 0x4) >> 2;
break;
case 6:
$color[1] = ($color[1] & 0x2) >> 1;
break;
case 7:
$color[1] = $color[1] & 0x1;
break;
}
$color[1] = $palette[$color[1] + 1];
break;
default:
return false;
break;
}
imagesetpixel($resource, $x, $y, $color[1]);
$p += $bytes_per_pixel;
++$x;
}
$p += $decal;
--$y;
}
fclose($handle['source']);
return $resource;
}
?>
Druga metoda (funkcja) ma to do siebie, że teoretycznie powinna być szybsza, bo pomijany jest krok zapisu do pliku. Przy małych ilościach plików pewnie jest to nieistotne natomiast przy dużej ilości plików pewnie jest bardzo istotne. Kodowanie wysyłane w nagłówku jest umyśle, ze względu na to, że nazwy plików odczytywane były na Windows XP. Nie mam bladego pojęcia jak to wygląda na Windows 7 czy innych wersjach/systemach. Oczywiście można konwertować na inny format niż ukochany PNG. Kwestia zmienienia nazwy funkcji i ustalenia odpowiedniego quality. Dokumentacja Twoim przyjacielem
Komentarze
Dodaj komentarz