Java: создание изображения из двоичных данных (как данных изображения, так и цветовой палитры) - PullRequest
2 голосов
/ 14 января 2010

Я пытаюсь создать изображение из двоичного файла. Файл содержит значок 32x32 и соответствующую ему 16 цветовую палитру.

Спецификация


Значок имеет длину 512 байт. Значок разделен на плитки размером 4х4. Размер каждой плитки 4х8.

Вот расположение байтов 4x8 для одной плитки:

B B B B
B B B B
B B B B
B B B B
B B B B
B B B B
B B B B
B B B B

Вот биты, расширенные из вышеуказанных байтов:

11110000 11110000 11110000 11110000
00001111 00001111 00001111 00001111
11110000 11110000 11110000 11110000
00001111 00001111 00001111 00001111
11110000 11110000 11110000 11110000
00001111 00001111 00001111 00001111
11110000 11110000 11110000 11110000
00001111 00001111 00001111 00001111

Разбиение каждого байта на четыре пикселя каждый дает следующую плитку:

1111 0000 1111 0000 1111 0000 1111 0000
0000 1111 0000 1111 0000 1111 0000 1111
1111 0000 1111 0000 1111 0000 1111 0000
0000 1111 0000 1111 0000 1111 0000 1111
1111 0000 1111 0000 1111 0000 1111 0000
0000 1111 0000 1111 0000 1111 0000 1111
1111 0000 1111 0000 1111 0000 1111 0000
0000 1111 0000 1111 0000 1111 0000 1111

Каждый 4-битный является индексом цвета в палитре.

Цветовая палитра длиной 32 байта содержит 16 цветов. Каждый цвет составляет 16 бит (5 для каждого компонента, в то время как последний не используется).

Проблема - Шаг 1


Мне удалось разобрать данные изображения в массив из 512 байтов, а цветовую палитру - в массив из 32 байтов. Но я не совсем уверен, как продолжить дальше.

Я прочитал все байты данных изображения в BitSet, но я не уверен, что это даже полезно.

Кроме того, я не знаю, как создать цвет из двух байтов.

Любая помощь / предложения / комментарии?

Спасибо.

Проблема - Шаг 2


Итак, с вашей помощью я создал IndexColorModel из цветовой палитры следующим образом:

int[] colors = new int[16*3];
for (int i = 0; i < 16; i++) {
  byte b1 = this.palette[i]; // byte 1: 5 bits of R and 3 bits of G
  byte b2 = this.palette[i+1]; // byte 2: 2 bits of G and 5 bits of B and 0.

  // colors are encoded in inverse order
  colors[i+2] = (b2 & 0x3E) >>> // red
  colors[i+1] = ((b1 & 0x07) << 2) | ((b2 & 0xC0) >> 6); // green
  colors[i] = (b1 & 0xF8) >>> 3; // blue
}

IndexColorModel cm = new IndexColorModel(5, 16*3, colors, 0, false, 0, DataBuffer.TYPE_BYTE);

Теперь мне нужно создать BufferedImage из массива байтов, которые я прочитал из двоичного файла, используя вышеупомянутый IndexColorModel.

Пока у меня есть это:

  DataBuffer buffer = new DataBufferByte(this.titleData, 32*32);

  int pixelStride = 4; //assuming r, g, b, skip, r, g, b, skip...
  int scanlineStride = 4*32; //no extra padding   
  int[] bandOffsets = {0, 1, 2}; //r, g, b
  WritableRaster raster = Raster.createInterleavedRaster(buffer, 32, 32, scanlineStride, pixelStride, bandOffsets, null);

  boolean isAlphaPremultiplied = false;

  BufferedImage bim = new BufferedImage(cm, raster, isAlphaPremultiplied, null);

Взято из здесь .

this.titleData - это массив из 512 байтов, который считывается из двоичного файла.

Приведенный выше код выдает следующее исключение:

Причина: java.awt.image.RasterFormatException: массив данных слишком мал (должно быть 4094)

Любая помощь? Еще раз большое спасибо.

Ответы [ 4 ]

2 голосов
/ 14 января 2010

Класс javax.imageio.ImageIO и его родственники - это то, что вам нужно. По сути, пакет javax.imageio.

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

Обновление

Все еще жду вашего ответа, будь то файл ввода / вывода или просто локальное изображение. В то же время ...

Если вы посмотрите на класс java.awt.image.BufferedImage, вы увидите константы для кодирования некоторых обычных побитовых отображений, конструкторы для создания изображения из растра, методы настройки цветовой модели, настройки растр и т. д.

Возможно, вы также захотите взглянуть на достойное руководство по этому вопросу. Я пойду искать один ...

Чтобы ответить на вопрос о том, как отобразить два байта в цвет, посмотрите на java.awt.image.ColorModel и java.awt.image.ComponentColorModel. Я думаю, что второй - тот, который вы хотите.

1 голос
/ 14 января 2010

Я пробился через это некоторое время назад (используя материал java.awt.image), но теперь я потрясен, обнаружив, что забыл слишком много, чтобы оказать большую помощь.

Если у вас слишком много проблем с подходом Java API, я бы хотел ответить на ваш вопрос Майклу Брюеру-Дэвису:

Учитывая, что цвет составляет 16 бит с 5 битами для каждого компонента (последний не используется), не могли бы вы показать мне, как создать цвет. Имейте в виду, что я читаю данные из двоичных байтов. Это означает, что я разбираю всю цветовую палитру в массив из 32 байтов. Другими словами, мне нужно сначала соединить два байта для каждого цвета. Спасибо.

byte b1 = 0x??; // byte 1: 5 bits of R and 3 bits of G
byte b2 = 0x??; // byte 2: 2 bits of G and 5 bits of B and 0.

int r = (b1 & 0xF8) >>> 3;
int g = ((b1 & 0x07) << 2) | ((b2 & 0xC0) >>> 6);
int b = (b2 & 0x3E) >>> 1;

В каждом случае вы маскируете интересующие биты в байте, используя AND для числа, в котором установлены только эти биты (представленные в шестнадцатеричном виде, потому что с ним проще работать), а затем сдвигаете биты так, чтобы они в конечном итоге выровнены по правому краю в результате

Остальное легко:

Color c = new Color(r, g, b);
0 голосов
/ 14 января 2010

Если формат изображения общеизвестен, классы ImageIO могут работать или может быть поставщик услуг, который вы можете найти, чтобы проанализировать его из ImageIO. Если это пользовательский формат, вам нужно свернуть свой собственный.

Сначала вам нужно определить свою цветовую модель , т.е. определить, как 16-битные цвета отображаются в цвета реального мира. Скорее всего, это 15-битный RGB (555) или 16-битный RGB (565), но все возможно (например, 4444 ARGB, с некоторыми байтами, используемыми для альфа / прозрачности).

Как только вы это сделаете, самое простое - создать и заполнить BufferedImage на основе заданной вами структуры листов.

Что-то вроде:

BufferedImage image = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
byte[] imageData;

for (int i = 0; i < imageData.length; ++i) {
    int x = // figure out x based on tiling
    int y = // figure out y based on tiling

    byte highBits = (imageData[i] >> 4) & 0xF;
    Color c = getColor(highBits); // translate bits into RGB color model
    image.setRGB(x, y, c.getRGB());

    x = // figure out for second bits, probably x+1?
    y = // figure out for second bits, probably unchanged?

    byte lowBits = imageData[i] & 0xF;
    c = getColor(lowBits);
    image.setRGB(x, y, c.getRGB());
}

Вы также можете определить свою собственную ColorModel и определить свое изображение таким образом, особенно если это формат файла, который вы собираетесь широко использовать.

0 голосов
/ 14 января 2010

Как вы кодируете цвета? Вы можете использовать класс Color для создания цветных объектов из их компонентов.

Затем вы можете нарисовать группу прямоугольников 1x1 нужного цвета на графическом объекте, чтобы построить ваше изображение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...