Szukam najszybszego sposobu na uzyskanie danych pikseli (w formularzu int[][]
) z pliku BufferedImage
. Moim celem jest możliwość adresowania piksela (x, y)
z obrazu za pomocą int[x][y]
. Nie działają wszystkie metody, które znalazłem (większość z nich zwraca int[]
s).
java
bufferedimage
javax.imageio
ryyst
źródło
źródło
getRGB
isetRGB
bezpośrednio?getRGB
isetRGB
bezpośrednio.Odpowiedzi:
Po prostu bawiłem się tym samym tematem, który jest najszybszym sposobem uzyskania dostępu do pikseli. Obecnie znam dwa sposoby, aby to zrobić:
getRGB()
metody BufferedImage, jak opisano w odpowiedzi @ tskuzzy.Uzyskując dostęp do tablicy pikseli bezpośrednio za pomocą:
Jeśli pracujesz z dużymi obrazami i problemem jest wydajność, pierwsza metoda absolutnie nie jest właściwą.
getRGB()
Metoda łączy alfa, czerwony, zielony i niebieski wartości w jednym int a następnie zwraca wynik, który w większości przypadków będziesz robić na odwrót, aby te wartości z powrotem.Druga metoda zwróci wartości czerwonego, zielonego i niebieskiego bezpośrednio dla każdego piksela, a jeśli istnieje kanał alfa, doda wartość alfa. Korzystanie z tej metody jest trudniejsze pod względem obliczania wskaźników, ale jest znacznie szybsze niż pierwsze podejście.
W mojej aplikacji udało mi się skrócić czas przetwarzania pikseli o ponad 90%, po prostu przełączając się z pierwszego podejścia na drugie!
Oto porównanie, które skonfigurowałem, aby porównać dwa podejścia:
Czy potrafisz odgadnąć wynik? ;)
źródło
convertTo2DUsingGetRGB
iconvertTo2DWithoutUsingGetRGB
. Pierwszy test trwa średnio 16 sekund. Drugi test trwa średnio 1,5 sekundy. Na początku myślałem, że „s” i „ms” to dwie różne kolumny. @Mota, świetne odniesienie.BufferedImage
jesttype
npTYPE_INT_RGB
lubTYPE_3BYTE_BGR
i uchwyt odpowiednio. To jest jedna z rzeczy, któregetRGB()
robią dla ciebie, to spowalniają :-(|=
zamiast+=
łączenia wartości w metodzie 2?Coś takiego?
źródło
BufferedImage
każdym razie chciałbym przechowywać piksele przy użyciu tablicy int 2D?Raster
bufora danych, co jest zdecydowanie dobrą rzeczą, ponieważ powoduje to przyspieszenie.Okazało się, że odpowiedź Moty dała mi 10-krotny wzrost prędkości - dzięki Mota.
Zapakowałem kod w wygodną klasę, która przyjmuje BufferedImage w konstruktorze i ujawnia równoważną metodę getRBG (x, y), która sprawia, że jest to kropla w zastępstwie kodu za pomocą BufferedImage.getRGB (x, y)
źródło
Odpowiedź Moty jest świetna, chyba że twój BufferedImage pochodzi z Monochrome Bitmap. Monochromatyczna mapa bitowa ma tylko 2 możliwe wartości swoich pikseli (na przykład 0 = czarny i 1 = biały). Gdy używana jest monochromatyczna mapa bitowa, plik
call zwraca surowe dane Pixel Array w taki sposób, że każdy bajt zawiera więcej niż jeden piksel.
Więc kiedy używasz obrazu Monochrome Bitmap do tworzenia obiektu BufferedImage, to jest to algorytm, którego chcesz użyć:
źródło
Jeśli to przydatne, spróbuj tego:
źródło
Oto kolejna implementacja FastRGB znaleziona tutaj :
Co to jest?
Odczytywanie obrazu piksel po pikselu za pomocą metody getRGB firmy BufferedImage jest dość powolne, ta klasa jest rozwiązaniem tego problemu.
Chodzi o to, że konstruujesz obiekt, przekazując mu instancję BufferedImage, a następnie odczytuje on wszystkie dane na raz i zapisuje je w tablicy. Gdy chcesz uzyskać piksele, zadzwoń do getRGB
Zależności
Rozważania
Chociaż FastRGB znacznie przyspiesza odczyt pikseli, może to prowadzić do dużego zużycia pamięci, ponieważ po prostu przechowuje kopię obrazu. Jeśli więc masz w pamięci 4 MB BufferedImage, po utworzeniu instancji FastRGB użycie pamięci wyniesie 8 MB. Możesz jednak odtworzyć wystąpienie BufferedImage po utworzeniu FastRGB.
Uważaj, aby nie wpaść w OutOfMemoryException podczas używania go na urządzeniach takich jak telefony z Androidem, gdzie RAM jest wąskim gardłem
źródło
To zadziałało dla mnie:
źródło
i
?