Widzę wiele odpowiedzi, w rzeczywistości nie odnosząc się do trzech pytań PO.
1) Słowo o wydajności: tablice bajtów są prawdopodobnie niewystarczające, chyba że można użyć dokładnej kolejności bajtów pikseli, która pasuje do bieżącej rozdzielczości i głębi kolorów kart graficznych.
Aby osiągnąć najlepszą wydajność rysowania, wystarczy przekonwertować obraz na buforowany obraz, który jest generowany z typem odpowiadającym bieżącej konfiguracji grafiki. Zobacz createCompatibleImage na https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Te obrazy będą automatycznie buforowane w pamięci karty graficznej po rysowaniu kilka razy bez żadnego wysiłku programistycznego (jest to standard w Swing od Java 6), a zatem faktyczny rysunek zajmie znikomą ilość czasu - jeśli nie zmieniłeś obrazu .
Zmiana obrazu nastąpi z dodatkowym transferem pamięci między pamięcią główną a pamięcią GPU - co jest wolne. Dlatego unikaj „przerysowywania” obrazu do BufferedImage, dlatego unikaj wykonywania getPixel i setPixel za wszelką cenę.
Na przykład, jeśli tworzysz grę, zamiast przyciągać wszystkich aktorów do BufferedImage, a następnie do JPanel, ładowanie wszystkich aktorów jako mniejsze BufferedImages jest znacznie szybsze i rysowanie ich jeden po drugim w kodzie JPanel na stronie ich właściwe położenie - w ten sposób nie zachodzi dodatkowy transfer danych między pamięcią główną a pamięcią GPU, z wyjątkiem początkowego transferu obrazów do buforowania.
ImageIcon użyje BufferedImage pod maską - ale w zasadzie kluczem jest przydzielenie BufferedImage z odpowiednim trybem graficznym i nie ma wysiłku, aby zrobić to dobrze.
2) Zwykłym sposobem na zrobienie tego jest narysowanie BufferedImage w przesłoniętej metodzie paintComponent JPanel. Chociaż Java obsługuje wiele dodatkowych dodatków, takich jak łańcuchy buforów kontrolujące VolatileImages buforowane w pamięci GPU, nie ma potrzeby korzystania z żadnego z nich, ponieważ Java 6 wykonuje dość dobrą pracę bez ujawniania wszystkich tych szczegółów przyspieszenia GPU.
Pamiętaj, że przyspieszenie GPU może nie działać w przypadku niektórych operacji, takich jak rozciąganie półprzezroczystych obrazów.
3) Nie dodawaj. Po prostu pomaluj jak wspomniano powyżej:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
„Dodawanie” ma sens, jeśli obraz jest częścią układu. Jeśli potrzebujesz tego jako obrazu tła lub pierwszego planu wypełniającego JPanel, po prostu narysuj paintComponent. Jeśli wolisz zaparzyć ogólny komponent Swing, który może wyświetlać twój obraz, to jest to ta sama historia (możesz użyć JComponent i zastąpić jego metodę paintComponent) - a następnie dodać to do układu komponentów GUI.
4) Jak przekonwertować tablicę na obraz buforowany
Konwersja tablic bajtów do formatu PNG, a następnie ich załadowanie wymaga dużych zasobów. Lepszym sposobem jest konwersja istniejącej tablicy bajtów na BufferedImage.
W tym celu: nie należy używać do pętli i kopiowania pikseli. To jest bardzo, bardzo wolne. Zamiast:
- poznaj preferowaną strukturę bajtów BufferedImage (obecnie bezpiecznie jest założyć RGB lub RGBA, czyli 4 bajty na piksel)
- poznaj używaną linię skanowania i skanuj (np. możesz mieć obraz o szerokości 142 pikseli - ale w rzeczywistości będzie on przechowywany jako tablica bajtów o szerokości 256 pikseli, ponieważ szybsze przetwarzanie i maskowanie nieużywanych pikseli przez sprzęt GPU )
- następnie po zbudowaniu tablicy zgodnie z tymi zasadami metoda setRGB z tablicy BufferedImage może skopiować tablicę do BufferedImage.
MemoryImageSource
niż konwertowanie ich do formatu JPEG lub PNG, a następnie czytanie,ImageIO
jak sugeruje większość odpowiedzi. Można dostaćImage
z punktu AMemoryImageSource
zbudowane z danych obrazu za pomocącreateImage
, a wyświetlacz jak zasugerował w jednym z odpowiedziami.