Convertir Bitmap en fichiers JPEG en utilisant la bibliothèque GD en PHP

voix
5

J'ai essayé de trouver un moyen de convertir des fichiers bitmap en JPEG en utilisant la bibliothèque GD en PHP.

J'ai essayé de nombreuses implémentations, mais rien ne semble fonctionner. J'ai essayé de dire à mon client qu'ils ne doivent pas utiliser des fichiers bitmap, mais il insiste sur le fait et ne fait franchement comprendre pas assez sur les ordinateurs pour les convertir en JPG lui-même.

Je ne peux pas utiliser ImageMagick sur ce serveur et je besoin d'une solution pure de GD. Nous vous remercions à l'avance pour toute aide.

MODIFIER:

Les images en mode point qui sont utilisés sont de 16 bits et qui est l'endroit où le problème se produit.

J'ai cette fonction que je travaille .... un peu:

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

L'image résultante est la suivante:

image

Si vous regardez l'image sur le côté gauche vous pouvez voir que l'image résultante est pas correctement alignée. Le petit ruban appartient sur le côté droit. Où est le code va mal? Le problème se produit dans l'autre, si 16 bits.

Je vous remercie encore une fois pour toute l'aide.

Créé 18/10/2009 à 22:35
source utilisateur
Dans d'autres langues...                            


4 réponses

voix
10

Utilisez cette fonction:

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

Il prend en charge plusieurs bitrates comme 16- et 32 ​​bits. De plus, il contient quelques corrections de bugs concernant la taille du fichier manquant, des palettes de couleurs négatives, la sortie d'erreur, en-tête de masque 16 bits supplémentaires (ce qui était le principal problème sur 16 bits) et la palette de couleurs réduite (biClrUsed).

J'espère que vous aimez ;)

Mise à jour en 2015: Cette fonction fait maintenant partie de dompdf et a été portée à la perfection. Maintenant , il couvre comprimé 4 et 8 bits, ne tient pas compte des en- têtes sans importance et prend en charge la 16-bit spécial 565 masque aussi bien.

Créé 19/04/2010 à 23:41
source utilisateur

voix
0

Du haut de ma tête:

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

Ça va prendre tout format GD peut traiter en entrée et en sortie un fichier jpeg. Je ne sais pas quelle version de GD que vous utilisez les gens, mais les poignées mes .bmp parfaitement et ainsi fait la version que nous avons utilisé à la précédente société où je travaillais. (Sous Mac OS X 10.6 et CentOS 5 respectivement)

modifier : oublié imagedestroy! Aie!

Créé 18/10/2009 à 23:32
source utilisateur

voix
0

Bien que GD ne supporte pas nativement BMP, un peu grand de googler fournit un peu userland implémentations d'une fonction imagecreatefrombmp ().

Je ne les ai pas essayé, mais je suis confiant au moins un d'entre eux pour vous.

Créé 18/10/2009 à 22:45
source utilisateur

voix
0

Que diriez - vous de la imagejpeg fonction?

bool imagejpeg ($ image des ressources [, nom de fichier string $ [, int qualité de $]])

imagejpeg () crée un fichier JPEG de l'image donnée.

Pour vous aider à supporter le format BMP dans GD, un coup d' oeil ici , par exemple.

EDIT: Ceci ne prend pas en charge images 16 bits qui est correct que la spécification du bitmap d'origine ne fonctionne pas. Dans votre cas, s'il vous plaît savoir quel modèle bit est utilisé pour coder la valeur de couleur. Je suppose qu'il est 5 bits pour R et B, 6 bits pour G et l'ordre est BGR dans cette solution (s'il vous plaît insérer dans le code lié à I ci-dessus):

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

Notez que je n'ai pas testé ce code (en particulier, je ne suis pas sûr que l'échelle à 0..255) et il ne fonctionnera que si le modèle de bits 5-6-5 a été utilisé (bien, il travaillera avec les autres aussi, mais les couleurs seront fausses).

Créé 18/10/2009 à 22:40
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more