2015-09-11 7 views
-1

Я хотел сжать/перемасштабировать изображение перед загрузкой. Вот код, который я использую для сжатия. Он отлично подходит для очень больших изображений, но этот particular image съел huge amount of RAM. Я связал необходимые изображения. Вот код, который я использую.Android-декодирование огромного объема памяти

Мне пришлось принудительно вызвать System.gc(), чтобы освободить слишком часто используемую память.

public static File compressImage(File image) throws IOException { 

     // Decode just the boundaries 
     final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 
     mBitmapOptions.inJustDecodeBounds = true; 

     final FileInputStream fileInputStream = new FileInputStream(image); 
     final Bitmap temporary = BitmapFactory.decodeStream(fileInputStream, null, mBitmapOptions); 
     if (temporary != null) 
      temporary.recycle(); 

     // Calculate inSampleSize 
     // Raw height and width of image 
     final int height = mBitmapOptions.outHeight; 
     final int width = mBitmapOptions.outWidth; 
     final int sideLength = 800; 
     closeQuietly(fileInputStream); 

     int reqHeight = height; 
     int reqWidth = width; 
     final int inDensity; 
     final int inTargetDensity; 

     if (height > width) { 

      inDensity = height; 
      inTargetDensity = reqHeight; 
      if (height > sideLength) { 

       reqHeight = sideLength; 
       reqWidth = (width * sideLength)/height; 
      } 
     } else if (width > height) { 

      inDensity = width; 
      inTargetDensity = reqWidth; 
      if (width > sideLength) { 
       reqWidth = sideLength; 
       reqHeight = (height * sideLength)/width; 
      } 
     } else { 

      reqWidth = sideLength; 
      reqHeight = sideLength; 
      inDensity = height; 
      inTargetDensity = reqHeight; 
     } 

     int inSampleSize = 1; 

     if (height > reqHeight || width > reqWidth) { 

      final int halfHeight = height/2; 
      final int halfWidth = width/2; 

      // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
      // height and width larger than the requested height and width. 
      while ((halfHeight/inSampleSize) > reqHeight && (halfWidth/inSampleSize) > reqWidth) 
       inSampleSize *= 2; 
     } 

     //now go resize the image to the size you want 
     mBitmapOptions.inSampleSize = inSampleSize; 
     mBitmapOptions.inDither = true; 
     mBitmapOptions.inPreferQualityOverSpeed = true; 
     mBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565; 
     mBitmapOptions.inJustDecodeBounds = false; 
     mBitmapOptions.inScaled = true; 
     mBitmapOptions.inDensity = inDensity; 
     mBitmapOptions.inTargetDensity = inTargetDensity * mBitmapOptions.inSampleSize; 

     final File tempFile = File.createTempFile("compressed_profile_photo", null); 
     final FileInputStream fInputStream = new FileInputStream(image); 
     final FileOutputStream fileOutputStream = new FileOutputStream(tempFile); 

     // will load & resize the image to be 1/inSampleSize dimensions 
     final Bitmap bitmap = BitmapFactory.decodeStream(fInputStream, null, mBitmapOptions); 
     bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fileOutputStream); 
     fileOutputStream.flush(); 
     bitmap.recycle(); 
     closeQuietly(fInputStream, fileOutputStream); 

     //noinspection ResultOfMethodCallIgnored 
     image.delete(); 
     return tempFile; 
    } 
+2

Изображение, на которое вы ссылаетесь, составляет 4208x5198 и будет принимать 4208 * 5198 * 2 = 41,7 МБ в формате RGB_565 только для отдельных пиксельных данных. Ваша диаграмма потребления памяти выглядит примерно так, поэтому вы получаете полноразмерное растровое изображение. Вызов 'System.gc()' может высвободить память раньше, но при вызове его вручную мало смысла, поскольку он будет отброшен в следующий раз, когда GC почувствует, что ему нужно (если у вас нет каких-либо требований в реальном времени и необходимо управлять сроками ГХ). – fadden

+0

Я попробовал изображение, которое в два раза превышает разрешение изображения, которое я связал, потребление памяти не было всплесками вообще. Вряд ли 5-10 mbs дополнительно. – Dexter

+1

Вы можете использовать трекер распределения DDMS (https://developer.android.com/tools/performance/allocation-tracker/index.html), чтобы точно определить, что выделяется, и откуда. – fadden

ответ

0

Был глупая ошибка в этой части:

if (height > width) { 

      inDensity = height; 
      inTargetDensity = reqHeight; 
      if (height > sideLength) { 

       reqHeight = sideLength; 
       reqWidth = (width * sideLength)/height; 
      } 
     } else if (width > height) { 

      inDensity = width; 
      inTargetDensity = reqWidth; 
      if (width > sideLength) { 
       reqWidth = sideLength; 
       reqHeight = (height * sideLength)/width; 
      } 
     } 

это должно быть так:

if (height > width) { 

      if (height > sideLength) { 

       reqHeight = sideLength; 
       reqWidth = (width * sideLength)/height; 
      } 
      inDensity = height; 
      inTargetDensity = reqHeight; 

     } else if (width > height) { 

      if (width > sideLength) { 
       reqWidth = sideLength; 
       reqHeight = (height * sideLength)/width; 
      } 
      inDensity = width; 
      inTargetDensity = reqWidth; 

     } 

Из-за этого изменения размера даже не происходит!

0

Возможно, просто следуйте the tip of the Official Training?

private void setPic() { 
    // Get the dimensions of the View 
    int targetW = mImageView.getWidth(); 
    int targetH = mImageView.getHeight(); 

    // Get the dimensions of the bitmap 
    BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
    bmOptions.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); 
    int photoW = bmOptions.outWidth; 
    int photoH = bmOptions.outHeight; 

    // Determine how much to scale down the image 
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH); 

    // Decode the image file into a Bitmap sized to fill the View 
    bmOptions.inJustDecodeBounds = false; 
    bmOptions.inSampleSize = scaleFactor; 
    bmOptions.inPurgeable = true; 

    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); 
    mImageView.setImageBitmap(bitmap); 
} 
Смежные вопросы