删除JAVA图像中的空白 我有一个关于在图像中切割空白空间的问题(或者只是裁剪它)。我想要一个这样的方法: public BufferedImage crop(BufferedImage input) { return output; } if (raster.getSample(x, y, 3) != 0)

删除JAVA图像中的空白 我有一个关于在图像中切割空白空间的问题(或者只是裁剪它)。我想要一个这样的方法: public BufferedImage crop(BufferedImage input) { return output; } if (raster.getSample(x, y, 3) != 0),java,swing,bufferedimage,Java,Swing,Bufferedimage,它应该做到这一点: 我知道我可以遍历所有像素以获得新边界,但对于图像1024x768,我必须遍历1024*768=786432(乘以2,因为我必须第一次遍历以获得高度边界,第二次遍历以获得宽度边界)像素。这不是一个好办法。有没有办法快速做到这一点?(如果可能的话,我不想使用任何额外的线程或任何额外的框架) 谢谢大家! 我想了很多,想出了这个方法 public static BufferedImage crop(BufferedImage image) { int minY = 0, m

它应该做到这一点:

我知道我可以遍历所有像素以获得新边界,但对于图像1024x768,我必须遍历1024*768=786432(乘以2,因为我必须第一次遍历以获得高度边界,第二次遍历以获得宽度边界)像素。这不是一个好办法。有没有办法快速做到这一点?(如果可能的话,我不想使用任何额外的线程或任何额外的框架)


谢谢大家!

我想了很多,想出了这个方法

public static BufferedImage crop(BufferedImage image) {
    int minY = 0, maxY = 0, minX = Integer.MAX_VALUE, maxX = 0;
    boolean isBlank, minYIsDefined = false;
    Raster raster = image.getRaster();

    for (int y = 0; y < image.getHeight(); y++) {
        isBlank = true;

        for (int x = 0; x < image.getWidth(); x++) {
            //Change condition to (raster.getSample(x, y, 3) != 0) 
            //for better performance
            if (raster.getPixel(x, y, (int[]) null)[3] != 0) {
                isBlank = false;

                if (x < minX) minX = x;
                if (x > maxX) maxX = x;
            }
        }

        if (!isBlank) {
            if (!minYIsDefined) {
                minY = y;
                minYIsDefined = true;
            } else {
                if (y > maxY) maxY = y;
            }
        }
    }

    return image.getSubimage(minX, minY, maxX - minX + 1, maxY - minY + 1);
}
我很惊讶,但这种方法的工作速度非常快(裁剪1024x768图像需要70-100毫秒)。我还在5000x5000图像上测试了它,不幸的是,这种方法在这种情况下非常慢(1000-1500毫秒)

它将图像划分为每个y坐标的垂直线。然后在这一行中查找非空白像素。如果未找到空白像素,则转到下一行,但如果找到,则查找minX和maxX。另外,如果minY还没有定义,它就定义了它,bool“minYIsDefined”就变成了真。但如果已经定义了minY,那么它就定义了maxY

编辑

正如在coments(thx FiReTiTi)中所建议的,使用“getSample()”方法,我们可以走得更快。这是因为“getPixel()”方法使用“getSample()”方法将其数组设置为3-4次(取决于图像类型)。因此,新的条件如下所示:

public BufferedImage crop(BufferedImage input) {
    return output;
}
if (raster.getSample(x, y, 3) != 0) 
我的测试表明,croping 1024x768图像所需的时间为10-30毫秒。在5000x5000图像的情况下,图像时间为100-300毫秒


希望它能帮助某些人:)

计算机速度很快,浏览1024 x 768像素图像的所有像素不会花费很多时间。除此之外,还有比扫描所有像素两次更聪明的方法——只需扫描到找到非白色像素,而不需要对水平和垂直像素分别进行扫描。使用getSample()而不是getPixel可以更快,使用DataBuffer(直接访问像素)可以更快。小心,image.getSubimage返回具有相同光栅的子图像,因此如果您修改它,您也将修改原始图像。@FiReTiTi“小心,image.getSubimage返回具有相同光栅的子图像,因此如果您修改它,您也将修改原始图像。”那么我如何防止这种情况?复制光栅并创建图像的新实例?这不会影响速度吗?@FiReTiTi刚刚测试过。子图像的光栅是原始光栅的副本。Raster.createWritableChild()创建新对象。@FiReTiTi感谢您介绍getSample()方法)它确实更快(第一次测试是14毫秒)我通常创建一个所需(裁剪)尺寸的新图像,然后使用DataBuffer和System.arraycopy将原始图像裁剪复制到结果图像中。真的很快。