Make an image fit in a rectangle
If I have an image of which I know the height and the width, how can I f开发者_如何学Pythonit it in a rectangle with the biggest possible size without stretching the image.
Pseudo code is enough (but I'm going to use this in Java).
Thanks.
So, based on the answer, I wrote this: but it doesn't work. What do I do wrong?
double imageRatio = bi.getHeight() / bi.getWidth();
double rectRatio = getHeight() / getWidth();
if (imageRatio < rectRatio)
{
// based on the widths
double scale = getWidth() / bi.getWidth();
g.drawImage(bi, 0, 0, (int) (bi.getWidth() * scale), (int) (bi.getHeight() * scale), this);
}
if (rectRatio < imageRatio)
{
// based on the height
double scale = getHeight() / bi.getHeight();
g.drawImage(bi, 0, 0 , (int) (bi.getWidth() * scale), (int) (bi.getHeight() * scale), this);
}
Determine the aspect ratio of both (height divided by width, say, so tall, skinny rectangles have an aspect ratio > 1).
If your rectangle's aspect ratio is greater than that of your image, then scale the image uniformly based on the widths (rectangle width / image width).
If your rectangle's aspect ratio is less than that of your image, then scale the image uniformly based on the heights (rectangle height / image height).
Here is my two cents:
/**
* Calculate the bounds of an image to fit inside a view after scaling and keeping the aspect ratio.
* @param vw container view width
* @param vh container view height
* @param iw image width
* @param ih image height
* @param neverScaleUp if <code>true</code> then it will scale images down but never up when fiting
* @param out Rect that is provided to receive the result. If <code>null</code> then a new rect will be created
* @return Same rect object that was provided to the method or a new one if <code>out</code> was <code>null</code>
*/
private static Rect calcCenter (int vw, int vh, int iw, int ih, boolean neverScaleUp, Rect out) {
double scale = Math.min( (double)vw/(double)iw, (double)vh/(double)ih );
int h = (int)(!neverScaleUp || scale<1.0 ? scale * ih : ih);
int w = (int)(!neverScaleUp || scale<1.0 ? scale * iw : iw);
int x = ((vw - w)>>1);
int y = ((vh - h)>>1);
if (out == null)
out = new Rect( x, y, x + w, y + h );
else
out.set( x, y, x + w, y + h );
return out;
}
This will not affect your aspect ration and will fit exactly on one side and not overshoot on the other side.
public static Rect getScaled(int imgWidth, int imgHeight, int boundaryWidth, int boundaryHeight) {
int original_width = imgWidth;
int original_height = imgHeight;
int bound_width = boundaryWidth;
int bound_height = boundaryHeight;
int new_width = original_width;
int new_height = original_height;
// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
return new Rect(0,0,new_width, new_height);
}
精彩评论