Invert certain colors in a bitmap (Android)

1

and welcome to my very first question on stackoverflow.com :)
I'm trying to invert specific colors of a Bitmap in Android app.
the idea is to have a night mode reading for kids story.
the story pages are colorful, including the text..

when I load the image in the normal mode; it will be displayed as is.
but when the user activates the night mode (press a button during reading) I want to invert the colors of the image.
BUT NOT all colors,,, only any black colored pixel to be inverted to white,,, and keep other colors as is,,,,

Following is an illustration of what I want to do (the upper part is inverting all colors,,, I want to achieve the lower part of the illustration): I used the following code,,, but still anti-aliased black pixels are not inverted very well!!

//Code snipet 
Bitmap copy = myBitmap.copy(myBitmap.getConfig(), true);
int length = copy.getWidth() * copy.getHeight();
int[] array = new int[length];
copy.getPixels(array,0,copy.getWidth(),0,0,copy.getWidth(),copy.getHeight());
for (int i=0;i<length-(length/10);i++){
    
    //trying to overcome text anti-aliasing
    if ( (array[i] & 0x00FFFFFF) <= 0x00222222)
    {
      array[i] = 0xffffffff;
    }
}
copy.setPixels(array,0,copy.getWidth(),0,0,copy.getWidth(),copy.getHeight());

enter image description here

The ACTUAL sample image i want to invert its colors

android
colors
invert
asked on Stack Overflow Jan 13, 2015 by Loay • edited Jun 20, 2020 by Community

3 Answers

0

If you definitely want to invert every colour then that could be done through code at runtime.

However, for performance and simplicity, if you know what the images are in advance, It may be better to create the inverted images in an image editing tool like Photoshop beforehand. That way you have complete control over them. Load them both into the activity but with the inverted image hidden.

Use

view.setVisibility(View.INVISIBLE) and view.setVisibility(View.VISIBLE)

initially set the visibility to invisible, then change it to visible when desired.

answered on Stack Overflow Jan 13, 2015 by Alt-Cat
0

"BackBitmap" would be the Bitmap object you are trying to convert.

Step 1 is to store all Colors of the pixels in an array by getPixels(...) method. (This will store the Colors row-by-row. This is critical to understand for the next step).

Step 2: create a second one-dimensional array where you store each individual pixel in the Bitmap by calling the getPixel(...)

Step 3: convert necessary colors by of the desired range by using a if statement "if ( (array[i] & 0x00FFFFFF) <= 0x00222222 || your Black color range)" and then simple equation that converts a positive image to negative and vice versa: neg_col = 0xFFFFFF - orig_col; .: array[i] = 0xFFFFFF - array2[i];

//step 1
    int length = BackBitmap.getWidth() * BackBitmap.getHeight();
    int[] array = new int[length];
    BackBitmap.getPixels(array, 0, BackBitmap.getWidth(), 0, 0, BackBitmap.getWidth(), BackBitmap.getHeight())

//step 2   
    int[] array2 = new int[length];
    int a2 = 0;

    for(int col = 0; col < BackBitmap.getHeight(); col++){
                for (int row = 0; row < BackBitmap.getWidth();row++){
                    array2[a2] = BackBitmap.getPixel(row,col);
                    a2++;
                    }
       }

//step 3
    for (int i=0;i<length;i++){
        if ((array[i] & 0x00FFFFFF) <= 0x00222222){
           array[i] = 0xFFFFFF - array2[i];
           }
       }

//the next line is here just to "override" this Bitmap's immutamility
            BackBitmap = BackBitmap.copy(Bitmap.Config.ARGB_8888, true);

            BackBitmap.setPixels(array, 0, BackBitmap.getWidth(), 0, 0, BackBitmap.getWidth(), BackBitmap.getHeight());

Hope this helps to the people who are struggling to convert a bitmap into a negative picture. In that case disregard the if statement.

answered on Stack Overflow Mar 19, 2016 by Samuel Hošovský
0

just loop over each pixel of the bitmap and inverse it's color as follow:

private void inverseBitmapColors(Bitmap bitmap) {

    for (int i = 0; i < bitmap.getWidth(); i++) {
        for (int j = 0; j < bitmap.getHeight(); j++) {
            bitmap.setPixel(i, j, bitmap.getPixel(i, j) ^ 0x00ffffff);
        }
    }
}

^ is XOR - Sets each bit to 1 if only one of the two bits is 1 we apply this operation for the pixel color with the 0x00ffffff value and that because the bitmap color value stored on 32 bits in this form:

1th 8 bits for alpha (transparency)

2th 8 bits for red

3th 8 bits for green

4th 8 bits for blue

we need to inverse the colors so no need to touch the alpha so we apply xor with the value 0x00 (first 2 numbers of the value 0x00ffffff) (00000000 in binary) so the alpha will never change the opposite for the red green and blue we need to get the complement of them so we apply xor with the value 0xff (11111111) for each one

answered on Stack Overflow Sep 14, 2020 by Osama Gazal

User contributions licensed under CC BY-SA 3.0