调整运行时图像时出现质量问题 [英] Quality problems when resizing an image at runtime

查看:107
本文介绍了调整运行时图像时出现质量问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在磁盘上的映像文件,我调整的文件,并保存回磁盘为新的图像文件。为了这个问题,我没有把它们装入内存,以显示在屏幕上,只调整它们的大小并重新保存它们。这一切都工作得很好。然而,缩放图像,对他们的文物与这里所示:<一href="http://stackoverflow.com/questions/2041207/android-quality-of-the-images-resized-in-runtime">android:调整运行时的图像质量

I have a image file on the disk and I am resizing the file and saving it back to disk as a new image file. For the sake of this question, I am not bringing them into memory in order to display them on the screen, only to resize them and resave them. This all works just fine. However, the scaled images have artifacts on them like shown here: android: quality of the images resized in runtime

它们保存这种失真,因为我可以拉他们从磁盘,看看他们在我的电脑上,他们仍然有同样的问题。

They are saved with this distortion, as I can pull them off the disk and look at them on my computer and they still have the same issue.

我使用code与此类似<一个href="http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966">Android:奇怪的内存不足问题脱$ C C位图$到内存:

I am using code similar to this Android: Strange out of memory issue to decode the bitmap into memory:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageFilePathString, options);

int srcWidth = options.outWidth;
int srcHeight = options.outHeight;
int scale = 1;

while(srcWidth / 2 > desiredWidth){
   srcWidth /= 2;
   srcHeight /= 2;
   scale *= 2;
}

options.inJustDecodeBounds = false;
options.inDither = false;
options.inSampleSize = scale;
Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(imageFilePathString, options);

然后我做的实际比例:

Then I am doing the actual scaling with:

Bitmap scaledBitmap = Bitmap.createScaledBitmap(sampledSrcBitmap, desiredWidth, desiredHeight, false);

最后,新调整后的图像保存到磁盘中的:

Lastly, the new resized image is saved to disk with:

FileOutputStream out = new FileOutputStream(newFilePathString);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);

然后,正如我所说,如果我拉的文件从磁盘,看看它,它有质量问题上面链接,看起来很可怕。如果我跳过createScaledBitmap,只是保存sampledSrcBitmap右后卫磁盘是没有问题的,它似乎只发生,如果大小的变化。

Then, as I mentioned, if I pull that file off the disk and look at it, it has that quality issue linked above and looks terrible. If I skip the createScaledBitmap and just save the sampledSrcBitmap right back to disk there is no problem, it seems to only happen if the size changes.

我都试过了,你可以在code见,设置inDither为false,这里提到的<一个href="http://groups.google.com/group/android-developers/browse_thread/thread/8b1abdbe881f9f71">http://groups.google.com/group/android-developers/browse_thread/thread/8b1abdbe881f9f71和中所提到的第一联交上方。这并没有改变任何东西。此外,在第一篇文章我联系,罗曼盖伊说:

I have tried, as you can see in the code, setting inDither to false as mentioned here http://groups.google.com/group/android-developers/browse_thread/thread/8b1abdbe881f9f71 and as mentioned in the very first linked post above. That didn't change anything. Also, in the first post I linked, Romain Guy said:

而不是调整的绘图时间   (这将是非常昂贵的),   尝试在屏幕外的位图来调整   并确保位图是32位   (ARGB888)。

Instead of resizing at drawing time (which is going to be very costly), try to resize in an offscreen bitmap and make sure that Bitmap is 32 bits (ARGB888).

不过,我不知道如何来确保位图保持为32位。在整个过程中。

However, I have no idea how to make sure the Bitmap stays as 32 bits through the whole process.

我也看过一对夫妇的其他文章像这样<一个href="http://android.nakatome.net/2010/04/bitmap-basics.html">http://android.nakatome.net/2010/04/bitmap-basics.html但他们似乎都被处理绘图和显示位图,我只是想调整它的大小,并将其保存回磁盘没有这个质量问题。

I have also read a couple other articles such as this http://android.nakatome.net/2010/04/bitmap-basics.html but they all seemed to be addressing drawing and displaying the Bitmap, I just want to resize it and save it back to disk without this quality problem.

谢谢了

推荐答案

尝试,我终于找到了一种方法,以质量好成绩完成这一步之后。我会写这件事的人可能会发现这个答案在未来有帮助的。

After experimenting I have finally found a way to do this with good quality results. I'll write this up for anyone that might find this answer helpful in the future.

要解决的第一个问题,文物和怪异的抖动引入的图像,你需要确保你的形象保持为32位ARGB_8888图像。我的问题使用code,你可以简单地前的第二代code加入这一行的选项。

To solve the first problem, the artifacts and weird dithering introduced into the images, you need to insure your image stays as a 32-bit ARGB_8888 image. Using the code in my question, you can simply add this line to the options before the second decode.

options.inPreferredConfig = Bitmap.Config.ARGB_8888;

补充说,文物都不见了,而且在整个图像边缘来通过锯齿状,而不是清脆之后。经过一些实验,我发现使用调整矩阵,而不是Bitmap.createScaledBitmap位图产生多大效果更清晰。

After adding that, the artifacts were gone but edges throughout the images came through jagged instead of crisp. After some more experimentation I discovered that resizing the bitmap using a Matrix instead of Bitmap.createScaledBitmap produced much crisper results.

通过这两个解决方案,将图像尺寸调整,现在完美。下面是情况下,code,我使用它的好处别人过这个问题来了。

With those two solutions, the images are now resizing perfectly. Below is the code I am using in case it benefits someone else coming across this problem.

// Get the source image's dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(STRING_PATH_TO_FILE, options);

int srcWidth = options.outWidth;
int srcHeight = options.outHeight;

// Only scale if the source is big enough. This code is just trying to fit a image into a certain width.
if(desiredWidth > srcWidth)
    desiredWidth = srcWidth;



// Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2
// from: http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966
int inSampleSize = 1;
while(srcWidth / 2 > desiredWidth){
    srcWidth /= 2;
    srcHeight /= 2;
    inSampleSize *= 2;
}

float desiredScale = (float) desiredWidth / srcWidth;

// Decode with inSampleSize
options.inJustDecodeBounds = false;
options.inDither = false;
options.inSampleSize = inSampleSize;
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(STRING_PATH_TO_FILE, options);

// Resize
Matrix matrix = new Matrix();
matrix.postScale(desiredScale, desiredScale);
Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0, sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
sampledSrcBitmap = null;

// Save
FileOutputStream out = new FileOutputStream(NEW_FILE_PATH);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
scaledBitmap = null;

编辑:在这个不断工作,我发现,图像仍然不是100%完美。我会进行更新,如果我能有所改进。

After continual work on this I have found that the images still aren't 100% perfect. I'll make an update if I can improve it.

更新: revisting这之后,我发现<一href="http://stackoverflow.com/questions/4821488/bad-image-quality-after-resizing-scaling-bitmap">this问题的SO 并有所提到的inScaled选择一个答案。这有助于与质量,以及使我增加了更新的答案上面包含它。我现在还空的位图,他们在完成后的使用情况。

Update: After revisting this, I found this question on SO and there was an answer that mentioned the inScaled option. This helped with the quality as well so I added updated the answer above to include it. I also now null the bitmaps after they are done being used.

此外,作为一个侧面说明,如果你是在一个web视图使用这些图片,请确保您这篇文章考虑。

Also, as a side note, if you are using these images in a WebView, make sure you take this post into consideration.

请注意:你还应该添加一个检查,以确保在宽度和高度有效的数字(不是-1)。如果是这样,它会导致inSampleSize环路成为无穷大。

Note: you should also add a check to make sure the width and height are valid numbers (not -1). If they are, it will cause the inSampleSize loop to become infinite.

这篇关于调整运行时图像时出现质量问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆