为双色图像着色的 LookupOp 内存高效替代方案?

问题描述 投票:0回答:1

给定一张白色和黑色的图像,没有灰色(在 ARGB 中:

0xFFFFFFFF
0xFF000000
),我想将黑色着色为特定颜色,将白色着色为另一种特定颜色。

为此,我目前使用以下代码:

    private LookupOp createLookupOp(Color foreground, Color background) {
        var lookupTable = new byte[4][256];

        var fg = foreground.getRGB();
        Arrays.fill(lookupTable[0], (byte) (fg >> 16));
        Arrays.fill(lookupTable[1], (byte) (fg >> 8));
        Arrays.fill(lookupTable[2], (byte) (fg));
        Arrays.fill(lookupTable[3], (byte) (fg >> 24));

        var bg = background.getRGB();
        lookupTable[0][0] = (byte) (bg >> 16);
        lookupTable[1][0] = (byte) (bg >> 8);
        lookupTable[2][0] = (byte) (bg);
        lookupTable[3][0] = (byte) (bg >> 24);

        return new LookupOp(new ByteLookupTable(0, lookupTable), null);
    }

然后我可以这样使用它:

var lookup = lookups.computeIfAbsent(colorPair, colors -> createLookupOp(colors.foreground, colors.background));
var coloredImage = lookup.filter(originalImage, null);
graphics2d.drawImage(coloredImage, originalWidth, originalHeight, null);

它完成了工作。但我质疑这个过程,因为它使用大量内存(每个颜色对至少 1kb),而且当我有数千张需要用不同颜色绘制的迷你图像时,创建速度相当慢。

为了加快速度,我将结果存储在地图中,但即便如此,在应用程序运行结束时我的地图中仍然有大约 200,000 个项目,大约 200 MB 存储在我的地图中。

我想知道是否有便宜又快速的替代品

LookupOp
.

java swing image-processing awt
1个回答
2
投票

这是我在评论中概述的想法的更详细版本,假设黑白图像是带有

IndexColorModel
的 1 位图像(如果不是,当然可以转换)。鉴于此,我们可以交换调色板或
IndexColorModel
,让图像立即重新着色。

代码看起来像这样:

// The original B/W image
IndexColorModel blackAndWhite = new IndexColorModel(1, 2, new int[] {0x000000, 0xFFFFFF}, 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage bwImage = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, blackAndWhite);

// A new color pair
Color red = Color.RED;
Color blue = Color.BLUE;

// Create a palette from the color pair
IndexColorModel redAndBlue = new IndexColorModel(1, 2, new int[] {red.getRGB(), blue.getRGB()}, 0, false, -1, DataBuffer.TYPE_BYTE);

// And finally a new two-colored image from the original image, using the new palette
BufferedImage rbImage = new BufferedImage(redAndBlue, bwImage.getRaster(), reaAndBlue.isAlphaPremultiplied(), null);

现在,两张图片共享光栅,所以改变一张也会改变另一张。这在内存和 CPU 方面非常便宜。但是,如果不需要,您可以在最后一行将

bwImage.getRaster()
替换为
bwImage.copyData(null)
,以创建“分离”副本。

您还可以为每对颜色缓存

IndexColorModel
s,就像您对上面的
LookupOp
s 所做的那样,但我不确定这是否值得(取决于您重复使用颜色对的频率)。

© www.soinside.com 2019 - 2024. All rights reserved.