2009-10-18 4 views
5

Ich habe versucht, eine Möglichkeit zum Konvertieren von Bitmap-Dateien in ein JPEG mit der GD-Bibliothek in PHP zu finden.Konvertieren von Bitmap-Dateien in JPEG mit der GD-Bibliothek in PHP

Ich habe zahlreiche Implementierungen versucht, aber nichts scheint zu funktionieren. Ich habe versucht, meinen Kunden zu sagen, dass sie keine Bitmap-Dateien verwenden sollten, aber er besteht darauf und versteht ehrlich gesagt nicht genug über Computer, um sie selbst zu JPG zu konvertieren.

Ich kann ImageMagick nicht auf diesem Server verwenden und ich brauche eine reine GD-Lösung. Vielen Dank im Voraus für jede Hilfe.

EDIT:

Die Bitmap-Bilder, die verwendet werden, sind 16-Bit und das ist, wo das Problem auftritt.

Ich habe diese Funktion, die ich gearbeitet haben .... irgendwie:

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; 
} 

Das resultierende Bild ist dies:

Uploaded Image

Wenn Sie auf das Bild auf der linken aussehen Seite können Sie sehen, dass das resultierende Bild nicht richtig ausgerichtet ist. Der kleine Splitter gehört auf der rechten Seite. Wo läuft der Code falsch? Das Problem tritt in dem 16-Bit-Else-If auf.

Vielen Dank noch einmal für die Hilfe.

+0

Hatte einen Blick auf Ihren Code, scheint richtig. Sind Sie sicher, dass das BMP-Format wie erwartet ist (54 Bytes, keine Palettendaten, Bilddaten folgen)? Da es sich um eine exotische BMP-Variante handelt, können zusätzliche/weniger Daten im Header zu diesem "Shifting" -Fehler führen. – schnaader

+0

Ich muss ehrlich sein, ich bin nicht wirklich sicher, was mit dem Bild los ist. Wenn es eine Möglichkeit gäbe, eines der Bilder per E-Mail an Sie zu senden, damit Sie es sich ansehen können ... Ich bin jetzt mehr denn je daran interessiert, was mit diesen Bilddateien passiert. Eine E-Mail, an die ich mich wenden kann, ist dphoebus bei g mail dot com und ich werde mit einem der Bilder antworten. –

Antwort

10

Mit dieser Funktion:

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

Es unterstützt mehrere Bitraten wie 16- und 32-Bit. Außerdem enthält es einige Bugfixes in Bezug auf fehlende Dateigröße, negative Farbpaletten, Fehlerausgabe, zusätzlichen 16-Bit Maskenkopf (dies war das Hauptproblem bei 16-Bit) und reduzierte Farbpalette (biClrUsed).

Hoffe es gefällt euch;)

-Update im Jahr 2015: Diese Funktion jetzt Teil von DOMPDF und wurde bis zur Perfektion gebracht. Jetzt deckt es komprimierte 4- und 8-Bit ab, ignoriert unwichtige Header und unterstützt auch die spezielle 16-Bit-565-Maske.

+0

Neue URL: https://github.com/dompdf/dompdf/blob/master/src/Helpers.php#L555 – Tominator

0

Wie wäre es mit der imagejpeg Funktion?

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

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

Für Hilfe BMP-Format in GD zu unterstützen, haben einen Blick here, zum Beispiel.

BEARBEITEN: Dies unterstützt keine 16-Bit-Bilder, was korrekt ist, da die ursprüngliche Bitmap-Spezifikation dies nicht unterstützt. In Ihrem Fall sollten Sie herausfinden, welches Bitmuster zum Codieren des Farbwerts verwendet wird. Ich nehme an, es ist 5 Bits für R und B, 6 Bits für G und die Reihenfolge BGR in dieser Lösung (fügen Sie bitte in den Code, den ich oben verlinkt):

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"; 
} 

Bitte beachte, dass ich diesen Code nicht testen (Genauer gesagt, bin ich mir nicht sicher, ob das auf 0..255 skaliert werden soll) und es funktioniert nur, wenn das 5-6-5-Bit-Muster verwendet wurde (gut, es wird auch mit anderen funktionieren, aber die Farben werden falsch sein).

+0

Vielen Dank für eine schnelle Antwort, aber ich laufe immer wieder auf dasselbe Problem. Die Bitmap-Dateien, die mein Client verwendet, sind 16-Bit-Bitmap-Dateien. JEDE Implementierung, die ich gefunden habe (einschließlich der, die du gezeigt hast), sind für 24-Bit-, 8-Bit-, 4-Bit- und 1-Bit-Bitmaps verantwortlich. –

+0

Nochmals vielen Dank. Ich habe diese Lösung ausprobiert. Die resultierende Datei, die zurückgegeben wurde, war ein durchgehend schwarzes Bild mit horizontalen grünen Linien, die gleichmäßig über die gesamte Länge des Bildes verteilt waren. –

0

Während GD BMP nicht nativ unterstützt, bietet ein wenig Googlen eine fewuserlandimplementations einer imagecreatefrombmp() - Funktion.

Ich habe sie nicht ausprobiert, aber ich bin zuversichtlich, dass mindestens einer von ihnen für Sie arbeiten wird.

+0

Danke nochmal. Ich habe sie alle ausprobiert. Wenn ich einige Tests mache, finde ich heraus, dass die Bitmaps, die gesendet werden, 16-Bit-Dateien sind. 16-Bit-Bilder werden in keiner dieser Implementierungen berücksichtigt. –

0

Aus der Spitze von meinem Kopf:

function convert_to_jpeg($input_path, $output_path) 
{ 
    $image = imagecreatefromstring(file_get_contents($input_path)); 
    imagejpeg($image, $output_path); 
    imagedestroy($image); 
} 

Das nehm jedes Format GD als Input verarbeiten kann und die Ausgabe einer JPEG-Datei. Ich weiß nicht, welche Version von GD Sie verwenden, aber meine Griffe .bmp perfekt und so hat die Version, die wir bei der vorherigen Firma, für die ich arbeitete, verwendet. (unter Mac OS X 10.6 und CentOS 5 jeweils)

bearbeiten: vergessen imagedestroy! Autsch!

+0

Hoffen wir, dass das auch für 16-bit BMP-Dateien funktioniert ... wäre die schnellste und eleganteste Lösung. – schnaader

+0

Vielen Dank für Ihre Hilfe. Ich habe dies versucht und bekam diesen Fehler: imagecreatefromstring() [function.imagecreatefromstring]: Daten sind nicht in einem anerkannten Format. Das liegt wahrscheinlich an den 16 Bit-Bitmaps, die mein Client verwendet. –

+0

Ich glaube nicht, dass ich jemals in ein 16-Bit-Bild geriet, aber es scheint für 24-Bit- und sogar RLE-kodierte Bilder gut zu funktionieren. – Kris

Verwandte Themen