AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi PNG in mehrere Teile aufteilen
Thema durchsuchen
Ansicht
Themen-Optionen

PNG in mehrere Teile aufteilen

Ein Thema von Gausi · begonnen am 2. Feb 2025 · letzter Beitrag vom 2. Feb 2025
Antwort Antwort
Benutzerbild von Gausi
Gausi
Online

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
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.540 Beiträge
 
Delphi 12 Athens
 
#2

AW: PNG in mehrere Teile aufteilen

  Alt Heute, 11:47
Frage am Rande: Kann ich die mit Quellenangabe in mein OpenSource-Projekt übernehmen? Finde da keine Lizenzangabe...
Die PngComponents in GetIt stehen unter der MPL. In der Regel hinken sie meinem GitHub-Repo etwas hinterher.
Ich sollte die Lizenz vielleicht mal in meinem Repo nachziehen...
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.743 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: PNG in mehrere Teile aufteilen

  Alt Heute, 12:20
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.
Das kann ich mir kaum vorstellen, denn das ist relativ aufwendig.

Wie wäre es, wenn du die Dateien selbst in eine Datei packst, so dass du die dann als MMF laden und dann direkt aus dem Arbeitsspeicher arbeiten kannst? Dafür kannst du z.B. auch Delphis TZipFile nehmen.

Dann fällt das Lesen vieler Dateien von der Festplatte weg (was aber bei SSDs weniger von Bedeutung ist als früher).

Wie lange dauert das denn aktuell?
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.540 Beiträge
 
Delphi 12 Athens
 
#4

AW: PNG in mehrere Teile aufteilen

  Alt Heute, 12:56
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.
Letzteres stelle ich mir nur schwer zu implementieren vor. Wie sollen diese ergänzten Icons denn angesprochen werden? Das ginge dann allenfalls über den Index, aber der ist seit ImageName eigentlich nur noch zweite Wahl.

Für den Anwender wäre es auch viel leichter eine neue Datei mit einem sprechenden Dateinamen an eine passende Stelle zu legen und diesen als Referenz zu verwenden. Das könnte man vermutlich leichter realisieren, als eine potenziell fehleranfällige Manipulation der Iconset-Dateien.

Außerdem, was machst du mit einer vom Anwender erweiterten Icon-Set-Datei, wenn du beim nächsten Release selbst neue Icons dazufügen willst?

Ich würde diesen One-File-Ansatz ohne zwingende Gründe eher nicht verfolgen. Mit TImageCollection.Add(AName: String; const AFileName: String); hat man auch einen einfachen Mechanismus mehrere unterschiedlich große Icons unter demselben Namen in die Collection einzulesen. Der ganze Aufwand beim Zusammensetzen der großen Images und das anschließende zerpflücken wär mir das nicht wert.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Gausi
Gausi
Online

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

AW: PNG in mehrere Teile aufteilen

  Alt Heute, 13:33
Danke schonmal für die Antworten.

Wie lange dauert das denn aktuell?
Ich bin noch in der Vorbereitungsphase. Das bisherige Konzept für diese "Skinfunktion" in meinem Player ist etwas in die Jahre gekommen und muss mal überarbeitet werden. Ich bin da grade am Ausloten was geht, praktikabel und wartbar ist. Wie lang die eine oder andere Variante dauert, kann ich nicht sagen. Aktuell ist das eigentliche Projekt auch nicht kompilierbar, weil ich begonnen habe, einige grundlegende Änderungen an einer eigenen Komponente zu machen, die mir das Leben später einfacher machen sollen. So kann ich jetzt z.B. für die Button-Grafiken den Button-Hintergrund und das Icon darauf separat angeben. Und als Zusatz noch ein weiteres OverlayIcon. Insgesamt wird die Bilddaten-Menge dadurch kleiner.

Wie sollen diese ergänzten Icons denn angesprochen werden? Das ginge dann allenfalls über den Index
Da habe ich mich vielleicht missverständlich ausgedrückt. Wenn, dann kann der Anwender ein ganzes Set an Icons ergänzen - in einem neuen Ordner. Die Anzahl ist fix (bis ggf. zum nächsten Release). Das ist aber bislang ein eher theoretisches Szenario, das bisher noch nicht vorgekommen ist.

Aber die Einwände sind nachvollziehbar, und die teile ich ja auch (daher auch das Topic). Diese Scanline-Orgie und mehrfaches rum-assignen scheint dafür eher eine Sackgasse zu sein. Ich werde dann vermutlich erstmal den Multifile-Ansatz verfolgen und versuchen, da ein überschaubares System für die Dateinamen hinzubekommen.

Ggf. reduziere ich auch den Aufwand beim Start, indem ich erstmal nur die benötigte Skalierungsstufe in die Collection lade, und bei einem Wechsel ggf. nachlade. Das sollte ja auch möglich sein.
The angels have the phone box.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.540 Beiträge
 
Delphi 12 Athens
 
#6

AW: PNG in mehrere Teile aufteilen

  Alt Heute, 16:45
Ich werde dann vermutlich erstmal den Multifile-Ansatz verfolgen und versuchen, da ein überschaubares System für die Dateinamen hinzubekommen.
Da kommt mir ein separater Subfolder pro Icon-Set in den Sinn.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz