压缩为 png 时位图颜色发生变化
我目前正在开发一个隐写 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 位图,并且其间不会发生变化。如果我将整个位图传递给文件浏览器活动并且在两个位置保存完全相同的位图,则代码仍然有效。我不知道还有什么可能导致这种情况。我正在寻找有关其他可能导致问题的原因的建议。抱歉,我打算在这两种情况下在输出上发布图像,但是堆栈溢出不会让我达到我的声誉水平,谢谢。
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 buffered_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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,在浪费了很多时间担心线程和我用来编码位图的算法之后,问题变得简单了一些。在解码要使用消息编码的图像文件时,我使用了
options.inPreferredConfig = Config.ARGB_8888;
在调试过程中,我进行了检查以确保它不会更改为 RGB_565。虽然位图对象作为 ARBG_8888 加载,但图像文件不包含 Alpha 通道,因此即使位图有一个用于 Alpha 级别的字节,并且允许我通过 Bitmap.setPixel( x, y, color) 位图对象从未意识到它设置了 alpha 值。当压缩位图时,由于对象认为没有 Alpha 通道,因此压缩为 RGB_565。不知何故,通过将位图传递给子活动并解析它来解决这个问题。我猜测当重新创建对象时,我设置的 alpha 值被识别。为了解决不将位图传递给子活动的问题,必须在从文件中解码位图后添加一个 Alpha 通道。我在此处找到了这样做的函数。不知道是否有更有效的方法
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 throughBitmap.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.I'm not sure if there is a more efficient method
对于像我这样偶然发现它的人来说,想知道为什么当你用 PNG 写出位图时颜色会发生变化。我发现在调用 bitmap.compress(PNG, 100, fileout) 之前使用 bitmap.setPreMultiplied(false) 可以保留图像的颜色(如果它具有 Alpha 通道值)。 Setpremultiplied 可防止写入磁盘的像素与 Alpha 通道相乘,从而生成不同的像素颜色值。
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.