Comment détecter la tranparence dans des images PNG en PHP de manière fiable

Publié le samedi 2 novembre 2024 à 04:00

Le besoin principal est de savoir si un PNG a de la transparence en utilisant PHP.

Les codes trouvés ne semblaient pas fonctionner de manière satisfaisante pour les différents types de PNG à contrôler.

J'ai fini par utiliser la fonction suivante:

function png_has_transparency($im) {
        //Retrieve content from imagick object
        $content = $im->getImageBlob();

        //Detect 32bit png (each pixel has tranparency level)
        if (ord(substr($content, 25, 1)) & 4) {
                //Fetch iterator
                $p = $im->getPixelIterator();

                //Loop on each row
                foreach($p as $r) {
                        //Loop on each row pixel
                        foreach($r as $pix) {
                                //Check if pixel has partial transparency
                                if ($pix->getColorValue(Imagick::COLOR_ALPHA) != 1) {
                                        return true;
                                }
                        }
                }
        //Check 8bit png transparency
        } elseif (stripos($content, 'PLTE') !== false || stripos($content, 'tRNS') !== false) {
                return true;
        }

        //Didn't found clue of transparency
        return false;
}

Cette fonction fonctionne avec les deux seules possibilités : PNG 8 et 32 bits.

Le premier cas est un PNG 32 bits avec transparence activée, on doit alors vérifier l'opacité de chaque pixel savoir si l'image a de la transparence ou non.

Le second cas est un PNG 8 bits, on a simplement à détecter un marqueur de transparence dans le contenu du fichier.

Dans cette configuration de fonction, on lit seulement une partie du PNG 32 bits jusqu'à détection d'un pixel transparent où on analyse le contenu jusqu'à trouver un marqueur de transparence dans un PNG 8 bits.

Les pires cas seront un PNG 32 bits avec marqueur de transparence sans pixel transparent ou PNG 8 bits sans marqueur de transparence.

Selon les probabilités de rencontrer les différents cas de transparence vous pouvez être intéressé pour renverser l'ordre des tests de cette fonction.

Un grand merci à ces articles qui expliquent plus en détail comment fonctionnent les différentes parties de ce code:

En espérant que cela puisse aider quelques personnes.