2013-02-27 5 views
11

Я ищу решение для следующей проблемы: как изменить размер Bitmap на фиксированный размер (например, 512x128). Соотношение сторон содержимого растрового изображения должно быть сохранено.Изменение размера растрового изображения до фиксированного значения, но без изменения соотношения сторон

Я думаю, что это должно быть что-то вроде этого:

  • создать пустой 512x128 растрового

  • масштаба оригинальные растровые вниз, чтобы соответствовать 512x128 пикселей с сохранением пропорций

  • скопируйте масштаб в пустую растровую карту (по центру)

Каков самый простой способ достичь этого?

Причина в том, что GridView испортил компоновку, когда соотношение сторон изображения отличается от другого. Вот скриншот (все изображения, кроме последнего, имеют соотношение сторон 4: 1):

screenshot

ответ

25

Попробуйте это, вычислите соотношение, а затем перемасштабируйте.

private Bitmap scaleBitmap(Bitmap bm) { 
    int width = bm.getWidth(); 
    int height = bm.getHeight(); 

    Log.v("Pictures", "Width and height are " + width + "--" + height); 

    if (width > height) { 
     // landscape 
     float ratio = (float) width/maxWidth; 
     width = maxWidth; 
     height = (int)(height/ratio); 
    } else if (height > width) { 
     // portrait 
     float ratio = (float) height/maxHeight; 
     height = maxHeight; 
     width = (int)(width/ratio); 
    } else { 
     // square 
     height = maxHeight; 
     width = maxWidth; 
    } 

    Log.v("Pictures", "after scaling Width and height are " + width + "--" + height); 

    bm = Bitmap.createScaledBitmap(bm, width, height, true); 
    return bm; 
} 
+2

плюс один добавленный для простого решения. Но я бы изменил отношение int к коэффициенту float/double, поскольку int/int может генерировать исключения, когда он пытается делить на 0. –

+0

Удивительное простое решение! Однако использование float вместо ints обязательно. В противном случае результат может быть неправильным большую часть времени (например, отношение становится равным 1, когда оно должно быть 1,4). – xip

+0

@ Хикару, ты прав, хотел сделать это, но так и не добрался до него. Спасибо за редактирование и напоминание -) –

0

https://developer.android.com/reference/android/graphics/Bitmap.html#createScaledBitmap(android.graphics.Bitmap, int, int, boolean)

и убедитесь, что оба dstWidth и dstHeight получаются из src.getWidth()*scale и src.getHeight()*scale , где scale - это значение, которое необходимо определить, чтобы удостовериться, что масштабированное растровое изображение находится внутри 512x128.

+0

'createScaledBitmap' не решает мою проблему. Это то, что я уже использую. В этом примере последнее изображение было масштабировано таким образом. –

+0

Если у вас уже есть уменьшенное растровое изображение (ширина меньше 512 или высота меньше 128 в вашем примере), просто установите эти атрибуты в ImageView вашего элемента GridView для android: layout_width = "512dp" и android: layout_height = "128dp »android: scaleType =« center »или андроид: scaleType =« centerInside » –

+0

Согласно моему объяснению, последнее изображение в примере уже уменьшено, поэтому оно уже макс. 128 пикселей. Несмотря на это, изображение отображает его больше, чем другие изображения. Также мне не нужен вид изображения с сеткой 512x128dp. –

2

Я наткнулся на ту же проблему несколько раз в своих проектах и ​​каждый раз из-за нехватки времени (и лени) я был бы доволен менее оптимальным решением. Но недавно я нашел некоторое время, чтобы решить эту проблему. Вот мое решение, и я надеюсь, что это поможет кому-то по линии ...

Bitmap scaleDownLargeImageWithAspectRatio(Bitmap image) 
      { 
       int imaheVerticalAspectRatio,imageHorizontalAspectRatio; 
       float bestFitScalingFactor=0; 
       float percesionValue=(float) 0.2; 

       //getAspect Ratio of Image 
       int imageHeight=(int) (Math.ceil((double) image.getHeight()/100)*100); 
       int imageWidth=(int) (Math.ceil((double) image.getWidth()/100)*100); 
       int GCD=BigInteger.valueOf(imageHeight).gcd(BigInteger.valueOf(imageWidth)).intValue(); 
       imaheVerticalAspectRatio=imageHeight/GCD; 
       imageHorizontalAspectRatio=imageWidth/GCD; 
       Log.i("scaleDownLargeImageWIthAspectRatio","Image Dimensions(W:H): "+imageWidth+":"+imageHeight); 
       Log.i("scaleDownLargeImageWIthAspectRatio","Image AspectRatio(W:H): "+imageHorizontalAspectRatio+":"+imaheVerticalAspectRatio); 

       //getContainer Dimensions 
       int displayWidth = getWindowManager().getDefaultDisplay().getWidth(); 
       int displayHeight = getWindowManager().getDefaultDisplay().getHeight(); 
       //I wanted to show the image to fit the entire device, as a best case. So my ccontainer dimensions were displayWidth & displayHeight. For your case, you will need to fetch container dimensions at run time or you can pass static values to these two parameters 

       int leftMargin = 0; 
       int rightMargin = 0; 
       int topMargin = 0; 
       int bottomMargin = 0; 
       int containerWidth = displayWidth - (leftMargin + rightMargin); 
       int containerHeight = displayHeight - (topMargin + bottomMargin); 
       Log.i("scaleDownLargeImageWIthAspectRatio","Container dimensions(W:H): "+containerWidth+":"+containerHeight); 

       //iterate to get bestFitScaleFactor per constraints 
       while((imageHorizontalAspectRatio*bestFitScalingFactor <= containerWidth) && 
         (imaheVerticalAspectRatio*bestFitScalingFactor<= containerHeight)) 
       { 
        bestFitScalingFactor+=percesionValue; 
       } 

       //return bestFit bitmap 
       int bestFitHeight=(int) (imaheVerticalAspectRatio*bestFitScalingFactor); 
       int bestFitWidth=(int) (imageHorizontalAspectRatio*bestFitScalingFactor); 
       Log.i("scaleDownLargeImageWIthAspectRatio","bestFitScalingFactor: "+bestFitScalingFactor); 
       Log.i("scaleDownLargeImageWIthAspectRatio","bestFitOutPutDimesions(W:H): "+bestFitWidth+":"+bestFitHeight); 
       image=Bitmap.createScaledBitmap(image, bestFitWidth,bestFitHeight, true); 

       //Position the bitmap centre of the container 
       int leftPadding=(containerWidth-image.getWidth())/2; 
       int topPadding=(containerHeight-image.getHeight())/2; 
       Bitmap backDrop=Bitmap.createBitmap(containerWidth, containerHeight, Bitmap.Config.RGB_565); 
       Canvas can = new Canvas(backDrop); 
       can.drawBitmap(image, leftPadding, topPadding, null); 

       return backDrop; 
      } 
18

Ответ Коэна Дамена не всегда учитывает максимальную высоту и максимальную ширину. Вот такой ответ:

private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) { 
    if (maxHeight > 0 && maxWidth > 0) { 
     int width = image.getWidth(); 
     int height = image.getHeight(); 
     float ratioBitmap = (float) width/(float) height; 
     float ratioMax = (float) maxWidth/(float) maxHeight; 

     int finalWidth = maxWidth; 
     int finalHeight = maxHeight; 
     if (ratioMax > 1) { 
      finalWidth = (int) ((float)maxHeight * ratioBitmap); 
     } else { 
      finalHeight = (int) ((float)maxWidth/ratioBitmap); 
     } 
     image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true); 
     return image; 
    } else { 
     return image; 
    } 
} 
+0

краже моего ответа в порядке. конечно, maxWidth и maxHeight являются переменными класса вместо параметров метода. –

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