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

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Loay
  • 13
  • 1
  • 3
  • http://stackoverflow.com/questions/7237915/replace-black-color-in-bitmap-with-red – Triode Jan 13 '15 at 07:44
  • Thanks, I already used this approach it works fine; but it doesn't work well with anti-aliased graphics :(
    If there is a solution using the setColorFilter(ColorMatrixColorFilter(float[])) it would be perfect!
    – Loay Jan 17 '15 at 12:26

3 Answers3

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.

Alt-Cat
  • 5,392
  • 1
  • 15
  • 16
  • Hi @Alt-Cat, as mentioned in the question: I don't want to invert all colors! I only want to invert any BLACK color (taking into account anti-aliasing) and keep other colors without change,,, I added a new illustration of the actual sample of an image I want to invert (activate the night-mode reading)... I also added code snipet – Loay Jan 14 '15 at 06:57
  • 2
    This was posted as an answer, but it does not attempt to answer the question. It should possibly be an edit, a comment, another question, or deleted altogether. – Phantômaxx Jan 14 '15 at 08:59
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.

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