给出一个白色和黑色的图像,没有灰色(在ARGB:0xFFFFFFFF0xFF000000中),我想用一种特定的 colored颜色 给黑色上色,而用另一种特定的 colored颜色 给白色上色.

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

    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);

它做到了这一点.但我对这个过程提出了质疑,因为它使用了大量的内存(每对 colored颜色 至少1KB),而且当我有数千张需要用不同 colored颜色 绘制的小图像时,创建它的速度相当慢.

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

我想知道这LookupOp有没有便宜又快的替代品.

推荐答案

下面是我在 comments 中概述的一个更详细的版本,假设黑白图像是1位图像和IndexColorModel位图像(如果不是,当然可以转换).考虑到这一点,我们可以只交换调色板或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 readAndBlue = 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(readAndBlue, bwImage.getRaster(), readAndBlue.isAlphaPremultiplied(), null);

现在,这两幅图像共享栅格,因此更改其中一幅图像也会更改另一幅图像.这在内存和CPU方面都非常便宜.但是,如果这不是您想要的,您可以在最后一行用bwImage.copyData(null)替换bwImage.getRaster(),以创建一个"分离的"副本.

你也可以为每一对 colored颜色 缓存IndexColorModel,就像你对上面的LookupOp所做的那样,但我不确定这是否值得(取决于你重复使用 colored颜色 对的频率).

Java相关问答推荐

表格栏上的事件过滤器在PFA中不起作用

ittext pdf延迟签名,签名无效

我无法将附件发送到NetBeans之外

如何在运行时动态创建表(使用Java、JPA、SprringBoot)

有没有办法让扩展变得多态?

无法使用ApacheSpark依赖项构建JavaFX应用程序

当Volatile关键字真的是必要的时候?

JOOQ中的子查询使用的是默认方言,而不是配置的方言

如何在Java记录中设置BigDecimal类型属性的精度?

使用Jolt将字段转换为列表

如何将其他属性引用到log4j2 yaml配置中?

使SLF4J在Android中登录到Logcat,在测试中登录到控制台(Gradle依赖问题)

使用正则表达式从字符串中提取多个值

try 在两个不同数组的数字之间求平均值

A.ForEach与For(类型a:集合)

无限递归Java问题

如何使用带有可选参数的类生成器?

如何使用Rascal Evaluator从编译的JAR访问Rascal函数?

为什么Spring要更改Java版本配置以及如何正确设置?

Java中的一个错误';s stdlib SocksSocketImpl?