我一直试图找到一种方法,使用PHP中的GD库将位图文件转换为JPEG格式。
我尝试了很多实现,但似乎没有任何工作。我试图告诉我的客户他们不应该使用Bitmap文件,但他坚持并且坦率地不了解计算机将其自己转换为JPG。
我无法在此服务器上使用ImageMagick,我需要纯GD解决方案。提前感谢您提供任何帮助。
修改
正在使用的位图图像是16位,这是问题发生的地方。
我有这个功能,我有工作....有点:
function ImageCreateFromBMP($filename) {
if (! $f1 = fopen($filename,"rb")) return FALSE;
$FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
if ($FILE['file_type'] != 19778) return FALSE;
$BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
$BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
$BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
$BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
$BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] = 4-(4*$BMP['decal']);
if ($BMP['decal'] == 4) $BMP['decal'] = 0;
$PALETTE = array();
if ($BMP['colors'] < 16777216 && $BMP['colors'] != 65536) {
$PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
}
$IMG = fread($f1,$BMP['size_bitmap']);
$VIDE = chr(0);
$res = imagecreatetruecolor($BMP['width'],$BMP['height']);
$P = 0;
$Y = $BMP['height']-1;
while ($Y >= 0) {
$X=0;
while ($X < $BMP['width']) {
if ($BMP['bits_per_pixel'] == 24)
$COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
elseif ($BMP['bits_per_pixel'] == 16) {
$COLOR = unpack("v",substr($IMG,$P,2));
$blue = ($COLOR[1] & 0x001f) << 3;
$green = ($COLOR[1] & 0x07e0) >> 3;
$red = ($COLOR[1] & 0xf800) >> 8;
$COLOR[1] = $red * 65536 + $green * 256 + $blue;
}
elseif ($BMP['bits_per_pixel'] == 8) {
$COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 4) {
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 1) {
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7;
elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
else
return FALSE;
imagesetpixel($res,$X,$Y,$COLOR[1]);
$X++;
$P += $BMP['bytes_per_pixel'];
}
$Y--;
$P+=$BMP['decal'];
}
fclose($f1);
return $res;
}
生成的图像是:
如果查看左侧的图像,可以看到生成的图像没有正确排列。小条子属于右手边。代码出错了什么地方?问题发生在16位else-if。
中再次感谢您的帮助。
答案 0 :(得分:11)
使用此功能:
http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm
它支持几种比特率,如16位和32位。此外,它包含一些关于丢失文件大小,负色调,错误输出,附加16位掩码头(这是16位的主要问题)和减少调色板(biClrUsed)的错误修正。
希望你喜欢它;)
2015年更新:此功能现在是DOMPDF的一部分,并且完美无缺。现在它涵盖了压缩的4位和8位,忽略了不重要的标题,并支持特殊的16位565掩码。
答案 1 :(得分:0)
imagejpeg功能怎么样?
bool imagejpeg(resource $ image [, string $ filename [,int $ quality]] )
imagejpeg()从中创建JPEG文件 给定的图像。
有关在GD中支持BMP格式的帮助,请查看here,例如。
编辑:这不支持16位图像,这是正确的,因为原始位图规范不支持它。在您的情况下,请找出用于编码颜色值的位模式。我假设R和B为5位,G为6位,此解决方案中的顺序为BGR(请插入我上面链接的代码中):
else if ($bits == 16) {
$gd_scan_line = "";
$j = 0;
while($j < $scan_line_size) {
$byte1 = $scan_line{$j++};
$byte2 = $scan_line{$j++};
$b = chr($byte1 >> 3) * (255 / 31);
$g = (chr($byte1 & 0x07) + chr($byte2 >> 5)) * (255 / 63);
$r = chr($byte2 & 0x1F) * (255 / 31);
$gd_scan_line .= "\x00$r$g$b";
}
请注意,我没有测试这段代码(具体来说,我不确定缩放到0..255)并且只有在使用5-6-5位模式时它才会起作用(好吧,它会也与他人合作,但颜色不对。)
答案 2 :(得分:0)
虽然GD本身不支持BMP,但有点大的Google搜索提供了imagecreatefrombmp()函数的few userland implementations。
我没有尝试过,但我相信其中至少有一个会为你效劳。
答案 3 :(得分:0)
脱离我的头顶:
function convert_to_jpeg( $input_path, $output_path )
{
$image = imagecreatefromstring(file_get_contents($input_path));
imagejpeg($image, $output_path);
imagedestroy($image);
}
这将采用GD可以作为输入处理的任何格式,并输出jpeg文件。我不知道你们用的是什么版本的GD,但是我的处理.bmp非常完美,我们在之前工作的公司使用的版本也是如此。 (分别在Mac OS X 10.6和CentOS 5上)
编辑:忘记了imagedestroy!哎哟!