Tôi có thể thấy nhiều câu trả lời, không thực sự giải quyết ba câu hỏi của OP.
1) Một từ về hiệu suất: mảng byte có thể không hiệu quả trừ khi bạn có thể sử dụng thứ tự byte pixel chính xác phù hợp với độ phân giải hiện tại của bộ điều hợp hiển thị và độ sâu màu.
Để đạt được hiệu suất vẽ tốt nhất, chỉ cần chuyển đổi hình ảnh của bạn thành BufferedImage được tạo với loại tương ứng với cấu hình đồ họa hiện tại của bạn. Xem createdCompiverseImage tại https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Những hình ảnh này sẽ được lưu tự động vào bộ nhớ của thẻ hiển thị sau khi vẽ một vài lần mà không cần bất kỳ nỗ lực lập trình nào (đây là tiêu chuẩn trong Swing kể từ Java 6), và do đó bản vẽ thực tế sẽ mất thời gian không đáng kể - nếu bạn không thay đổi hình ảnh .
Việc thay đổi hình ảnh sẽ đi kèm với việc chuyển bộ nhớ bổ sung giữa bộ nhớ chính và bộ nhớ GPU - tốc độ chậm. Do đó, tránh "vẽ lại" hình ảnh thành BufferedImage, tránh thực hiện getPixel và setPixel bằng mọi cách.
Ví dụ: nếu bạn đang phát triển một trò chơi, thay vì vẽ tất cả các diễn viên trò chơi vào BufferedImage và sau đó đến JPanel, thì việc tải tất cả các diễn viên dưới dạng BufferedImages nhỏ hơn và rút từng người một trong mã JPanel của bạn vị trí thích hợp của chúng - theo cách này không có truyền dữ liệu bổ sung giữa bộ nhớ chính và bộ nhớ GPU ngoại trừ việc chuyển hình ảnh ban đầu để lưu vào bộ đệm.
ImageIcon sẽ sử dụng BufferedImage dưới mui xe - nhưng về cơ bản phân bổ BufferedImage với chế độ đồ họa phù hợp là chìa khóa và không có nỗ lực nào để thực hiện đúng.
2) Cách thông thường để thực hiện việc này là vẽ BufferedImage theo phương thức PaintComponent được ghi đè của JPanel. Mặc dù Java hỗ trợ một số lượng tốt các tính năng bổ sung khác như chuỗi bộ đệm kiểm soát VoliverseImages được lưu trong bộ nhớ GPU, nhưng không cần sử dụng bất kỳ tính năng nào trong số này kể từ Java 6, hoạt động khá tốt mà không cần tiết lộ tất cả các chi tiết về tăng tốc GPU này.
Lưu ý rằng khả năng tăng tốc GPU có thể không hoạt động đối với các hoạt động nhất định, chẳng hạn như kéo dài hình ảnh mờ.
3) Không thêm. Chỉ cần vẽ nó như đã đề cập ở trên:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
"Thêm" có ý nghĩa nếu hình ảnh là một phần của bố cục. Nếu bạn cần điều này làm hình nền hoặc hình nền trước lấp đầy JPanel, chỉ cần vẽ trong paintComponent. Nếu bạn thích pha một thành phần Swing chung có thể hiển thị hình ảnh của bạn, thì đó là câu chuyện tương tự (bạn có thể sử dụng JComponent và ghi đè phương thức paintComponent của nó) - sau đó thêm nó vào bố cục các thành phần GUI của bạn.
4) Cách chuyển đổi mảng thành Bufferedimage
Chuyển đổi mảng byte của bạn thành PNG, sau đó tải nó khá tốn tài nguyên. Một cách tốt hơn là chuyển đổi mảng byte hiện tại của bạn thành BufferedImage.
Cho rằng: không sử dụng cho các vòng lặp và sao chép pixel. Đó là rất rất chậm. Thay thế:
- tìm hiểu cấu trúc byte ưa thích của BufferedImage (ngày nay có thể giả định RGB hoặc RGBA là 4 byte cho mỗi pixel)
- tìm hiểu đường quét và quét kích thước đang sử dụng (ví dụ: bạn có thể có hình ảnh rộng 142 pixel - nhưng trong thực tế, nó sẽ được lưu trữ dưới dạng một mảng byte rộng 256 pixel do xử lý nhanh hơn và che dấu các pix không được sử dụng bởi phần cứng GPU )
- sau đó khi bạn có một bản dựng mảng theo các nguyên tắc này, phương thức mảng setRGB của BufferedImage có thể sao chép mảng của bạn vào BufferedImage.
MemoryImageSource
hơn là chuyển đổi chúng sang định dạng JPEG hoặc PNG và sau đó đọc vớiImageIO
hầu hết các câu trả lời gợi ý. Bạn có thể nhận đượcImage
từ mộtMemoryImageSource
cấu trúc với dữ liệu hình ảnh của mình bằng cách sử dụngcreateImage
và hiển thị như được đề xuất trong một trong các câu trả lời.