Я вижу много ответов, на самом деле не обращаясь к трем вопросам ОП.
1) Слово о производительности: байтовые массивы, вероятно, неэффективны, если вы не можете использовать точный порядок байтов в пикселях, который соответствует вашим адаптерам дисплея, текущему разрешению и глубине цвета.
Чтобы добиться максимальной производительности при рисовании, просто преобразуйте изображение в BufferedImage, созданный с типом, соответствующим вашей текущей графической конфигурации. См. CreateCompatibleImage на https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Эти изображения будут автоматически кэшироваться в памяти видеокарты после рисования несколько раз без каких-либо усилий по программированию (это стандартно в Swing начиная с Java 6), и, следовательно, фактическое рисование займет незначительное количество времени - если вы не изменили изображение ,
Изменение изображения будет сопровождаться дополнительной передачей памяти между основной памятью и памятью GPU, что является медленным. Избегайте «перерисовки» изображения в BufferedImage, поэтому избегайте использования getPixel и setPixel во всех отношениях.
Например, если вы разрабатываете игру, вместо того, чтобы рисовать всех игровых акторов в BufferedImage, а затем в JPanel, гораздо быстрее загружать всех акторов как меньшие BufferedImages и рисовать их по одному в вашем коде JPanel в их правильное положение - таким образом, нет никакой дополнительной передачи данных между основной памятью и памятью GPU, кроме начальной передачи изображений для кэширования.
ImageIcon будет использовать BufferedImage под капотом - но в основном распределение BufferedImage с правильным графическим режимом является ключевым, и нет никаких усилий, чтобы сделать это правильно.
2) Обычный способ сделать это - нарисовать BufferedImage в переопределенном методе paintComponent в JPanel. Хотя Java поддерживает большое количество дополнительных полезных функций, таких как цепочки буферов, управляющие VolatileImages, кешируемыми в памяти графического процессора, нет необходимости использовать ни один из них, так как Java 6 работает достаточно хорошо, не раскрывая всех этих деталей ускорения графического процессора.
Обратите внимание, что ускорение графического процессора может не работать для определенных операций, таких как растяжение полупрозрачных изображений.
3) Не добавляйте. Просто нарисуйте, как указано выше:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
«Добавление» имеет смысл, если изображение является частью макета. Если вам нужно это как фоновое или переднее изображение, заполняющее JPanel, просто нарисуйте paintComponent. Если вы предпочитаете создавать универсальный компонент Swing, который может отображать ваше изображение, то это та же история (вы можете использовать JComponent и переопределить его метод paintComponent), а затем добавить его в свой макет компонентов GUI.
4) Как преобразовать массив в Bufferedimage
Преобразование ваших байтовых массивов в PNG, а затем их загрузка довольно ресурсоемки. Лучший способ - преобразовать существующий байтовый массив в BufferedImage.
Для этого: не используйте петли и не копируйте пиксели. Это очень, очень медленно. Вместо:
- узнать предпочитаемую структуру байтов BufferedImage (в настоящее время можно предположить RGB или RGBA, что составляет 4 байта на пиксель)
- изучите отсканированную линию и размер сканирования при использовании (например, у вас может быть изображение шириной 142 пикселя - но в реальной жизни оно будет храниться в виде байтового массива шириной 256 пикселей, поскольку это быстрее обрабатывать и маскировать неиспользуемые пиксели с помощью оборудования графического процессора )
- затем, если у вас есть сборка массива в соответствии с этими принципами, метод массива setRGB объекта BufferedImage может скопировать ваш массив в BufferedImage.
MemoryImageSource
чем конвертировать их в формат JPEG или PNG, а затем читать,ImageIO
как предлагает большинство ответов. Вы можете получитьImage
изMemoryImageSource
созданного с вашим данными изображения, используяcreateImage
, и отобразить, как предложено в одном из ответов.