Alex Girke
Alex Girke

Reputation: 53

Change colour of a bitmap fastly

I was trying to realize an actually simple action, namely to change the color of a normal bitmap. Unfortunately, there appeared a few errors. In my case I want a bitmap of grey steel to turn into redder steel. Therefore, I wrote some code, which gets the color int of each pixel and raises the red value for each one. Now two things happen: Firstly, it really takes a long, long time to convert all the pixels, even if I use an AsyncTask. Secondly, when it finishes one cycle, the whole bitmap kind of rotates and multiplies like in the picture below. Is there any way to smoothly realize my aim? The thing is that I often see this action in other apps without having problems, so the must be a way to reach my goal.

Thank you!

PS: Please do not be irritated by the comments, they are just tries to find another way!

"steel image" https://drive.google.com/file/d/0B72QIg-baxzjakJsQkFRZFVFOFU/edit?usp=sharing

public void adjustColor(Bitmap bmp)
{       
    /*for(int i=0; i<bmp.getHeight()-1; i++) {          
        for(int j=0; j<bmp.getWidth()-1; j++) { 
            if(bmp.getPixel(j, i) != Color.TRANSPARENT) {
            if(Color.green(bmp.getPixel(j, i)) <= 175 && Color.green(bmp.getPixel(j, i)) >= 65) {
                red = Color.red(bmp.getPixel(j, i));
                green = Color.green(bmp.getPixel(j, i));
                blue = Color.blue(bmp.getPixel(j, i));
                if (i == bmp.getHeight()-1) {
                    red = Color.red(bmp.getPixel(j, bmp.getHeight()));
                    green = Color.green(bmp.getPixel(j, bmp.getHeight()));
                    blue = Color.blue(bmp.getPixel(j, bmp.getHeight()));} 
                if ((red + mOfen.heatQ/10) <= 205) red = red + mOfen.heatQ/10;
                bmp.setPixel(j, i, Color.rgb(red, green, blue)); 
            }}
        }
    }*/

    for(int h=0; h<bmp.getWidth()*bmp.getHeight(); h++) {
        int x = h-bmp.getWidth()*(((int)h/bmp.getWidth()+1)-1);
        int y = h/bmp.getWidth();
        Log.d("roh", "y " + Integer.toString(y));
        Log.d("roh", "height " + Integer.toString(bmp.getHeight()));
        if(Color.green(bmp.getPixel(x, y)) <= 175 && Color.green(bmp.getPixel(x, y)) >= 65) {
            bmp.setPixel(x, y, Color.WHITE); 
                red = Color.red( allpixels[h] );
                green = Color.green( allpixels[h] );
                blue = Color.blue( allpixels[h] );
    /*          for(int n=1; n<=10; n++) {              
                    /*Log.d("roh", "left " + Float.toString(mOfen.rRoh[n-1].left));
                    Log.d("roh", "right " + Float.toString(mOfen.rRoh[n-1].right)); 
                    Log.d("roh", "n " + Integer.toString(n));
                    Log.d("roh", "x+RohX " + Float.toString(x+RohX)); 
                    Log.d("roh", "top " + Float.toString(mOfen.rRoh[n-1].top));
                    Log.d("roh", "bottom " + Float.toString(mOfen.rRoh[n-1].bottom)); 
                    Log.d("roh", "n " + Integer.toString(n));
                    Log.d("roh", "y+RohY " + Float.toString(y+RohY)); */
    /*              if( mOfen.rRoh[n-1].left < x+RohX && y+RohY > mOfen.rRoh[n-1].top &&
                        mOfen.rRoh[n-1].right > x+RohX &&  y+RohY < mOfen.rRoh[n-1].bottom) {
                        /*if ((mOfen.heat[n-1]) <= 245 && (mOfen.heat[n-1]) > red ) red = mOfen.heat[n-1]; */ if(red<255) red++; 
    /*                  Log.d("red", "red" + Integer.toString(red)); 
                        Log.d("red", Float.toString(x+mOfen.rRoh[n-1].left)); 
                        Log.d("red", Float.toString((mOfen.rRoh[n-1].left))); 
                        }}  */
                allpixels[h] = Color.rgb(red, green, blue); 
        }
    }


    copyArrayIntoBitmap(bmp);
    //bmp.setPixels(allpixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight()); 
}

public void copyBitmapIntoArray(Bitmap bmp) 
{
    allpixels = new int[bmp.getWidth()*bmp.getHeight()];

    int count = 0;
    for(int i=0; i<bmp.getHeight()-1; i++) {            
        for(int j=0; j<bmp.getWidth()-1; j++) { 
            allpixels[count] = bmp.getPixel(j, i);
            count++;
        }
    } 
}

public void copyArrayIntoBitmap(Bitmap bmp) 
{
    int count = 0;
    for(int i=0; i<bmp.getHeight()-1; i++) {            
        for(int j=0; j<bmp.getWidth()-1; j++) { 
            bmp.setPixel(j, i, allpixels[count]);
            count++;
        }
    } 
} 

Upvotes: 1

Views: 689

Answers (2)

Greg Giacovelli
Greg Giacovelli

Reputation: 10184

So your code and your question have different operations being said. Looks like you are doing a little more than just globally updating all pixels to be a bit more red. I say this because both code in your question, commented and uncommented, have a conditional part in them that determines how much more red to make a pixel. I also assume this is why a simple LightingColorFilter will not work, since you need to choose which pixels are affected.

Some issues I spotted immediately:

I am betting you are running into a lot of I/O issues with regards to all the memory allocation and memory copying in this code. WxH is your number of pixels, obviously. But that is also a fairly large amount of entites to do an operation on. So your calls to getPixel() and setPixel() iteratively are very very slow already and doing this for each pixel is just impractical. You should use bulk getPixels() and setPixels() if you are going to do it this way. Just this alone should speed up a large chunk of your process.

Now if you want a forward compatible performance boost (like one that scales better with better hardware), you could look into RenderScript This allows you to do work on a per pixel level, but across multiple CPU's and GPU's. It's sort of like a map-reduce framework for your image buffers. You will have to write some C, but if you find this component to be used a lot then this will probably help out quite a bit and be pretty snappy (especially for larger images).

Upvotes: 1

Miroslav Michalec
Miroslav Michalec

Reputation: 1659

Try to use LightingColorFilter, some examples are here: LightingColorFilter example or how to use the LightingColorFilter to make the image form dark to light

Upvotes: 0

Related Questions