删除图像 JAVA 中的空白 space
Remove blank space in image JAVA
我有一个关于剪切图像中的空白 space(或只是裁剪)的问题。我想要这样的方法:
public BufferedImage crop(BufferedImage input) {
return output;
}
它应该这样做:
我知道我可以遍历所有像素以获得新的边界,但是对于图像 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);
}
此方法仅适用于 alpha。要使用 "jpg",您需要更改此处的条件(此处为 true 表示当前像素不为空):
if (raster.getPixel(x, y, (int[]) null)[3] != 0)
我很惊讶,但这种方法工作得非常快(裁剪 1024x768 图像需要 70-100 毫秒)。我还对 5000x5000 图像进行了测试,不幸的是,这种方法在这种情况下非常慢(1000-1500 毫秒)。
它针对每个 y 坐标将图像分成垂直线。然后它在这一行中寻找非空白像素。如果没有找到空白像素,它会转到下一行,但如果找到它,它会寻找 minX 和 maxX。此外,如果 minY 尚未定义,它会定义它并且 bool "minYIsDefined" 为真。但是,如果已经定义了 minY,则它会定义 maxY。
编辑:
正如评论中所建议的那样 (thx FiReTiTi),使用 'getSample()' 方法我们可以走得更快。这是因为 'getPixel()' 方法使用 'getSample()' 方法使它成为数组 3-4 次(取决于图像类型)。所以新的条件看起来像这样:
if (raster.getSample(x, y, 3) != 0)
我的测试表明裁剪 1024x768 图像所花费的时间为 10-30 毫秒。在 5000x5000 图像的情况下,时间为 100-300 毫秒。
希望对大家有所帮助:)
我有一个关于剪切图像中的空白 space(或只是裁剪)的问题。我想要这样的方法:
public BufferedImage crop(BufferedImage input) {
return output;
}
它应该这样做:
我知道我可以遍历所有像素以获得新的边界,但是对于图像 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);
}
此方法仅适用于 alpha。要使用 "jpg",您需要更改此处的条件(此处为 true 表示当前像素不为空):
if (raster.getPixel(x, y, (int[]) null)[3] != 0)
我很惊讶,但这种方法工作得非常快(裁剪 1024x768 图像需要 70-100 毫秒)。我还对 5000x5000 图像进行了测试,不幸的是,这种方法在这种情况下非常慢(1000-1500 毫秒)。
它针对每个 y 坐标将图像分成垂直线。然后它在这一行中寻找非空白像素。如果没有找到空白像素,它会转到下一行,但如果找到它,它会寻找 minX 和 maxX。此外,如果 minY 尚未定义,它会定义它并且 bool "minYIsDefined" 为真。但是,如果已经定义了 minY,则它会定义 maxY。
编辑:
正如评论中所建议的那样 (thx FiReTiTi),使用 'getSample()' 方法我们可以走得更快。这是因为 'getPixel()' 方法使用 'getSample()' 方法使它成为数组 3-4 次(取决于图像类型)。所以新的条件看起来像这样:
if (raster.getSample(x, y, 3) != 0)
我的测试表明裁剪 1024x768 图像所花费的时间为 10-30 毫秒。在 5000x5000 图像的情况下,时间为 100-300 毫秒。
希望对大家有所帮助:)