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 :

Resize d'un PNG avec transparence


Sujet :

Delphi

  1. #81
    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,

    j'ai bien une solution mais elle exige que l'on possède le fichier source PNG "PNGImage.pas" ...
    modifier la portée des variables "Private" en "Protected" de l'objet "TChunckIHDR" et voilà ...

    on a ainsi accès à toutes les données pour extraire proprement un PNG8, avec palette en Bitmap32, qui est fidèle à l'originale avec un canal alpha.

    le code peut convertir tout fichier Png 1,4,8,24 bits


    C'est pas la solution la plus élégante mais elle est rapide et simple à mettre en oeuvre et donne un résultat fidèle à l'originale et il est même possible d'effectuer le redimensionnement directement à la conversion ...

    Si toute fois la méthode vous intéresse quand même dites le et je posterais la marche à suivre et le code.
    @+ Cirec

  2. #82
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Je suis pour ma part intéressé de découvrir cette méthode, en attendant la solution de sub0

  3. #83
    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
    ok
    1°) faire une copie de "pngimage.pas" dans le répertoire de ton application:

    2°) dans cette copie à la ligne 490 devrait commencer l'objet "TChunckIHDR" que tu modifies comme suit:
    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
      {Information header chunk}
      TChunkIHDR = class(TChunk)
      protected                           // *** ajouté
      //private                           // *** mis en commentaire
        {Current image}
        ImageHandle: HBitmap;
        ImageDC: HDC;
        ImagePalette: HPalette;
        {Output windows bitmap}
        HasPalette: Boolean;
        BitmapInfo: TMaxBitmapInfo;
        {Stores the image bytes}
        {$IFDEF Store16bits}ExtraImageData: Pointer;{$ENDIF}
        ImageData: pointer;
        ImageAlpha: Pointer;
     
        {Contains all the ihdr data}
        IHDRData: TIHDRData;
    //  protected                         // *** mis en commentaire
        BytesPerRow: Integer;
    l'unité "UPng2Bmp32.pas" qui fait tout le boulot:
    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    unit UPng2Bmp32;
     
    interface
    uses Windows, SysUtils, Graphics, PngImage;
    procedure PartialTransPng2Bmp32(aPNGImage: TPNGImage; aBMP: TBitmap);
     
    implementation
     
    type
      // l'astuce qui permet d'avoir accès à la section Protected
      // de la classe TChunckIHDR
      THackChunkIHDR = class(TChunkIHDR);
     
    {Copy a PNG to a BMP32 using partial transparency
     Original code grabed from PngImage.pas:
     procedure TPngImage.DrawPartialTrans(DC: HDC; Rect: TRect);
     adapted by Cirec}
    procedure PartialTransPng2Bmp32(aPNGImage: TPNGImage; aBMP: TBitmap);
    type
      {Access to pixels}
      TPixelLine = Array[Word] of TRGBQuad;
      pPixelLine = ^TPixelLine;
    var
      Header: THackChunkIHDR;
     
      {Transparency/palette chunks}
      TransparencyChunk: TChunktRNS;
      PaletteChunk: TChunkPLTE;
      PaletteIndex: Byte;
      CurBit: Integer;
      Data: PByte;
     
      {Buffer bitmap modification}
      BytesPerRowDest,
      BytesPerRowSrc,
      BytesPerRowAlpha: Integer;
      ImageSource, ImageSourceOrg,
      AlphaSource     : pByteArray;
      ImageData       : pPixelLine;
      i, j, i2, j2    : Integer;
     
      {For bitmap stretching}
      W, H            : Cardinal;
      Stretch         : Boolean;
      FactorX, FactorY: Double;
    begin
      if not Assigned(aBMP) then Exit;
      aBMP.PixelFormat := pf32bit;
      W := aBMP.Width;
      H := aBMP.Height;
     
      Header := THackChunkIHDR(aPNGImage.Header); {Fast access to header}
      Stretch := (W <> Header.Width) or (H <> Header.Height);
      if Stretch then FactorX := W / Header.Width else FactorX := 1;
      if Stretch then FactorY := H / Header.Height else FactorY := 1;
     
      {Obtain number of bytes for each row}
      BytesPerRowAlpha := Header.Width;
      BytesPerRowDest := (((32 * W) + 31) and not 31) div 8; {Number of bytes for each image row in destination}
      BytesPerRowSrc := (((Header.BitmapInfo.bmiHeader.biBitCount * Header.Width) +
        31) and not 31) div 8; {Number of bytes for each image row in source}
     
      {Obtains image pointers}
      ImageData := aBMP.ScanLine[0];
      AlphaSource := Header.ImageAlpha;
      Longint(ImageSource) := Longint(Header.ImageData) +
        Header.BytesPerRow * Longint(Header.Height - 1);
      ImageSourceOrg := ImageSource;
     
      case Header.BitmapInfo.bmiHeader.biBitCount of
        {R, G, B images}
        24:
          FOR j := 1 TO H DO
          begin
            {Process all the pixels in this line}
            FOR i := 0 TO W - 1 DO
            begin
              if Stretch then i2 := trunc(i / FactorX) else i2 := i;
              pRGBTriple(@ImageData[i])^ := pRGBTriple(@ImageSource[i2 * 3])^;
              ImageData[i].rgbReserved := AlphaSource[i2];
            end;
     
            {Move pointers}
            Dec(Longint(ImageData), BytesPerRowDest);
            if Stretch then j2 := trunc(j / FactorY) else j2 := j;
            Longint(ImageSource) := Longint(ImageSourceOrg) - BytesPerRowSrc * j2;
            Longint(AlphaSource) := Longint(Header.ImageAlpha) + BytesPerRowAlpha * j2;
          end;
        {Palette images with 1 byte for each pixel}
        1,4,8: if Header.ColorType = COLOR_GRAYSCALEALPHA then
          FOR j := 1 TO H DO
          begin
            {Process all the pixels in this line}
            FOR i := 0 TO W - 1 DO
              with ImageData[i], Header.BitmapInfo do begin
                if Stretch then i2 := trunc(i / FactorX) else i2 := i;
                rgbRed := ImageSource[i2];
                rgbGreen := ImageSource[i2];
                rgbBlue := ImageSource[i2];
                rgbReserved := AlphaSource[i2];
              end;
     
            {Move pointers}
            Longint(ImageData) := Longint(ImageData) - BytesPerRowDest;
            if Stretch then j2 := trunc(j / FactorY) else j2 := j;
            Longint(ImageSource) := Longint(ImageSourceOrg) - BytesPerRowSrc * j2;
            Longint(AlphaSource) := Longint(Header.ImageAlpha) +
              BytesPerRowAlpha * j2;
          end
        else {Palette images}
        begin//******************
          {Obtain pointer to the transparency chunk}
          TransparencyChunk := TChunktRNS(aPNGImage.Chunks.ItemFromClass(TChunktRNS));
          PaletteChunk := TChunkPLTE(aPNGImage.Chunks.ItemFromClass(TChunkPLTE));
     
          FOR j := 1 TO H DO
          begin
            {Process all the pixels in this line}
            i := 0;
            repeat
              CurBit := 0;
              if Stretch then i2 := trunc(i / FactorX) else i2 := i;
              Data := @ImageSource[i2];
     
              repeat
                {Obtains the palette index}
                case Header.BitDepth of
                  1: PaletteIndex := (Data^ shr (7-(I Mod 8))) and 1;
                2,4: PaletteIndex := (Data^ shr ((1-(I Mod 2))*4)) and $0F;
                 else PaletteIndex := Data^;
                end;
     
                {Updates the image with the new pixel}
                with ImageData[i] do
                begin
                  rgbReserved := TransparencyChunk.PaletteValues[PaletteIndex];
                  rgbRed := PaletteChunk.Item[PaletteIndex].rgbRed;
                  rgbGreen := PaletteChunk.Item[PaletteIndex].rgbGreen;
                  rgbBlue := PaletteChunk.Item[PaletteIndex].rgbBlue;
                end;
     
                {Move to next data}
                inc(i); inc(CurBit, Header.BitmapInfo.bmiHeader.biBitCount);
              until CurBit >= 8;
            until i >= Integer(W);
     
            {Move pointers ********}
            Longint(ImageData) := Longint(ImageData) - BytesPerRowDest;
            if Stretch then j2 := trunc(j / FactorY) else j2 := j;
            Longint(ImageSource) := Longint(ImageSourceOrg) - BytesPerRowSrc * j2;
          end
        end {Palette images **********}
      end {case Header.BitmapInfo.bmiHeader.biBitCount};
    end;
     
     
     
    end.
    et pour tester une fiche deux TImage et un TButton et pngimage dans les uses:
    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
    ...
    var
      Form1: TForm1;
      aPng: TPngImage;
    implementation
     
    {$R *.dfm}
    uses UPng2Bmp32;
     
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      aPng := TPngImage.Create;
      aPng.LoadFromFile('Output_0001.png');
      Image1.Picture.Assign(aPng);
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      aPng.Free;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      aBMP: TBitmap;
    begin
      aBMP := TBitmap.Create;
      try
        aBMP.Width := aPNG.Width;   // aPNG.Width div 2;
        aBMP.Height := aPNG.Height; // aPNG.Height div 2;
        aBMP.PixelFormat := pf32bit;
        if aPng.TransparencyMode = ptmPartial then
          PartialTransPng2Bmp32(aPNG, aBMP);
        aBMP.SaveToFile('Png2BMP32.bmp');
        aBMP.AlphaFormat := afPremultiplied;
        Image2.Picture.Assign(aBMP);
      finally
        aBMP.Free;
      end;
     
    end;
     
    end.
    voilà

  4. #84
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Merci beaucoup je vais tester ca, il y a une version particulière de pngimage.pas ou peu importe ?

  5. #85
    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
    alors tout au début de pngimage.pas j'ai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const
      LibraryVersion = '1.564';
    mais si le code à modifier est identique au mien ça devrait aussi fonctionner ...
    de toutes façons tu fais les modifications sur une copie dans le répertoire de l'application teste donc pas de soucis à avoir si ça ne fonctionnait pas

    @+ Cirec

  6. #86
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Merci pour toutes ces infos, je vais essayer ca ce week-end. Il faudra juste que je trouve une fonction pour enregistrer le bitmap32 en png mais ca doit pas être le plus dur...

  7. #87
    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
    Citation Envoyé par NicCo Voir le message
    Merci pour toutes ces infos, je vais essayer ca ce week-end. Il faudra juste que je trouve une fonction pour enregistrer le bitmap32 en png mais ca doit pas être le plus dur...
    effectivement ... avec TPNGImage c'est très simple

    ps: comme j'ai répondu sur les deux sites tu pourrais aussi ton avis sur CS_CCM. Merci

    @+ Cirec

  8. #88
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Oui pour le TPngImage mais il faut remettre le Bitmap32 dans un PngImage

    Et oui merci je vais faire ca

  9. #89
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Salut

    J'étais également parti sur une solution similaire en mettant BitmapInfo de TChunkIHDR en public... Du coups, j'arrive bien à récupérer les composantes de la palette et donc le masque alpha. Seulement, c'est le "remixage" qui ne fonctionnait pas (problème d'assignation & duplication des images) ... Je vais réessayé autrement en essayant d'utiliser vos codes et je vous tiens au courant.
    De retour parmis vous après 10 ans!!

  10. #90
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Merci beaucoup encore une fois

  11. #91
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    De rien. Au passage, peut-être une autre piste si ça vous parle :

    Dans pngImage.pas, on peut trouver ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     {.$DEFINE Store16bits}            //Stores the extra 8 bits from 16bits/sample
    Le point après l'accolade sert à désactiver cette fonctionnalité qui semble être plus ou moins liée à ce dont on a besoin...
    Je vais tout de même continuer de développer l'idée de départ.
    De retour parmis vous après 10 ans!!

  12. #92
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    voici donc la fonction de chargement d'un PNG vers un TBitmap32 spéciale pour le format de tes PNG. J'espère que cela te conviendra. Je n'ai pas eu trop le temps de tout vérifier dans les détails, mais ça semble correspondre à ton besoin...

    Pour utiliser cette méthode, il faudra mettre en public BitmapInfo de TChunkIHDR dans pngImage.pas :
    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
    Function LoadPNGBitmap(ifn: ShortString; Var FinalBitmap: TBitmap32): Boolean;
    Var
      PNG: TPNGObject;
      i, j: Integer;
      TransparencyChunk: TChunktRNS;
      Entries: Word;
      Alpha: TBitmap32;
      f : TColor32;
      bR, bG, bB : Byte; // couleurs du pixel du background
      cR, cG, cB : Byte; // couleurs du pixel de l'image opaque
      R, G, B, A : Byte; // couleurs du pixel final
     
    Begin
     
      // On charge l'image PNG...
      Result := False;
      If (FileExists(ifn) = False) Then Begin
        ShowMessage('Image ' + ExtractFilename(ifn) + ' introuvable.');
        Exit;
      End;
      PNG := TPNGObject.Create;
      Try PNG.LoadFromFile(ifn);
      Except
        ShowMessage('Erreur format PNG (' + ExtractFilename(ifn) + ')');
        Exit;
      End;
     
      // Récupération du masque alpha du PNG
      TransparencyChunk := TChunktRNS(PNG.Chunks.ItemFromClass(TChunktRNS));
      with PNG.Header do begin
        Entries := (1 shl Byte(BitmapInfo.bmiHeader.biBitCount));
        for i := 0 to Entries - 1 do begin
          A := Byte(TransparencyChunk.PaletteValues[i]);
          BitmapInfo.bmiColors[i].rgbRed := Byte($FF-A);
          BitmapInfo.bmiColors[i].rgbGreen := 0;
          BitmapInfo.bmiColors[i].rgbBlue := 0;
          BitmapInfo.bmiColors[i].rgbReserved := 0;
        end;
      end;
      PNG.RemoveTransparency;
     
      // On stocke le masque alpha dans un TBitmap
      Alpha := TBitmap32.Create;
      Alpha.Assign(PNG);
     
      // On charge de nouveau le PNG opaque dans un autre TBitmap32
      FinalBitmap := TBitmap32.Create;
      PNG.LoadFromFile(ifn);
      PNG.Header.ColorType := COLOR_RGBALPHA;
      FinalBitmap.assign(PNG);
     
      // Imaginons que dans cet exemple, on veuille seulement un background blanc
      // Après, ce sera facile de récupérer les pixels d'une autre image de fond...
      bR := 255;
      bG := 255;
      bB := 255;
     
      // On fusionne l'image opaque avec le masque alpha + la couleur du fond
      For j := 0 To FinalBitmap.Height - 1 Do begin
        For i := 0 To FinalBitmap.Width - 1 Do begin
     
          A := Byte(Alpha.Canvas.Pixels[i, j]);
     
          f := FinalBitmap.Pixels[i, j];
          cR := redComponent(f);
          cG := greenComponent(f);
          cB := blueComponent(f);
     
          R := Byte(cR + A * (bR - cR) Div $FF);
          G := Byte(cG + A * (bG - cG) Div $FF);
          B := Byte(cB + A * (bB - cB) Div $FF);
          FinalBitmap.Pixels[i, j] := setAlpha(Color32(R, G, B), A);
        end;
      end;
     
      // On peut l'afficher vite fait pour voir...
      Form1.Image1.Picture.Assign(FinalBitmap);
     
      PNG.Free;
      Result := True;
    End;
    Bon courage
    De retour parmis vous après 10 ans!!

  13. #93
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Merci beaucoup il faut que j'essaye tout ca au plus tôt
    Il faut aussi que je trouve une fonction pour convertir le Bitmap32 vers PNG, mais il y a sans doute cela quelque part si le Bitmap32 est "standard".

  14. #94
    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
    Citation Envoyé par NicCo Voir le message
    Merci beaucoup il faut que j'essaye tout ca au plus tôt
    Il faut aussi que je trouve une fonction pour convertir le Bitmap32 vers PNG, mais il y a sans doute cela quelque part si le Bitmap32 est "standard".
    le code d'Eric donné plus haut sait le faire sans problème
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  15. #95
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Bon je viens d'essayer la méthode de sub0 mais j'ai un souci sur cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Entries := (1 shl Byte(BitmapInfo.bmiHeader.biBitCount));
    Je suppose que c'est en liaison avec la modification de pngimage.pas que j'ai également faite en passant "BitmapInfo: TMaxBitmapInfo;" de Private à Public mais sans succès. Même chose avec la modification proposée par Cirec un peu plus haut. J'ai peut être oublié quelque chose...

    Edit : Je n'avais pas copié le fichier pngimage.pas dans mon dossier de projet, d'où l'erreur de compilation... Je continue mes tests. La fonction de Eric SIBERT nécessite QGraphics pour l'enregistrement, je suppose que ca fait partie de QT et qu'il faut que j'installe QT ?

  16. #96
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    J'ai trouvé une fonction qui semble enregistrer correctement le Bitmap32 en PNG mais je viens de voir qu'il y a un problème : le fond de l'image n'est pas transparent mais blanc.
    Même chose sur la Form lorsque j'affiche l'image via la fonction de Load.

  17. #97
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    salut

    Dans la fonction de chargement que je t'ai donné, on a bien la couleur de fond blanc (voir commentaires dans le code, ligne 52).
    Ensuite, la fonction setAlpha() doit normalement redéfinir le masque alpha de l'image rendue...

    Peut-on voir le code de ta fonction d'enregistrement d'un Bitmpa32 dans un fichier PNG ?

    [EDIT] Je croyais que ton objectif était de redimensionner une image PNG avant de la fusionner à un autre bitmap d'arrière-plan et dans ce cas, je pense que la fonction de chargement que je t'ai donné est suffisante. Par contre, effectivement, pour enregistrer l'image PNG dans un fichier au format RGBA, ce n'est peut-être pas suffisant...
    De retour parmis vous après 10 ans!!

  18. #98
    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,

    petites précisions à propos du code que j'ai donné plus haut:

    à compter de Delphi 2009 l'IDE prend complètement en charge le BMP32 bits dans TBitmap.
    Donc plus besoin d'utiliser une lib externe (TBitmap32)

    Ensuite mon code est certes plus long mais il prend en charge tous les PNG avec une transparence partiel et le converti en un TBitmap avec un vrai canal Alpha. Le fichier ainsi produit est en tous points identique à celui qui a été converti avec Gimp et l'affichage du Bitmap donne le même résultat que l'affichage du Png d'origine.


    en ce qui concerne le code de Sub0:
    j'ai testé mais le résultat n'est pas au rendez-vous ... le fichier produit n'est pas un vrai Bmp32 il n'a pas de canal alpha (enfin si mais il n'est pas utilisé) sans compter qu'il est beaucoup plus long à l'exécution, on charge deux fois le Png et on utilise deux Bitmap dont un qui n'est pas libéré !
    du coup le fichier produit est totalement différent et en devient inutilisable et c'est normal puisqu'au lieu de récupérer les informations et de simplement les stocker dans le bitmap avec le canal alpha tu les "interprètes" (tu recalcules chaque pixel en fonction du fond et de la transparence) d'ailleurs NiCo en a déjà fait les frais:
    Citation Envoyé par NiCo Voir le message
    ... le fond de l'image n'est pas transparent mais blanc.
    Même chose sur la Form lorsque j'affiche l'image via la fonction de Load.

    sinon as tu déjà essayé avec mon code ?

    et voici de quoi convertir un bitmap 32Bits avec canal Alpha en PNG:
    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
    unit UBmp32ToPng;
     
    interface
    uses Windows, SysUtils, Graphics, PngImage;
     
    function Bmp32ToPng(SrcBmp: TBitmap): TPngImage;
     
    implementation
     
    function Bmp32ToPng(SrcBmp: TBitmap): TPngImage;
    var
      X, Y            : Integer;
      SrcPixLine,
      DestPixLine     : Pointer;
      PSrcPixLine     : PRGBQuad absolute SrcPixLine;
      PDestPixLine    : PRGBTriple absolute DestPixLine;
      IsPremultiplied : Boolean;
    begin
      if not assigned(SrcBmp) or (SrcBmp.PixelFormat <> pf32Bit) or (SrcBmp.Empty) or
        ((SrcBmp.Width <= 0) or (SrcBmp.Height <= 0)) then
         raise EInvalidGraphicOperation.Create('Bitmap invalide. Impossible à convertir') ;
     
      Result := TPNGImage.CreateBlank(COLOR_RGBALPHA, 8, SrcBmp.Width, SrcBmp.Height);
      with Result do
      try
        IsPremultiplied := SrcBmp.AlphaFormat = afPremultiplied;
        if IsPremultiplied then
          SrcBmp.AlphaFormat := afIgnored;
        // on sélectionne tous les filtres pour une meilleur compression
        Filters := [pfNone, pfSub, pfUp, pfAverage, pfPaeth];
        for Y := 0 to SrcBmp.Height - 1 do
        begin
          SrcPixLine := SrcBmp.ScanLine[Y];
          DestPixLine := Scanline[Y];
     
          for X := 0 to SrcBmp.Width - 1 do
          begin
            PDestPixLine^ := PRGBTriple(PSrcPixLine)^;
            AlphaScanline[Y]^[X] := PSrcPixLine^.rgbReserved;
     
            Inc(PSrcPixLine);
            Inc(PDestPixLine);
          end;
        end;
     
      finally
        if IsPremultiplied then
          SrcBmp.AlphaFormat := afPremultiplied;
      end;
    end;
    end.
    et l'utilisation(aBMP contient le Bitmap 32bits):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        with Bmp32ToPng(aBMP) do
        try
          SaveToFile('Bmp32ToPNG.png');
        finally
          Free;
        end;
    @+ Cirec

  19. #99
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Merci Cirec!

    J'ai encore une ancienne version de Delphi et j'utilise toujours Gr32... Mais c'est vrai que la méthode que j'ai utilisé est pourrie. Je vais essayer de comprendre et d'utiliser ton travail pour adapter mon code.
    De retour parmis vous après 10 ans!!

  20. #100
    Membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2014
    Messages
    143
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Mars 2014
    Messages : 143
    Points : 60
    Points
    60
    Par défaut
    Bon finalement je viens de tester le code et je dois avouer que c'est parfait pour ouvrir et enregistrer un fichier en PNG, un grand merci et un grand bravo Cirec ! et merci aussi à sub0 pour le temps passé à m'aider et ses codes.
    Ensuite j'ai voulu resizer avec une fonction de sub0 (fonction Stretch32), j'ai un problème au niveau des couleurs mais ca reste à vérifier.
    Par contre, je n'arrive pas à assembler 2 images côte à côte, je perds le masque alpha si je fais un aBmp2.Canvas.Draw(0,0,aBmp) et aBmp2.Canvas.Draw(1500,0,aBmp) et que j'enregistre aBmp2. Il ne faut peut être pas faire de Draw ou il faut paramétrer le aBmp2 autrement.
    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
    aPng := TPngImage.Create;
      aPng.LoadFromFile('D:\Test\Output_0001.png');
     
      aBMP := TBitmap.Create;
      aBMP.Width := aPNG.Width;   // aPNG.Width div 2;
      aBMP.Height := aPNG.Height; // aPNG.Height div 2;
      aBMP.PixelFormat := pf32bit;
     
      if aPng.TransparencyMode = ptmPartial then PartialTransPng2Bmp32(aPNG, aBMP);
      aBMP.AlphaFormat := afPremultiplied;
     
      aBmp2 := TBitmap.Create;
      aBmp2.Width:=2000;
      aBmp2.Height:=aBmp.Height;
      aBmp2.PixelFormat:=pf32bit;
     
      aBmp2.Canvas.Draw(0,0,aBmp);
      aBmp2.Canvas.Draw(1304,0,aBmp);
     
      aBmp2.AlphaFormat := afPremultiplied;
     
      Bmp32ToPng(aBMP2).SaveToFile('D:\Test\Cirec.png');
     
      aBMP.Free;
      aBmp2.Free;
      aPng.Free;

Discussions similaires

  1. [GD] Miniature en cache d'image PNG avec transparence
    Par a.brioit dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 27/01/2012, 23h42
  2. PNG avec transparence entre IE7 et FireFox2
    Par Daikyo dans le forum Mise en page CSS
    Réponses: 18
    Dernier message: 27/02/2008, 16h38
  3. Image PNG avec transparence
    Par BlackStorm dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 11/09/2007, 15h00
  4. [D5] Zoom d'image PNG avec transparence
    Par Thierry Laborde dans le forum Delphi
    Réponses: 9
    Dernier message: 12/06/2006, 15h41
  5. Traitements d'image sur PNG avec transparence
    Par Ingham dans le forum Langage
    Réponses: 16
    Dernier message: 02/08/2004, 16h42

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