2

几天来,我一直在努力。几周,也许。字面上地。:(

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

听着,我不是想在这里发射火箭。我要做的就是调整相机图像的大小并将其转储到 OutputStream 甚至是临时文件。肯定有人在外面做了这样的事情。我不需要你为我写代码,我也不需要我的手。但是在我的各种编程流产和痴迷谷歌搜索的日子里,我什至不知道该往哪个方向前进。粗略地说,有谁知道如何解码 JPEG,对其进行下采样,以 JPEG 重新压缩,然后发送出去在 OutputStream 上而不分配大量内存?

4

2 回答 2

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);
}

感谢这个链接

于 2014-07-14T20:36:02.473 回答
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;
    }
}
于 2013-04-24T05:26:07.013 回答