2013-02-27 3 views
11

Bitmap의 크기를 고정 크기 (예 : 512x128)로 변경하는 방법에 대한 해결책을 찾고 있습니다. 비트 맵 내용의 종횡비는 보존되어야합니다.고정 값으로 비트 맵의 ​​크기를 조정했지만 종횡비를 변경하지 않고

는 나는 이런 식으로 뭔가해야한다고 생각 :

  • 규모 원본 비트 맵 다운 가로 세로 비율

  • 를 유지으로 512x128 픽셀에 맞게 빈 512x128 비트 맵을 만들 크기를 비어있는 비트 맵에 복사 (가운데 맞춤)

이것을 달성하는 가장 간단한 방법은 무엇입니까?

이유는 이미지의 종횡비가 다른 경우 GridView은 레이아웃을 엉망으로 만듭니다. 여기서 스크린 샷이다 (1 마지막 제외한 모든 이미지 (4)의 종횡비가)

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/int가 0으로 나누기를 시도 할 때 예외를 생성 할 수 있기 때문에 int/ratio를 float/double ratio로 변경합니다. –

+0

굉장히 간단한 해결책! int 대신 float를 사용하는 것은 필수 다. 그렇지 않으면 대부분의 경우 결과가 잘못 될 수 있습니다 (예 : 1.4 일 때 비율이 1이 됨). – xip

+0

@Hikaru 당신이 옳다는 것을 원했지만 그렇게하고 싶지는 않았습니다. 편집 및 알림 주셔서 감사합니다 -) –

0

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

를 상기 dstWidthdstHeight 모두 src.getWidth()*scalesrc.getHeight()*scale로부터 수득되었는지 확인 여기서 scale은 스케일 된 비트 맵이 512x128 안에 들어 있는지 확인해야하는 값입니다.

+0

'createScaledBitmap'는 내 문제를 해결하지 못합니다. 그게 내가 이미 사용하는거야. 이 예에서 마지막 이미지는 그런 식으로 축척되었습니다. –

+0

크기가 축소 된 비트 맵 (너비가 512보다 작거나 높이가 128보다 작은 경우)의 경우 GridView 항목의 ImageView에서 이러한 속성을 android : layout_width = "512dp"및 android : layout_height = "128dp로 설정하면됩니다 "android : scaleType ="center "또는 android : scaleType ="centerInside " –

+0

내 설명에 따르면 예제의 마지막 이미지는 이미 축소되어 있으므로 이미 최대 크기입니다. 128px 높이. 그럼에도 불구하고, 이미지보기는 다른 이미지보다 크게 표시합니다. 또한 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

Coen Damen의 대답이 Max Height 및 Max Width를 항상 존중하지는 않습니다. 대답은 다음과 같습니다.

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는 params 대신에 클래스 변수입니다. –

관련 문제