2009-10-18 83 views
5

我一直在試圖找出一種方法來使用PHP中的GD庫將位圖文件轉換爲JPEG格式。使用PHP中的GD庫將位圖文件轉換爲JPEG

我嘗試了很多實現,但似乎沒有任何工作。我試圖告訴我的客戶,他們不應該使用位圖文件,但他堅持並坦率地不理解計算機將其自己轉換爲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; 
} 

產生的圖像是這樣的:

Uploaded Image

如果你看看像左手你可以看到最終的圖像沒有正確排列。小銀條屬於右邊。代碼出錯了?問題發生在16位的其他地方,如果。

再次感謝您的所有幫助。

+0

看看你的代碼,看起來是正確的。你確定BMP格式如預期的那樣(54字節,沒有調色板數據,後面的圖像數據)?由於這是一些外來的BMP變體,頭部中可能會有額外/較少的數據導致這種「移位」錯誤。 – schnaader 2009-10-19 02:19:17

+0

我必須誠實地說,我不確定圖像上發生了什麼。如果有辦法通過電子郵件將其中一張圖片發送給您,以便您可以查看該圖片......現在我比以往更感興趣這些圖像文件正在發生什麼。我可以通過g mail mail com與dphoebus聯繫一封電子郵件,我會回覆其中一張圖片。 – 2009-10-20 13:07:52

回答

10

使用此功能:

http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm

它支持多種比特率像16位和32位。此外,它還包含一些關於缺少文件大小,負面調色板,錯誤輸出,附加16位掩碼標題(這是16位的主要問題)和減少的調色板(biClrUsed)的一些錯誤修正。

希望你喜歡它;)

更新2015年:現在這個功能是DOMPDF一部分,被帶到完美。現在它覆蓋了4位和8位壓縮,忽略了不重要的標題,並支持特殊的16位565掩碼。

+0

新網址:https://github.com/dompdf/dompdf/blob/master/src/Helpers.php#L555 – Tominator 2016-09-06 14:21:59

0

imagejpeg功能如何?

bool imagejpeg (resource $image [, string $filename [, int $quality ]] )

imagejpeg() creates a JPEG file from the given image .

爲了幫助支持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位模式的情況下才有效(也可以與其他模式一起使用,但顏色會錯誤)。

+0

謝謝你的快速回復,但我仍然遇到同樣的問題。我的客戶端使用的位圖文件是16位位圖文件。我發現的每個實現(包括您所展示的)都包含24位,8位,4位和1位位圖。 – 2009-10-18 22:06:55

+0

再次感謝您。我試過這個解決方案。返回的結果文件是純黑色圖像,水平綠線與圖像的整個長度間隔相等。 – 2009-10-19 00:27:36

0

儘管GD本身並不支持BMP,但有一點Google的搜索功能提供了imagecreatefrombmp()函數的一個fewuserlandimplementations

我還沒有嘗試過,但我相信至少有一個會爲你工作。

+0

再次感謝。我已經全部嘗試過了。再次當我做一些測試時,我發現提交的位圖是16位文件。在這些實現中沒有考慮16位圖像。 – 2009-10-18 22:08:01

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版本是什麼,但是我的手柄完全符合我們以前使用過的公司的版本。 (在Mac OS X 10上。6和CentOS 5分別)

編輯:忘記imagedestroy!哎喲!

+0

我們希望能夠適用於16位BMP文件......將是最快捷最優雅的解決方案。 – schnaader 2009-10-18 22:34:21

+0

謝謝你的幫助。我這給了一個嘗試,得到這個錯誤: imagecreatefromstring()[function.imagecreatefromstring]:數據不是可識別的格式。 這可能是由於我的客戶正在使用的darn 16位位圖。 – 2009-10-19 00:25:44

+0

我不認爲我遇到過16位圖像,但它似乎可以很好地適用於24位,甚至RLE編碼的圖像。 – Kris 2009-10-20 09:53:47