Aller au contenu

Bug de PHP/GD ?


Sujets conseillés

Posté (modifié)

Bonsoir,

Etant fervant utilisateur de la librairie GD pour PHP (pour créer/manipuler des images), je suis confronté à ce qui me semble être un bug. En effet, le code suivant, censé générer un quart de disque complètement blanc sur fond noir, a un résultat plutôt étonnant, voyez plutôt :

- sur un serveur mutualisé : http://www.web2master.fr/ellipse.php

- sur un serveur dédié : http://local.izipub.com/exp/ellipse_whub.php

Le code est le même sur les deux fichiers :

<?php

$size=200;

$im=imagecreate($size,$size); // on crée une image carrée
$back=imagecolorallocate($im,0,0,0); // on remplit l'image de noir
$color=imagecolorallocate($im,255,255,255); // on crée la couleur blanche
for($i=0;$i<$size;$i+=0.1) // on se décale de 0.1 pixels à chaque itération (mathématiquement, racine de 1/2=0.7 pixels devrait suffire)
imageellipse($im,0,0,$i,$i,$color); // on crée une ellipse de largeur

header('Content-type: image/png'); // on informe le navigateur que c'est une image
imagepng($im); // on affiche l'image

?>

Même en mettant un décalage de 0.01 pixels, on obtient exactement le même résultat... Par contre, si on change la largeur du trait à 2 avec imagesetthickness, l'image créée par le serveur dédié devient correcte... Sauf que je ne peux pas me permettre une épaisseur de 2 pixels ! De plus, le serveur mutualisé ne prend pas en compte imagesetthickness avec la fonction imageellipse...

PS : Je sais bien que mon code équivaut à la fonction imagefilledellipse, mais c'est un code créé pour l'exemple, celui d'origine étant bien trop complexe !

Merci d'avance pour vos réponses :)

Modifié par ZeBrian
Posté

Bonsoir,

Petite question avant de vraiment chercher à résoudre ce problème, pourquoi ne pas utiliser imagefilledellipse qui fait le travail dont tu semble avoir besoin.

Deuxièmement je ne vois pas ce que tu cherches à faire avec le "0.1" les pixels sur un écran ne peuvent être qu'entier (c'est pour cela que tous les paramètre concernant les pixels de l'image dans les fonctions de GD/GD2 sont des entiers) donc décaler de 0.1 ou 1 ne changera rien. Ces "points noir" sont en fait simplement les point théorique où l'ellipse que tu dessines ont une valeur "médiane" (.5) et l'algorithme utilisé pour suivre cette "ligne" (courbe) est prévu pour utiliser des entier donc il arrondi soit vers le haut soit vers le bas pour trouver le point le plus proche. Bref ce n'est pas un bug, simplement une limitation due à l'affichage par "pixels" (maintenant si tu connais un autre moyen pour afficher une image sous forme digitale dépêche toi de la breveter ;))

Tu pourrais t'amuser à coder une fonction qui retrouve ces points noire à chaque fois qu'une ellipse est dessinée dans ta boucle (il suffit d'analyser la façon d'arrondir utilisée par l'algorithme de imageellipse et d'utiliser une matrice correspondante), mais franchement ça parait inutile, autant utiliser un seul appel (sans boucle) de la fonction imagefilledellipse

Bonne continuation !

P.S. : N'oublie pas de supprimer les "image ressources" (imagedestroy) que tu crée à la fin de ton script... ce n'est pas primordial en PHP, mais comme pratique de programmation en général c'est très important (surtout lorsqu'il n'y a pas de garbage collector... heureusement PHP en a un bon).

Posté (modifié)

Tout d'abord merci de ta réponse rapide !

Par rapport à ta proposition d'imagefilledellipse, bien sûr qu'elle serait adaptée à l'exemple que j'ai donné, mais elle est autrement moins adaptée à mon cas réel ! En fait, le script que je programme est un générateur de dégradés arrondis plus ou moins courbés. Utiliser la fonction imagefilledellipse se révèlerait extrêmement peu rentable en temps de calcul...

Mais ta réponse semble confirmer ce que je redoutais : les développeurs n'ont pas prévu le cas où l'on voudrait créer des ellipses accolées ! Il me semblait évident que la fonction imageellipse prendrait pour paramètre des flottants, et que l'arrondi aurait lieu uniquement une fois que la position des points aurait été calculée... :unsure:

Dommage, je vais donc tenter de créer la fonction dont tu me parles, ou carrément ne pas utiliser la fonction imageellipse et fixer la couleur de chacun des points de mon image à partir d'un algorithme élaboré par mes soins... J'y perds beaucoup en performances mais puisqu'il n'y a pas d'autre solution, autant faire cela ! :wacko:

Par rapport à imagedestroy, je l'ai oublié sur mon exemple mais il est dans mon script ;-)

Modifié par ZeBrian
Posté

De rien.

À mon avis le temps d'évaluer quel pixels sont manquants tu auras déjà fini de faire ton dégradé avec imagefilledellipse, mais ce n'est qu'à vue de nez que je te dis ça (as-tu fait des mesures entre imageellipse et imagefilledellipse ?), il faudrait coder cette fonction et comparer les deux méthodes. D'ailleurs tu n'es pas le premier à te pencher sur ce problème et tous semblent avoir optés pour imagefilledellipse :

Bonne chance et si tu réussis à coder la fonction corrigeant les pixels manquants à cause des arrondis cela serait sympathique de la partager avec nous ;)

Posté

Merci de ta réponse TheRec ! En effet, j'ai testé avec imagefilledellipse et le temps de génération était largement augmenté (multiplié par 10 ou 20)...

Mais mon problème est réglé, j'ai tout simplement codé un algorithme qui dessine pixel par pixel et qui est relativement rapide :-P

Posté

Il serait intéressant (pas pour moi uniquement) de partager cela avec la communauté, pourrais-tu poster le code en question s'il te plaît ?

Merci d'avance.

Posté

Désolé TheRec, je n'avais pas vu ta dernière réponse !

Voici tout d'abord le code de mon générateur (malheureusement non commenté, je vais essayer de prendre l'habitude de le faire...) : http://local.izipub.com/exp/gradient.phps

Pour obtenir un dégradé, il vous faudra accéder à votre fichier PHP en précisant des paramètres GET :

- type : type de dégradé (8 choix : topleft, topright, bottomleft, bottomright, top, bottom, left et right)

- size : taille en pixels de votre dégradé (dans le cas d'un dégradé horizontal ou vertical, une bande de 1 pixel de largeur sera générée car il vous suffit de demander à votre feuille CSS de la répéter)

- radius : uniquement applicable aux coins, cette propriété à définir entre 0 et 100 donne la courbure de l'arrondi

- back : la couleur de fond (inutile de la préciser si vous avez défini des couleurs aux extrémités 0 et 100) en hexadécimal à 6 chiffres

- colors : les différentes couleurs de votre dégradé, en précisant pour chacune à quel pourcentage de la longueur elle devra être.

Pour colors, la syntaxe à répéter est très stricte. Il faudra préciser la position, un double point, la couleur attribuée à cette position (en hexadécimal à 6 chiffres), puis recommencer en séparant par une virgule pour chaque nouvelle valeur.

On aura donc toujours quelquechose du type : ...&colors=0:ffff00,40:00ab66,100:008800

Un exemple complet : http://local.izipub.com/exp/gradient.php?t...f&radius=50

Bonne soirée !

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...