裁剪图像的透明边缘
Crop transparent edges of an image
我正在尝试创建一个函数,该函数仅从右侧和左侧裁剪 BufferedImage
的透明边缘。
所以,我在网上找到了这个方法,但是我不太明白 pixels[]
数组填充的是什么?我假设它是每个像素的 alpha、红色、绿色、蓝色值(根据 (j*width+i)*4
中的 4
判断,它选择每四个元素),但这个数组的长度是 299208
用于 68x67
图像(我知道它不是 2 的幂,请忽略它)。
那么,我该如何完成这个,我很好奇这个像素阵列中实际存储了什么?
public static BufferedImage trimHorizontally(BufferedImage img) {
final byte[] pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData();
int width = img.getWidth(), height = img.getHeight();
int x0, x1;
int j, i;
leftLoop:
for(i = 0; i < width; i++) {
for(j = 0; j < height; j++) {
if(pixels[(j*width+i)*4] != 0) {
break leftLoop;
}
}
}
x0 = i;
rightLoop:
for(i = width-1; i >= 0; i--) {
for(j = 0; j < height; j++) {
if(pixels[(j*width+i)*4] != 0) {
break rightLoop;
}
}
}
x1 = i+1;
return img.getSubimage(x0, 0, x1-x0, height);
}
我在上面的代码中基本上做的是从左侧和右侧扫描图像,检查 alpha 值并标记我需要裁剪的距离,但它会抛出异常,因为循环在没有检测到任何不透明像素的情况下完成(我正在裁剪的图像肯定不是透明的)。
我检查了一下,发现大于0
的alpha值实际上在pixels[]
数组的35000
的索引之上,并且(j*width+i)*4
计算我只能达到18000
.....
快速修复
您可以使用以下方式制作像素:
final int[] pixels = ((DataBufferInt)img.getAlphaRaster().getDataBuffer()).getData();
并删除 (j*width+i)*4
中的 *4
。这只会让您的 pixels[]
只包含 alpha 值,而不包含 RGB。
然而,有一个更安全(没有不安全的 DataBuffer
转换)、更易读的解决方案:
首选版本
我所做的更改是停止使用可怕的 byte
数组,并简单地使用 getRGB()
method instead. The alpha value can be gotten by creating a Color
using the RGB+alpha constructor, and then the getAlpha()
方法。
现在以下代码对我有用:
public static BufferedImage trimHorizontally(BufferedImage img) {
int width = img.getWidth(), height = img.getHeight();
int x0, x1;
int j, i;
int alpha;
leftLoop:
for(i = 0; i < width; i++) {
for(j = 0; j < height; j++) {
if(new Color(img.getRGB(i, j), true).getAlpha() != 0) {
break leftLoop;
}
}
}
x0 = i;
rightLoop:
for(i = width-1; i >= 0; i--) {
for(j = 0; j < height; j++) {
if(new Color(img.getRGB(i, j), true).getAlpha() != 0) {
break rightLoop;
}
}
}
x1 = i+1;
return img.getSubimage(x0, 0, x1-x0, height);
}
备注:
img
必须是 TYPE_INT_ARGB
, or some other type that keeps it's alpha value in the last byte of getRGB()
's data (if you don't know what this means, just try the above code and if it doesn't work covert to ARGB 类型。)
还要确保使用 image format that supports transparency(不是 JPG)。
我正在尝试创建一个函数,该函数仅从右侧和左侧裁剪 BufferedImage
的透明边缘。
所以,我在网上找到了这个方法,但是我不太明白 pixels[]
数组填充的是什么?我假设它是每个像素的 alpha、红色、绿色、蓝色值(根据 (j*width+i)*4
中的 4
判断,它选择每四个元素),但这个数组的长度是 299208
用于 68x67
图像(我知道它不是 2 的幂,请忽略它)。
那么,我该如何完成这个,我很好奇这个像素阵列中实际存储了什么?
public static BufferedImage trimHorizontally(BufferedImage img) {
final byte[] pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData();
int width = img.getWidth(), height = img.getHeight();
int x0, x1;
int j, i;
leftLoop:
for(i = 0; i < width; i++) {
for(j = 0; j < height; j++) {
if(pixels[(j*width+i)*4] != 0) {
break leftLoop;
}
}
}
x0 = i;
rightLoop:
for(i = width-1; i >= 0; i--) {
for(j = 0; j < height; j++) {
if(pixels[(j*width+i)*4] != 0) {
break rightLoop;
}
}
}
x1 = i+1;
return img.getSubimage(x0, 0, x1-x0, height);
}
我在上面的代码中基本上做的是从左侧和右侧扫描图像,检查 alpha 值并标记我需要裁剪的距离,但它会抛出异常,因为循环在没有检测到任何不透明像素的情况下完成(我正在裁剪的图像肯定不是透明的)。
我检查了一下,发现大于0
的alpha值实际上在pixels[]
数组的35000
的索引之上,并且(j*width+i)*4
计算我只能达到18000
.....
快速修复
您可以使用以下方式制作像素:
final int[] pixels = ((DataBufferInt)img.getAlphaRaster().getDataBuffer()).getData();
并删除 (j*width+i)*4
中的 *4
。这只会让您的 pixels[]
只包含 alpha 值,而不包含 RGB。
然而,有一个更安全(没有不安全的 DataBuffer
转换)、更易读的解决方案:
首选版本
我所做的更改是停止使用可怕的 byte
数组,并简单地使用 getRGB()
method instead. The alpha value can be gotten by creating a Color
using the RGB+alpha constructor, and then the getAlpha()
方法。
现在以下代码对我有用:
public static BufferedImage trimHorizontally(BufferedImage img) {
int width = img.getWidth(), height = img.getHeight();
int x0, x1;
int j, i;
int alpha;
leftLoop:
for(i = 0; i < width; i++) {
for(j = 0; j < height; j++) {
if(new Color(img.getRGB(i, j), true).getAlpha() != 0) {
break leftLoop;
}
}
}
x0 = i;
rightLoop:
for(i = width-1; i >= 0; i--) {
for(j = 0; j < height; j++) {
if(new Color(img.getRGB(i, j), true).getAlpha() != 0) {
break rightLoop;
}
}
}
x1 = i+1;
return img.getSubimage(x0, 0, x1-x0, height);
}
备注:
img
必须是 TYPE_INT_ARGB
, or some other type that keeps it's alpha value in the last byte of getRGB()
's data (if you don't know what this means, just try the above code and if it doesn't work covert to ARGB 类型。)
还要确保使用 image format that supports transparency(不是 JPG)。