Быстрая загрузка изображения PNG в массив в Java - PullRequest
3 голосов
/ 12 октября 2010

Я хочу загрузить (и декодировать) изображения PNG и преобразовать их в одномерный массив в Java.Я, очевидно, могу сделать это с помощью ImageIO.read (), а затем скопировать пиксели в массив, но это потребляет вдвое больше памяти (растр + конечный массив) и требует больше времени на обработку, чем хотелось бы.

Как я должен идти об этом?В худшем случае я могу сам реализовать спецификацию PNG, но это кажется довольно сложной задачей.В идеале я бы хотел реализацию PNG, к которой я мог бы подключиться.Менее идеальным, но все же хорошим, было бы легко понять (в отличие от кода com.sun) считыватель PNG, который я могу (и могу) изменить.

Ответы [ 3 ]

8 голосов
/ 12 октября 2010

Если вы пытаетесь получить пиксельные данные в виде массива, вы можете использовать ImageIO.read(), чтобы получить BufferedImage, а затем BufferedImage.getRaster().getDataBuffer(), чтобы получить DataBuffer. Оттуда вам нужно проверить, какой тип BufferedImage у вас есть, чтобы определить, как разыграть DataBuffer. Например. если у вас есть изображение TYPE_INT_RGB, вам следует привести к DataBufferInt, а затем вы можете позвонить DataBufferInt.getData(), чтобы получить int[], который содержит данные. Таким образом, вы получаете не копию, а настоящий массив, поддерживающий BufferedImage.

Однако , есть большая оговорка ко всему этому: ImageIO.read() часто НЕ даст вам тип изображения, который вы хотите. Например, вы часто получаете TYPE_CUSTOM, с которым вы ничего не можете сделать, кроме как скопировать в тип изображения, который вам действительно нужен.

Итак, , вы сможете получать данные изображения только через ImageIO.read(), не делая вторую копию, если вам повезет, что ImageIO.read() даст вам изображение в нужном формате. , Если вы хотите проверить, какие типы доступны из ImageIO, вы можете позвонить ImageIO.getImageReaders(), чтобы получить Iterator для всех читателей, которые утверждают, что могут читать ваш поток, а затем вы можете использовать ImageReader.getImageTypes(0) для получите Iterator для типов изображений, которые читатель может прочитать. Вы могли бы найти читателя, который даст вам тип изображения, который вы хотите таким образом, но не задерживает дыхание.

Если ваши изображения не огромные, их копирование выполняется довольно быстро. Если ваши изображения огромны , вам, возможно, придется прибегнуть к использованию BufferedImage.getRGB() для записи необработанных данных изображения на диск по одной строке за раз (но сделайте это сжатым, используйте GZIPOutputStream) Позвольте исходному изображению собрать мусор, создайте новый BufferedImage нужного типа и, наконец, прочитайте строки обратно с диска, записав их в новое изображение, используя BufferedImage.setRGB(). (Я написал кое-что для этого всего несколько дней назад, поэтому подробности у меня в голове довольно свежие. Источник LGPL для этого здесь .)

3 голосов
/ 12 октября 2010

Зачем вам одномерный массив? Какова большая цель?

На что опираются любые рекомендации.

Обычно вы можете декодировать PNG в доступное для памяти растровое изображение (ImageIO.read() возвращает BufferedImage, что и есть) и просто обращаться к его пикселям напрямую ... как одномерный массив (используя BufferedImage.getRaster().getDataBuffer()) .

0 голосов
/ 12 октября 2010

использовать Java с готовностью ()

...