首页 > 解决方案 > 在java中区分16位和8位grascale图像

问题描述

我正在尝试读取 .png grayscaleimages 并将灰度值转换为 double[][]数组。我需要将它们映射到 0 到 1 之间的值。

我使用的是 BufferedImage,我试图找出使用的颜色深度,img.getColorModel().getColorSpace().getType()但返回的 TYPE_5CLR 或 TYPE_6CLR 通用组件颜色空间没有帮助。

目前我正在阅读这样的值:

BufferedImage img = null;
        try {
            img = ImageIO.read(new File(path));
        } catch (IOException e) {
            return null;
        }

        double[][] heightmap= new double[img.getWidth()][img.getHeight()];
        WritableRaster raster = img.getRaster();
        for(int i=0;i<heightmap.length;i++)
        {
            for(int j=0;j<heightmap[0].length;j++)
            {
                heightmap[i][j]=((double) raster.getSample(i,j,0))/65535.0;
            }
        }

如果 65535 是 8 位的,那么它应该是 256,但我不知道什么时候。

标签: javaimage-processing

解决方案


我在评论中写道,您可以使用ColorModel.getNormalizedComponents(...),但由于它使用float值并且不必要的复杂,因此实现这样的转换可能更容易:

BufferedImage img;
try {
    img = ImageIO.read(new File(path));
} catch (IOException e) {
    return null;
}

double[][] heightmap = new double[img.getWidth()][img.getHeight()];

WritableRaster raster = img.getRaster();

// Component size should be 8 or 16, yielding maxValue 255 or 65535 respectively
double maxValue = (1 << img.getColorModel().getComponentSize(0)) - 1;

for(int x = 0; x < heightmap.length; x++) {
    for(int y = 0; y < heightmap[0].length; y++) {
        heightmap[x][y] = raster.getSample(x, y, 0) / maxValue;
    }
}

return heightmap;

请注意,上述代码仅适用于灰度图像,但这似乎是您的输入。所有颜色分量的分量大小可能相同getComponentSize(0)getSample(x, y, 0).

PS:为了清楚起见x,我重命名了您的变量y。如果您交换高度图中的尺寸并x在内部循环中循环,而不是y由于更好的数据局部性,您很可能会获得更好的性能。


推荐阅读