Android中的程序化图像大小调整,内存问题

时间:2013-04-24 05:17:55

标签: android image out-of-memory

天,我已经花在了这个上面。也许是几周。从字面上看。 :(

所以我在SD卡上有一张图像,很可能是内置摄像头出来的。我想拍摄该图像并将其下采样到任意大小(但总是更小,从不更大)。我的代码使用标准的Android Bitmap方法来解码,调整大小,重新压缩和保存图像。只要最终图像小于3MP左右,一切正常。如果图像较大,或者我尝试同时执行其中的几个,则应用程序会因OutOfMemoryError崩溃。我知道为什么会这样,我知道这是出于一个完全正当的理由,我只是希望它不再发生。

看,我不是想在这里发射火箭。我想要做的就是调整相机图像的大小并将其转储到OutputStream甚至是临时文件。当然有人在那里一定做过这样的事情。我不需要你为我编写代码,我也不需要手持。但在我的各种编程堕胎和痴迷谷歌的日子之间,我甚至都不知道要进入哪个方向。粗略地说,有没有人知道如何解码JPEG,对其进行缩减采样,以JPEG格式重新压缩,然后将其发送出去在没有分配大量内存的OutputStream上?

2 个答案:

答案 0 :(得分:3)

好的,我知道它有点迟了但是,我遇到了这个问题,我找到了解决办法。它实际上很容易,我相信它支持api 10(我在10之前不知道)。我用手机试过了。它是一个拥有8mp相机的三星Galaxy s2,代码完美地调整了相机图像到168x168以及我在网络上找到的图像。我也使用文件管理器检查了图像。我从未尝试过将图像调整为更大的重建。

private Bitmap resize(Bitmap bp, int witdh, int height){
    return Bitmap.createScaledBitmap(bp, width, height, false);
}

你可以像这样保存它

private void saveBitmap(Bitmap bp) throws FileNotFoundException{
    String state = Environment.getExternalStorageState();
    File folder;
    //if there is memory card available code choose that
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        folder=Environment.getExternalStorageDirectory();
    }else{
        folder=Environment.getDataDirectory();
    }
    folder=new File(folder, "/aaaa");
    if(!folder.exists()){
        folder.mkdir();
    }

    File file=new File(folder, (int)(Math.random()*10000)+".jpg");
    FileOutputStream os=new FileOutputStream(file);
    bp.compress(Bitmap.CompressFormat.JPEG, 90, os);
}

感谢这个link

答案 1 :(得分:0)

以下代码来自我之前的项目。关键点是“options.inSampleSize”。

public static Bitmap makeBitmap(String fn, int minSideLength, int maxNumOfPixels) {
    BitmapFactory.Options options;
    try {
        options = new BitmapFactory.Options();

        options.inPurgeable = true;
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(fn, options);
        if (options.mCancel || options.outWidth == -1
                || options.outHeight == -1) {
            return null;
        }
        options.inSampleSize = computeSampleSize(
                options, minSideLength, maxNumOfPixels);
        options.inJustDecodeBounds = false;
        //Log.e(LOG_TAG, "sample size=" + options.inSampleSize);

        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeFile(fn, options);
    } catch (OutOfMemoryError ex) {
        Log.e(LOG_TAG, "Got oom exception ", ex);
        return null;
    }
}

private static int computeInitialSampleSize(BitmapFactory.Options options,
        int minSideLength, int maxNumOfPixels) {
    double w = options.outWidth;
    double h = options.outHeight;

    int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
            (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
    int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
            (int) Math.min(Math.floor(w / minSideLength),
            Math.floor(h / minSideLength));

    if (upperBound < lowerBound) {
        // return the larger one when there is no overlapping zone.
        return lowerBound;
    }

    if ((maxNumOfPixels == UNCONSTRAINED) &&
            (minSideLength == UNCONSTRAINED)) {
        return 1;
    } else if (minSideLength == UNCONSTRAINED) {
        return lowerBound;
    } else {
        return upperBound;
    }
}