cot*_*aws 28 android resize image bitmap
我在磁盘上有一个图像文件,我正在调整文件大小并将其作为新的图像文件保存回磁盘.为了这个问题,我没有将它们带入内存以便在屏幕上显示它们,只是为了调整它们并重新保存它们.这一切都很好.但是,缩放后的图像上有如下所示的工件:android:运行时调整大小的图像质量
它们会因为这种失真而被保存,因为我可以将它们从磁盘上取下并在计算机上查看它们,但它们仍然存在同样的问题.
在将图像加载到Bitmap对象以将位图解码到内存时,我使用类似于此奇怪的内存不足问题的代码:
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);
Run Code Online (Sandbox Code Playgroud)
然后我正在进行实际缩放:
Bitmap scaledBitmap = Bitmap.createScaledBitmap(sampledSrcBitmap, desiredWidth, desiredHeight, false);
Run Code Online (Sandbox Code Playgroud)
最后,新调整大小的图像将保存到磁盘:
FileOutputStream out = new FileOutputStream(newFilePathString);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
Run Code Online (Sandbox Code Playgroud)
然后,正如我所提到的,如果我将该文件从磁盘中拉出来并查看它,它就会将质量问题链接到上面并且看起来很糟糕.如果我跳过createScaledBitmap并将samplesSrcBitmap直接保存回磁盘就没有问题,似乎只有在大小改变时才会发生.
我已经尝试过,正如您在代码中看到的那样,设置inDither为false,如http://groups.google.com/group/android-developers/browse_thread/thread/8b1abdbe881f9f71所述,并在上面的第一个链接帖子中提到.这并没有改变任何事情.另外,在我链接的第一篇文章中,罗曼盖伊说:
不要在绘图时调整大小(这将是非常昂贵的),尝试在屏幕外位图中调整大小并确保位图为32位(ARGB888).
但是,我不知道如何确保Bitmap在整个过程中保持32位.
我还阅读了其他一些文章,例如http://android.nakatome.net/2010/04/bitmap-basics.html,但它们似乎都在解决绘图和显示位图,我只想调整它的大小和将其保存回磁盘而不存在此质量问题.
非常感谢
cot*_*aws 55
经过实验,我终于找到了一种方法,可以获得高质量的结果.我会为任何可能在将来找到这个答案的人写这篇文章.
为了解决第一个问题,图像中引入了伪影和奇怪的抖动,您需要确保图像保持为32位ARGB_8888图像.使用我的问题中的代码,您可以在第二次解码之前将此行添加到选项中.
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Run Code Online (Sandbox Code Playgroud)
添加之后,工件已经消失,但整个图像的边缘都是通过锯齿状而不是清晰的.经过一些实验,我发现使用Matrix而不是Bitmap.createScaledBitmap调整位图大小会产生更加清晰的结果.
有了这两个解决方案,图像现在可以完美地调整大小.下面是我正在使用的代码,以防其他人遇到此问题.
// 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: https://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;
Run Code Online (Sandbox Code Playgroud)
编辑:经过不断的努力,我发现图像仍然不是100%完美.如果我能改进它,我会做一个更新.
更新: 在撤销之后,我在SO上找到了这个问题,并且有一个答案提到了inScaled选项.这也有助于提高质量,所以我添加了上面的答案以包含它.我现在也在使用它们之后使位图为空.
另外,作为旁注,如果您在WebView中使用这些图像,请务必考虑此帖子.
注意:您还应该添加一个检查以确保宽度和高度是有效数字(不是-1).如果是,则会导致inSampleSize循环变为无限.
在我的情况下,我将图像绘制到屏幕上.这就是我所做的让我的图像看起来正确(littleFluffyKitty的答案加上其他一些东西的组合).
对于我实际加载图像时的选项(使用decodeResource),我设置以下值:
options.inScaled = false;
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Run Code Online (Sandbox Code Playgroud)
当我实际绘制图像时,我像这样设置我的绘图对象:
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
Run Code Online (Sandbox Code Playgroud)
希望其他人发现它也很有用.我希望只有"是的,让我的调整大小的图像看起来像垃圾"和"不,请不要强迫我的用户用勺子挖出他们的眼睛",而不是所有无数的不同选项.我知道他们想给我们很多控制权,但也许一些常用设置的辅助方法可能会有用.
| 归档时间: |
|
| 查看次数: |
32673 次 |
| 最近记录: |