I have an array:
$resolutions = array(
'480x640',
'480x800',
'640x480',
'640x960',
'800x1280',
'2048x1536'
);
I want to retrieve closest larger value with the nearest aspect ratio (same orientation).
So, in case of $needle = '768x1280'
- 800x1280
.
And, in case of $needle = '320x240'
- 640x480
. While the closest here is 480x640
it shouldn't be matched, because its aspect ratio differs too much.
So on, and so forth.
Purpose:
I have a set of images with resolutions as specified in $resolutions
. Those images are going to be used for smartphone wallpapers.
With JavaScript, I am sending over a request with screen.width
and screen.height
to determine $needle
.
On the server side, I am going to fetch the closest larger value of the given resolution, scale it down to fit the whole screen while preserving aspect ratio, and if something overlaps the dimensions, crop it to perfectly fit the screen.
Problem:
While everything is pretty simple with scaling and cropping, I cannot think of a way to find out the closest larger value, to load the reference image.
Hints:
In case it helps, $resolutions
and $needle
can be in a different format, ie.: array('width' => x, 'height' => y)
.
Tries:
I tried to experiment with levenshtein distance: http://codepad.viper-7.com/e8JGOw
Apparently, it worked only for 768x1280
and resulted 800x1280
. For 320x240
it resulted in 480x640
but that does not fit this time.
Would it be easier if you had a single number to compare against?
It's a ratio, so just do, for example: 640 / 480 = 1.33*
Then you at least have something nice and simple to compare against the dimensions you are sending and presumably come up with a tolerance?
A simple example, which assume that the ratio array is ordered from lowest to highest. If this was a problem then we would create a search that ordered by the area (x by y).
I've built in a tolerance, so that it will match 'nearby' aspect ratios, as you allude to in your question.
This function should pass both test cases you have given.
Well, this turned out larger than I anticipated, but I think this meets the criteria. It works by breaking the available resolutions down to their ratio. Then sorting by the delta between the target ratio and the available ratios ascending, then by size (pixels) descending. Returning the top match - which should be the closest, smallest match.
Usage:
First of all, I would store the haystack using width first, height second:
Then, calculate dimension differences between needle and each item, followed by the area size:
Then you filter the list based on which resolutions are bigger; the first match is the one closest to the needle aspect ratio:
Try this
You can first extract the arrays like:
Then you can match the given needle with the array with
in_array
andarray_search
like:When you have the key just increment it for the closest greater value. I'll let you do that by yourself.
Made a quick class. Should competently find the minimum resolution for any two numbers that you specify. I have preloaded it with the resolutions you specified but the
$_resolutions
array could be set to whichever standards you like, and can also be changed on-the-fly.Example Usage