IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

Manipulation laborieuse des pixels d'un bitmap vs les pixels de la form


Sujet :

Delphi

  1. #1
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut Manipulation laborieuse des pixels d'un bitmap vs les pixels de la form
    Bonjour,

    Ça fait bien longtemps que je n'étais pas venu poster une question ici, plutôt habitué ces derniers temps au bistrot forum Lazarus , mais là, je retourne aux origines.
    Contexte : D7perso tournant sur w2K sp4 (virtualisé dans une machine Linux mais ça, on s'en fiche).

    Le problème : la compréhension de l'écriture des pixels d'un bitmap vs la même écriture dans le canvas d'une form.

    Je suis parti du sympathique article dont Paul TOTH m'a récemment fourni le lien, j'ai vu la jolie image en bas de la page, et je me suis employé à refaire la même chose jusqu'à arriver au même résultat, ce qui ne fut pas trop compliqué grâce au copier/coller.
    Ensuite, j'ai voulu refaire la même chose dans un TImage, en passant par un TBitmap intermédiaire, et c'est là que ça se complique.

    Comme j'avais des soucis, pour essayer de les cerner j'ai commencé par changer la couleur mais une couleur uniforme dans un carré, pour voir les défauts, laisse tomber !, alors j'ai changé la taille du canvas et du carré je suis passé au rectangle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const
      IMAGE_WIDTH  = 256;
      IMAGE_HEIGHT = 128;//256;
    et là, tout de suite, j'ai relevé que la note de Paul, sur sa page, en date du 29/05/2013, semble erronée ! Ben oui, Paul, regarde les images (note : les images présentées dans ce post sont toutes réduites de moitié) :
    Nom : rouge_yx_xy.jpg
Affichages : 365
Taille : 6,5 Ko à gauche le mode yx conseillé , à droite le mode xy d'origine

    En plus, en utilisant le mode d'origine (Pixels[x, y]), j'affiche bien l'image présentée en bas de la page web.
    Car oui, en mettant [y, x], je ne retrouvais pas l'image et je me suis dit que Paul n'avait pas fait de nouvelle capture malgré la modif du 29/05.
    Nom : paul_xy_yx.jpg
Affichages : 425
Taille : 19,2 Ko à gauche le mode xy d'origine , à droite le mode yx conseillé

    Et ça n'est jamais bon de faire des suppositions sur ce qu'ont fait (ou pu faire) les autres : en informatique, àmha, il faut des certitudes, sinon on avance en plein brouillard...
    Paul, message perso, il serait bon que tu clarifies ce point.


    Ceci étant dit, le problème que je rencontre est résumé ainsi : écrire des pixels colorés sur le canvas de la form est simple et très joli, voir ci-dessus ; écrire ces mêmes pixels sur le canvas d'un TBitmap est (devrait être ?) aussi simple mais affiche des abominations :
    Nom : bads.jpg
Affichages : 350
Taille : 8,7 Ko

    J'ai tout essayé de ce que je connais : inverser x et y, inverser le sens de balayage (de for variable = 0 to valeur-1 do à for variable = valeur-1 downto 0 do), commencer le balayage d'abord avec la width ou d'abord avec la height, pf24bit ou pf32bit, plusieurs méthodes de recopie dans l'image d'affichage, dans tous les cas c'est la cata !
    D'où ce post, dans l'espoir d'idées lumineuses...

    Ah, le code (pour tester, une TImage à la taille des constantes données plus haut) sur une form et zou !) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    procedure TForm1.FormCreate(Sender: TObject);
    var
      x, y: Integer;
      SrcBmp: TBitmap;
    begin
      DoubleBuffered := True; // rajouté par moi
    {  // 3 lignes direct du site sans changer une virgule
      for x := 0 to IMAGE_WIDTH - 1 do
        for y := 0 to IMAGE_HEIGHT - 1 do
          pixels[y, x] := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16);
    }
      SrcBmp := TBitmap.Create;
      with SrcBmp do begin
        SrcBmp.PixelFormat:=pf32bit;
        //SrcBmp.PixelFormat:=pf24bit;
        SrcBmp.Width := IMAGE_WIDTH;
        SrcBmp.Height := IMAGE_HEIGHT;
      end;
      with SrcBmp.Canvas do
        for x := 0 to IMAGE_WIDTH-1 do
    //    for x := IMAGE_WIDTH-1 downto 0 do
    //      for y := IMAGE_HEIGHT-1 downto 0 do
          for y := 0 to IMAGE_HEIGHT-1 do
    //        Pixels[x, y] := clRed; // ça c'est bon ! Ah mais quand même...
    //        Pixels[x, y] := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16);
            Pixels[x, y] := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16) or $FF000000;
    
    // essais d'affichage, tous identiques
    //  image1.Canvas.Draw(0, 0, SrcBmp);
    //  image1.Picture.Assign(SrcBmp);
      image1.Picture.Graphic := SrcBmp;
    end;
    Je ne mets pas celui du FormPaint, c'est celui de Paul, juste que je lui rajoute un Exit; au début, quand j'active le couple bitmap et image.
    Ce FormPaint inclut en bas qq lignes pour écrire sur la form, chose qui ne m'intéresse pas pour l'instant.

    Quelqu'un va pouvoir m'expliquer pourquoi je ne peux pas manipuler simplement les pixels d'un bitmap ?

    Mille mercis par avance...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Parce qu'il faut clamper tes valeurs (*), ou faire des modulo (**) (<- en gros si c'est supérieur à 255 il faut revenir à 0)

    * ->
    Si Color < 0 -> Color = 0
    Si Color > 255 -> Color = 255


    ** ->
    Color = (Color % 256)

  3. #3
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par foetus Voir le message
    Parce qu'il faut clamper tes valeurs (*),

    * ->
    Si Color < 0 -> Color = 0
    Si Color > 255 -> Color = 255
    Euh, comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    //      pixels[y, x] := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16);
        begin
          aColor := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16);
          if aColor < 0 then aColor := 0;
          if aColor > 255 then aColor := 255;
          pixels[y, x] := aColor;
        end;
    Parce que ça donne ça, et je ne trouve pas ça terrible-terrible...
    à gauche avant la modif, au centre ton idée, et à droite ton idée en utilisant le bitmap :

    Nom : foetus_info.jpg
Affichages : 424
Taille : 55,8 Ko


    Ah, travailler avec Pixels[x, y] quand l'objet est rectangulaire me génère un Access Violation ! , et je ne sais pas encore pourquoi (je viens de le découvrir maintenant).
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 684
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 684
    Points : 13 093
    Points
    13 093
    Par défaut
    Citation Envoyé par Jipété Voir le message
    j'ai relevé que la note de Paul, sur sa page, en date du 29/05/2013, semble erronée
    Cela concerne le tableau de couleurs utilisé pas SetDIBitsToDevice et non la propriété Pixels du canvas. Peut-être aurait-il fallu l'appeler autrement pour éviter la confusion
    La seule chose qui me semble être incorrect est le remplissage de ce tableau qui devrait être de IMAGE_HEIGHT -1 downto 0 puisque le premier pixel est en bas à gauche.

  5. #5
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Cela concerne le tableau de couleurs utilisé pas SetDIBitsToDevice et non la propriété Pixels du canvas. Peut-être aurait-il fallu l'appeler autrement pour éviter la confusion
    x 1000 !

    Citation Envoyé par Andnotor Voir le message
    La seule chose qui me semble être incorrect est le remplissage de ce tableau qui devrait être de IMAGE_HEIGHT -1 downto 0 puisque le premier pixel est en bas à gauche.
    Comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        for x := 0 to IMAGE_WIDTH-1 do
          for y := IMAGE_HEIGHT-1 downto 0 do
            Pixels[x, y] := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16);
    ça donne l'image de gauche, déjà présentée :
    Nom : bads.jpg
Affichages : 359
Taille : 8,7 Ko
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Euh, comme ça ?
    Mais non voyons

    Reprenons: Il y a plusieurs formats de couleurs (RGB, RGBA, HSV, ...) mais en Delphi c'est du BGR.

    Une couleurs BGR est codée sur 4 octets, et l'octet le plus à gauche c'est 0, le 2ième c'est le bleu, le 3ième le vert (Green) et le 4ième (le plus à droite) le rouge.

    Et les valeurs vont de 0 à 255 pour chaque composante.

    Il faut faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
           blue, red, green: Integer;
        begin
          blue := (x + x);
          green := (x - y);
          red := (x + y);
     
          if blue < 0 then blue := 0;
          if blue > 255 then blue := 255;
     
          if green < 0 then green := 0;
          if green > 255 then green := 255;
     
          if red < 0 then red := 0;
          if red > 255 then red := 255;
     
          aColor := 0x00000000;
          aColor := red or (green shl 8) or (blue shl 16);
     
          pixels[y, x] := aColor;
        end;
    Mais ton calcul c'est de la m^rd^ parce que (x + y) ou (x + y) dépassera souvent 255 et tu auras du noir
    D'où le modulo qui permet de "faire un tour"


    Citation Envoyé par Jipété Voir le message
    je ne sais pas encore pourquoi (je viens de le découvrir maintenant).
    Il ne faut pas taper hors buffer

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 684
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 684
    Points : 13 093
    Points
    13 093
    Par défaut
    En fait le remplissage du tableau est correct puisqu'il est inversé ensuite à l'utilisation par -IMAGE_HEIGHT (je parle toujours de SetDIBitsToDevice).

  8. #8
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Alors, déjà mon article a pour but de montrer qu'un tableau de TColor est plus simple à manipuler que des ScanLines...et c'est surtout beaucoup plus rapide que la propriété Pixels[] de TBitmap ! Ce dernier présent un seul avantage, c'est que tu n'as pas à te préoccuper du PixelFormat, tu donnes une couleur RGB et le bitmap se débrouille avec. En ScanLine tu dois tenir compte du format pour savoir comment définir un pixel, avec mon tableau (tel qu'il est déclaré) c'est forcément du 32Bits.

    ensuite le xy/yx c'est en effet pour mon tableau puisque tableau[a, b] c'est tableau[a * width + b], on a donc bien tableau[y, x]

    comme indiqué dans l'article "SetDIBitsToDevice(Bmp.Canvas.Handle,..." permet de dessiner dans un TBitmap sans problème.

    finalement pour éviter les problèmes de "clamp" tu peux utiliser TBitmap.Pixels[x, y] : =RGB(r, g, b);" les paramètres étant des Byte tu ne dépasseras pas 255, mais du coup 256 donnera 0, c'est comme si tu faisais un modulo 256 sur chaque valeur...ou comme le propose foetus tu bornes la valeur entre 0 et 255.

    Je ne reviens pas sur la notion de canal alpha déjà évoquée sur le forum Lazarus
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Merci à vous trois pour vos pistes, vos tentatives, vos renseignements, etc.

    Avec tout ça, j'en suis là : à gauche l'écriture sur le canvas de la form, à droite dans le TImage chargé par le TBitmap de travail...

    Nom : nouvelessai.jpg
Affichages : 372
Taille : 12,1 Ko

    J'ai trituré l'image de droite dans tous les sens, pas moyen d'arriver à trouver le même positionnement de couleurs que sur l'image de gauche.
    C'est pour moi le plus perturbant.

    Pas mal, ton idée, foetus, mais du coup on perd toute la géométrie du dessin de Paul, et le rendu des couleurs, même si on reste dans les mêmes tons. Je ne pense pas que ça soit la bonne solution.

    Bien tenté, Andnotor, mais j'ai essayé les 4 combinaisons possibles et c'est toujours pareil, la couleur blanche toujours opposée au rouge, se colle en haut à droite (à condition d'inverser xy par rapport au dessin sur canvas : si pas d'inversion elle se colle en bas à gauche et terminé !) et n'en démord pas !
    Oui, on va dire que je prends l'écriture sur le canvas de la form (avec le texte) comme référence, et j'aimerais bien avoir, un jour..., un bitmap représentant le même dessin (sans le texte). Mission impossible ?
    Ou c'est lié au fait qu'on mélange les x et les y des déplacements avec le paramétrage des couleurs ?

    En tout état de cause, ayant créé une procédure commune aux deux affichages de ces couleurs, je m'attendais à retrouver les mêmes couleurs, éventuellement pas aux mêmes endroits. Mais là ça fait beaucoup de changements pour une procédure identique...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    begin
      DoubleBuffered := True;
    {$IFDEF FORMCANVAS}
      for x := 0 to IMAGE_WIDTH - 1 do
        for y := 0 to IMAGE_HEIGHT - 1 do
    {$ELSE}
      SrcBmp := TBitmap.Create;
      with SrcBmp do begin
        SrcBmp.PixelFormat:=pf32bit;
        //SrcBmp.PixelFormat:=pf24bit;
        SrcBmp.Width := IMAGE_WIDTH;
        SrcBmp.Height := IMAGE_HEIGHT;
      end;
      with SrcBmp.Canvas do
    //    for x := 0 to IMAGE_WIDTH-1 do // blanc en haut à droite
        for x := IMAGE_WIDTH-1 downto 0 do // blanc en haut à droite
    //      for y := IMAGE_HEIGHT-1 downto 0 do  // blanc en haut à droite
          for y := 0 to IMAGE_HEIGHT-1 do    // blanc en haut à droite
    {$ENDIF}
     
    // les couleurs, communes aux deux cibles :
        begin
          blue := (x + x); green := (x - y); red := (x + y);
          if blue < 0 then blue := 0; if blue > 255 then blue := 255;
          if green < 0 then green := 0; if green > 255 then green := 255;
          if red < 0 then red := 0; if red > 255 then red := 255;
    {$IFDEF FORMCANVAS}
          Pixels[y, x] := red or (green shl 8) or (blue shl 16);
    {$ELSE}
    //      Pixels[x, y] := red or (green shl 8) or (blue shl 16);
          Pixels[y, x] := red or (green shl 8) or (blue shl 16);
    {$ENDIF}
        end;
     
    {$IFNDEF FORMCANVAS}
      image1.Visible := True;
      image1.Canvas.Draw(0, 0, SrcBmp);
    //  image1.Picture.Assign(SrcBmp);
    //  image1.Picture.Graphic := SrcBmp;
    {$ENDIF}
     
    end;
    Pas plus pour le moment.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    il faut réfléchir un peu ... et sortir les maths

    En haut à gauche, c'est du noir RGB(0, 0, 0)
    En bas à gauche, c'est du bleu RGB(0, 0, 255)
    En haut à droite, c'est blanc RGB(255, 255, 255)
    En bas à droite, c'est du rose RGB(255, 0, 255)

    Donc:
    • Le rouge est incrémenté de gauche à droite de 0 à 255, quelle que soit la ligne
    • Le vert est incrémenté en cercle centré sur le coin supérieur droit (plus on se rapproche et plus on tend vers 255)
    • Le bleu est incrémenté en cercle inverse centré sur le coin supérieur gauche (plus on s'éloigne et plus on tend vers 255)

  11. #11
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par foetus Voir le message
    il faut réfléchir un peu ... et sortir les maths -- snip --
    Tu sais quoi ? Tout ce que tu as dit je le sais !
    Le seul problème c'est de passer ça dans le bitmap...

    Je me suis inspiré de ce que Paul disait, et j'ai fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {$IFDEF FORMCANVAS}
          Pixels[y, x] := rgb(red, green, blue);
    {$ELSE}
    //      Pixels[y, x] := rgb(red, green, blue);
          Pixels[x, y] := rgb(red, green, blue);
    {$ENDIF}
    J'ai même viré ces histoires de shl pour y voir clair, c'est rigolo j'ai une image de base (celle avec le texte, le $IFDEF FORMCANVAS) pleine de triangles colorés, et ensuite j'ai inversé le $DEFINE et j'ai joué avec le bitmap et les 4 possibilités de balayage : | downto to | downto downto | to to | to downto.
    La boucle extérieure travaille avec IMAGE_WIDTH et l'intérieure avec IMAGE_HEIGHT, je réalise après coup que j'aurais pu tester l'inverse également. Bon, je poste ça et j'y retourne... [EDIT] : c'était pas la peine, ça n'a rien changé, je retombe sur les même images A et B.
    downto tout le monde aura compris que c'est la boucle for big downto 0 quand to c'est l'inverse, for 0 to big.

    J'ai rajouté l'option xy / yx, ça donne 8 possibilités et voilà les résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       |   EXT  INT|   EXT    INT  |EXT INT| EXT  INT  |
       | downto to | downto downto | to to | to downto |
    yx |     A     |       B       |   A   |     B 
    xy |     A     |       B       |   A   |     B
    Il y a donc 4 images A identiques, et 4 images B identiques. Et voilà à quoi ça ressemble :
    Nom : essaibytes.jpg
Affichages : 422
Taille : 30,9 Ko

    À gauche vous aurez reconnu l'image de base, et au centre et à droite les images bitmap, A puis B.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  12. #12
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    il y a quelque chose qui me chagrine dans tes explications

    1) Form.Canvas ou Bitmap.Canvas, ça reste un Canvas que tu peux passer en paramètre d'une fonction commune qui se fiche de savoir si c'est une fiche ou bitmap.

    2) Pixel[x, y] := f(x, y)...qu'importe l'ordre dans lequel tu calcules les pixels (to/downto) vu que la couleur d'un pixel ne dépend que de sa position.

    3) tes deux images de droites subissent une rotation à 90° l'un part rapport à l'autre à cause du [x, y] et [y, x]

    4) la différence couleur vient de RGB(). Dans mon code il y a des débordements:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      couleur := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16)
      couleur := RGB(x + y, (x - y) + (x + y) div 256, (x + x) + ((x - y) + (x + y) div 256) div 256);
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  13. #13
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    il y a quelque chose qui me chagrine dans tes explications

    3) tes deux images de droites subissent une rotation à 90° l'un part rapport à l'autre à cause du [x, y] et [y, x]
    Il y a plusieurs choses que je ne capte pas dans ton retour :

    il a fallu que je fasse subir une rotation de 90° anti-horaire à celle du centre, en effet, puis un effet miroir selon l'axe horizontal pour basculer ce qui était en haut en bas.
    Du coup, oui, les deux images de droite se retrouvent identiques, mais en aucun cas similaires à celle de gauche, qui est le but à atteindre.
    Nom : rotationpaul.jpg
Affichages : 436
Taille : 43,4 Ko

    Citation Envoyé par Paul TOTH Voir le message
    4) la différence couleur vient de RGB(). Dans mon code il y a des débordements:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      couleur := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16)
      couleur := RGB(x + y, (x - y) + (x + y) div 256, (x + x) + ((x - y) + (x + y) div 256) div 256);
    Les débordements j'ai dû les éliminer en utilisant des bytes comme tu l'as plus tôt suggéré car ce nouveau code me produit exactement les mêmes images et couleurs que celui d'il y a quelques heures.


    Citation Envoyé par Paul TOTH Voir le message
    2) Pixel[x, y] := f(x, y)...qu'importe l'ordre dans lequel tu calcules les pixels (to/downto) vu que la couleur d'un pixel ne dépend que de sa position.
    La couleur d'un pixel, pour moi, dépend surtout de ce qu'on a mis dans ses bytes R G B et éventuellement A. Non ?

    Citation Envoyé par Paul TOTH Voir le message
    1) Form.Canvas ou Bitmap.Canvas, ça reste un Canvas que tu peux passer en paramètre d'une fonction commune qui se fiche de savoir si c'est une fiche ou bitmap.
    Oui, sauf que dans ton code le boulot pour "redescendre" sur le canvas de la fiche cette Array de TColor est fait par SetDIBitsToDevice.
    Je pourrais essayer de lui faire manger de la cible genre TBitmap ou TImage, à cette fonction Windows, mais mon souci, c'est qu'elle n'existe pas dans Lazarus, qu'un forum a suggéré d'utiliser BitBlt, que je n'y arrive pas dans ton code (normal, BitBlt veut un handle to source device context comme source, et pas une array de pixels), alors imagine dans Lazarus, et c'est comme ça que je me retrouve ici à poser mes questions incompréhensibles...
    Désolé...

    Merci en tout cas pour l'implication, et je m'en vais creuser une nouvelle piste, la transformation d'une array de pixels en bitmap, me semble avoir des posts là-dessus...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  14. #14
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    Salut,

    avec ce code j'obtiens bien le même résultat que l'original :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ...
    var // j'ai juste modifié la variable pixels en apixels pour pouvoir l'utiliser plus bas ...
      apixels: array[0..IMAGE_HEIGHT - 1, 0..IMAGE_WIDTH - 1] of TColor; // hauteur puis largeur, et non l'inverse
    procedure TForm4.Button2Click(Sender: TObject);
    var
      x, y: Integer;
      SrcBmp: TBitmap;    
    begin
      DoubleBuffered := True; // rajouté par moi
      SrcBmp := TBitmap.Create;
      with SrcBmp do begin
        SrcBmp.PixelFormat:=pf32bit;
        SrcBmp.Width := IMAGE_WIDTH;
        SrcBmp.Height := IMAGE_HEIGHT;
      end;
     
      with SrcBmp.Canvas do
      for y := 0 to IMAGE_HEIGHT-1 do
        for x := 0 to IMAGE_WIDTH-1 do
          with PRGBQuad(@aPixels[y, x])^ do
            Pixels[x, y] := RGB(rgbRed, rgbGreen, rgbBlue);
      image1.Picture.Graphic := SrcBmp;
    end;

  15. #15
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonsoir,

    et bienvenue au club !

    Citation Envoyé par Cirec Voir le message
    Salut,

    avec ce code j'obtiens bien le même résultat que l'original [--snip--]
    Tu as bien de la chance, car moi je ne gagne qu'une magnifique image toute noire , qui ne mérite absolument pas une copie d'écran
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  16. #16
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut

    il ne te manquerais pas l'initialisation du tableau dans le form create par le plus grand des hasard ^^

    le code de paul

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    const
      IMAGE_WIDTH  = 256;
      IMAGE_HEIGHT = 256;
    var
      pixels: array[0..IMAGE_HEIGHT - 1, 0..IMAGE_WIDTH - 1] of TColor; // hauteur puis largeur, et non l'inverse
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      x, y: Integer;
    begin
      for x := 0 to IMAGE_WIDTH - 1 do
        for y := 0 to IMAGE_HEIGHT - 1 do
          pixels[y, x] := (x + y) or ((x - y) shl 8 ) or ((x + x) shl 16);
    end;
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  17. #17
    Membre éprouvé
    Avatar de Cirec
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    467
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 467
    Points : 1 072
    Points
    1 072
    Par défaut
    re,
    Bonsoir,

    et bienvenue au club !

    Citation Envoyé par Cirec Voir le message
    Salut,

    avec ce code j'obtiens bien le même résultat que l'original [--snip--]
    Tu as bien de la chance, car moi je ne gagne qu'une magnifique image toute noire , qui ne mérite absolument pas une copie d'écran
    merci pour l’accueil
    ... ça me surprend que tu aies une image noire !!!

    voici le code complet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    unit Unit4;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, StdCtrls;
     
    type
      Tfrm_DibTest = class(TForm)
        img_Result: TImage;
        btn_Go: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormPaint(Sender: TObject);
        procedure btn_GoClick(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      frm_DibTest: Tfrm_DibTest;
     
    implementation
     
    {$R *.dfm}
     
    const
      IMAGE_WIDTH  = 256;
      IMAGE_HEIGHT = 256;
    var
      aPixels: array[0..IMAGE_HEIGHT - 1, 0..IMAGE_WIDTH - 1] of TColor; // hauteur puis largeur, et non l'inverse
     
    procedure Tfrm_DibTest.FormCreate(Sender: TObject);
    var
      x, y: Integer;
    begin
      DoubleBuffered := True; // rajouté par moi  déplacé ici
      for x := 0 to IMAGE_WIDTH - 1 do
        for y := 0 to IMAGE_HEIGHT - 1 do
          aPixels[y, x] := (x + y) or ((x - y) shl 8 ) or ((x + x)shl 16);
    end;
     
    procedure Tfrm_DibTest.FormPaint(Sender: TObject);
    var
      BitsInfos: TBitmapInfo;
    begin
      FillChar(BitsInfos, SizeOf(BitsInfos), 0);
      with BitsInfos do
      begin
        with bmiHeader do
        begin
          biSize          := SizeOf(TBitmapInfoHeader);
          biWidth         := IMAGE_WIDTH;
          biHeight        := -IMAGE_HEIGHT; // inverser le DIB pour avoir le tête en haut
          biPlanes        := 1;
          biBitCount      := 32;
        end;
      end;
      SetDIBitsToDevice(
        Canvas.Handle,
        10, 10, IMAGE_WIDTH, IMAGE_HEIGHT,
        0, 0, 0, IMAGE_HEIGHT,
        @aPixels,
        BitsInfos,
        0
      );
    end;
     
    procedure Tfrm_DibTest.btn_GoClick(Sender: TObject);
    var
      x, y: Integer;
      SrcBmp: TBitmap;
    begin
      SrcBmp := TBitmap.Create;
      try
        with SrcBmp do begin
          SrcBmp.PixelFormat:=pf32bit;
          SrcBmp.Width := IMAGE_WIDTH;
          SrcBmp.Height := IMAGE_HEIGHT;
        end;
     
        with SrcBmp.Canvas do
        for y := 0 to IMAGE_HEIGHT-1 do
          for x := 0 to IMAGE_WIDTH-1 do
            with PRGBQuad(@aPixels[y, x])^ do
              Pixels[x, y] := RGB(rgbRed, rgbGreen, rgbBlue);
        img_Result.Picture.Graphic := SrcBmp;
      finally
        SrcBmp.Free;
      end;
    end;
    end.
    ... par-contre je n'arrive pas à ajouter une image au message :s

  18. #18
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par Cirec Voir le message
    voici le code complet:
    [--snip--]
    Spectaculaire ! Redoutable ! Terrifiant ! Champion

    Citation Envoyé par Cirec Voir le message
    ... par contre je n'arrive pas à ajouter une image au message :s
    Bouge pas, je le fais pour toi :

    Nom : cirec.jpg
Affichages : 424
Taille : 77,0 Ko

    Allez hop !,

    Mais cependant, si tu avais 5 minutes, pourrais-tu, sans vouloir abuser, me réécrire ça en français, surtout la ligne en gras, comme si c'était un roman, histoire pour moi de bien comprendre ? Grand merci par avance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        with SrcBmp.Canvas do
        for y := 0 to IMAGE_HEIGHT-1 do
          for x := 0 to IMAGE_WIDTH-1 do
            with PRGBQuad(@aPixels[y, x])^ do
              Pixels[x, y] := RGB(rgbRed, rgbGreen, rgbBlue);
    Et encore mille bravos, et merci aussi à tous ceux qui m'ont supporté toute la journée
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Jipété Voir le message
    me réécrire ça en français, surtout la ligne en gras, comme si c'était un roman, histoire pour moi de bien comprendre ?
    En gros tu vas prendre la valeur (en hexadécimal 0x00BBGGRR) à la position Pixels[y, x] et tu vas la mettre dans une structure tagRGBQuad qui a 4 attributs (rgbRed, rgbGreen, rgbBlue + rgbReserved)

    Le terme technique c'est "caster"

  20. #20
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Oui, mais dans cette ligne (with PRGBQuad(@aPixels[y, x])^ do), pourquoi l'arrobase et l'accent circonflexe ?
    Pourquoi ne peut-on faire sans, indépendamment des cris scandalisés du compilo ?
    Et pourquoi [y, x] sur cette ligne et [x, y] sur celle de dessous ?
    Et pourquoi l'idée d'utiliser ça ne m'est-elle pas venue ? Ça ou un PRGBTriple ? À cause du 32 bits ? Voir ci-dessous...
    (non, là j'ai la réponse : c'est tellement mal foutu ces choses que ce n'est pas mémorisable, enfin, en ce qui me concerne.)

    C'est ça qu'il faut m'expliquer, pour m'éviter de revenir vous embêter avec des questions tordues.

    D'ailleurs, j'en ai deux, pour demain :
    1- comment utiliser correctement les 24 et 32 bits ? Parce que par exemple le code de Cirec arrive en 32 et compile bien sous Windows2000 avec D7 (pas bien jeune, tout ça), compile bien aussi sous un Debian récent dans un Lazarus pas trop vieux mais là, rien n'est affiché tant que je ne redescends pas en 24 bits.
    Et ça me gonfle de faire des choses sans savoir pourquoi surtout quand, dans d'autres codes, c'est l'inverse qu'il faut faire...

    2- regardez cette image (réduite de moitié) :
    Nom : compar_times.jpg
Affichages : 410
Taille : 30,8 Ko

    j'ai poussé les constantes de Cirec à 480-480 puisque l'image de gauche est à 640-480 ; ensuite j'ai exécuté, et l'image de droite a pris 1510 millisecondes pour être affichée (monstrueux !) quand celle de gauche n'a mis que 3 millisecondes, avec un code "optimisé" pour les accès à Scanline de chez efg, "optimisé" entre guillemets car un code basique travaillant sur les mêmes dimensions s'est affiché en seulement 2 millisecondes.


    Bon, on verra ça dans les jours qui viennent...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Réponses: 1
    Dernier message: 31/03/2015, 15h36
  2. bibliothèques pour lire les pixels d'un bitmap
    Par nonozor dans le forum Bibliothèques
    Réponses: 2
    Dernier message: 28/08/2008, 00h15
  3. Lire les pixels de grandes images sans les ouvrir
    Par psicot dans le forum Multimédia
    Réponses: 1
    Dernier message: 16/04/2007, 18h59
  4. Manipuler avec des classes
    Par poussinphp dans le forum FMOD
    Réponses: 3
    Dernier message: 03/06/2006, 18h20
  5. Réponses: 14
    Dernier message: 04/01/2006, 14h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo