压缩到png时位图颜色发生变化

时间:2011-02-27 05:36:06

标签: android graphics bitmap png steganography

我目前正在开发一个steganogrpahy android应用程序作为一个类项目。我创建了一个对象,它将在另一个图像中编码图像并返回编码的位图。此代码在单独的线程中运行。

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();

对位图进行编码后,我将位图传递给我创建的文件浏览器活动,以将位图保存为png图像。此方法适用于较小的图像,但是,当编码大图像并将其传递给子活动时,应用程序会冻结并返回主活动。

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);
 }

我假设一个大的位图在使用意图的活动之间发送很大,所以我决定简单地将图像保存在临时位置并将图像的位置传递给子活动。然后将png图像保存在用户指定和删除临时图像文件的位置。

private void save_bitmap( Bitmap image, String location )
{
    FileOutputStream fileOutputStream = new FileOutputStream(location);
    BufferedOutputStream buffered_output_stream = new 
        BufferOutputStream(fileOutputStream);
    image.compress(CompressFormat.PNG, 0, buffered_output_stream);
    buffered_output_stream.flush();
    buffered_output_stream.close();
}

这解决了从一个活动向另一个活动发送大位图的问题,然而,却产生了一个我无法解决的新问题。在将文件位置传递给子活动之前保存的临时图像和使用文件浏览器重新保存图像之后的图像文件都略微改变了颜色。这种颜色变化是肉眼无法识别的,但是在解码图像时会引起很多问题。 我有一个想法是Bitmap.Config正在从ARGB_8888变为ARGB_4444或RGB_565但是,在调试后情况并非如此。位图被实例化为ARGB_8888并保存为ARGB_8888位图,并且之间不会发生变化。如果我将整个位图传递给文件浏览器活动,并且我在两个位置都保存完全相同的位图,代码仍然有效。关于还有什么可能导致这种情况,我没有任何想法。我正在寻找关于还有什么可能导致问题的建议。对不起,我打算在两种情况下在输出上发布图像,但是,堆栈溢出不会让我达到我的声誉级别谢谢。

2 个答案:

答案 0 :(得分:6)

好的,经过许多长时间的浪费时间,担心线程和我用来编码位图的算法问题有点简单了。解码用我正在使用的消息编码的图像文件options.inPreferredConfig = Config.ARGB_8888;在调试期间,我正在检查以确保它没有更改为RGB_565。虽然位图对象是作为ARBG_8888加载的,但是图像文件不包含alpha通道,因此即使位图具有alpha级别的字节,也允许我通过Bitmap.setPixel( x, y, color)位图编辑像素的alpha字节对象从未识别出它设置了alpha值。当压缩压缩到RGB_565的位图时,因为对象认为没有alpha通道。通过将位图传递给子活动并解析它,以某种方式解决了这个问题。我猜测当对象被重新创建时,我设置的alpha值被识别出来。为了解决将位图传递给子活动的问题,必须在从文件解码位图之后添加alpha通道。我发现了一个功能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;
} 

我不确定是否有更有效的方法

答案 1 :(得分:0)

对于像我这样偶然发现它的人,想知道为什么一旦用PNG将其写出来,bitnap颜色就会改变。我发现在调用bitmap.compress(PNG,100,fileout)之前使用bitmap.setPreMultiplied(false)可以保留图像的颜色(如果具有alpha通道值)。 Setpremultiplied防止写入磁盘的像素乘以alpha通道,从而生成不同的像素颜色值。