This is a general question regarding an algorithm to zoom an image to fit the width of a screen, there are some givens and some constraints. We can assume we are using Java but this question is more mathematical that language dependent.
First of all, the image loads and fits into the dimensions of the screen vertically first, not horizontally.
We can get the dimensions of the screen and the dimensions of the image with methods, but we cannot set the dimensions of either (We only have getters not setters).
imageWidth = image.getWidth(); //integer
imageHeight = image.getHeight(); //integer
screenWidth = screen.getWidth(); //integer
screenHeight = screen.getHeight(); //integer
The only method to resize the image is by setting scale (zooming essentially).
image.setScale(some float); // optionally image.setZoom(integer);
What I would like to know is how to calculate the scale (zoom) level for some l x h image so that it fits a L x H screen horizontally?
All you have to do to make the Image fill your screen is scale along the x axis:
scaling_factor = screen.getWidth()/image.getWidth()
image.setScale(zoom_factor);
The formula is very intuitive:
The image height is irrelevant. The scaling you desire would be the same for a landscape and vertical image, as long as the width of both images are the same
When the image's width increases, your scaling factor decreases
When your screen size increses, the scaling factor increases.
Related
I'm writing an app in Appcelerator that will be running different mobile screens. So, there will be many screen sizes and ratios.
Let me simply ask like this; I have an image object and I want it to protect its ratio on different screens.
How can I calculate the width & height of this object for different screens?
Object Sizes in 1920 X 1080 screen is 885 X 109.
(For example) What should be the sizes of 812 X 375(iPhone X size) screen?
Thanks in advance.
You can use
Alloy.Globals.WIDTH = (OS_ANDROID) ? Ti.Platform.displayCaps.platformWidth / Ti.Platform.displayCaps.logicalDensityFactor : Ti.Platform.displayCaps.platformWidth;
Alloy.Globals.HEIGHT = (OS_ANDROID) ? Ti.Platform.displayCaps.platformHeight / Ti.Platform.displayCaps.logicalDensityFactor : Ti.Platform.displayCaps.platformHeight;
to get the proper device size.
But I'm not sure if I understand the question. You don't need to do anything special about the aspect ration of your image on different devices. You can use Ti.UI.SIZE on width or height and a fixed value on the other property to keep the aspect ratio. E.g. if you image should always be 300dp width set the height to Ti.UI.SIZE.
If you want to adjust the image width to the device screen width but keep a left/right margin you can use
image.width = Ti.UI.FILL;
image.left = 10;
image.right = 10;
imahe.height = Ti.UI.SIZE;
For other calculations you can use the Alloy.Globals.WIDTH or Alloy.Globals.WIDTH from above (put it into alloy.js) and multiply it by the image ratio to get the other side.
I'm running a script that resizes images that are too large. I've used "resize_to_fit" to reduce images to a specific pixel size depending on the longer side, but I'm wondering if it's possible to do it with this logic instead: for any image whose width x height product is greater than a set value, resize the image so that the new width and height values are as large as possible while still being under that value. In other words, I don't want to arbitrarily resize the dimensions more than necessary, and I'd want to retain aspect ratio in this conversion. This may be more of a math question than a ruby one, but in any case, this is what I've tried:
image = Magick::Image.read(image_file)[0];
dimensions = image.columns, image.rows
resolution = dimensions[0] * dimensions[1]
if resolution > 4000000
resolution_ratio = 4000000 / resolution.to_f
dimension_ratio = dimensions[0].to_f * resolution_ratio
img = img.resize_to_fit(dimension_ratio,dimension_ratio)
img.write("#{image}")
end
So let's say an image has a width of 2793px and a height of 1970px. The resolution would be 5,502,210. It thus goes through the conditional statement, and as of right now, outputs a new width of 2030 and height of 1432. The product of these two is 2,906,960—which is obviously well under 4,000,000. But there are other possible width x height combinations whose product could be much closer to 4,000,000 pixels than 2,906,960 is. Is there a way of determining that information, and then resizing it accordingly?
You need to properly calculate the ratio, which is a square root from your desired dimension divided by (row multiplied by col):
row, col = [2793, 1970]
ratio = Math.sqrt(4_000_000.0 / (row * col))
[row, col].map &ratio.method(:*)
#⇒ [
# [0] 2381.400006266842,
# [1] 1679.6842149465374
#]
[row, col].map(&ratio.method(:*)).reduce(:*)
#∞ 3999999.9999999995
the background of my question is the following.
I have a picture and a crop rectangle which describes how the picture should be cropped to produce the resulting picture. The crop rectangle is always smaller or at maximum the size of the picture.
Now it should be possible to rotate the crop rectangle.
This means that when rotating the crop regtanle inside the picture, the crop must be scaled in order that its extends does not exceed the photo.
Can anybode help me with a formula of how to compute the scale of the crop rectanlge based on the axis aligned photo regtancle?
My first attempt was to compute a axis aligned bounding box of the crop rectanlge and than make this fit it the photo rectangle. But somehow i get stuck with this approach,
Edited:
One more think to note:
- The crop rectangle can have other dimension and another center point inside the surrounding rectangle. This means the crop rectangle can be much smaller but for example is located at the lower left bound of the picture rectangle. So when rotating the smaller crop it will also exceed its limits
Thanks in advance
Sebastian
When you rotate an axis-aligned rectangle of width w and height h by an angle φ, the width and height of the rotated rectangle's axis-aligned bounding box are:
W = w·|cos φ| + h·|sin φ|
H = w·|sin φ| + h·|cos φ|
(The notation |x| denotes an absolute value.) This is the bounding box of the rotated crop rectangle which you can scale to fit the original rectangle of width wo and height ho with the factor
a = min(wo / W, ho / H)
if a is less than 1, the rotated crop rectangle fits inside the original rectangle and you don't have to scale. Otherwise, reduce the crop rectangle to the scaled dimensions
W′ = a·W
H′ = a·H
You could start checking if the dimension of the cropped rectangle fit in the old rectangle:
bound_x = a * cos(theta) + b * sin(theta)
bound_y = b * cos(theta) + a * sin(theta)
Where a and b are the new dimensions, theta us the angle and bound_x and bound_y should be smaller of the original rectangle.
Let's assume we have a container with the size of 500 x 300 (w x h).
Inside this container we have a canvas with the same size, but with a different reference system inside it, with the size of 700 x 1000.
When I put an image of 700 x 1000 in this canvas it will obviously appear distorted, because the canvas occupies the entire 500 x 300 pixels of its parent container - even if inside it is still 700 x 1000.
Now, I am trying to figure out a formula to scale the image in the interlal reference system so the image doesn't appear distorted then loaded in the canvas.
Can anybody help?
First of all, if you have w = 700, h = 1000, i.e. w_container / w_canvas = 5/7 != h_container / h_canvas = 3/10, you will not be able to load you image not being distorted and taking entire space of the container. I just can tell you how to resize your image properly.
To save the width-height ratio of your image (equals 7/10, I think this is what you mean under "distorted image") you should calculate how your image's ratio rescales after putting the image on the canvas.
canvas_ratio(7/10) * x = container_ratio(5/3), hence x = 50/21. So if your image has the ratio y, then it will become y*x = y*50/21.
So you should just resize your image before putting it on the canvas such a way that after multiplying this ratio by x it would be 7/10 (the ratio when your image looks perfect). We have an equation y*50/21 = 7/10, hence y = 147/500. That's the ratio your image should have!
For example, you can make image size 294x1000, and after putting it to the canvas it will have height of 300 pixels in your container's coordinate system and 294*(500/700) = 210 pixel width (unfortunately, not 500). Hope this will be useful information for you.
Good luck!
I need to generate new dimensions for an image to match a ratio of a given width and height ...but without increasing the size of the original.
The concept seems oh so simple yet I can't seem to join the dots.
Also, for code samples the language is PHP.
Update:
This is what I have so far:
http://codepad.org/fTdCNhQf
This is the output I need:
Example Image • (can't embed yet)
Since enlarging is not an option, your only options are cropping and extending.
Try this: let's say your image is W*H, and the desired aspect ratio of width to height is R.
Using the width and the aspect ratio, calculate the target height TH = W/R
Using the height and the aspect ratio, calculate the target width TW = H*R
Calculate area changes aH = ABS(TH-H)*W and aW = ABS(TW-W)*H
if aH is less than aW, use target width; pad or crop the image horizontally based on the sign of TH-H
Otherwise, use target height; pad or crop the image vertically based on the sigh of TW-W
Here is a quick example:
Target R: 5/6
Image: W=200, H= 300;
TH = 200/5*6 = 240
TW = 300*5/6 = 250
aH = 60*200=12000
aW = 50*300=15000
Resulting action: since aH is less than aW, crop image vertically to 240
Are you using something like ImageMagick libraries to generate an image or do you just need to generate the new dimensions based on a known ratio? Also, do you need to discover the ratio from the existing image?
This may be useful then:
http://www.zedwood.com/article/119/php-resize-an-image-with-gd