Java流-处理rgb值
我正在开发一个简单的图像处理工具,应该能够对给定的图像应用过滤器。我想知道如何用lambda表达式和流以函数的方式解决这个问题 我编写了一个方法,该方法将内核作为ArrayList返回,并带有argb值,然后可以根据我要应用的过滤器对其进行进一步处理。例如,如果我想应用一个长方体过滤器,我必须将所有元素相加,然后除以元素数。当然,我必须分别对所有rgb值进行处理 我以前得到的值如下所示:Java流-处理rgb值,java,lambda,filter,java-stream,argb,Java,Lambda,Filter,Java Stream,Argb,我正在开发一个简单的图像处理工具,应该能够对给定的图像应用过滤器。我想知道如何用lambda表达式和流以函数的方式解决这个问题 我编写了一个方法,该方法将内核作为ArrayList返回,并带有argb值,然后可以根据我要应用的过滤器对其进行进一步处理。例如,如果我想应用一个长方体过滤器,我必须将所有元素相加,然后除以元素数。当然,我必须分别对所有rgb值进行处理 我以前得到的值如下所示: // Get rgb values: r = (argb >> 16) &
// Get rgb values:
r = (argb >> 16) & 0xff;
g = (argb >> 8) & 0xff;
b = argb & 0xff;
// Write back to argb:
argb = (0xFF << 24) | (r << 16) | (g << 8) | b;
我在这里写的是完全错误的,因为它需要整个argb值。但也许你们可以帮我把这个图片改成一个工作示例,我可以在以后用于其他过滤器
提前谢谢
编辑:同时,我通过如下拆分值绕过了这个问题。这是可行的,但仍然有重复的代码。如果有人知道如何在更少的代码,我很乐意知道 无论如何,谢谢你
IntStream.range(0, src.length).parallel().forEach(i -> {
ArrayList<Integer> values = getKernelValues(filterSize, src, i, width, height);
int r = values
.stream()
.map(j -> (j >> 16) & 0xff)
.reduce(0, (j, k) -> j + k);
r /= (filterSize * filterSize);
int g = values
.stream()
.map(j -> (j >> 8) & 0xff)
.reduce(0, (j, k) -> j + k);
g /= (filterSize * filterSize);
int b = values
.stream()
.map(j -> j & 0xff)
.reduce(0, (j, k) -> j + k);
b /= (filterSize * filterSize);
dst[i] = 0xff << 24 | r << 16 | g << 8 | b;
});
IntStream.range(0,src.length).parallel().forEach(i->{
ArrayList值=GetKernelValue(filterSize、src、i、宽度、高度);
int r=值
.stream()
.map(j->(j>>16)和0xff)
.减少(0,(j,k)->j+k);
r/=(filterSize*filterSize);
int g=值
.stream()
.map(j->(j>>8)和0xff)
.减少(0,(j,k)->j+k);
g/=(filterSize*filterSize);
int b=值
.stream()
.map(j->j&0xff)
.减少(0,(j,k)->j+k);
b/=(filterSize*filterSize);
dst[i]=0xff我觉得你需要平均所有的r值、g值和b值。如果我是正确的,首先要注意的是,你不能在int的8位空间内对每个值求和,因为在你将结果除以值的数量之前,总和将超过8位。所以你需要做的第一件事是提取r、g、a将b值转换为单独的整数值以保存总和。您可以创建带有整数字段的RGB类,但整数数组可以:
static int[] unpackARGB(int argb){
return new int[] { (argb >> 16) & 0xff, (argb >> 8) & 0xff, argb & 0xff };
}
static int packARGB(int[] ints){
return (0xff << 24 + ints[0] & 0xff) << 16 + (ints[1] & 0xff) << 8 + ints[2] & 0xff;
}
稍后,我们需要将每个值除以,使其回到其8位范围,因此这种方便的方法将有助于:
static int[] divRGB(int[] arr1, int divisor){
return new int[] { arr1[0]/divisor, arr1[1]/divisor, arr1[2]/divisor };
}
然后,我们可以创建一个函数来执行平均操作:
public static int averageRGB(IntStream ints, int size) {
int[] sum = ints
.parallel()
.mapToObj(i -> unpackARGB(i))
.reduce(new int[]{0,0,0}, (a, v) -> sumRGB(a, v));
return packARGB(divRGB(sum, size));
}
从列表中,您可以这样调用它:
int result = averageRGB(integerList.stream().mapToInt(i->i), integerList.size());
您当前的代码有什么问题?如上一段getKernelValues()中所述返回argb整数值的ArrayList。但当然,您需要单独处理所有颜色通道。仍然不清楚您期望的输出类型。您可以发布一个示例吗?嗯,仍然不确定如何更好地解释它。也许可以举一个示例,说明我从getKernelValues()获得的值。此示例适用于图片中任意位置的9x9筛选器大小。int:-8224126///hex:0xff828282 int:-8092540///hex:0xff848484 int:-8224126///hex:0xff828282 int:-8224126///hex:0xff828282 int:-8092540///hex:0xFF8484 int:-8224126///hex:0xFF8282 int:-8224126///hex:0xff828282 int:-8092540///hex:0xff848484 int:-8224126///hex:0xff828282抱歉,它在这里不起作用
public static int averageRGB(IntStream ints, int size) {
int[] sum = ints
.parallel()
.mapToObj(i -> unpackARGB(i))
.reduce(new int[]{0,0,0}, (a, v) -> sumRGB(a, v));
return packARGB(divRGB(sum, size));
}
int result = averageRGB(integerList.stream().mapToInt(i->i), integerList.size());