I am working on a simple image processing tool that should be able to apply filters on a given image. I was wondering how I would solve this in a functional way with lambda expressions and streams.
I wrote a method that returns a kernel as ArrayList with argb values, that can then be further processed depending on which filter I'd like to apply. For example if I'd like to apply a box filter, I'd have to sum all elements and divide it by the number of elements. But of course I have to do this with all rgb values separately.
I used to get the values as followed:
// 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;
But I am not sure how I would write this with streams, or what to insert here to split the values and process them independently and put the results back together.
IntStream.range(0, src.length).parallel().forEach(i ->
dst[i] = getKernelValues(3, src, i, width, height).stream()
.mapToInt(Integer::intValue)
.sum() / 9);
What I wrote here is totally wrong, because it takes the whole argb value. But maybe you guys can help me to change that pice to a working example I can use for other filters later.
Thanks in advance.
edit:
In the meantime I got roundabout the problem by splitting the values as followed. This works, but still has duplicated code. If someone knows how to this in less code, I'd be happy to know.
Thanks anyway.
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;
});