Подтвердить что ты не робот

Включить массив пикселей в объект изображения с помощью Java ImageIO?

В настоящее время я превращаю массив значений пикселей (первоначально созданных с помощью объекта java.awt.image.PixelGrabber) в объект Image, используя следующий код:

public Image getImageFromArray(int[] pixels, int width, int height) {
    MemoryImageSource mis = new MemoryImageSource(width, height, pixels, 0, width);
    Toolkit tk = Toolkit.getDefaultToolkit();
    return tk.createImage(mis);
}

Можно ли достичь такого же результата с помощью классов из пакета ImageIO, поэтому мне не нужно использовать набор инструментов AWT?

Toolkit.getDefaultToolkit(), похоже, не на 100% надежнее и иногда выдает AWTError, тогда как классы ImageIO всегда должны быть доступны, поэтому меня интересует изменение моего метода.

4b9b3361

Ответ 1

Вы можете создать изображение без использования ImageIO. Просто создайте BufferedImage, используя тип изображения, соответствующий содержимому массива пикселей.

public static Image getImageFromArray(int[] pixels, int width, int height) {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            WritableRaster raster = (WritableRaster) image.getData();
            raster.setPixels(0,0,width,height,pixels);
            return image;
        }

При работе с PixelGrabber не забудьте извлечь информацию RGBA из массива пикселей до вызова getImageFromArray. Вот пример этого в дескриптор метода в javadoc PixelGrabber. После этого убедитесь, что тип изображения в конструкторе BufferedImage равен BufferedImage.TYPE_INT_ARGB.

Ответ 2

С помощью растра я получил ArrayIndexOutOfBoundsException, даже когда я создал BufferedImage с TYPE_INT_ARGB. Однако использование setRGB(...) метода BufferedImage работало для меня.

Ответ 3

JavaDoc в BufferedImage.getData() говорит: "Растр, который является копией данных изображения."

Этот код работает для меня, но я сомневаюсь в его эффективности:

        // Получаем картинку из массива.
        int[] pixels = new int[width*height];
            // Рисуем диагональ.
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {
                    if (i == j) {
                        pixels[j*width + i] = Color.RED.getRGB();
                    }
                    else {
                        pixels[j*width + i] = Color.BLUE.getRGB();
                        //pixels[j*width + i] = 0x00000000;
                    }
                }
            }

BufferedImage pixelImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    
    pixelImage.setRGB(0, 0, width, height, pixels, 0, width);

Ответ 4

У меня был хороший успех, используя java.awt.Robot, чтобы захватить снимок экрана (или сегмент экрана), но для работы с ImageIO вам необходимо сохранить его в BufferedImage вместо образа памяти источник. Затем вы можете вызвать один статический метод ImageIO и сохранить файл. Попробуйте что-то вроде:

// Capture whole screen
Rectangle region = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capturedImage = new Robot().createScreenCapture(region);

// Save as PNG
File imageFile = new File("capturedImage.png");
ImageIO.write(capturedImage, "png", imageFile);

Ответ 5

Поскольку это один из самых высоких проголосовавших вопросов, отмеченных ImageIO на SO, я думаю, что есть еще место для лучшего решения, даже если вопрос старый.: -)

Взгляните на класс BufferedImageFactory.java из моего проекта с открытым исходным кодом изображения в GitHub.

С его помощью вы можете просто написать:

BufferedImage image = new BufferedImageFactory(image).getBufferedImage();

Другое дело, что этот подход, в худшем случае, имеет одинаковую производительность (время) в качестве примеров, основанных на PixelGrabber уже в этом потоке. Для большинства распространенных случаев (обычно JPEG) это примерно в два раза быстрее. В любом случае он использует меньше памяти.

В качестве бонусного бонуса сохраняется цветовая модель и макет пикселя исходного изображения, а не переводится в int ARGB с цветной моделью по умолчанию. Это может сэкономить дополнительную память.

(PS: factory также поддерживает подвыборку, регионы интереса и слушателей прогресса, если кому-то интересно.: -)

Ответ 6

У меня была та же проблема, что и все остальные, пытающиеся применить правильный ответ на этот вопрос, мой массив int фактически получает OutOfboundException, где я исправил его, добавив еще один индекс, потому что длина массива должна быть widht * height * 3 после этого я не смог получить изображение, поэтому я исправил его, установив растровое изображение

public static Image getImageFromArray(int[] pixels, int width, int height) {
        BufferedImage image = new BufferedImage(width, height,     BufferedImage.TYPE_INT_ARGB);
        WritableRaster raster = (WritableRaster) image.getData();
        raster.setPixels(0,0,width,height,pixels);
        image.setData(raster); 
        return image;
    }

И вы можете увидеть изображение, если и показать его на ярлыке на jframe, подобном этому

    JFrame frame = new JFrame();
    frame.getContentPane().setLayout(new FlowLayout());
    frame.getContentPane().add(new JLabel(new ImageIcon(image)));
    frame.pack();
    frame.setVisible(true);

настройка изображения на изображенииIcon(). Последний совет, который вы можете попробовать изменить Bufferedimage.TYPE_INT_ARGB на что-то еще, что соответствует изображению, полученному вами от этого типа, очень важно. У меня был массив из 0 и -1, поэтому я использовал этот тип BufferedImage.TYPE_3BYTE_BGR