Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine which aspect ratios are closest

Given a rectangular shape S, with aspect ratio sx/sy, and two other rectangular shapes A (with aspect ratio ax/ay) and B (with aspect ratio bx/by) how can I find out which of shape A or B has the closest aspect ratio to S? The shapes' sizes are unimportant.

Is it just whichever of (sx/sy)/(ax/ay) and (sx/sy)/(bx/by) is closest to 1?

What I am actually trying to do is find out which shape on a PPTX slide would best fit an image that will be resized and then cropped to fit that shape. I guess another approach would be to work out which shape results in the fewest pixels being lost, although in my code it will be easier if I can do it by comparing aspect ratios.

In the end I went with the algorithm below, implemented as follows (thanks to Matt Ball for his feedback):

ShapeInPPTXLocation closest;
double imageAR = a_imageDim.getWidth()/a_imageDim.getHeight();
double aspectRatioCandidateA = a_candidateA.getWidth()/a_candidateA.getHeight();
double aspectRatioCandidateB = a_candidateB.getWidth()/a_candidateB.getHeight();
double closenessScoreA=1-(imageAR/aspectRatioCandidateA);
double closenessScoreB=1-(imageAR/aspectRatioCandidateB);

if (Math.abs(closenessScoreA) <= Math.abs(closenessScoreB))
{
    closest=a_candidateA;
}
else
{
    closest=a_candidateB;
}
like image 354
Martin Wilson Avatar asked May 02 '12 15:05

Martin Wilson


1 Answers

Is it just whichever of (sx/sy)/(ax/ay) and (sx/sy)/(bx/by) is closest to 1?

That sounds reasonable. You could also just minimize the difference:

let target_ratio = sx/sy
let a_ratio = ax/ay
let b_ration = bx/by

if |target_ratio - a_ratio| < |target_ratio - b_ratio|
    a_ratio is closer to target
else
    b_ratio is closer to target

Update: the algorithm in this answer does not quite work, as explained in the comments below. The OP updated his question to include the algorithm that he used, which works seems to work fine.

like image 126
Matt Ball Avatar answered Oct 03 '22 02:10

Matt Ball