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

Langage Delphi Discussion :

Superposer deux images au format BMP, JPG ou PNG


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut Superposer deux images au format BMP, JPG ou PNG
    Bonjour

    D7 pro

    J'aimerai pouvoir superposer deux images et ensuite pouvoir enregistrer le résultat dans une troisième image.
    Le format m'es égale BMP, JPG ou PNG.

    Qui a une idée ?

    En fait j'essaye de mettre un fond de page dans un f :
    Je pars du Postscript vers des fichiers BMP ou PNG(avec Ghostscript)
    je mélange mon image obtenu avec mon fond de page(le format m'es égale BMP, JPG ou PNG)
    Je re enregistre le tous sur pdf



    Merci par avance

    Henri

  2. #2
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Salut,

    J'aimerai pouvoir superposer deux images et ensuite pouvoir enregistrer le résultat dans une troisième image.
    ... quand tu dis "superposer" je suppose que tu veux dire "fusionner" de sorte que le résultat ressemble à une seule image d'un fondu-enchaîné.

    Dans ce cas tu peux trouver ici du code : http://www.efg2.com/Lab/ImageProcessing/Tween.htm

    A +
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Bonjour

    Oui, tous a fait
    Mais j’aimerai le faire dans mon application(D7 pro), non pas un soft tiers appeler en ligne de commande
    J’ai trouvé un composant TPGNimage mais il ne s’installe pas bien, il manque toujours un truc.
    Sinon une autre série de composants fait par un Brésilien, mais l’exemple qui donne ne fonctionne pas non plus.

    Donc, pour le moment j’ai RIEN

    Cordialement
    Henri

  4. #4
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Salut,

    Mais j’aimerai le faire dans mon application(D7 pro), non pas un soft tiers appeler en ligne de commande
    ... Ben, qu'est-ce-qui t'empêche sous D7 de recopier les parties fonctionnelles du code Tween du site d'efg2 dans ton application et de les adapter à tes besoins ?

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Bonjour

    C'est que je suis pas malin à ce point pour trifouiller dans ces composant .
    Si je trouvais quelque chose de tous fait, je serai plus à l'aise.
    ç'a bien dû être fait quelque part, je dois pas être le premier à avoir besoin de fusionner deux images

    Merci de votre réponse et bon Noël

    Henri

  6. #6
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Salut,

    Tiens voiçi le code d'une petite fonction qui renvoie le BitMap du résultat de la fusion de deux BitMaps's Bmp1 et Bmp2 en fonction du coefficient k1 <= 1 qui représente le "poids" de l'intensité des couleurs de Bmp1 dans le résultat, le "poids" de celles de Bmp2 étant pris égal à k2 := 1 - k1.

    Code de la fonction :
    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
    type
      TRGBArray = ARRAY[0..0] OF TRGBTriple; // élément de bitmap (API windows)
      pRGBArray = ^TRGBArray;     // type pointeur vers tableau 3 octets 24 bits
     
    function FusionnerBmp(Bmp1,Bmp2 : tBitMap; k1 : Extended) : tBitMap;
    var      k2 : Extended;
             S1,S2,SR : array[0..2047] of pRGBArray; //<- Pour ScanLine's
             x,y : integer;
    begin    if (Bmp1.width <> Bmp2.width) or (Bmp1.height <> Bmp2.height) then
             begin showMessage('Bmp1 et Bmp2 : doivent être de même taille');
                        Result:=nil;
                        EXIT;
             end;
             if k1>1 then k1:=1;
             k2:=1-k1;
             Result:=tBitMap.Create;
             With Result do
             begin width:=Bmp1.width; height:=Bmp1.height; pixelformat:=pf24bit; end;
             for y:=0 to Bmp1.Height-1 do
             begin S1[y]:= Bmp1.ScanLine[y];
                   S2[y]:= Bmp2.ScanLine[y];
                   SR[y]:= Result.ScanLine[y];
                   for x:=0 to Bmp1.Width-1 do
                   begin SR[y,x].rgbtRed  :=trunc(k1*S1[y,x].rgbtRed   + k2*S2[y,x].rgbtRed);
                         SR[y,x].rgbtGreen:=trunc(k1*S1[y,x].rgbtGreen + k2*S2[y,x].rgbtGreen);
                         SR[y,x].rgbtBlue :=trunc(k1*S1[y,x].rgbtBlue  + k2*S2[y,x].rgbtBlue);
                   end;
              end;
    end;
    Code d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.btnFusionnerClick(Sender: TObject);
    var       BmpResultat : tBitMap; k1 : Extended;
    begin     k1:=StrToFloat(Edit1.text);
              BmpResultat:=FusionnerBmp(Image1.picture.BitMap,Image2.picture.BitMap, k1);
              Image3.picture.BitMap:=BmpResultat;
    end;
    Pour tester, suffit d'une Form avec 3 TImage, un TEdit pour la saisie du coefficient k1, et un TButton, et de charger la propriété Picture de Image1 et de Image2 avec les fichiers *.BMP des images à fusionner.

    Les deux images à fusionner doivent être de même taille sinon il faudra modifier le code en fonction de besoins qui n'ont pas encore été annoncés.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Sitôt lu sitôt fait

    La fusion se fait bien, mais avec une valeur négative
    k1 = 0 : image2 copié dans image3
    k1 = 1 : image1 copié dans image3
    k1 = -1 début de la fusion

    si je diminue à l’extrême, je chope tous les pixels parasite
    ceci dit votre code fonctionne bien, mais le résultat sur l’image3 est difficilement utilisable, c’est trouble
    Il faudrait que je ne touche pas l’image1 , mais que je superpose juste l’image2

    En gros : j’essaye fusionner une page à fond blanc avec du texte sur un pré imprimé( une feuille à fond blanc avec un logo)

    En plus détaillé :

    Je récupère sur un serveur Unix un fichier PostScript(*.ps) destiné à une imprimante multi bac( 4 bac) .
    - Chaque bac à peut avoir un papier particulier( le pré imprimé)
    - le numéro du bac est dans le fichier PostScript(*.ps)
    - chaque page de mon document aura un fond de page particulier (sera dirigé vers un bac spécifique)
    - a l’aide de Ghostcript, j’éclate ce *.ps en XX images, j’ai le choix du format, le seul qui me paraît convenir est le BMP ou PNG
    - en fonction de l’image issu de Ghostcript (qui n’est que du texte, une extraction d’un PDF) parmi XX que je récupère, je veux fusionner/superposer une image de mon pré imprimé, comme si c’était l’imprimante qui l’avait fait

    Pour avoir une idée du document , je n’ai qu’a interpréter le Postscript avec Acrobat, MAIS je n’ai que du texte sans fond de page, donc je peut pas faire de calage.
    Alors qu’avec l’image en fond, c’est comme si je j’avais imprimé

    Donc il me faut superposer/fusionner deux image.
    L’image1 est Toujours du texte( noir ou bleu)
    L’image2 est toujours une feuille blanche avec un ou plusieurs logos

    Grace à vos lignes de codes, c’a ma fait un petit cadeau Noël supplémentaire, MERCI

    Cordialement et Bonne Fête
    Henri

  8. #8
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    La fusion se fait bien, mais avec une valeur négative
    k1 = 0 : image2 copié dans image3
    k1 = 1 : image1 copié dans image3
    k1 = -1 début de la fusion
    ... Oups, autant pour moi j'avais écrit "k1 <= 1" ce qui est incomplet, il faut prendre k1 compris entre 0 et 1 et :
    - avec k1=1 le résultat est effectivement 100% de l'intensisté de image 1 qui est reproduit
    - avec k1=0.4 par exemple, la fusion prend en compte 40% de l'intensité des couleurs de image 1 et 60% de celles de image 2, en bref si image 1 est par exemple un carré rouge vif sur fond blanc situé à gauche et image 2 un cercle bleu Navy sur fond blanc situé à droite le résultat de la fusion est un carré dont le rouge est moins vif et un cercle dont le bleu est également moins vif.

    Mais comme le carré est situé à gauche et le cercle à droite on pourrait modifier le code pour faire k1 = 1 et k2 = 0 en fonction de x,y pour le carré et l'inverse pour le cercle afin de reproduire à 100% l'intensité des deux couleurs.

    Il faudrait que je ne touche pas l’image1 , mais que je superpose juste l’image2 ...
    L’image1 est Toujours du texte( noir ou bleu)
    L’image2 est toujours une feuille blanche avec un ou plusieurs logos
    ... Bon, je suppose que le texte est positionné de sorte qu'il n'empiète pas sur les logos et dans ce cas il faut ajouter dans les boucles du code des tests sur les valeurs de x et de y en fonction desquels on fait varier la valeur de k1 et de k2 de sorte que :
    - k2 = 1 et k1 = 0 dans la zone des logos pour reproduire à 100% l'intensité des leurs couleurs,
    - k1 = 1 et k2 = 0 dans la zone du texte pour éviter d'éclairicr le texte.

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Bonjour

    Tous fonctionne correctement chez moi sous Vista "at home", mais pas avec mon antique NT4 sp2 du boulot !
    << Access violation at adress 00453BE9 in module 'Project10exe'. read of address 01F53000>>
    Donc pour le moment, je peux pas le tester.

    Ceci dit, j'aurai juste(mais comment) à copier l'image 1 sur l'image2, simple à dire !
    ç'a peut se faire pixel à pixel ?

    Comment compléter votre code ?

    Merci

    cordialement
    Henri

  10. #10
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Re-bonjour,


    Voiçi le code modifié en supposant que le rectangle de délimitation la la zone des logos n'empiète pas dans la zone du texte, et réciproquement :

    Code de la fonction :
    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
    type
      TRGBArray = ARRAY[0..0] OF TRGBTriple; // élément de bitmap (API windows)
      pRGBArray = ^TRGBArray;     // type pointeur vers tableau 3 octets 24 bits
     
    function AdditionnerBmp(BmpTexte,BmpLogos : tBitMap; RectLogos : tRect) : tBitMap;
    var      k1,k2 : Extended;
             S1,S2,SR : array[0..2047] of pRGBArray;
             x,y : integer; Point : tPoint;
    begin    if (BmpTexte.width <> BmpLogos.width) or (BmpTexte.height <> BmpLogos.height) then
             begin showMessage('Bmp1 et Bmp2 : doivent être de même taille');
                        Result:=nil;
                        EXIT;
             end;
             Result:=tBitMap.Create;
             With Result do
             begin width:=BmpTexte.width; height:=BmpTexte.height; pixelformat:=pf24bit; end;
             for y:=0 to BmpTexte.Height-1 do
             begin S1[y]:= BmpTexte.ScanLine[y];
                   S2[y]:= BmpLogos.ScanLine[y];
                   SR[y]:= Result.ScanLine[y];
                   for x:=0 to BmpTexte.Width-1 do
                   begin Point.x:=x; Point.y:=y;
                         if PtInRect(RectLogos, Point)
                         then begin k2:=1; k1:=0; end  //<<<
                         else begin k1:=1; k2:=0; end;  //<<<
                         SR[y,x].rgbtRed  :=trunc(k1*S1[y,x].rgbtRed   + k2*S2[y,x].rgbtRed);
                         SR[y,x].rgbtGreen:=trunc(k1*S1[y,x].rgbtGreen + k2*S2[y,x].rgbtGreen);
                         SR[y,x].rgbtBlue :=trunc(k1*S1[y,x].rgbtBlue  + k2*S2[y,x].rgbtBlue);
                   end;
              end;
    end;
    Code d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TfrmFusionnerBMP.btnAdditionnerClick(Sender: TObject);
    var       BmpResultat : tBitMap; RectLogos : tRect;
    begin     RectLogos:=Rect(0,0,80,80); //< Rectangle de la zone des Logos
              BmpResultat:=AdditionnerBmp(Image1.picture.BitMap,Image2.picture.BitMap,RectLogos);
              Image3.picture.BitMap:=BmpResultat;
    end;
    Testé marche sous D5 + WinXp

    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    Voiçi une autre possibilité pour le code qui évite de s'enquiquiner avec le problème du dimensionnement du rectangle de délimitation la zone des logos et qui part du principe que la lisibilité du texte est prioritaire :

    Code de la fonction :
    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
    type
      TRGBArray = ARRAY[0..0] OF TRGBTriple; // élément de bitmap (API windows)
      pRGBArray = ^TRGBArray;     // type pointeur vers tableau 3 octets 24 bits
     
    function Superposer2Bmp(BmpTexte,BmpLogos : tBitMap; CoulFondTexte : tColor) : tBitMap;
    var      k1,k2 : Extended;
             S1,S2,SR : array[0..2047] of pRGBArray;
             R1,G1,B1 : byte; cl1 : tColor; //<- Composantes et couleur du pixel courant sur BmpTexte
             x,y : integer; Point : tPoint;
    begin    if (BmpTexte.width <> BmpLogos.width) or (BmpTexte.height <> BmpLogos.height) then
             begin showMessage('Bmp1 et Bmp2 : doivent être de même taille');
                        Result:=nil;
                        EXIT;
             end;
             Result:=tBitMap.Create;
             With Result do
             begin width:=BmpTexte.width; height:=BmpTexte.height; pixelformat:=pf24bit; end;
             for y:=0 to BmpTexte.Height-1 do
             begin S1[y]:= BmpTexte.ScanLine[y];
                   S2[y]:= BmpLogos.ScanLine[y];
                   SR[y]:= Result.ScanLine[y];
                   for x:=0 to BmpTexte.Width-1 do
                   begin R1:=S1[y,x].rgbtRed; G1:=S1[y,x].rgbtGreen; B1:=S1[y,x].rgbtBlue;
                         cl1:=RGB(R1,G1,B1);
                         if cl1<>CoulFondTexte // si cl1 <> CoulFondTexte alors le pixel appartient à du texte
                         then begin k1:=1; k2:=0; end
                         else begin k2:=1; k1:=0; end;
                         SR[y,x].rgbtRed  :=trunc(k1*S1[y,x].rgbtRed   + k2*S2[y,x].rgbtRed);
                         SR[y,x].rgbtGreen:=trunc(k1*S1[y,x].rgbtGreen + k2*S2[y,x].rgbtGreen);
                         SR[y,x].rgbtBlue :=trunc(k1*S1[y,x].rgbtBlue  + k2*S2[y,x].rgbtBlue);
                   end;
              end;
    end;
    ... avec ce code si un logo se trouve à cheval sur une partie du texte c'est le texte qui est pris en compte de façon prioritaire, quelle que soit sa couleur, comme si le logo servait de fond d'écran.
    A cet effet il est indispensable que le BitMap BmpTexte contienne du texte placé sur fond de couleur uniforme. (Pour la bonne et simple raison que l'on ne pourrait pas écrire if cl1 = CouleurDuTexte then ... puisque du texte noir par exemple n'est pas noir partout vu que son contour a généralement subi un traitement anti-aliasing formé par des pixels en nuances de gris, et des nuances de bleu dans le cas d'un texte bleu, etc, ce qui alourdirait le code s'il fallait tester toutes les nuances utilisées ... en supposant de plus que l'on connaisse les valeurs des nuances utilisées)

    Code d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TfrmFusionnerBMP.btnSuperposerClick(Sender: TObject);
    var       BmpResultat : tBitMap; CoulFondTexte : tColor;
    begin     CoulFondTexte := clWhite; //< Couleur du fond du BitMap de Texte
              BmpResultat:=Superposer2Bmp(Image1.picture.BitMap,Image2.picture.BitMap,CoulFondTexte);
              Image3.picture.BitMap:=BmpResultat;
    end;
    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Bonsoir Gilbert


    Je suis rentrer de vacance dans mon Dauphiné natal et je me suis empressé d’essayer vos nouvelles fonctions.

    Merci pour ton second exemple, il fonctionne à la perfection sous vista(l’avant dernier ne fonctionnait pas !).
    Mais pas sur une machine NT pour lequel il est destiné, casse-pied comme truc.
    J’ai toujours une erreur << Access violation at adress xxx xxx xxx >>

    C’a bloque quand je passe y > de 400 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for y :=0 to BmpTexte.Height-1 do
    begin 
      S1[y]:= BmpTexte.ScanLine[y];
      S2[y]:= BmpLogos.ScanLine[y];
    end;
    Vous m’avez beaucoup avancé, je suis sûr que c’est jouable, c’a ne doit pas tenir à beaucoup de chose

    Bonne année à vous ainsi qu’au autres de ce group de news
    Cordialement

    Henri

  13. #13
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour et bonne année,

    C’a bloque quand je passe y > de 400 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for y :=0 to BmpTexte.Height-1 do
    begin 
      S1[y]:= BmpTexte.ScanLine[y];
      S2[y]:= BmpLogos.ScanLine[y];
    end;
    ... tu veux dire que ça bloque quand BmpTexte.Height-1 est supérieur à 400 ?
    ... Bizarre ! Car on a bien déclaré var S1,S2,SR : array[0..2047] of pRGBArray; et entre 400 et 2047 il y a une sacrée marge.

    Comme le code fonctionne aussi bien sous Vista que sous XP mais pas sous NT ça provient très certainement d'une subtilité de différence spécifique à NT. Par contre comme je ne connais pas NT je suis sec. Et les messages d'erreur du style << Access violation at adress xxx xxx xxx >> c'est de l'hébreu déchiffrable uniquement par ceux qui s'y connaissent en Assembleur.

    Donc désolé, là je suis sec.

    A +
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 696
    Points : 13 135
    Points
    13 135
    Par défaut
    Plusieures petites choses:

    1. var S1,S2,SR : array[0..2047] of pRGBArray;
    On ne travaille de toute façon que sur une ligne à la fois. Inutile donc d'utiliser un array de scanline.
    Une déclaration comme ceci est suffisante: var S1,S2,SR : pRGBArray;. Le code s'en trouvera d'autant simplifé.

    2. S'il y a un blocage, c'est que l'un des bitmaps n'est pas en 24 bits. Il faudrait au minimum forcer le PixelFormat à pf24bit.

    3. L'utilisation de ces k1 et k2 n'est pas optimale puisqu'elle n'empèchera pas d'avoir une bordure blanche autour du texte.
    Il faut au contraire considérer que la couleur (ou plutôt l'une de ses composantes, le bleu par exemple) du texte EST la composante alpha .
    Ensuite le calcul de la couleur résultante se fera comme suit:
    (foreground_color * alpha) + (background_color * (100% - alpha))

  15. #15
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Bonjour Gilbert

    Certaine images sont obtenu à partir de Ghostscript (les textes qui proviennent de mes pdf),
    les autres sont scanné (les fond de page avec logos)
    je n'arrive pas à les mettre exactement de la même taille, et c'est ça le problème, sinon c'a fonctionne avec NT.
    il faut donc que je joue avec les dimensions et le poids des images.
    Celle que je scanne passe toujours, celle que j'obtiens avec Ghostscript ne fonctionne pas, même si je prends les deux bmp identique .

    J'utlilise cette commande Ghostscript en ligne de commande pour extraire mes images d'un *.ps :

    gswin32c.exe -sPAPERSIZE=a4 -dCompatibilityLevel=1.3 -dPDFSETTINGS=/prepress -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bmp256 -r150 -sOutputFile="%0d.bmp" -c save pop -f "8.ps"


    je produis des bipmap avec ce paramètre : -sDEVICE=bmp256
    la résolution avec ce paramètre : -r150 (150 dpi)
    le format de la page avec ce paramètre : -sPAPERSIZE=a4


    Que signifie le pf24bit ?
    est-il compatible avec le format bmp256 et la résolution 150 DPI ?

    Encore merci de votre aide

    Cordialement.
    Henri

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 696
    Points : 13 135
    Points
    13 135
    Par défaut
    pf24bit veut dire que tu travailles avec les 3 composantes R,G,B qui font chacune 8 bits (3x8=24).

    Bmp256 correspond à un pf8bit. La valeur ne correspond pas à une teinte comme en 24 bits, mais à un index dans une palette de 256 couleurs prédéfinies.

    Le TRGBTriple attend obligatoirement un bitmap 24 bits !

    Force simplement la profondeur des couleurs au début de la procédure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    BmpTexte.PixelFormat := pf24bit;
    BmpLogos.PixelFormat := pf24bit;

  17. #17
    Membre habitué
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Points : 150
    Points
    150
    Par défaut
    Bonjour

    J'ai toutes cette palette de choix de pixelisations(ou je sais pas le terme exacte) pour faire des images a partir de Ghostscript.
    J'ai aussi le format png qui se prêterai assez bien à cette manip : png16, png16, mpng256, pngalpha, pnggray, pngmono

    Certaine fonctionnent si je les superpose, d'autre pas :
    quand je fais ceci, elles ont la même taille.

    bmp16 : ne fonctionne pas entre elles,
    bmp16m : mauvais rendu, violet, pisseux
    bmp256 : ne fonctionne pas entre elles,
    bmp32b : OK mais sur fond noir
    bmpgray : ne fonctionne pas entre elles,
    bmpmono : ne fonctionne pas entre elles,
    bmpsep1 : ne fonctionne pas entre elles,
    bmpsep8 : ne fonctionne pas entre elles,


    Ceci C'est quand j'essaye de les superposer entre elle, venant de Ghostscript avec la commande que j'avais donné dans le message d'y hier.
    Mais si j'essaye, et c'est le but de superposer une de ces image et une image scanné , c'a ne fonctionne jamais,

    alors que c'a fonctionne bien avec ce que je scanne, mais le but c'est de superposer une image scanné + une image de Ghostscrip

    Selon vous quel serai le format le plus adapté ? (pf24bit, pf8bit, autre ....)

    Cordialement.

    Henri

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 696
    Points : 13 135
    Points
    13 135
    Par défaut
    Ce qu'il faut bien comprendre est que la déclaration des variables pour une utilisation avec ScanLine dépend du codage de l'image.

    pf8bit => pByteArray,
    pf24bit => pRGBTriple,
    pf32bit => pRGBQuad.

    Comme dis précédemment, as-tu essayé de forcer le PixelFormat à pf24bit ? Cela doit suffire pour fonctionner avec la procédure proposée par Gilbert Greyer. Quelle que soit les images en entrée.

    Travailler avec des PNG est tout à fait possible. Mais il faut passer par des composants tiers pour la lecture des pixels.

    Je vais voir si j'ai un peu de temps pour te faire une petite démo.

  19. #19
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour,

    Lors de mes tests du code j'ai effectivement utilisé des BitMaps qui étaient d'origine en 24 bits donc je m'étais contenté de déclarer uniquement le BitMap-Result en pixelformat:=pf24bit;

    Par contre il est préférable de forcer le pixelformat du BmpTexte et du BmpLogos dès l'entrée dans la fonction à pf24bit comme le rappelle Andnotor.

    En cas d'utilisation de fichiers-image autres que du *.bmp le plus simple est de les passer dans une moulinette qui les convertit en *.bmp de toutes façons la fonction ne marche que si c'est du BitMap puisque Scanline est une propriété liée au TBitMap. Même le *.jpg faut le convertir avant.

    A +
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 696
    Points : 13 135
    Points
    13 135
    Par défaut
    Voici une démo complète.

    Les images de fond et de texte ont volontairement des caractéristiques différentes:
    - Fond : 250x250, 24 bits,
    - Texte : 200x200, 8 bits.

    Comme dans ton enoncé le texte est bleu ou noir.
    Le zip ci-dessous inclus la démo complète avec les images de bases.


    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
    type
      PRGBTripleArray = ^TRGBTripleArray;
      TRGBTripleArray = array[0..0] of TRGBTriple;
     
    function Combine(aTextBmp, aFondBmp: TBitmap): TBitmap;
    var
      CT    :PRGBTripleArray;  //Couleur pixel Texte
      CF    :PRGBTripleArray;  //Couleur pixel Fond
      B     :byte;             //Composante bleue
      Alpha :byte;             //Transparence
      x, y  :integer;
      MaxX, MaxY :integer;
     
      //Routine pour la combinaison du Texte et du Fond ***********************
      function DoCombine(F, B, A :byte) :byte;
      begin
        //(foreground_color * alpha) + (background_color * (100% - alpha)).
        Result := EnsureRange((Round(F*A/255) +Round(B*(1-(A/255)))), 0, 255);
      end;
      //***********************************************************************
     
    begin
      //Force les images en 24 bits
      aTextBmp.PixelFormat := pf24bit;
      aFondBmp.PixelFormat := pf24bit;
     
      //Crée l'image résultante
      Result := TBitmap.Create;
      //Assigne l'image de fond à l'image résultante
      Result.Assign(aFondBmp);
     
      //Boucle maximum sur les plus petites Largeur/Hauteur
      MaxX := Min(aTextBmp.Width, aFondBmp.Width) -1;
      MaxY := Min(aTextBmp.Height, aFondBmp.Height) -1;
     
      for y := 0 to MaxY do
      begin
        CT := aTextBmp.ScanLine[y];
        CF := Result.ScanLine[y];
     
        for x := 0 to MaxX do
        begin
          //Le texte pouvant être noir ($000000) ou bleu ($0000FF), on considérera
          //l'inverse du rouge (ou du vert) comme composante alpha (Transparence).
          Alpha := 255 -CT[x].rgbtRed;
     
          //Si la composante bleue vaut $FF => texte bleu (ou transparent)
          //sinon texte noir. Il y a manifestement une petite erreur sur la
          //conversion 8 bits => 24 bits. Test sur $F0 donne un bleu parfait!
          if CT[x].rgbtBlue >= $F0 then B := $FF else B := $00;
     
          //Combinaison du Texte et du Fond (R et G toujours à $00)
          CF[x].rgbtRed   := DoCombine(0, CF[x].rgbtRed, Alpha);
          CF[x].rgbtGreen := DoCombine(0, CF[x].rgbtGreen, Alpha);
          CF[x].rgbtBlue  := DoCombine(B, CF[x].rgbtBlue, Alpha);
        end;
      end;
    end;
    Images attachées Images attachées    
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. Superposer deux images - CSS
    Par lhpp dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 21/04/2010, 18h38
  2. Superposer deux images plus d'autres "libres"
    Par Deallyra dans le forum Mise en page CSS
    Réponses: 16
    Dernier message: 11/06/2007, 15h10
  3. Enregistrer une image de format BMP
    Par bilal_inf dans le forum C++Builder
    Réponses: 1
    Dernier message: 07/04/2007, 17h18
  4. Superposer deux images
    Par Grafokoy dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 02/12/2006, 23h54
  5. superposer deux images ?
    Par terminoz dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 20/08/2005, 09h04

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