Thema: Delphi PNG verschmelzen

Einzelnen Beitrag anzeigen

Renate Schaaf

Registriert seit: 25. Jun 2020
Ort: Lippe
114 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: PNG verschmelzen

  Alt 10. Jun 2023, 18:41
Zitat:
Aber jetzt: Der Stern wird auf dem Icon nur da gezeichnet, wo der Hintergrund NICHT transparent ist..... Vielleicht noch eine Idee?
Dazu muss man erst einen Hintegrund erstellen. Leider kann man nicht einfach ein TPngImage erzeugen und auf dessen Canvas malen. Da braucht man eine TBitmap. Die Alpha-Unterstützung und die Unterstützung der verschiedenen Graphik-Formate ist in Delphi ziemlich hauruck-artig umgesetzt. Will man was machen, was etwas außer der Reihe ist, muss man frickeln. Dein Problem ist ein wunderbares Beispiel dafür.

Hier ist die erste Methode, die aber nicht ganz geht, siehe Kommentare:

Code:
procedure TForm1.btnIconWithStarClick(Sender: TObject);
var
  png: TPngImage;
  bm: TBitmap;
begin
  png := TPngImage.Create;
  try
    // png für die richtige Größe erstellen. Das 128,128 garantiert nicht, dass das
    // png wirklich eine Größe von 128x128 hat. Es wird nur das nächstbeste genommen.
    png.Assign(ImageCollection.GetSourceImage(ImageCollection.GetIndexByName
      ('Icon'), 128, 128));

    // Eine Bitmap für schwarzen Hintergrund machen
    // pf32bit wird für den alpha-channel gebraucht.
    bm := TBitmap.Create;
    try
      bm.PixelFormat := pf32bit;
      bm.SetSize(png.Width, png.height);
      bm.Canvas.Brush.Color := clBlack;
      bm.Canvas.FillRect(Rect(0, 0, bm.Width, bm.height));
      // png per alpha-blend auf den canvas von bm zeichen
      bm.Canvas.Draw(0, 0, png);
      // 'Star' auf bm zeichnen per ImageCollection.Draw
      // Das Rect kann bei Bedarf angepasst werden
      ImageCollection.Draw(bm.Canvas, Rect(0, 2 * bm.height div 3,
        bm.Width div 3, bm.height), 'Star');
      // bm enthält als alpha die durchsichtigen Teile von icon und star kombiniert.
      // Jetzt nur noch dieses alpha anwenden:
      bm.Alphaformat := afDefined;

      // Kombiniertes Bild anzeigen
      Image1.Picture.Graphic := bm;
      // Image1 zeigt jetzt wahrscheinlich die richtige Kombination an.

      // Das folgende geht aber nicht, weil VCL.Graphics nicht das alpha von bm auf png überträgt,
      // sondern die transparente Farbe, wahrscheinlich weil darüber die wenigsten Leute
      // meckern würden. Und wenn man bm erst transparent macht, gibt das immer hässliche Resultate.
      png.Assign(bm);
      // Das kombinierte Bild speichern
      png.SaveToFile('IconWithStar.png');
    finally
      bm.Free;
    end;
  finally
    png.Free;
  end;
end;
Um das Ergebnis nun auch korrekt abzuspeichern, brauchst du nun wirklich ein TWicImage.

Code:
procedure TForm2.btnIconWithStarTheRightWayClick(Sender: TObject);
var
  png: TPngImage;
  bm: TBitmap;
  wic: TWicImage;
begin
  png := TPngImage.Create;
  try
    // png für die richtige Größe erstellen. Das 128,128 garantiert nicht, dass das
    // png wirklich eine Größe von 128x128 hat. Es wird nur das nächstbeste genommen.
    png.Assign(ImageCollection.GetSourceImage(ImageCollection.GetIndexByName
      ('Icon'), 128, 128));

    // Eine Bitmap für schwarzen Hintergrund machen
    // pf32bit wird für den alpha-channel gebraucht.
    bm := TBitmap.Create;
    try
      bm.PixelFormat := pf32bit;
      bm.SetSize(png.Width, png.height);
      bm.Canvas.Brush.Color := clBlack;
      bm.Canvas.FillRect(Rect(0, 0, bm.Width, bm.height));
      // png per alpha-blend auf den canvas von bm zeichen
      bm.Canvas.Draw(0, 0, png);
      // 'Star' auf bm zeichnen per ImageCollection.Draw
      // Das Rect kann bei Bedarf angepasst werden
      ImageCollection.Draw(bm.Canvas, Rect(0, 2 * png.height div 3,
        png.Width div 3, png.height), 'Star');
      // bm enthält als alpha die durchsichtigen Teile von icon und star kombiniert.
      // Jetzt nur noch dieses alpha anwenden:
      bm.Alphaformat := afDefined;

      // Wenn du jetzt die Kombination als png mit dem richtigen Alpha speichern willst,
      // brauchst du ein TWicImage:
      wic := TWicImage.Create;
      try
        wic.Assign(bm);
        wic.ImageFormat := wifPng;
        //Das vorige Bild aus image1 löschen, sonst werden die übereinander gemalt, was dich irritiert hat
        image1.Picture:=nil;
        //kombiniertes Bild anzeigen
        Image1.Picture.Graphic:=wic;
        // Das kombinierte Bild speichern
        wic.SaveToFile('IconWithStar.png');
      finally
        wic.Free;
      end;
    finally
      bm.Free;
    end;
  finally
    png.Free;
  end;
end;
Edit: Jetzt fällt mir auf, dass man png.canvas gar nicht mehr braucht. Kann man also von vornherein mit TWicImage statt TPngImage arbeiten.
Renate

Geändert von Renate Schaaf (10. Jun 2023 um 19:54 Uhr)
  Mit Zitat antworten Zitat