PHP GD kütüphanesini kullanarak JPEG içine Bitmap eğe

5 Cevap php

PHP GD kütüphanesi kullanarak bir JPEG Bitmap dosyalarını dönüştürmek için bir yol bulmaya çalışıyorlar.

Ben çok sayıda uygulamaları denedim ama hiçbir şey iş gibi görünüyor. Ben onlar Bitmap dosyaları kullanmak gerektiğini müvekkilimi anlatmaya çalıştım ama o ısrar ediyor ve doğrusunu kendi başına JPG onları dönüştürmek için bilgisayarlar hakkında yeterli idrak etmez.

Ben bu sunucuda ImageMagick kullanamazsınız ve ben saf GD çözüm gerekir. Her türlü yardım için şimdiden teşekkür ederiz.

EDIT:

Kullanılmakta olan bitmap görüntüler 16-bit ve sorunun nerede oluştuğunu olmasıdır.

Ben tür .... çalışma var bu işlevi vardır:

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

The resulting image is this: Uploaded Image

Eğer sol taraftaki resmin bakarsanız çıkan görüntü doğru dizilmiş olmadığını görebilirsiniz. Küçük şerit sağ tarafta aittir. Nerede kodu yanlış oluyor? Sorun 16-bit else-if gerçekleşiyor.

Tüm yardım için tekrar teşekkür ederiz.

5 Cevap

Tamam ben işlevini tamamladı:

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

Şimdi 16 destekler - ve 32-bit hem de. Artı eksik dosya boyutu, negatif renk paletleri, hata çıktı, ek 16 bit maskesi başlığında (bu 16-bit ana sorun) ve azaltılmış renk paleti (biClrUsed) ile ilgili bazı hata düzeltmeleri içeriyor.

Hoşuna umut ;)

GD doğal BMP desteklemiyor olsa da, googling biraz büyük bir few userland implementations bir imagecreatefrombmp arasında () fonksiyonu sağlar.

Ben onları denemedim, ama ben bunlardan en az biri sizin için çalışacaktır eminim.

Nasıl imagejpeg fonksiyonu hakkında?

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

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

GD BMP formatında destek yardım için, örneğin, bir görünüm here var.

EDIT: Bu orijinal bitmap şartname bunu desteklemiyor gibi doğru 16 bit görüntüleri desteklemiyor. Senin durumunda, bit desen renk değerini kodlamak için kullanılan olduğunu öğrenmek lütfen. Ben R ve B için 5 bit, 6 G bit ve sipariş (yukarıda bağlantılı koduna lütfen takın) bu çözelti içinde BGR olduğunu varsayıyorum:

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

(Iyi, diğerleri ile çalışacak bu kodu test etmedi (özellikle, ben 0 .. 255 emin ölçekleme hakkında emin değilim) ve 5-6-5 bit deseni kullanılmış ise sadece çalışacağını unutmayın , çok, ama renkler) yanlış olur.

Kafamın üst Off:

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

Yani herhangi GD giriş olarak işleyebilir biçimi ve çıkış bir jpeg dosyası alacağım. Ben millet kullandığınız GD hangi sürümünü bilmiyorum, ama benim işler. Mükemmel bmp ve bu yüzden ben çalıştı önceki şirkette kullanılan versiyon yaptım. (Mac OS X 10.6 ve sırasıyla CentOS 5 üzerinde)

edit: imagedestroy unuttum! ah!

-> Schnaader

Eğer bir çözüm buldun?

Ben php.net comments işlevsel 16 Bit fonksiyonu buldum. Ama bazı hata düzeltmeleri içermek zorunda.

Bu şimdiye kadar benim sonuç:

if ($bmp['colors'] < 16777216) {
 if (!($palette = @unpack('V' . $bmp['colors'], fread($fh, $bmp['colors'] * 4)))) {
  // no palette found: rewind
  $palette = array();
  fseek($fh, 54);
 }
}
...
switch ($bmp['bits_per_pixel']) {
...
case 16:
 // some have palette
 if ($palette) {
  $color = @unpack('n', substr($img, $p, 2));
  if (!$color) {
   break;
  }
  $color[1] = $palette[ $color[1] + 1 ];
 }
 else {
  $color = @unpack('v', substr($img, $p, 2));
  if (!$color) {
   break;
  }
  $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3);
 }
 break;

Bu görüntü ile çalışır, bu bir palet yok. $ Paletiyle:

maxrev.de/img/cache/crx21271442365.jpg

Olmadan (unset $ palet):

maxrev.de/img/cache/crx21271442268.jpg

Daha sonra ben önerisi ile başka bir fonksiyonu test ettik. Daniel dediği gibi çalışmıyor. Bu:

case 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 .= $byte2;
 }

Sonuçlar (belki ^ ^ yardımcı olur):

maxrev.de/img/cache/crx21271442644.jpg