Растр в BufferedImage с использованием IndexColorModel

Я пытаюсь представить изображение из растра только с одной полосой, полученной из файла DICOM с помощью ImageIO. Я не хочу напрямую читать буферизованное изображение с помощью ImageIO, потому что мне нужны реальные значения из файла (растр, включенный в BufferedImage, полученный непосредственно с помощью ImageIO, всегда немного отличается и нормализован до (0-255)).

Для получения растра я использую следующий код:

Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM");
ImageReader reader = iter.next();
DicomImageReadParam param = (DicomImageReadParam) reader.getDefaultReadParam();
ImageInputStream iis = ImageIO.createImageInputStream(dicomFile);
reader.setInput(iis, true);
Raster raster = reader.readRaster(0, param);

Затем, чтобы преобразовать его в BufferedImage с пользовательской IndexColorModel:

IndexColorModel colModel = grayColorModel(window, level);
BufferedImage buffered = new BufferedImage(colModel, (WritableRaster) raster, colModel.isAlphaPremultiplied(), null);

используя следующую функцию для построения IndexColorModel:

public IndexColorModel grayColorModel(int window, float level) {
    window = window;
    byte[] r = new byte[window];
    byte[] g = new byte[window];
    byte[] b = new byte[window];

    for (int i = 0; i < window; i++) {
        int val = (int) Math.round((255 - level) * 2 * i / window + 2 * level - 255);
        if (val > 255) {
            val = 255;
        }
        if (val < 0) {
            val = 0;
        }
        r[ i] = (byte) val;
        g[ i] = (byte) val;
        b[ i] = (byte) val;
    }

    return (new IndexColorModel(**NR OF BITS**, window, r, g, b));
}

Проблема, которая у меня есть, как-то связана с привязкой информации из растра, который имеет только один канал, к IndexColorModel, который имеет 3. Когда я использую 8 в количестве бит, типы данных просто не совпадают, и я получаю следующее ошибка:

java.lang.IllegalArgumentException: Raster ShortInterleavedRaster: width = 512 height = 512 #numDataElements 1 is incompatible with ColorModel IndexColorModel: #pixelBits = 8 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@28ec9a1a transparency = 1 transIndex   = -1 has alpha = false isAlphaPre = false
    at java.awt.image.BufferedImage.<init>(BufferedImage.java:630)

Когда я использую число больше 8, я не получаю ошибку, но представленное изображение имеет неправильную интенсивность. Самые высокие и самые низкие значения отображаются просто черным цветом.

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

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

У кого есть опыт в этом?

Спасибо


person npb    schedule 13.04.2014    source источник
comment
Это уже было решено   -  person npb    schedule 13.04.2014


Ответы (1)


Просто решил это сейчас. Единственная большая проблема заключается в том, что модель indexcolormodel должна быть достаточно большой, чтобы отобразить все значения. Если растр содержит какое-то значение, превышающее размер массивов отображаемых значений, цветовая модель просто возвращает 0, и вместо белого пятна на изображении появляется темное пятно. Затем вы просто получаете максимальное значение и делаете палитру достаточно большой. Надеюсь, это убережет других от потери времени на такую ​​простую вещь...

Учитывая это, окончательный код для IndexColorModel выглядит так:

public IndexColorModel grayColorModel(int window, float level, int maxval) {
    int length = window;
    if (maxval > window) {
        length = maxval;
    }

    byte[] r = new byte[length];
    byte[] g = new byte[length];
    byte[] b = new byte[length];

    for (int i = 0; i < length; i++) {
        int val = Math.round((255 / (float) window) * ((float) i - level + (float) window * 0.5f));
        if (val > 255) {
            val = 255;
        }
        if (val < 0) {
            val = 0;
        }
        r[ i] = (byte) val;
        g[ i] = (byte) val;
        b[ i] = (byte) val;
    }
    return (new IndexColorModel(16, length, r, g, b));
}
person npb    schedule 14.04.2014
comment
Я думаю, это работает, но, может быть, другим вариантом будет использование модели серого цвета? - person Harald K; 14.04.2014
comment
Возможно, есть и другие более простые способы создания кастомных шкал, но я их не нашел. В моем случае я хотел сохранить значения в растре и просто изменить их интерпретацию. После того, как это работает, легче создавать новые индивидуальные шкалы. - person npb; 14.04.2014