开发者

Bitmap color change while compressing to png

开发者 https://www.devze.com 2023-02-13 12:37 出处:网络
I\'m currently working on a steganogrpahy android app as a class project. I\'ve created an object that will encode an image with in another image and return an encoded bitmap. This code is run in a se

I'm currently working on a steganogrpahy android app as a class project. I've created an object that will encode an image with in another image and return an encoded bitmap. This code is run in a seprate thread.

new Thread(new Runnable()  
{  
   public void run()  
    {  
        Bitmap encoded_image = null;  
        Encryptor encryptor = new Encryptor();  
        encoded_image = encryptor.encode_image_in_image(  
            image_location,message_image_location);  
    }  
}).start();

After encoding the bitmap I was passing the bitmap to a file browser activity that I've created to save the bitmap as a png image. This method works for smaller images however, when a large image is encoded and passed to the sub activity the application freezes and returns to the main activity.

private void pass_image_to_file_browser( Bitmap image )
{
    Intent intent = new Intent(Encrypt.this,FileBrowser.class);
    intent.putExtra( Intent.EXTRA_STREAM, image );
    startActivity( intent );
}

@Override
 public void onCreate(Bundle savedInstanceState) 
 {
    super.onCreate(savedInstanceState);
    Bundle bundle = this.getIntent().getExtras();
    Bitmap image = bundle.getParacable(Intent.EXTRA_STREAM);
 }

I was assuming a large bitmap was to large to send between activities using an intent so I decided to simply save the image in a temporary location and pass the image's location to the sub activity. Which then saves the png image where the user specifies and deletes the temporary image file.

private void save_bitmap( Bitmap image, String location )
{
    FileOutputStream fileOutputStream = new FileOutputStream(location);
    BufferedOutputStream buf开发者_JAVA技巧fered_output_stream = new 
        BufferOutputStream(fileOutputStream);
    image.compress(CompressFormat.PNG, 0, buffered_output_stream);
    buffered_output_stream.flush();
    buffered_output_stream.close();
}

This solves the problem of sending a large bitmap from one activity to another however, has created a new problem that I haven't been able to solve. Both the temporary image that is saved before passing the file location to the sub activity and the image file after re saving the image using the file browser have both had their color changed slightly. This color change is unrecognizable to the naked eye but, when decoding the image it causes lots of problems. One thought I had was that the Bitmap.Config was changing from ARGB_8888 to ARGB_4444 or RGB_565 however, after debug this is not the case. The bitmap is instantiated as an ARGB_8888 and saved as an ARGB_8888 bitmap and never changes in between. The code still works if I pass the entire bitmap to the file browser activity and I'm saving the bitmaps exactly the same in both places. I do not have any thoughts on what else could be causing this. I'm looking for suggestions on what else could be causing the problem. Sorry I was going to post images on the output in both cases however, stack overflow wouldn't let me at my reputation level Thanks.


Ok, after many long wasted hours worrying about the thread and the algorithm I was using to encode the the bitmap the problem was a little simpler. While decoding the image file that was to be encoded with a message I was using options.inPreferredConfig = Config.ARGB_8888; During debugging I was checking to make sure this didn't change to RGB_565. Although the bitmap object was loaded as ARBG_8888 the image file did not contain an alpha channel and thus even though the bitmap had a byte for the alpha level and would allow me to edit the alpha byte of a pixel through Bitmap.setPixel( x, y, color) the bitmap object never recognized that it had alpha values set. When compressing the bitmap compressed to RGB_565 since the object thought that there was no alpha channel. Somehow this problem was resolved by passing the bitmap to a sub activity and parsing it. I'm guessing when object was being recreated the alpha values I had set were recognized. To solve the problem with out passing the bitmap to a subactivity one must add an alpha channel after decoding a bitmap from a file. I found a function to do so here.

private Bitmap adjustOpacity( Bitmap bitmap )
{
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    int[] pixels = new int[width * height];
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    dest.setPixels(pixels, 0, width, 0, 0, width, height);
    return dest;
} 

I'm not sure if there is a more efficient method


For anyone who stumbles upon it, like me, wondering why bitnap colors change once you write it out in PNG. I have found out that using bitmap.setPreMultiplied(false) before calling bitmap.compress(PNG, 100, fileout) preserves the color of your image if it has alpha channel values. Setpremultiplied prevents the pixels written onto disk from being multiplied by alpha channel, thus generating different pixel color values.

0

精彩评论

暂无评论...
验证码 换一张
取 消