从SD卡中选择图像,调整图像大小并将其保存回SD卡。

28

我正在开发一个应用程序,需要从SD卡中选择一个图像并显示在图像视图中。现在我想让用户通过点击按钮来增加/减少其宽度,然后将其保存回SD卡。

我已经完成了图片的选择和在UI上显示的部分,但是无法找到如何调整大小的方法。请有经验的开发者给予建议。

7个回答

51

就在昨天我做了这件事

File dir=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
Bitmap b= BitmapFactory.decodeFile(PATH_ORIGINAL_IMAGE);
Bitmap out = Bitmap.createScaledBitmap(b, 320, 480, false);

File file = new File(dir, "resize.png");
FileOutputStream fOut;
try {
    fOut = new FileOutputStream(file);
    out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
    fOut.flush();
    fOut.close();
    b.recycle();
    out.recycle();               
} catch (Exception e) {}

同时不要忘记回收你的位图:这将节省内存。

您还可以获取新创建文件的路径字符串:newPath = file.getAbsolutePath();


7
BitmapFactory.decodeFile()方法在打开大尺寸图片时可能会抛出OOM异常,需要使用“options”参数来打开,这样你将得到原始图像的缩小版本。 - jxgn
我需要在原始图像上缩小并保存,而不是在修改后的图像上。我在图库应用程序中注意到了这一点。我向大小为6.33 MB的图像添加了一些效果,在添加效果后,尺寸变成了507 KB。信息丢失非常大,我不想这样。 - jxgn
它的工作很好,但如何保留图像质量。 - Akshay kumar

13

Kotlin中避免OutOfMemoryException的解决方案

fun resizeImage(file: File, scaleTo: Int = 1024) {
    val bmOptions = BitmapFactory.Options()
    bmOptions.inJustDecodeBounds = true
    BitmapFactory.decodeFile(file.absolutePath, bmOptions)
    val photoW = bmOptions.outWidth
    val photoH = bmOptions.outHeight

    // Determine how much to scale down the image
    val scaleFactor = Math.min(photoW / scaleTo, photoH / scaleTo)

    bmOptions.inJustDecodeBounds = false
    bmOptions.inSampleSize = scaleFactor

    val resized = BitmapFactory.decodeFile(file.absolutePath, bmOptions) ?: return
    file.outputStream().use {
        resized.compress(Bitmap.CompressFormat.JPEG, 75, it)
        resized.recycle()
    }
}

3

尝试使用这个方法:

public static Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth, float newHeight) {   
if(bitmapToScale == null)
    return null;
//get the original width and height
int width = bitmapToScale.getWidth();
int height = bitmapToScale.getHeight();
// create a matrix for the manipulation
Matrix matrix = new Matrix();

// resize the bit map
matrix.postScale(newWidth / width, newHeight / height);

// recreate the new Bitmap and set it back
return Bitmap.createBitmap(bitmapToScale, 0, 0, bitmapToScale.getWidth(), bitmapToScale.getHeight(), matrix, true);  
} 

1

这里是我的静态方法:

public static void resizeImageFile(File originalImageFile, File resizedImageFile, int maxSize) {
    Bitmap bitmap = BitmapFactory.decodeFile(originalImageFile.getAbsolutePath());
    Bitmap resizedBitmap;
    if (bitmap.getWidth() > bitmap.getHeight()) {
        resizedBitmap = Bitmap.createScaledBitmap(bitmap, maxSize, maxSize * bitmap.getHeight() / bitmap.getWidth(), false);
    } else {
        resizedBitmap = Bitmap.createScaledBitmap(bitmap, maxSize * bitmap.getWidth() / bitmap.getHeight(), maxSize, false);
    }

    FileOutputStream fileOutputStream;
    try {
        fileOutputStream = new FileOutputStream(resizedImageFile);
        resizedBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
        fileOutputStream.flush();
        fileOutputStream.close();
        bitmap.recycle();
        resizedBitmap.recycle();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

1


0
最好使用多点触控来增加/减少宽度,而不是使用按钮。这里有一个很棒的库。一旦用户决定保存图像,图像转换矩阵必须被持久地存储(在您的SQLite数据库中)。下次用户打开图像时,您需要调用矩阵并将其应用于您的图像。
我以前做过这个。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接