2013-04-24 76 views
2

天,我花了这个工作。也许是几个星期。从字面上看。 :(Android中的编程图像调整大小,内存问题

所以我有一个SD卡上的图像,很可能是从内置相机出来的,我想拍摄该图像并将其缩小到任意大小(但始终更小,并且不会更大)。我的代码使用标准的Android位图方法来解码,调整大小,重新压缩和保存图像。只要最终图像小于3MP左右,一切都可以正常工作。如果图像较大,或者如果我尝试做几个这些应用程序一旦崩溃,就会发生OutOfMemoryError事件,我知道为什么会发生这种情况,而且我知道这是出于完全合法的原因,我只是希望它不会再发生了。在这里启动一个火箭,我想要做的就是调整一个摄像头图像并将其转储到一个OutputStream或甚至是一个临时文件乐。当然有人在那里肯定做过这样的事情。我不需要你为我写代码,也不需要我的手。但是,在我的各种编程堕胎和痴迷谷歌搜索的日子之间,我甚至不知道应该走哪个方向。粗略地说,没有人知道如何解码JPEG,对其进行下采样,将其重新压缩为JPEG,然后发送出去在OutputStream上没有分配大量的内存?

+0

喜欢请发表您的logcat,会帮助你 – umesh 2013-04-24 05:24:53

+0

你能告诉你想最后用此图片做什么,我的意思是上传或显示在ImageView等.. – SREEJITH 2013-04-24 05:29:24

+0

嘿adi,为什么你不试试@Evan Lis解决方案,这是最好的,调整和显示图像的视野。 – umesh 2013-04-24 05:34:22

回答

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; 
    } 
} 
+0

最佳答案,它的唯一办法 – umesh 2013-04-24 05:35:07

3

好吧我知道这有点晚了,但是,我有这个问题,我找到了解决办法。这实际上很简单,我相信它支持回api 10(我不知道10之前)。我用我的手机试了一下。这是一个带有8mp照相机的三星Galaxy S2,代码将照相机图像完美调整为168x168以及我在网上找到的图像。我也使用文件管理器检查了图像。我从来没有尝试调整图像大小resoulation。

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