Если я правильно понял вопрос, вы пытаетесь преобразовать поток данных выборки байтов в BufferedImage
.
Чтобы уточнить несколько вещей, 4-байтовый/пиксел изображения представляет собой 32-бит/пиксель изображения (как 4 * 8 32), однако фактические цветовые компоненты могут только охватывают 24-бит (3 байта) так как для Alpha (прозрачность) остается один 8-битный компонент. Учитывая этот факт, совершенно нормально иметь 24-битное изображение с 8 бит на цветной канал и альфа-канал (где изображение тогда будет 3-байтовым/пиксельным изображением).
Причина, по которой вы получаете исключение несовместимости, заключается в том, что вы используете неправильный метод для создания своего WritableRaster.
Учитывая, что ваш ввод данных в виде массива байтов, и что вы пытаетесь создать изображение, где каждый байт хранит не весь пиксель, но образец пикселя метод createPackedRaster()
сразу считается неподходящим метод рассматривает каждый элемент данных (т. е. каждый байт) как свой собственный пиксель, который определенно не является тем, что вы пытаетесь выполнить здесь.
Чтобы определить, какие из методов «создать» вам нужно использовать, вам необходимо определить формат входящих данных.
три основных типов кодирования образца показан ниже:
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()
, и он должен (возможно, я ошибаюсь здесь) работает одинаково.
4 байта - это 32-разрядное изображение. –