PHP - Notes perso sur Imagick 2 - ImagickDraw... si on dessinait ?

Deuxième épisode de mes notes perso sur la bibliothèque Image magic pour évoquer la classe ImagickDraw qui, comme son nom l'indique, permet de dessiner avec Imagick. ( 1er épisode )

On va se limiter à des usages basiques parce que la lecture du sommaire suffit à imaginer des possibilités certes alléchantes mais totalement hors de propos en ce qui me concerne (courbes de bézier etc)

Spoiler: c'est nettement moins intuitif et simple que pour le traitement d'image... l'écart entre Imagick et GD dans le domaine du tracé n'est plus si évident: ça mériterait de faire un classe pour simplifier tout ça... ( /me se jette sur son bujo pour griffonner spasmodiquement)

Préambule

Cette classe crée un objet servant d'instructions à appliquer ensuite à un objet Imagick.

On partira du principe que vous avez fait des instances des classes comme suit:

$im=new Imagick(); # l'image dans laquelle vous allez appliquer l'objet ImagickDraw
$draw=new ImagikDraw();

Ajouter un texte

Fixer les caractéristiques

  • $draw->setFont(fonte); : sélectionne la fonte à utiliser
  • $draw->setFontSize(taille); : définit la taille en pixels
  • $draw->setFillColor(couleur);: définit la couleur de fond (normalement, couleur est un objet ImagickPixel, voir 1er épisode mais on peut passer une chaîne au format de couleur CSS )
  • $draw->setTextAlignment(alignement); : une des constantes d'alignement imagick::ALIGN_LEFT imagick::ALIGN_CENTER Imagick::ALIGN_RIGHT
  • $draw->setTextDecoration(decoration): une des constantes de décoration imagick::DECORATION_UNDERLINE imagick::DECORATION_OVERLINE imagick::DECORATION_LINETROUGH et bien d'autres (comme du... bruit ?!).
  • $draw->setTextAntialias(true);: ajouter de l'antialias
  • l'espacement :
    • entre les mots : $draw->setTextInterwordSpacing(taille)
    • entre les lignes : $draw->setTextInterlineSpacing(taille)

Tracer le texte

  • $draw->annotation(x,y,texte) : trace un texte dans la police sélectionnée
  • $im->annotateImage( $draw, 0, 0, 0, $fontName ); : ajoute le texte à l'image.

Obtenir des infos utiles

  • obtenir la liste des polices disponibles: $im->queryFonts($pattern = "*") 🆒 on peut filtrer avec une pattern à la façon de glob().
  • obtenir les infos fixées par setXXX : getXXX ... ainsi on a getFont(), getFontSize() etc...
  • obtenir les dimensions de la boîte de texte: $im->queryFontMetrics($draw, text); on récupère un tableau comme ci-dessous
  • 
    Array
    (
        [characterWidth] => 9
        [characterHeight] => 9
        [ascender] => 9 # la taille au-dessus de la baseline
        [descender] => -2 # la taille sous la baseline
        [textWidth] => 71
        [textHeight] => 10
        [maxHorizontalAdvance] => 12
        [boundingBox] => Array
            (
                [x1] => 0
                [y1] => -2
                [x2] => 6.890625
                [y2] => 7
            )
        [originX] => 70
        [originY] => 0
    )
    

    Dessiner des formes

    Fixer les caractéristiques

    • opacité du trait : $draw->setStrokeOpacity(0-1);
    • couleur du trait : $draw->setStrokeColor(couleur);
    • épaisseur du trait : $draw->setStrokewidth(nb);
    • type de trait : $draw->setStrokeDashArray() Le motif semble être plein de possibilités car on peut le définir très spécifiquement et même utiliser une image comme motif (->setStrokePatternURL)
    • couleur de remplissage : $draw->setFillColor(couleur);

    Formes

    • cercle : $draw->circle ($x, $y, $x + $r, $y);
    • ellipse : $draw->ellipse($ox,$oy,$rx,$ry,$start,$end);
    • point : $draw->point ($x, $y);
    • polygone : $draw->polygon ($tableau_de_coordonnées); : array( 'x' => 3, 'y' => 4 ), array( 'x' => 2, 'y' => 6 )
    • ligne brisée : $draw->polyline ($tableau_de_coordonnées); : array( 'x' => 3, 'y' => 4 ), array( 'x' => 2, 'y' => 6 )
    • rectangle : $draw->rectangle ($x, $y, $x2, $y2); )
    • rectangle arrondi: $draw->roundRectangle ($x, $y, $x2, $y2,$rayonx,$rayony);

    Exemple

    Pour écrire un texte dans une image:

    
    $text='pipo et mollo';
    $im=new Imagick();
    $draw=new ImagickDraw();
    //var_dump($im->queryFonts('*'));exit;
    $draw->setFont( 'Courier' );
    $draw->setFontSize( 20 );
    $draw->setFillColor( 'black' );
    $draw->setTextAntialias(true);
    $metrics = $im->queryFontMetrics($draw, $text);
    $draw->annotation(0,$metrics['ascender'],$text);
    $im->newImage( 300, 20, 'lightblue');
    $im->drawImage($draw);
    $im->setImageFormat( 'png' );
    header('Content-type: image/jpeg');
    exit($im);  
    
    ce qui donne cette image
    index2.png
    C'est pas ouf...

    Il serait intéressant de pousser les tests mais là, j'ai pas le temps...

    Peut-être reprendrais-je des trucs existant avec tout ça ( scriptopic, RoR, Stamp mematic etc etc.)

    Et c'est là que Bronco prit  conscience de la quantité de   merdes affligeantes qu'il avait  codées sur un coup de tête  à la va-comme-je-te-pousse   et qu'il avait infligées à tous...

    PHP - Notes perso sur Imagick, un résumé de pourquoi je vire GD à coups de pompes dans l'oignon.

    Allez, pour une fois, j'ai un peu de temps devant moi, je vais éplucher un peu la lib Image magick dont je parlais il n'y à guère...

    La base

    charger UNE image

    Simple: pas besoin de plusieurs fonctions selon le format, il suffit de $images = new Imagick('image.jpg');

    charger DES images (et là c'est fort)

    Même pas nécessaire de passer par un foreach, on fournit le tableau des fichiers voire directement un glob: $images = new Imagick(glob('images/*.JPG'));

    Sauver une image

    $im->writeImage('image.jpg');

    Faire une miniature

    Si on laisse une dimension à 0, les proportions sont conservées (quand tu vois la merde que c'est avec GD !) $image->thumbnailImage(100, 0);

    Output une image

    header('Content-type: image/jpeg');
    $image = new Imagick('image.jpg');
    # ici on effectue un traitement puis on sort le résultat
    echo $image;

    Récupération d'infos sur les images

    • taille $im->getImageWidth() $im->getImageHeight()
    • format $im->getImageFormat()

    création d'une nouvelle image

    $im->NewImage(largeur,hauteur,couleur de fond);

    création d'une couleur

    Comme pour GD, il faut créer un objet couleur dans les traitements d'image, mais c'est plus simple qu'avec GD (et plus complet): il suffit de passer une couleur selon les normes CSS. Du coup, la transparence n'est pas gérée par une connerie de paramètre «alpha» mais simplement par ... rgba()... 💖

    $couleur=new ImagickPixel("white");
    $couleur=new ImagickPixel("#FFF");
    $couleur=new ImagickPixel('rgb(255,255,200)');
    $couleur=new ImagickPixel('rgba(255,255,200,0.5)');

    🆒 ⮕ Ça peut paraître compliqué, mais en fait, dans les fonctions où on est sensé utiliser ImagickPixel, je me suis aperçu qu'on pouvait tout simplement passer une string contenant la couleur css... elles se démerdent seules. 😍

    Traitements

    Ajouts

    • de bordure ->borderImage(couleur,largeur bords verticaux, largeur bords horizontaux): $im->borderImage(new ImagickPixel("white"), 5, 5);
    • de texte :
    • de stéganographie (cacher un filigrane dans une image) ->steganoImage():

    Modification de couleurs

    • sepia ->sepiaToneImage(force) : une valeur raisonnable est 80 (sic)
    • solarisation ->solarizeImage(force)
    • négatif ->negateImage(gris): $im->negateImage(0);
    • niveaux
      • $im->normalizeImage();
      • $im->autoLevelImage();
    • gamma ->gammaImage(niveau) : $im->gammaImage(5);
    • contraste $im->contrastImage(niveau)
    • luminosité et contraste $im->brightnessContrastImage(niveau luminosite, niveau contraste);
    • égalisation $im->equalizeImage()
    • coloriser ->colorizeImage(couleur,opacite) : $im->colorizeImage("red",0.5); 🤬 pas réussi à l'utiliser pour ce test...

    Modification de taille et d'orientation

    • redimensionner :
      • ->resizeImage(largeur,hauteur, filtre, flou) : $i->resizeImage(250,0,Imagick::FILTER_POINT,0);
      • ->scaleImage(largeur,hauteur): pas encore compris la différence avec la précédente
      • recadrer ->cropImage(largeur,hauteur,x,y): $im->cropImage(200,200,50,50);
      • 💖 créer une miniature à la taille donnée en recadrant l'image autour du centre ->cropThumbnailImage(largeur,hauteur)
    • retourner :
      • $im->flipImage() pour retourner horizontalement
      • $im->flopImage() pour retourner verticalement
    • pivoter ->rotateimage(color, $angle): $im->rotateImage(new ImagickPixel('#00000000'), 75);

    Modifications de qualité

    • modification d'opacité ->setImageOpacity(0-1) : $im->->setImageOpacity(0.3);
    • netteté ->sharpenImage(rayon, deviation,canal):
    • amélioration ->enhanceImage()
    • flou :
      • flou tout court ->blurImage(rayon, décalage): $im->blurImage(5,2);
      • gaussien ->gaussianBlurImage(rayon, deviation) : $im->gaussianBlurImage(5,2);
      • de mouvement ->motionBlurImage(rayon,deviation,angle) : $im->motionBlurImage(5,5,45);
    • réduction du nombre de couleurs ->posterizeImage(nb de couleurs, 0/1) :$im->posterizeImage(5,0);
    • ajout de bruit ->addNoiseImage(type) : `$im->addNoiseImage(imagick::NOISE_GAUSSIAN ); voir les constantes de type de bruit

    Modification d'aspect et déformations

    • aspect crayon $im->sketchImage(rayon, deviation, angle);
    • aspect fusain $im ->charcoalImage(rayon, deviation);
    • aspect emboss ->shadeImage(gris, angle, hauteur):
      • $im->->shadeImage(1, 90, 2); # emboss + image grisée
      • $im->shadeImage(0, 90,2) # emboss sur l'image d'origine (couleur)
    • peinture à l'huile ->oilPaintImage(rayon) : $im->oilPaintImage(5);
    • détection de bords ->edgeImage(rayon) : $im->edgeImage(5);
    • vagues ->waves(amplitude,longueur): $im->waveImage( 10, 10);
    • déformation ->distortImage(methode, arguments[],0) : voir les constantes de déformation

    interactions d'images

    Conclusion

    Image Magick me semble particulièrement bien nommée tant les possibilités sont énormes et la simplicité d'utilisation étonnante: on sent une volonté de se simplifier la vie lors de l'utilisation... c'est juste beau.

    Je voulais mettre une image de chaque effet dans les descriptions mais:

    1. ça prenait une place de ouf
    2. je préfère reprendre certaines de mes applis/api avec imagick
    3. j'ai plus le temps, les autres arrivent
    4. j'ai la flemme.

    [EDIT] En fait, j'ai fait une page de test même si tout n'est pas concluant : http://test.warriordudimanche.net/imagick/

    Outils gratuits en ligne de traitement d'image automatique (et de video et de son) MAJ

    📋 Note pour plus tard

    Image

    Vidéo et son

    Générateur

    Bionic Reading API Documentation (bionic-reading-bionic-reading-default) | RapidAPI

    Tiens, il existe une API qui permet de transformer du texte en Bionic Reading, cette technique améliorant la lecture en mettant en gras le début du mot. Je m'interrogeais justement sur la pertinence d'implémenter ça sur mon appli de documents en espagnol pour les élèves éprouvant des difficultés de lecture...

    Bon, il faudra que je fasse une couche d'interface afin que les données des élèves ne transitent pas vers le site de l'API, comme pour celle de synthèse vocale... mais rien de trop ardu.

    A creuser.

    Linux Mint : Les dossiers utilisateurs déplacés...

    Depuis quelques jours, un truc étrange s'est manifesté sur mon ordi portable: les dossiers Document, Images, Téléchargement, Bureau avaient tous été déplacés dans un sous-dossier à ouatmille niveaux sans aucune raison visible...

    Au cas où ça vous arrive, remettez-les à leur place (en drag drop ou via le terminal) puis éditez le fichier : ~/.config/user-dirs.dirs pour rétablir les chemins d'origine. Redémarrez et voilà...

    Nicolas Vivant: En #France, les suites collaboratives #Microsoft #Office 365 et #Google #Workspace sont proscrites dans les services de l'État.

    Merci à @sebsauvage pour le partage !

    « Amis de la fonction publique d'État, si on vous pose la question... En #France, les suites collaboratives #Microsoft #Office 365 et #Google #Workspace sont proscrites dans les services de l'État. Les bases réglementaires : → Note de la CNIL (27/05/2021) : https://www.cnil.fr/fr/la-cnil-appelle-evolutions-dans-utilisation-outils-collaboratifs-etatsuniens-enseignement-superieur-recherche → Circulaire 6282-SG (05/07/2021) et note (15/09/2021) : https://acteurspublics.fr/upload/media/default/0001/36/acf32455f9b92bab52878ee1c8d83882684df1cc.pdf → Ministre de l'Éducation Nationale, en réponse à une question écrite (2022) : https://questions.assemblee-nationale.fr/q16/16-971QE.htm

    droit #juridique #numerique »

    Notes sur la gravure laser

    Notes tirées de la doc sur le site sculpfun

    https://sculpfun.com/blogs/news/settings-guide

    • plus la vitesse est basse, plus le matériau subira de brûlures indésirables: pour la découpe, il vaut donc mieux augmenter la vitesse et le nombre de passes que faire le contraire
    • quand on ignore les réglages d'un matériau, tester en commençant par 10% / 1000 mm/m et augmenter l'intensité
    • nettoyer régulièrement la lentille
    • comme la focale du laser est fixe, lors des découpes le point de focale devient de moins en moins optimal au fur et à mesure des passes: on propose pour les matériaux les plus épais, de régler la focale au milieu du matériau. Ainsi, pour un 10mm d'épaisseur, on règle 5mm plus bas que la cale.

      LaserFocusOverview-1024x576.png

    • certains matériaux sont toxiques si on les brûle: voir PDF
    • Les réglages sont souvent à affiner mais on peut partir des suivants: PDF

      S9reglages.png

    • Pour des matériaux plus exotiques comme le cuir, le verre transparent, l'acrylique transparente ou le miroir :
      • verre transparent: peindre en noir, graver puis nettoyer (pas de découpe possible) 1000-2000 mm/min 60-80%
      • acrylique transparente : comme le verre, peindre avant de graver (pas de découpe possible)
      • miroir: ⛔ on grave le dos du miroir pas la face (danger !) 1000-2000 mm/min 30-80%
      • cuir : 1000-2000 mm/min 20 – 60%
      • acier inox: marquage au marqueur noir, 800-1500 mm/min 20-70%, nettoyage

    s9reglages complementaires.png

    (...)

    SwebDev - La fonction CSS clamp()

    Clamp permet de spécifier trois valeurs pour une propriété : la valeur minimale, la valeur préférée et la valeur maximale.

    Glopglop N°1

    Ainsi, on pourra donner des tailles fixes comme minimum et maximum et une taille variable (pourcentages ou valeur de viewport) comme valeur préférée: la valeur variable sera utilisée, mais bornée au minimum et au maximum. ex: clamp(20px, 5vw, 54px)

    Glopglop N°2

    On peut faire des calculs directement dans clamp() : font-size: clamp(20px, 16px + 5vw, 54px);

    Glopglop N°3

    Clamp peut être utilisé sur les paddings, les margins etc... Tout ce qui a une valeur numérique (length, number, percentage...)

    Super Useful CSS Resources 🌈 - DEV Community 👩‍💻👨‍💻

    De côté pour plus tard: en particulier les usages exotiques de CSS.

    Il ne faut jamais débattre avec l’extrême-droite | by Nicolas Galita | Dépenser, repenser | Medium

    Très bon article ! Je me résume quelques idées ici.

    Principe #1 | L’extrême droite n’est ni inculte, ni stupide, ni méchante

    Ce sont des gens habiles qui appliquent des stratégies de décrédibilisation et de communication.

    il suffit de passer son temps à lancer des accusations ou des trucs faux courts, sur un ton confiant. De manière à générer en face de longues justifications. Quand la personne a fini de se dépêtrer on lance une autre accusation. Et ainsi de suite.

    La personne qui accuse, donne une impression de certitude. Celle qui se justifie donne l’impression d’être en faute.

    Débattre avec quelqu’un d’extrême-droite sous entend que, si ça se trouve, il a raison.

    Soit on éduque, soit on ignore. Mais en aucun cas ça peut être un débat.

    Pour, elle, le but du débat d’humilier l’adversaire.

    Principe #2| Comprendre les mécaniques d’audience

    Ils ne débattent que si ça leur permet de gagner de l'audience, donc avec des gens dont il peuvent récupérer de l'audience ou des partisans.

    il ne faut jamais répondre à un adversaire qui a une audience significativement inférieure à la sienne.

    Principe #3| L’extrême-droite n’est pas sincère quand elle appelle à la liberté d’expression ou à la démocratie

    Elle utilise nos valeurs à nos dépends en les pervertissant.

    La libre expression et la démocratie ne sont pas des valeurs d’extrême-droite. Elle s’en contrefiche. En revanche, elle sait que ce sont des valeurs chères aux autres camps politiques.

    L’extrême-droite est pour la liberté d’expression uniquement quand elle est marginale ou en conquête du pouvoir. Une fois qu’elle l’a, elle réduit l’opposition au silence. Elle a raison : elle comprend très bien que sa meilleure manière de prendre le pouvoir est de profiter d’une faille de la “démocratie”.

    Ça marche tellement bien que, même quand elle obtient la parole, l’extrême-droite continue à clamer partout qu’elle n’a pas la parole. [...] C’est ridicule uniquement si on se place du point de vue de la recherche de la vérité. Mais l’important n’est pas d’avoir raison, l’important est de gagner. Or, cette stratégie est ultra-gagnante. Plus Zemmour crie qu’il est censuré et plus on lui offre des tribunes. Pourquoi arrêterait-il ?

    Principe #4| La loi de Brandolini

    certaines bêtise prennent vingt secondes à dire, mais des heures à réfuter.

    le souci c’est que dans un débat en direct, il est impossible de dire “attends, je vais chercher la réfutation dans une vidéo de 20 minutes”. D’ailleurs, même quand on connaît la réfutation, c’est quasiment impossible de la déployer en direct. L’autre va nous couper la parole, nous empêcher de dérouler…

    Principe #5| La fenêtre d’Overton

    La fenêtre d’Overton est l’ensemble des propos acceptés en public par la société sur un sujet donné [...] On ne débat que des idées dont les deux réponses sont dans la fenêtre d’Overton.

    L’extrême-droite comprend donc qu’il lui faut d’abord déplacer la fenêtre dans son sens, pour espérer faire élire un des siens. [...] Ce processus s’appelle “la normalisation”.

    Voilà pourquoi l’extrême-droite veut être de tous les débats [...] Parce que ça lui permet de déplacer la fenêtre d’Overton. De banaliser ses idées. [...] Quand on est vraiment en dehors de la fenêtre d’Overton, il n’y a pas de mauvaise publicité.

    Conclusion: le meilleur moyen de lutter contre l'extrême droite

    1- cesser de leur tendre le micro

    Morale de l’histoire : quand l’adversaire pleure [pour se plaindre de ne pas bénéficier d'une écoute démocratique] on n’est pas censé lui donner ce qu’il demande. Au contraire, c’est le signe que notre combat fonctionne. [...] L’extrême-droite se plaindra qu’on lui refuse le débat, jusqu’à ce qu’on accepte. Mais si on accepte jamais…elle est dans l’impasse

    Pour vous déculpabiliser en tant que modérateur sur vos pages de commentaires / réseaux sociaux etc. :

    Les gens d’extrême-droite sont libres d’avoir leur petits espaces d’expression, sans qu’on soit obligé de leur offrir nos grands espaces, volontairement.

    2. pour les plus extrêmes, les bannir.

    des gens comme Dieudonné ou Alain Soral ont subi ces bannissements, avec succès. Car oui, le bannissement fonctionne.

    On devrait plutôt réfléchir à quels groupes d’extrême-droite il faut bannir ou dissoudre, plutôt que de passer notre temps à vouloir débattre avec les mouvements les plus “modérés” de l’extrême-droite.

    Via https://www.parigotmanchot.fr/liens/shaare/LfhUSg

    Make Beautifully Resilient Apps With Progressive Enhancement

    Notes perso de lecture rapide et en diagonale.

    rien d'essentiel ne doit dépendre de javascript, en particulier les formulaires.

    • JS peut être désactivé
    • le navigateur peut être obsolète (oui, windows, c'est de toi que je parle)
    • des extensions peuvent bloquer le script
    • le client a peut être une connexion lente qui va timeout
    • le client a peut être une connexion intermittente (genre le train)
    • il peut y avoir un firewall qui bloque certaines choses.
    • etc

    En gros, JS devrait être réservé à des choses qu'on ne peut pas faire autrement et/ou non essentielles.

    Pour les formulaires, on peut partir d'un formulaire normal fonctionnant normalement et l'améliorer via JS: capturer l'événement onsubmit et gérer l'envoi au serveur via des promises et fetch, traiter les erreurs etc.

    Si JS ne fonctionne pas, le formulaire continuera de faire son job avec le comportement par défaut de submit mais de façon moins sexy, c'est tout.

    Et si les envois et retours se font en JSON et tout le merdier ?

    Problème de type de retour et de format de réception

    L'auteur propose d'utiliser le header côté serveur pour identifier qui de JS ou de HTML est à l'origine de la requête (avec Sec-Fetch-Mode par exemple ) et ainsi adapter le comportement du serveur (traitement des données et composition de la réponse)

    En gros:

    • si ça vient de JS ➜ gère le JSON et renvoie du JSON pour que JS gère la réponse
    • si ça vient de HTML ➜ gère le formulaire normalement et renvoie une nouvelle page HTML composée côté serveur.

    Re: Choses vues, sur le web et ailleurs Affiches de la campagne de l

    En effet, les analyses sont pertinentes.

    1. il y a confusion entre laïcité et vivre ensemble/assimilation
    2. les hommes et femmes politiques ne sont pas stupides
    3. conclusion: cette confusion est entretenue à dessein pour justifier un poids raciste en usant de la laïcité.

    Any questions ?!

    laicité2.png

    laicité1.png

    Via https://ecirtam.net/opennews/

    Ressources pour créer des jeux d'aventure

    Plein de générateurs utiles   pour des JDR et éventuellement  un EPI avec un copain   l'année prochaine...

    Cartographie

    Background

    Divers

    Fil RSS des articles