2014-01-27 4 views
0

Я пытался кодировать некоторые данные (представленные в виде массива байтов 0-255) в формате изображения PNG с Java. Данные считываются с использованием метода HTML canvas getImageData() в JavaScript (аналогично этому: http://blog.nihilogic.dk/2008/05/compression-using-canvas-and-png.html).Java ImageIO PNG Кодирование Неправильно?

Однако выходные данные не всегда идентичны входным данным. Некоторые из значений, по-видимому, отличаются от ввода. Кажется, что кодирование работает как изображение с высоким разрешением 1 пиксель и является неправильным только для изображения с несколькими строками. У меня была идея, что это может быть вызвано поэтапной фильтрацией изображений PNG каким-то образом, но на самом деле не знаю.

кажется, что каждое неверное значение только когда-либо неправильно, 1 или 2.

Вот код Java, но я задаюсь вопросом, если она также может быть проблема с апи ImageIO, в частности, его PNG кодер?

public static File encodeInPng(byte[] data, String filename) throws java.io.IOException{ 
    int width = (int)Math.ceil(Math.sqrt(data.length)); 
    int height = (int)Math.ceil((double)data.length/width); 

    BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); 

    int x = 0, y = 0; 
    for (byte b : data) { 
     bufImg.getRaster().setPixel(x, y, new int[]{b&0xFF}); 
     x++; 
     if (x == width) { 
      x = 0; 
      y ++; 
     } 
    } 

    File f = new File(filename); 
    ImageIO.write(bufImg, "png", f); 

    return f; 
} 

Edit: Проблема возникает только для PNG файлов в течение определенного размера (около 50 килобайтов, или, возможно, 256x256px).

+0

um, Я думаю, что вы действительно не хотите тегировать JavaScript. Удаленные. –

+0

'y = 0;' похоже на ошибку. Может быть, вы имели в виду 'x = 0;'? – Obicere

+0

Вы правы, хотя исходный код был прав (я изменил некоторые имена переменных при публикации, чтобы сделать более читаемыми). – user2272952

ответ

0

Хорошо, поэтому я обнаружил, что проблема возникла только для изображений размером более 256x256. Я немного исследовал и обнаружил существующие (хотя и разные) проблемы, с которыми люди сталкивались в Chrome (с элементом холста и изображением этого размера). Поэтому я попытался использовать Firefox и никаких ошибок!

Похоже, что элемент холста Chrome далек от совершенства.

[Использование Chrome Версия 32.0.1700.77]

Edit: Кроме того, установка хром: // флаги "Отключить ускоряются 2D холст" делает его работу в Chrome.

0

Расчеты размеров довольно уродливые, а некоторые части кода могут быть немного более эффективными и чистыми - некоторые полировки появляются ниже. Но ваш код кажется в основном правильным, и он работает для меня. Можете ли вы передать пример, где «выходные данные не идентичны входным данным»?

public static File encodeInPng(byte[] data, String filename) 
     throws java.io.IOException { 
    int width = (int) Math.ceil(Math.sqrt(data.length)); 
    int height = data.length/width; 
    BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); 
    int[] pix = new int[1]; 
    int pos = 0; 
    for(int y = 0; y < height; y++) { 
     for(int x = 0; x < width; x++) { 
      pix[0] = data[pos++] & 0xFF; 
      bufImg.getRaster().setPixel(x, y, pix); 
     } 
    } 
    File f = new File(filename); 
    ImageIO.write(bufImg, "png", f); 
    return f; 
} 
+1

Является ли это (слегка) более безопасным для определения «высоты = (data.length + width-1)/width'?Тогда вы уверены, что буфер назначения достаточно велик. В настоящее время, если 'data.length% width> 0', вы пропустите целую строку, не так ли? Но да, я бы хотел заглянуть в PNG с простым кодированным сообщением. – usr2564301

Смежные вопросы