Einzelnen Beitrag anzeigen

Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
893 Beiträge
 
Delphi 11 Alexandria
 
#1

PNG in mehrere Teile aufteilen

  Alt Heute, 11:12
Zuerst dachte ich, das ginge ganz einfach. Dann habe ich ChatGPT gefragt, und das hat rumhalluziniert und dabei den Knackpunkt gewissenhaft ignoriert. Und weil ich weiß, dass hier ein paar PNG-Experten unterwegs sind, frage ich lieber hier mal nach.

Mit Blick auf Unterstützung für Skalierung möchte ich zur Laufzeit ein paar ImageCollections füllen, die dann wie üblich VirtualImageListen als Quelle dienen. Der Plan ist (um die Anzahl der Dateien klein zu halten), dass alle Icons für eine VirtualImageList in einer Datei liegen (bzw. je eine Datei für 100%, 125%, 150%, ...). Zur Laufzeit soll diese große PNG-Datei dann häppchenweise in die ImageCollection eingefügt werden - inklusive Transparenz und Alphakanal. Und da erscheint mir der Code, den ich mir zusammengesucht habe, etwas umständlich.

Direkt eincompilieren (gefüllte ImageCollection auf einem DataModul etc) möchte ich die Bilddaten nicht, da ich mehrere Icon-Sets zur Auswahl mitliefern möchte, die erst zur Laufzeit geladen werden sollen - und die ggf. auch vom Anwender ergänzt werden können.

Quelle u.a. von Stackoverflow

Delphi-Quellcode:
procedure LoadImagesFromPNG(const AFileName: string; AImageCollection: TImageCollection;
  AImageSize: Integer);
var
  SourcePng, singleIconPNG: TPngImage;
  i, Count: Integer;
  Item: TImageCollectionItem;
  newImageCollectionItem : TImageCollectionSourceItem;
  SrcRect: TRect;
  srcAlphaArray: pByteArray;
  destAlphaArray: pByteArray;
  X, Y, xOffset, yOffset: Integer;
begin
  SourcePng := TPngImage.Create;
  try
    SourcePng.LoadFromFile(AFileName);
    Count := SourcePng.Width div AImageSize;
    for i := 0 to Count - 1 do begin
      yOffset := 0;
      xOffset := i * aImageSize;
      SrcRect := Rect(i * AImageSize, 0, (i + 1) * AImageSize, AImageSize);

      singleIconPNG := TPNGImage.CreateBlank(COLOR_RGBALPHA, 8, AImageSize, AImageSize);
      try
        singleIconPNG.CreateAlpha;
        singleIconPNG.Canvas.CopyMode := cmSrcCopy;
        singleIconPNG.Canvas.CopyRect(Rect(0, 0, AImageSize, AImageSize), SourcePng.Canvas, SrcRect);
        if SourcePng.TransparencyMode = ptmPartial then begin
          // Update destination png with tranparency data from original
          for Y := 0 to SourcePng.Height - 1 do begin
            srcAlphaArray := SourcePng.AlphaScanline[Y];
            destAlphaArray := singleIconPNG.AlphaScanline[Y + YOffset];
            for X := 0 to SourcePng.Width - 1 do
              destAlphaArray^[X] := srcAlphaArray^[X + XOffset];
          end;
        end;

        // Testweise als einzelnes PNG speichern
        singleIconPNG.SaveToFile(AFilename + i.ToString + '.png');

        // Neues Item in der ImageCollection hinzufügen
        // Code von ChatGPT, dass muss natürlich noch angepasst werden für mehrere Auflösungen
        Item := AImageCollection.Images.Add;
        Item.Name := Format('%s_%d', [ExtractFileName(AFileName), i]);
        newImageCollectionItem := Item.SourceImages.Add;
        newImageCollectionItem.Image.Assign(singleIconPNG);
      finally
        singleIconPNG.Free;
      end;
    end;
  finally
    SourcePng.Free;
  end;
end;
Die PNGComponents von Uwe Raabe habe ich kurz danach auch gefunden, die Funktion SlicePNG ist ja recht ähnlich dazu. Die würde ich grade auch bevorzugen - zuerst Slicen und für jede Auflösungsstufe die PNG-Listen erstellen lassen und die dann in die ImageCollection schaufeln. Frage am Rande: Kann ich die mit Quellenangabe in mein OpenSource-Projekt übernehmen? Finde da keine Lizenzangabe...

Mein "Problem" ist nun, ob sich der Aufwand dann überhaupt noch "lohnt". Meine Hoffnung ist, dass das Laden einer Datei und Aufteilen in kleinere Grafiken schneller geht als das Laden von vielen einzelnen Dateien. Bei dem Code bin ich mir da aber nicht mehr so sicher. Es geht dabei um ca. 100 Icons (aufgeteilt in 3 Gruppen), die ich in 4 oder 5 Auflösungen anbieten möchte (Für 100-200% Skalierung). Also ~500 Dateien einzeln laden vs. ~5 (bzw. 15) Dateien laden und splitten.

Hat jemand in der Hinsicht Erfahrungswerte oder kann eine kompetente Schätzung abgeben, was sinnvoller wäre?
The angels have the phone box.
  Mit Zitat antworten Zitat