JPEG

© Quesaco. Dernier ajout : 12 juillet 2006.

Si perçante soit la vue, on ne se voit jamais de dos. Proverbe chinois


Libraire de fonctions PHP JPEG permettant l’édition de fichiers JPEG/JFIF.

Librairie de fonctions / PHP 4

PHP Lib JPEG

Fonctions PHP JPEG : La libraire des fonctions JPEG permet l’édition de fichiers JPEG/JFIF. Les fonctions présentées ici sont expérimentales, mais devrait permettrent au novice de mieux comprendre la structure du format de fichier image JPEG/JFIF.

Le format de fichier JPEG est basé sur un assemblage d’éléments, de segments, enveloppés de marqueurs.

Structure d’un fichier JPEG JFIF :

NomMarqueurLegendDescription
M_SOI0xff 0xd8Start of image Début du fichier (magic number)
M_APP00xff 0xe0Application marker, used for JFIFSegment Application.
...Divers segments suivent...
......
M_SOS0xff 0xdaStart of scanL’image commence ici.
M_EOI0xff 0xd9End of imageL’image prend fin ici. Le fichier aussi.

Un fichier JPEG correctement constitué commence donc par la séquence "0xff 0xd8", contient en général le segment APP0 (qui contient parfois la vignette - thumbnail - de l’image, mais ce n’est guère plus pratiqué), suivi d’un ou plusieurs segments de tables Huffman et autres extensions, et prend fin avec le segment de l’image compressée.

Liste des segments disponibles :

MarqueurValeurLegend
0xc0M_SOF0Baseline DCT
0xc1M_SOF1Extended sequential DCT
0xc2M_SOF2Progressive DCT
0xc3M_SOF3Lossless (sequential)
0xc5M_SOF5Differential sequential DCT
0xc6M_SOF6Differential progressive DCT
0xc7M_SOF7Differential lossless
0xc8M_JPGJPEG extensions
0xc9M_SOF9Extended sequential DCT
0xcaM_SOF10Progressive DCT
0xcbM_SOF11Lossless (sequential)
0xcdM_SOF13Differential sequential DCT
0xceM_SOF14Differential progressive DCT
0xcfM_SOF15Differential lossless
0xc4M_DHTDefine Huffman tables
0xccM_DACDefine arithmetic conditioning table
0xd0M_RST0Restart
0xd1M_RST1Restart
0xd2M_RST2Restart
0xd3M_RST3Restart
0xd4M_RST4Restart
0xd5M_RST5Restart
0xd6M_RST6Restart
0xd7M_RST7Restart
0xd8M_SOIStart of image
0xd9M_EOIEnd Of Image
0xdaM_SOSStart Of Scan
0xdbM_DQTDefine quantization tables
0xdcM_DNLDefine number of lines
0xddM_DRIDefine restart interval
0xdeM_DHPDefine hierarchical progression
0xdfM_EXPExpand reference image(s)
0xe0M_APP0Application marker, used for JFIF
0xe1M_APP1Application marker
0xe2M_APP2Application marker
0xe3M_APP3Application marker
0xe4M_APP4Application marker
0xe5M_APP5Application marker
0xe6M_APP6Application marker
0xe7M_APP7Application marker
0xe8M_APP8Application marker
0xe9M_APP9Application marker
0xeaM_APP10Application marker
0xebM_APP11Application marker
0xecM_APP12Application marker
0xedM_APP13Application marker
0xeeM_APP14Application marker, used by Adobe
0xefM_APP15Application marker
0xf0M_JPG0Reserved for JPEG extensions
0xfdM_JPG13Reserved for JPEG extensions
0xfeM_COMComment
0x01M_TEMTemporary use
0x100M_ERRORDummy marker, internal use only
0xffM_SMSStart Marker Segment

Normalement, le fichier est terminé par un EOI (End of Image) qui est à la fois la fin du segment image (votre image compressée) et la fin du fichier.

Il arrive parfois que le fichier soit abimé. jpeginfo vous indique "Premature end of JPEG file", et la commande PHP imagecreatefromjpeg refuse de charger le fichier (PHP <5.1.3+). Si ce fichier ne s’affiche pas correctement sur votre navigateur (Firefox, etc.), c’est qu’il est tronqué. Si par contre l’image est bonne, c’est qu’il manque la marqueur de fin de fichier (EOI) et que parfois, la fin du segment image (de SOS à EOI) est erronée.

kzo_jpeg_struct_get ()

La commande kzo_jpeg_struct_get () disponible ici est une version beta de ce qui pourra peut-être vous servir à mieux comprendre la structure d’une image JPEG. Cette fonction vous renvoie un tableau multi-dimensionné contenant l’ensemble des informations rencontrées dans ce fichier JPEG (structure et ses segments).

Voici en exemple (résultat et image), ce que donne kzo_jpeg_struct_get () :

Segment #0
#0 APP: M_APP0 [0xe0] (Application marker, used for JFIF)
#0 Length: 16
#0 Identifier: JFIF
#0 Version: 1.2
#0 Units: 0
#0 Xdensity: 100
#0 Ydensity: 100
#0 XThumbnail: 0
#0 YThumbnail: 0
#0 data: <... 0 bytes length ...>

Segment #1
#1 APP: M_APP12 [0xec] (Application marker)
#1 Length: 17
#1 Data: <... 14 bytes length ...>

Segment #2
#2 APP: M_APP14 [0xee] (Application marker, used by Adobe)
#2 Length: 38
#2 Data: <... 35 bytes length ...>

Segment #3
#3 APP: M_DQT [0xdb] (Define quantization tables)
#3 Length: 132
#3 Table: <... 129 bytes length ...>

Segment #4
#4 APP: M_SOF2 [0xc2] (Progressive DCT)
#4 Length: 17
#4 Data: <... 14 bytes length ...>

Segment #5
#5 APP: M_DHT [0xc4] (Define Huffman tables)
#5 Length: 213
#5 Data: <... 210 bytes length ...>

Segment #6
#6 APP: M_SOS [0xda] (Start Of Scan)
#6 scan: <... 6089 bytes length ...>

Segment #7
#7 APP: M_EOI [0xd9] (End Of Image)

Voici un code PHP en exemple à compléter pour utiliser kzo_jpeg_struct_get () :

<?php 
    
echo("<pre>");
    
$filename "votre-image-jpeg.jpg";
    echo(
"Filename: $filename\n");
    echo(
"Filesize: ".filesize($filename)." bytes\n");

    
$image_file file_get_contents($filename);

    
$data kzo_jpeg_struct_get($image_fileTRUE);
    
    for(
$ii=0$ii<255$ii++) 
    {
        if(!isset(
$data['segments'][$ii])) break;
        echo(
"\n");
        echo(
"Segment #$ii\n");
        foreach(
$data['segments'][$ii] as $key=>$value)
        {
            switch(
$key)
            {
                case 
'APP':
                    
$index=dechex(ord($value[1]));
                    
$value=$marqueur_array[$index]
                    . 
" [0x$index] ($marqueur_legend_array[$index])";
                    break;
                case 
'Comment':
                    
$value=htmlspecialchars(trim($value));
                    break;
                case 
'Version':
                    
$major=ord($value[0]);
                    
$minor=ord($value[1]);
                    
$value "".$major.".".$minor;
                    break;
                case 
'Length':
                case 
'Xdensity':
                case 
'Ydensity':
                    
$value = (ord($value[0])<<8) + (ord($value[1]));
                    break;
                case 
'Units':
                case 
'XThumbnail':
                case 
'YThumbnail':
                    
$value ord($value[0]);
                    break;
                case 
'Identifier':
                    
$value=trim($value);
                    break;
                default:
                    
$value="<... ".strlen($value)." bytes length ...>";
                    break;
            }
            echo(
"<strong>#$ii $key</strong>: $value\n");
        }
    }
    echo(
"</pre>");
?>

Zip - 2.6 ko
kzo_jpeg_struct_get. inc-2.zip

kzo_jpeg_scansize_get ()

Avec kzo_jpeg_struct_get (), vous pouvez obtenir la taille du scan contenu dans le fichier JPEG par :

<?php
    
if($result)
    {
        for(
$segment=0;$segment<count($result['segments']);$segment++)
        {
            if(isset(
$result['segments'][$segment]['scan'])) 
            {
                print(
strlen($result['segments'][$segment]['scan']). " bytes");
                break;
            }
        }
    }
?>

mais le plus simple, si vous ne voulez que la taille du scan, est d’utiliser kzo_jpeg_scansize_get ().

Zip - 2.2 ko
kzo_jpeg_struct_get. inc-2.zip

Quelques liens utiles pour en savoir plus sur le format de fichier JPEG :

- http://computing.ee.ethz.ch/sepp/xmedcon-0.8.13-mo.SEPP/xmedcon-0.8.13/libs/ljpg/read.c
- http://cvsweb.xfree86.org/cvsweb/xc/programs/Xserver/XIE/mixie/jpeg/Attic/jwrjfif.c ?rev=1.1.1.3
- http://www.tug.org/tex-archive/support/jpeg2ps/readjpeg.c
- http://www.cb1.com/ john/computing/emacs/lisp/graphics/jpeg-mode.el
- http://www.mindspring.com/ nesssoft/src/jpginfo.txt
- http://dev.w3.org/cvsweb/Amaya/libjpeg/jcmarker.c ?rev=1.4&content-type=text/x-cvsweb-markup
- http://www.w3.org/Graphics/JPEG/jfif.txt
- http://www.fileformat.info/format/jpeg/