akhy
akhy

Reputation: 5900

How to selectively apply processing algorithm to certain color channel(s) in Java

I'm developing an image processing library for Android which has ability to apply adjustments to image.

At first, I process each bits like this:

public int[] getProcessedPixels(int[] pixels) {
    int a, r, g, b;
    for(int i = 0; i < pixels.length; i++) {

        a = Color.alpha(pixels[i]);
        r = Color.red(pixels[i]);
        g = Color.green(pixels[i]);
        b = Color.blue(pixels[i]);

        a = doSomethingWithThisChannel(a);
        r = doSomethingWithThisChannel(r);
        g = doSomethingWithThisChannel(g);
        b = doSomethingWithThisChannel(b);

        // Merge back all 4 channels to pixel value
        pixels[i] = Color.argb(a, r, g, b);
    }

    return pixels;
}

// Usage sample
int[] pixels = bitmap.getAllPixels(); // each pixels is hexa 0xAARRGGBB
int[] resultPixels = getProcessedPixels(pixels); // it returns  result pixels

Since I'm developing a library, I want to let developers who use it to be able to apply "doSomethingWithThisChannel" method to any channel(s) as needed

I want to change the method like this (it's a copy of the above method, but simplified):

public int[] getProcessedPixels(int[] pixels) {
    // assume process all channels if not specified
    return getProcessedPixels(pixels, Channel.ALL);
}

public int[] getProcessedPixels(int[] pixels, int channels) {
    int a, r, g, b;
    for(int i = 0; i < pixels.length; i++) {
        pixels[i] = doSomethingWithTHESEChannels(pixels[i], channels);
    }

    return pixels;
}

// Usage sample
int channels = Channel.RED | Channel.GREEN; // ONLY apply processing to RED & GREEN channels
int[] pixels = bitmap.getAllPixels(); // each pixels is hexa 0xAARRGGBB
int[] resultPixels = getProcessedPixels(pixels, channels);

This is my static class to define "bitmasks" (cmiiw) for each ARGB color channel I used in the code above:

public class Channel {
    public static final int NONE = 0x00000000;
    public static final int ALL = 0xffffffff;
    public static final int ALPHA = 0xff000000;
    public static final int RED = 0x00ff0000;
    public static final int GREEN = 0x0000ff00;
    public static final int BLUE = 0x000000ff;
}

Do you have any suggestion how should I implement doSomethingWithTHESEChannels method above? I'm pretty sure it will involve bitmask/bit-manipulation.

Upvotes: 0

Views: 189

Answers (1)

blackSmith
blackSmith

Reputation: 3154

Here is a implementation of the doSomethingWithTHESEChannels method as per your design :

    private int doSomethingWithTHESEChannels(int i, int channels) {

    if (Channel.NONE == channels) {
        return i;
    }

    int a, r, g, b;
    a = (i & Channel.ALPHA) >> 24;
    r = (i & Channel.RED) >> 16;
    g = (i & Channel.GREEN) >> 8;
    b = i & Channel.BLUE;

    int cur = channels & Channel.ALL;
    if (cur == Channel.ALL) {
        System.out.println("all found");
        a = transform(a);
        r = transform(r);
        g = transform(g);
        b = transform(b);

    } else {
        cur = channels & Channel.ALPHA;
        if (cur == Channel.ALPHA) {
            System.out.println("alpha found");
            a = transform(a);
        }
        cur = channels & Channel.RED;
        if (cur == Channel.RED) {
            System.out.println("red found");
            r = transform(r);
        }
        cur = channels & Channel.GREEN;
        if (cur == Channel.GREEN) {
            System.out.println("green found");
            g = transform(g);
        }

        cur = channels & Channel.BLUE;
        if (cur == Channel.BLUE) {
            System.out.println("blue found");
            b = transform(b);
        }

    }

    return (a << 24 | r << 16 | g << 8 | b);

}

The transform method is the operation to be applied to a channel. The Sysouts are just for testing purposes. You may change the type of a,r,g,b variables to byte with proper type-castings if needed.

However, I suggest you to move the above channel detection blocks(if conditions) to the getProcessedPixels method itself. Then you can pass the entire pixels array to a transform method. This way you will eliminate the redundant condition checks for each pixel. If you need hint on this, just leave a reply, I will update the answer.

Upvotes: 1

Related Questions