Bilder Pixel genau anpassen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Bilder Pixel genau anpassen

    Moin Moin Jungs und Mädels,

    weiss jemand von Euch wie man ein Bild pixelgenau skalieren kann?

    Ich dachte ich hätte eine Lösung, aber das System scheint wohl irgendwelche Dubiose Merkmale mit einfließen zu lassen, so, dass eine ganz andere Bildgrösse herauskommt als ursprünglich erwartet.

    Das Problem ist derzeit, dass das Bild aufgeblasen word, statt auf die Pixelzahl zu reduzieren.

    Schon mal vielen Dank

    Wolf
  • Wolf schrieb:

    Ich dachte ich hätte eine Lösung, aber das System scheint wohl irgendwelche Dubiose Merkmale mit einfließen zu lassen, so, dass eine ganz andere Bildgrösse herauskommt als ursprünglich erwartet.
    Wie erstellt Du denn Dein Image? Wenn Du z. B. in einen mit UIGraphicsBeginImageContextWithOptions erstellten Context malst, kannst Du über die Parameter size und scale eine pixel-basierte Größe vorgeben:
    The size (measured in points) of the new bitmap context. This represents the size of the image returned by the UIGraphicsGetImageFromCurrentImageContext function. To get the size of the bitmap in pixels, you must multiply the width and height values by the value in the scale parameter.
    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Aktuell mache ich es folgendermaßen:


    Quellcode

    1. private func resizePic() {
    2. guard let localMainData = mainData, mainData?.image != nil else { return }
    3. let targetSize = CGSize(width: 900, height: 1200)
    4. let widthScaleRatio = targetSize.width / (localMainData.image?.size.width)!
    5. let heightScaleRatio = targetSize.height / (localMainData.image?.size.height)!
    6. let scaleFactor = min(widthScaleRatio, heightScaleRatio)
    7. let scaledImageSize = CGSize(width: localMainData.image!.size.width * scaleFactor, height: localMainData.image!.size.height * scaleFactor)
    8. let renderer = UIGraphicsImageRenderer(size: scaledImageSize)
    9. let scaledImage = renderer.image { _ in
    10. localMainData.image!.draw(in: CGRect(origin: .zero, size: scaledImageSize))
    11. }
    12. dbR?.pic = scaledImage.pngData()
    13. }
    Alles anzeigen
    Das Problem dabei ist, die Grösse passt nicht zum Speicherplatz verbrauch. Ich vermute, dass hier noch ein versteckter Faktor mit reinspielt. Hier würde ich erwarten, dass das Bild auf 900x1200 Pixel skaliert wird.

    Oder könnt es daran liegen, dass ich das Bild derzeit in die Datenbank ablege?
  • Stimmt nun die Dimension des Images in Pixeln nicht oder irritiert Dich der belegte Speicherplatz? Mir klingt es eher nach letzterem.

    Ich habe auch festgestellt, dass Images z. B. in CloudKit wesentlich mehr Speicherplatz in Anspruch nehmen, als die reinen Image-Daten rechtfertigen. Allerdings habe ich nicht analysiert, was diesen Overhead erzeugt. Ich vermute die grundsätzliche Ablage in CKAssets...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Wolf schrieb:

    Quellcode

    1. guard let localMainData = mainData, mainData?.image != nil else { return }
    Nur eine kleine Anmerkung. Wenn Du deine guard-Anweisung anders schreiben würdest, dann musst Du nicht immer localMainData.image! oder localMainData.image? schreiben. Wobei image? völlig unnötig ist, denn einmal sollte es genügen zu überprüfen ob image gültig ist oder nicht.

    Könnte in dieser Richtung aussehen

    Quellcode

    1. guard let image = mainData?.image else {
    2. return
    3. }
    Ansonsten, wie MyMattes es eigentlich schon erwähnt hat, gebe dir mal scale von deinem Bild aus. Dein Bild ist ja so groß wie im Renderer angegeben. Da kannst Du mal von scaledImage size und scale ausgeben.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von manoh ()

  • Noch ein bisschen rumgelesen und kurz etwas ausprobiert. Kann es sein, dass dein scaledImage.scale auf 2 oder so gesetzt ist, weil Du beim Anlegen vom Renderer kein Format mit angegeben hast. Jedenfalls war das bei mir in Playground so

    Quellcode

    1. import UIKit
    2. let bird = UIImage(named: "bird.jpg")
    3. if let bird = bird {
    4. let widthScale = 300 / bird.size.width
    5. let heightScale = 300 / bird.size.height
    6. let scale = min(widthScale, heightScale)
    7. let size = CGSize(
    8. width: bird.size.width * scale,
    9. height: bird.size.height * scale
    10. )
    11. let renderer = UIGraphicsImageRenderer(size: size)
    12. let image = renderer.image { (context) in
    13. bird.draw(in: CGRect(origin: .zero, size: size))
    14. }
    15. print("Image size \(image.size)")
    16. print("Image scale \(image.scale)")
    17. } else {
    18. print("Image not found!")
    19. }
    Alles anzeigen
  • Hallo Manoh,

    vielen dank für deine Hilfe. Ich selbst bin noch am rumlesen...

    und vermute aktuell, dass auch .scale falsch ist. Stattdessen sollte wohl .nativescale besser arbeiten.

    Das Bild kommt ursprünglich von der Kamera oder von der Photolib (die routine isr einfach der ImageResizer, bevor das Bild persistiert wird). Da weiss ich zu Anfang nicht, welche Größe se es hat, oder anders gesagt ist es mir egal. Ich habe für mich nur definiert, dass das Bild welches ich in der DB speichern möchte nicht größer sein soll als 900x1200px oder anders gesagt nicht grösser als 1MP. Nach meinen Erfahrungen reicht das für fast alles, Online und als Print (Output als größere Nachbelichtung mal abgesehen).


    Das mit dem guard let, schaue ich mir auch noch genauer an. Ich war einfach froh, dass es damals überhaupt lief, doch dann kamen die unangenehmen Überraschungen, wie lange Speicherzeit und hoher Speicherverbrauch. Nachdem ich auch später noch vorhabe, das ganze via iCloud zu synchronisieren, muss ich da auch auf den Speicherverbrauch achten. Werde die Bilder wohl auch aus der zentralen Tabelle auslagern und in eine eigene Tabelle einspielen, damit es nicht immer mitgeladen werden muss, wenn man eine DB Abfrage startet.

    @myMattes: Danke, dass du meine Vermutung bestätigst und mir noch ein paar Stichworte geliefert hast.
    Daneben ist beides der Fall, zum einen möchte ich natürlich ein Bild skaliert haben, wie ich es möchte, da ist meine native Sprache Pixel, zum anderen möcht ich auch nicht unnötig Speicherplatz und Rechenleistung verbraten. Dass das Bild (Binary), wenn es über das Netz geht immer mehr Speicher benötigt wie als natives File, ist klar, da müssen die Sonderzeichen Escaped werden, damit diese nicht mit anderen Protokollen in Konflikt kommen. Dadurch steigt natürlich der Speicherverbrauch. Muss ich wohl dann später auch in Kauf nehmen. Aktuell ist noch keine Cloud Anbindung vorhanden und CoreData ist dafür alleine verantwortlich.

    Schöne Grüße
    Wolf
  • Wolf schrieb:


    Ich habe für mich nur definiert, dass das Bild welches ich in der DB speichern möchte nicht größer sein soll als 900x1200px oder anders gesagt nicht grösser als 1MP.
    Und was erwartest Du dann als Speicherbedarf? Mit welchen Farbtiefen und wieviel Bit für den Alpha-Kanal wird Dein PNG erstellt? Hinzu kommt dann eine verlustfreie Komprimierung, die einen genaue Vorhersage etwas schwierig macht. Vielleicht ist ein (verlustbehaftetes) JPEG auch gut genug? So habe ich zumindest entschieden.

    Dennoch ist ein Export aus CoreData bei mir "winzig" klein im Vergleich zum CoreData-Verbrauch ... ich werde das bei mir auch mal näher analysieren müssen.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Moin Mattes,

    tja, zumindest keine 30 Meg. Das ist mir einfach zu heftig.

    Ich werd wohl auch auf JPEG mit 75% umstellen. Das heisst dann auch die Datenbank scannen, schauen wo PNG drin steht, konvertieren und Zurückspeichern. Dann sollte wieder einiges an Speicher freigegeben werden. Werde die Routine auch noch umschreiben und in eine Lib verpacken. Dann lässt es sich auch unproblematisch in anderen Projekten einsetzen.

    Hoffe, dass dann auch das Speichern von Bildern flotter geht, sonst muss ich da dann auch noch was umbauen.

    Schöne Grüsse
    Wolf