使用IndexColorModel将光栅转换为BufferedImage

时间:2014-04-13 14:27:48

标签: bufferedimage java-2d javax.imageio raster color-mapping

我正在尝试使用ImageIO从DICOM文件中仅使用一个波段来呈现来自Raster的图像。我不想使用ImageIO直接读取缓冲的图像,因为我需要文件中的实际值(直接用ImageIO获得的BufferedImage中包含的栅格总是有点不同,并标准化为(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);

然后,使用自定义IndexColorModel将其转换为BufferedImage:

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有关。当我在位数中使用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的数字时,我没有得到错误但是显示的图像没有正确的强度。最高和最低值仅以黑色显示。

我发现问题出在数据类型和通道数量上,但是我在盘旋,我不知道Raster如何使用IndexColorModel以及如何使它们兼容。

在理解了这个问题之后,我可以更自由地从光栅中的像素值创建其他色阶。

有经验的人吗?

由于

1 个答案:

答案 0 :(得分:1)

现在就解决了。唯一的大问题是indexcolormodel需要足够大才能映射所有值。如果栅格包含的某个值大于映射值数组的大小,则colormodel只返回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));
}