Я бачу багато відповідей, не дуже вирішуючи три питання ОП.
1) Слово про продуктивність: байтові масиви, ймовірно, неефективні, якщо ви не можете використовувати точний порядок байт пікселів, який відповідає поточній роздільній здатності та глибині кольорів адаптерів дисплея.
Щоб досягти найкращої продуктивності малювання, просто перетворіть своє зображення в BufferedImage, який генерується з типом, відповідним вашій поточній графічній конфігурації. Дивіться createCompatibleImage на веб- сайті https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Ці зображення будуть автоматично кешовані в пам'яті картки дисплея після малювання кілька разів без будь-яких зусиль програмування (це стандартно в Swing, оскільки Java 6), і тому власне малювання займе незначну кількість часу - якщо ви не змінили зображення .
Змінення зображення відбудеться з додатковою передачею пам’яті між основною пам'яттю та пам’яттю графічного процесора - що відбувається повільно. Уникайте "перемальовування" зображення в BuferiImage, тому уникайте використання getPixel і setPixel будь-якими способами.
Наприклад, якщо ви розробляєте гру, замість того, щоб малювати всіх акторів гри до BufferedImage, а потім до JPanel, набагато швидше завантажувати всіх акторів як менших BufferedImages і малювати їх по одному у своєму коді JPanel на їх правильне положення - таким чином не відбувається додаткової передачі даних між основною пам'яттю і пам'яттю GPU, крім початкової передачі зображень для кешування.
ImageIcon використовуватиме BufferedImage під кришкою, але в основному ключовим є виділення BufferedImage у відповідному графічному режимі, і для цього не докладається жодних зусиль.
2) Звичайним способом цього є нанесення BuferiImage методом JPAnel, що перекривається фарбою. Хоча Java підтримує велику кількість додаткових вигод, таких як буферні ланцюги, які управляють VolatileImages, кешованими в пам'яті GPU, немає необхідності використовувати жодне з них, оскільки Java 6, яка виконує досить гарну роботу, не піддаючи всі ці подробиці прискорення GPU.
Зауважте, що прискорення GPU може не працювати для певних операцій, наприклад, розтягування напівпрозорих зображень.
3) Не додавати. Просто намалюйте його, як було сказано вище:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
"Додавання" має сенс, якщо зображення є частиною макета. Якщо вам це потрібно як фонове або фонове зображення, що заповнює JPanel, просто намалюйте paintComponent. Якщо ви віддаєте перевагу заготовленню загального компонента Swing, який може показувати ваше зображення, то це та сама історія (ви можете використовувати JComponent і замінити її метод paintComponent) - а потім додайте це до свого макета компонентів графічного інтерфейсу.
4) Як перетворити масив у буферне зображення
Перетворення байтових масивів у PNG та завантаження його досить ресурсомістке. Кращий спосіб - перетворити наявний масив байтів у BufferedImage.
Для цього: не використовувати для циклів і копіювати пікселі. Це дуже повільно. Замість цього:
- вивчити кращу байтну структуру BufferedImage (сьогодні безпечно вважати RGB або RGBA, що становить 4 байти на піксель)
- вивчіть сканування та скануйте розмір у використанні (наприклад, у вас може бути зображення шириною 142 пікселів - але в реальному житті воно буде зберігатися як байтовий масив 256 пікселів, оскільки швидше обробити та замаскувати невикористані пікселі апаратним забезпеченням GPU )
- то, як тільки у вас буде побудова масиву згідно з цими принципами, метод масиву setRGB масиву BufferedImage може скопіювати свій масив у BufferedImage.
MemoryImageSource
ніж для перетворення їх у формат JPEG або PNG, а потім читання з урахуваннямImageIO
більшості відповідей. Ви можете отриматиImage
зMemoryImageSource
побудованих ваших даних зображень, використовуючиcreateImage
та відображати, як було запропоновано в одній з відповідей.