将具有特定颜色的 BufferedImage 像素转换为区域的快速方法

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

我正在使用 Java 制作一个图像编辑应用程序,并且想要制作一个按颜色选择工具。按颜色选择工具使我的变量

selection
Area
的子类)根据所选图像中的像素是否为特定颜色(
int
)来突出显示它们。在此代码片段中,
selectedImage
是用于创建
Area
的BufferedImage。

int selectedColor = selectedImage.getRGB(...based on MouseEvent...);
for(int x = 0 ; x < selectedImage.getWidth() ; x++){
    for(int y = 0 ; y < selectedImage.getHeight() ; y++){
        if(selectedImage.getRGB(x, y) == selectedColor){
            selection.add(new Area(new Rectangle(x, y, 1, 1)));
        }
    }
}

我在 StackOverflow 或 Oracle 文档中没有真正找到任何有用的内容来解决我的问题。我找到了

LookUpOp
,它几乎能够满足我的需求,但它只能通过转换
BufferedImage
来工作,而我无法将其变成
Area

此代码可以工作,但是速度太慢,无法成为使该工具工作的可接受方式。

java bufferedimage area
1个回答
0
投票

我编写了一个脚本来对此进行分析。我发现与更新区域相比,RGB 查找和迭代顺序无关紧要。正如您所建议的 Path2D 可以显着改善结果。

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;

public class PixelPaths {
    static class Result{
        Path2D p = new Path2D.Double();
        public void add(Shape s){
            p.append(s, false);
        }
        public Area build(){
            return new Area(p);
        }
    }
    static int w = 512;
    static int h = 512;

    public static void main(String[] args){
        BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

        Graphics2D g = (Graphics2D)img.getGraphics();
        g.setColor(Color.BLUE);
        g.fillRect(w/10, h/10, w/8, h/8);
        g.fillRect( w/4, h/4, w/2, h/2);
        Result result = new Result();
        long start = System.nanoTime();
        int chosen = img.getRGB(w/2, h/2);
        for(int j = 0; j<h; j++){
            for(int i = 0; i<w; i++){
                int p = img.getRGB(i, j);
                if(p == chosen){
                    result.add( new Area(new Rectangle(i, j, 1, 1)));
                }
            }
        }
        Area finished = result.build();
        long finish = System.nanoTime();

        System.out.println("iterated in: " + (finish - start)/1e9  + " seconds");

        g.setColor(Color.RED);
        g.draw(finished);
        g.dispose();
        JLabel label = new JLabel(new ImageIcon(img));
        JFrame frame = new JFrame("Vector to Path");
        frame.add(label);
        frame.pack();
        frame.setVisible(true);
    }
}

512x512 的运行时间从 4.5 秒缩短到不到一秒。它似乎随着更大的图像线性缩放。 2048 x 2048 大约需要 1.3 秒。

更改迭代顺序,即在外循环中迭代 j 并没有对查找速度产生任何影响,但在创建区域之后却起到了作用。

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