Bild zuschneiden, um kleinste Größe durch entfernen der transparenten Pixel in java
Habe ich ein sprite-Blatt, das hat jedes Bild zentriert in einem 32x32-Zelle. Die tatsächlichen Bilder sind nicht 32x32, aber etwas kleiner. Was ich gerne tun möchte, ist nehmen Sie eine Zelle aus, und Ernte die transparenten Pixel, sodass das Bild ist so klein wie es nur sein kann.
Wie würde ich das in Java (JDK 6)?
Hier ist ein Beispiel, wie ich bin derzeit brechen der Fliese Blatt in Zellen:
BufferedImage tilesheet = ImageIO.read(getClass().getResourceAsStream("/sheet.png");
for (int i = 0; i < 15; i++) {
Image img = tilesheet.getSubimage(i * 32, 0, 32, 32);
//crop here..
}
Meine aktuelle Idee zu testen, wurde jedes pixel von der Mitte der Arbeit meinen Weg, um zu sehen, wenn es transparent ist, aber ich Frage mich, ob es wäre schneller/sauberer Weg, dies zu tun.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, das ist genau das, was Sie tun sollten, eine Schleife über das array von Pixel check für alpha-und dann verwerfen. Obwohl, wenn Sie, zum Beispiel, hätte einen Stern es wird nicht die Größe des Bildes kleiner werden, bewusst.
Gibt es eine triviale Lösung – scan jedem pixel. Der Algorithmus, der Balg hat Konstante Leistung
O(w•h)
.Aber dies ist viel effektiver:
Dieser Algorithmus folgt der Idee von pepan's Antwort (siehe oben) und ist 2 bis 4 mal wirksamer. Der Unterschied ist: es ist nie durchsucht jedes pixel zweimal und versucht zu Vertrag Suchbereich auf jeder Bühne.
Methode, die Leistung im schlimmsten Fall ist
O(w•h–a•b)
Bitmap
mit weißem hintergrund. Ich würde hier posten, wenn jemand interessiert ist.Dieser code funktioniert für mich. Der Algorithmus ist einfach, es geht von Links/oben/rechts/unten im Bild und findet den ersten pixel in der Spalte/Zeile, die ist nicht transparent. Es erinnert sich dann die neue Ecke des beschnittenen Bildes und schließlich gibt es den sub-image of the original image.
Gibt es Dinge, die verbessert werden könnten.
Dem Algorithmus erwartet wird, gibt es die alpha-byte in den Daten. Es wird nicht auf einen index außerhalb der array-Ausnahme, wenn es nicht ist.
Der Algorithmus erwartet, dass es mindestens einen nicht-transparenten pixel im Bild. Es wird scheitern, wenn das Bild komplett transparent ist.
}
Wenn Ihr Blatt schon hat transparente Pixel, die
BufferedImage
zurückgegebengetSubimage()
wird, zu. Die Standard -Graphics2D
composite-Regel istAlphaComposite.SRC_OVER
, das sollte reichen fürdrawImage()
.Wenn die sub-Bilder haben eine unterschiedliche Hintergrundfarbe, verwenden Sie eine
LookupOp
mit einem vier-Komponenten -LookupTable
setzt, die die alpha-Komponente zu null für Farben, die mit dem hintergrund.Ich würde die traverse pixel-raster nur als letzten Ausweg.
Nachtrag: Extra transparente Pixel stören können mit collision detection, etc. Beschneiden Sie benötigen arbeiten mit einem
WritableRaster
direkt. Anstatt von der Mitte aus, ich würde anfangen mit den Grenzen, mit einem paar vongetPixels()
/setPixels()
Methoden ändern können eine Zeile oder Spalte zu einer Zeit. Wenn eine ganze Zeile oder Spalte, die null-alpha, markieren Sie es für die Beseitigung, wenn du später einen sub-Bild.