2015-04-30 2 views
0

у меня есть изображение 3264х2448.Как уменьшить изображение без потери качества и сохранения соотношения сторон?

я загрузить его в растровом crudeImage = BitmapFactory.decodeFile(picturePath); затем установить в ImageView imageCrop.setImageBitmap(crudeImage); Проблема состоит в том, что это очень большой (3264х2448) и моя библиотека cropper

работают очень медленно с этим изображением. Я хочу уменьшить изображение до меньшего размера. но и сохранить качество и пропорцию. Как это может быть сделано?

+0

«Сделать это меньше» * означает * снижение качества. – chrylis

+0

это хорошо, но пусть потеря будет невелика.важно поддерживать соотношение сторон – ip696

+0

, или вам может и не понадобиться это делать, и я просто не могу понять, насколько моя библиотека работает медленнее при обработке больших изображений. – ip696

ответ

1

Вы должны прочитать Loading Large Bitmaps Efficiently.

По существу, рассчитать размер выборки сначала

public static int calculateInSampleSize(
      BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    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; 
     } 
    } 

    return inSampleSize; 
} 

затем загрузить изображение, используя размер выборки:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
     int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 
+0

, может быть, это глупо, но я не могу понять. У меня есть готовое растровое изображение. Как исправить метод decodeSampledBitmapFromResource? Я хочу дать ему растровое изображение. – ip696

+0

Вместо этого используйте 'BitmapFactory.decodeFile (путь, параметры)'. Вы можете прочитать другие связанные методы «BitmapFactory» из [doc] (http://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeFile%28java.lang.String%29) – goofyz

0

Я использую это, чтобы изменить размер растрового изображения. Может быть, может быть полезно для вас.

public Bitmap resizeBitmap(Bitmap bitmap, int newWidth, int newHeight) 
{ 
    //bitmap it's the bitmap you want to resize 
    //newWidth and newHeight are the with and height that you want to the new bitmap 
    int width = bitmap.getWidth(); 
    int height = bitmap.getHeight(); 
    float scaleWidth = ((float) newWidth)/width; 
    float scaleHeight = ((float) newHeight) /height; 

    Matrix matrix = new Matrix(); 
    matrix.postScale(scaleWidth, scaleHeight); 

    Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false); 
    return resizedBitmap; 
} 

Надеюсь, это поможет вам.

+0

int newWidth, int newHeight - вот в чем проблема. Я не знаю, что положить. потому что на большом экране на мощной потребности телефона, такой как старый 1280x720 800x600 – ip696

0

Если вы читаете учебник here вы увидите, Google дает очень подробное руководство по масштабированию растровых изображений без чрезмерного использования памяти.

В частности, эти два метода (из учебника):

public static Bitmap decodeSampledBitmapFromResource(File file, int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(file, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeFile(file, options); 
} 

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight){ 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    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; 
     } 
    } 

    return inSampleSize; 
} 

выполнит свое масштабирование, сохраняя пропорцию.

Трюк с этими двумя методами является то, что первая операция декодирования устанавливается только декодировать свойства об изображении (размеры и другую информацию), как установлено:

options.inJustDecodeBounds = true; 

, в котором новый масштабный коэффициент вычисляется пропорционально методом вычислениеInSampleSize().

Затем изображение декодируется снова, на этот раз с

options.inJustDecodeBounds = false; 

, а также масштабного коэффициента набора, так что растровое завод автоматически масштабирует во время декодирования, уменьшая объем памяти.

Какое разрешение изображения необходимо декодировать, это действительно зависит от вашего прецедента. Но, если конкретное изображение не должно быть увеличено позже, вам нужно не больше, чем физический размер экрана устройства, которое может быть получено с помощью:

Display display = getWindowManager().getDefaultDisplay(); 
Point size = new Point(); 
display.getRealSize(size); 

в каком объекте size будет держать размер экрана устройства.

Смежные вопросы