Превратить массив пикселей в объект Image с помощью Java ImageIO? - PullRequest
27 голосов
/ 24 сентября 2008

В настоящее время я превращаю массив значений пикселей (первоначально созданный с помощью объекта 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?

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

Ответы [ 6 ]

27 голосов
/ 24 сентября 2008

Вы можете создать изображение без использования 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. Пример этого есть в handlepixelmethod в javadoc PixelGrabber. После этого убедитесь, что тип изображения в конструкторе BufferedImage равен BufferedImage.TYPE_INT_ARGB.

7 голосов
/ 30 апреля 2009

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

3 голосов
/ 03 февраля 2011

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);
2 голосов
/ 24 сентября 2008

У меня был хороший успех при использовании 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);
0 голосов
/ 21 июня 2016

У меня была та же проблема, что и у всех остальных, пытающихся применить правильный ответ на этот вопрос, мой массив int фактически получает исключение OutOfboundException, в котором я исправил его, добавив еще один индекс, потому что длина массива должна составлять * высота * 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);

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

0 голосов
/ 05 июня 2013

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

Посмотрите на класс BufferedImageFactory.java из моего проекта imageio с открытым исходным кодом на GitHub.

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

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

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

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

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

...