Image Downscaling - image

I need a bit of a clarification on this Process.
I am trying to downsize from 6000 * 4000 pixel to 960 * 960 for website space purpose using MagickImageMagic.
Would doing the same from 2000 * 2000 to 960 * 960 make any impact on the quality of the image.
I need some understanding weather I should proceed with capturing with resolution close to the target or should I go for high resolution for better quality.
var imageforLightbox = new MagickImage(Path.Combine(SOURCE_PATH, filename));
MagickGeometry size = new MagickGeometry(1920, 1080);
size.IgnoreAspectRatio = false;
imageforLightbox.Resize(size);

Related

Preserving aspect ratio when using torch's image.display

I have the following very simple script written in lua. I am running it with qlua.
require "image"
input_image = image.load(arg[1])
image.display{image = input_image}
If the image is large the qt window simply takes the whole screen, which also stretches the image to fit the screen.
I can't figure out a way to keep this from happening.
Thanks!
If the image is large, resize it down to what you can configure as "Max height/Max width", while preserving the aspect ratio.
Sample code:
maxSize = 480
-- find the smaller dimension, and resize it to maxSize (while keeping aspect ratio)
local iW = input:size(3)
local iH = input:size(2)
if iW < iH then
input = image.scale(input, maxSize, maxSize * iH / iW)
else
input = image.scale(input, maxSize * iW / iH, maxSize)
end

GUI Button for all screen resolutions

I am using OnGUI Buttons on a car game and attached forward and backward buttons on it. But they keep on adjusting on all screens badly.
I have tried various online solutions, but failed. I am using this:
GUI.RepeatButton (new Rect (Screen.width - 780, Screen.height - 130, 120, 120), LeftBtnTexture, TransparentStyle)
I know this is wrong, what will be alternative width and height setting for all screens. :(
Take a look at Screen.dpi - http://docs.unity3d.com/ScriptReference/Screen-dpi.html
It will allow you to specify button size in inches. But be aware that dpi could be unavailable (equals zero) or maybe even incorrect, therefore you should do some sanity check. For example:
public float sizeInInches = 0.5;
float dpi = Screen.dpi;
if (dpi < 25 || dpi > 800) {
dpi = 150;
}
float sizeInPx = sizeInInches * dpi;
As an alternative for some cases, you may want to set GUI element size in percent of screen dimensions, like sizeInPx = Screen.width * 0.1;

Scaling an image proportionally based on the image's dimensions and my restriction size

Looking for an expression that allows me to accomplish this:
I have an image of arbitrary width/height, whose dimensions I can grab before I draw it.
Because the image may be very large, I want to scale it down.
My canvas is going to have width w and height h.
For illustration purposes let's just say it's 320x240.
If the dimensions of the image are equal or smaller than the dimensions of the canvas, then the scale ratio is just 1.
If they are larger, I will scale it proportional to how much larger it is compared to the canvas size.
So for example if my image is 640x480, my scale ratio will be 0.5
If my image is 640x240, my scale ratio would still be 0.5
Similarly if it were 320x480
Can this be written in a single math expression? For ex:
def scale_ratio(canvas_width, canvas_height, image_width, image_height)
#math formula for calculating scale
return scale
function scale(canvas_width, canvas_height, image_width, image_height) {
return Math.min(Math.max(canvas_width / image_width, canvas_height / image_height), 1);
}
EDIT: You might want to do something like this to reduce rounding errors:
var scale_width = image_width;
var scale_height = image_height;
if (image_width > canvas_width || image_height > canvas_height) {
var image_ratio = image_height / image_width;
if (image_ratio * canvas_width > canvas_height) {
scale_width = canvas_height / image_ratio;
scale_height = canvas_height;
} else {
scale_width = canvas_width;
scale_height = image_ratio * canvas_width;
}
}

Resize image by pixel amount

I tried to find out, but I couldn't.
A image, for example, 241x76 has a total of 18,316 pixels (241 * 76).
The resize rule is, the amount of pixels cannot pass 10,000.
Then, how can I get the new size keeping the aspect ratio and getting less than 10,000 pixels?
Pseudocode:
pixels = width * height
if (pixels > 10000) then
ratio = width / height
scale = sqrt(pixels / 10000)
height2 = floor(height / scale)
width2 = floor(ratio * height / scale)
ASSERT width2 * height2 <= 10000
end if
Remember to use floating-point math for all calculations involving ratio and scale when implementing.
Python
import math
def capDimensions(width, height, maxPixels=10000):
pixels = width * height
if (pixels <= maxPixels):
return (width, height)
ratio = float(width) / height
scale = math.sqrt(float(pixels) / maxPixels)
height2 = int(float(height) / scale)
width2 = int(ratio * height / scale)
return (width2, height2)
An alternative function in C# which takes and returns an Image object:
using System.Drawing.Drawing2D;
public Image resizeMaxPixels(int maxPixelCount, Image originalImg)
{
Double pixelCount = originalImg.Width * originalImg.Height;
if (pixelCount < maxPixelCount) //no downsize needed
{
return originalImg;
}
else
{
//EDIT: not actually needed - scaleRatio takes care of this
//Double aspectRatio = originalImg.Width / originalImg.Height;
//scale varies as the square root of the ratio (width x height):
Double scaleRatio = Math.Sqrt(maxPixelCount / pixelCount);
Int32 newWidth = (Int32)(originalImg.Width * scaleRatio);
Int32 newHeight = (Int32)(originalImg.Height * scaleRatio);
Bitmap newImg = new Bitmap(newWidth, newHeight);
//this keeps the quality as good as possible when resizing
using (Graphics gr = Graphics.FromImage(newImg))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(originalImg, new Rectangle(0, 0, newWidth, newHeight));
}
return newImg;
}
}
with graphics code from the answer to Resizing an Image without losing any quality
EDIT: Calculating the aspect ratio is actually irrelevant here as we're already scaling the width and height by the (square root) of the total pixel ratio. You could use it to calculate the newWidth based on the newHeight (or vice versa) but this isn't necessary.
Deestan's code works for square images, but in situations where the aspect ratio is different than 1, a square root won't do. You need to take scale to the power of aspect ratio divided by 2.
Observe (Python):
def capDimensions(width, height, maxPixels):
pixels = width * height
if (pixels <= maxPixels):
return (width, height)
ratio = float(width) / height
scale = (float(pixels) / maxPixels)**(width/(height*2))
height2 = round(float(height) / scale)
width2 = round(ratio * height2)
return (width2, height2)
Let's compare the results.
initial dimensions: 450x600
initial pixels: 270000
I'm trying to resize to get as close as possible to 119850 pixels.
with Deestan's algorithm:
capDimensions: 300x400
resized pixels: 67500
with the modified algorithm:
capDimensions. 332x442
resized pixels: 82668
width2 = int(ratio * height / scale)
would better be
width2 = int(ratio * height2)
because this would potentially preserve the aspect ratio better (as height2 has been truncated).
Without introducing another variable like 'sc', one can write
new_height = floor(sqrt(m / r))
and
new_width = floor(sqrt(m * r))
given m=max_pixels (here: 10.000), r=ratio=w/h (here: 241/76 = 3.171)
Both results are independent of each other! From each new_value, you can calculate the other dimension, with
(given: new_height) new_width = floor(new_height * r)
(given: new_width) new_height = floor(new_width / r)
Because of clipping the values (floor-function), both pairs of dimensions may differ in how close their ratio is to the original ratio; you'd choose the better pair.
Scaling images down to max number of pixels, while maintaining aspect ratio
This is what I came up with this afternoon, while trying to solve the math problem on my own, for fun. My code seems to work fine, I tested with a few different shapes and sizes of images. Make sure to use floating point variables or the math will break.
Pseudocode
orig_width=1920
orig_height=1080
orig_pixels=(orig_width * orig_height)
max_pixels=180000
if (orig_pixels <= max_pixels) {
# use original image
}
else {
# scale image down
ratio=sqrt(orig_pixels / max_pixels)
new_width=floor(orig_width / ratio)
new_height=floor(orig_height / ratio)
}
Example results
1920x1080 (1.77778 ratio) becomes 565x318 (1.77673 ratio, 179,670 pixels)
1000x1000 (1.00000 ratio) becomes 424x424 (1.00000 ratio, 179,776 pixels)
200x1200 (0.16667 ratio) becomes 173x1039 (0.16651 ratio, 179,747 pixels)

Resizing images maintaining aspect ratio

I want to resize the images while maintaining the aspect ratio for displaying images on the web page. The maximum image size can be 640x480. What equation can be used to resize the images? I don't care about the newly resized image size. The resolution should be near to 640x480 pixels
I explain using C pseudo-code. First calculate the aspect ratio of the image you want to resize ("testImage"):
double rat = (double)testImage.Width / (double)testImage.Height;
Then we compare it with the aspect ratio of a 640x480 picture. If testImage's ratio ("rat") is bigger than the ratio of a 640x480 picture, then we know if we resize the picture so that its Width becomes 640, its height will not be more than 480. If testImage's aspect ratio is smaller, then we can resize the picture so that height becomes 480 without the width exceeding 640 pixels.
const double rat640x480 = 640.0 / 480.0;
if (rat > rat640x480)
testImage.Resize(Width := 640, Height := 640 / rat);
else
testImage.Resize(Width := 480 * rat, Height := 480);
Code in JAVA becomes
double ratio640x480 = 640.0 / 480.0;
double sourceRatio = (double) bitmap.getWidth() / (double) bitmap.getHeight();
if (sourceRatio > ratio640x480)
bitmap = Bitmap.createScaledBitmap(bitmap, 640, (int) (640 / sourceRatio), true);
else
bitmap = Bitmap.createScaledBitmap(bitmap, (int) (480 * sourceRatio), 480, true);

Resources