android - 压缩为 png 时位图颜色发生变化

标签 android graphics bitmap png steganography

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

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

在对位图进行编码后,我将位图传递给我创建的文件浏览器 Activity ,以将位图另存为 png 图像。此方法适用于较小的图像,但是,当对大图像进行编码并将其传递给子 Activity 时,应用程序会卡住并返回到主 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);
 }

我假设大位图太大,无法使用 Intent 在 Activity 之间发送,所以我决定简单地将图像保存在临时位置并将图像的位置传递给子 Activity 。然后将 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();
}

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

最佳答案

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

不知道有没有更高效的方法

关于android - 压缩为 png 时位图颜色发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5131651/

相关文章:

java - 二维 java 图形

android - 将 Drawable/Bitmap 转换为 ResourceID (android)

Android KitKat 不支持 TLSv1.2

android - 在 Android Sqlite 中,ROWID 与主键相同吗?

java - 支持证书 Pinner 中主机名中的端口号

ios - 从 iPhone 相机 (AVCaptureSession) 捕获 24 bpp 位图中的图像

android - 来自画廊的图像自动旋转 - Android

java - 如何正确检查 Android 设备上的互联网连接?

java - JfreeChart XYPlot 放大/缩小后卡住

python - Pygame图形错误: Couldn't open blue. png