2014-01-03 2 views
0

У меня есть изображение, в котором каждый пиксель составляет 4 байта, т. Е. Красная маска равна 0xFF0000, зеленый - 0xFF00 и синий 0xFF. Я прочитал в изображение и передать его функции в качестве функции (байт imgBuff, Int W, внутр ч) тогда яПопытка рисовать 24-битное изображение в Java

void fun(byte imgBuff,int w,int h) 
    { 
     Graphics g; 
     BufferedImage img; 
     DataBuffer dBuffer = new DataBufferByte(imgBuff, w * h); 
     WritableRaster wr = Raster.createPackedRaster(dBuffer,w,h,24,null); 
     DirectColorModel dcm = new DirectColorModel(24,0xFF0000,0xFF00,0xFF); 
     img = new BufferedImage(dcm,wr,false,null); 
     g = getGraphics(); 
     g.drawImage(img,x,y,w,h,null); 
    } 

Но когда я бегу я получаю

Исключение в потоке " Thread-23" java.lang.IllegalArgumentException: растровый [email protected] несовместима с ColorModel DirectColorModel: rmask = ff0000 gmask = ff00 bmask = ФФ amask = 0

Как я перехожу из bytebuffer через PackedRaster в буферное изображение для 24 бит в течение четырех байтов

+3

4 байта - это 32-разрядное изображение. –

ответ

3

Если я правильно понял вопрос, вы пытаетесь преобразовать поток данных выборки байтов в BufferedImage.

Чтобы уточнить несколько вещей, 4-байтовый/пиксел изображения представляет собой 32-бит/пиксель изображения (как 4 * 8 32), однако фактические цветовые компоненты могут только охватывают 24-бит (3 байта) так как для Alpha (прозрачность) остается один 8-битный компонент. Учитывая этот факт, совершенно нормально иметь 24-битное изображение с 8 бит на цветной канал и альфа-канал (где изображение тогда будет 3-байтовым/пиксельным изображением).

Причина, по которой вы получаете исключение несовместимости, заключается в том, что вы используете неправильный метод для создания своего WritableRaster.

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

Чтобы определить, какие из методов «создать» вам нужно использовать, вам необходимо определить формат входящих данных.

три основных типов кодирования образца показан ниже:

Image Sample Encoding Demonstration

Image Source amor.cms.hu-berlin.de

Они диапазон последовательный формат (BSQ), диапазон перемежается Pixel Format (BIP) и Band Interleaved по линейному формату (bil). На изображении показано, как может быть закодировано трехмерное изображение образца. Для простоты мы рассмотрим только последние два (BIP и BIL), поскольку BSQ редко используется (, насколько я знаю).

Если данные изображения проходят в формате BIP, также просто знают, как чередуются пиксели, вам нужно будет использовать метод для чтения входных данных. Как указано в документации:

Создает растр на основе PixelInterleavedSampleModel с указанным типом данных.

Другой фактор, который мы должны определить, что если байт данных, проходящий через содержит альфа, по существу, является ли данные изображения, как этот (при условии, BIP):

RGBRGB ....

или

RGBARGBA ....

Поскольку существует много перегруженных методов, использующих разные параметры, мы будем использовать тот, который принимает тип данных, ширину, высоту, полосы и местоположение.

Для типа данных мы будем использовать константу DataBuffer.TYPE_BYTE, так как мы вводим массив байтов.

Ширина и высота поставляются нашими параметрами метода, здесь нет ничего смешного.

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

Заявление будет выглядеть следующим образом:

//Replace '4' with '3' if your image doesn't have alpha 
WritableRaster wr = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null); 

Следующая часть, чтобы беспокоиться о том является ColorModel. Поскольку мы больше не используем метод createPackedRaster(), нам необходимо изменить тип нашей ColorModel, а также на ComponentColorModel. Поскольку это становится немного длинным, я просто покажу вам, что я сделал (пожалуйста, прочитайте только documentation).

Как следует:

ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB); 

//Change the first 'true' to 'false' if you don't have alpha. 
ComponentColorModel ccm = new ComponentColorModel(sRGB, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); 

Теперь, монтаж все это вместе:

void fun(byte[] imgBuff,int w,int h) throws IOException{ 
    WritableRaster wr = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null); 

    wr.setDataElements(0, 0, w, h, imgBuff); 

    ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB); 

    ComponentColorModel ccm = new ComponentColorModel(sRGB, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); 

    BufferedImage img = new BufferedImage(ccm, wr, false, null); 
} 

Вы заметите, я добавил строку wr.setDataElements(0, 0, w, h, imgBuff). Эта строка эффективно делает фактическую совокупность данных в WritableRaster напрямую с использованием массива байтов (нет необходимости создавать объект DataBufferByte).

Ранее я говорил о BIP и BIL. Изменение метода выше от BIP до BIL должно так же просто, как замена метода createInterleavedRaster() на createBandedRaster(), и он должен (возможно, я ошибаюсь здесь) работает одинаково.

+0

Хорошо, у меня почти такая работа, но не в состоянии сортировать цветную сторону вещей. У меня есть BandedRaster, а порядок байтов - один байт Alpha, за которым следует один байт Red, за которым следует один байт Green, за которым следует один байт Blue. Но цвет не получается правильным, например, если мои данные имеют 0x00FFFFFF, тогда он должен быть белым, когда его выходившая бирюза –

+0

Код выглядит следующим образом WritableRaster wr = Raster.createBandedRaster (DataBuffer.TYPE_BYTE, w, h, 4, null); wr.setDataElements (0, 0, w, h, imgBuff); ColorSpace sRGB = ColorSpace.getInstance (ColorSpace.CS_sRGB); ComponentColorModel ccm = new ComponentColorModel (sRGB, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); img = new BufferedImage (ccm, wr, false, null); –

+0

@ user2873619 Просто укажите, если ваши данные поступают как «ARGB», тогда его пиксель чередуется не с BIL (который будет отображаться как «AARRGGB B ...» (для изображения шириной 2 пикселя). Абсолютно необходимо использовать «WritableRaster's» Я лично придерживаюсь простых для циклов манипуляции изображениями. Еще одна вещь, указывающая на то, что входные данные 0x00, 0xFF, 0xFF, 0xFF не будут белыми, потому что альфа - 0 (полностью прозрачная). Причина, по которой вы видите некоторые Нечетный цвет заключается в том, что цветовое пространство 'sRGB' определяет данные в формате' RGBA'. Таким образом, ваша альфа отображается на красный, красный на зеленый и т. д. – initramfs

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