Convert Resolutions depending on which Resolution the user is running - c#

Im making a Program which makes stuff Easier for a Game with fast Inputs. Since my Tool right now is only for 1920x1080 and i want to get it going for multiple Resolutions. Thats how i have it right now for 1920x1080.
SetCursorPos(105, 640);
System.Threading.Thread.Sleep(30);
sim.Mouse.LeftButtonClick();
System.Threading.Thread.Sleep(30);
SetCursorPos(274, 547);
System.Threading.Thread.Sleep(30);
sim.Mouse.LeftButtonClick();
System.Threading.Thread.Sleep(1560);
sim.Keyboard.KeyPress(VirtualKeyCode.VK_T);
System.Threading.Thread.Sleep(50);
SetCursorPos(274, 547);
sim.Mouse.LeftButtonClick();
System.Threading.Thread.Sleep(1610);
SetCursorPos(274, 547);
sim.Mouse.LeftButtonClick();
System.Threading.Thread.Sleep(1610);
SetCursorPos(274, 547);
sim.Mouse.LeftButtonClick();
SetCursorPos(960, 540);
I kinda want the Program detects the actual Screen Resolution and converts the Pixel Location from 1920x1080 to its needed Locations.

Theoretically...store your (x, y) coordinates as decimal numbers representing the "percentage" of the original resolution you developed them in.
For instance, your first point is (105, 640). As a "percentage point", divide the x-coordinate by 1920, and the y-coordinate by 1080 to get (0.0546875, 0.5925925925925926). This can be stored using the PointF structure.
Now you can use those decimal percentage numbers to get the desired equivalent point in any resolution by simply multiplying them by the width/height of the screen.
You can get the current screen resolution using Screen.Bounds:
Rectangle rc = Screen.PrimaryScreen.Bounds;

What you need is Scaling.
You've coded for a fixed resultion of 1920x1080. I.e. 1920 pixels width and 1080 pixels height.
If you need to scale this you can get the current screen resultion and then calculate the ratio.
Let's say the resolution is 640x480. Then you'd calculate the X (or width) ratio with:
640 / 1920 = 0.3333...
and the Y (or height) ratio with:
480 / 1080 = 0.4444...
To scale you now multiply width and height with respective ratio:
SetCursorPos(105 * 0.3333, 640 * 0.4444)
In code it would look something like:
int currentX = SystemParameters.PrimaryScreenHeight;
int currentY = SystemParameters.PrimaryScreenWidth;
var xScale = currentX / 1920;
var yScale = currenty / 1080;
SetCursorPos(105 * xScale, 640 * yScale);

Related

Calculate coordinates rectangle for picture cropping, when picture bigger than rectangle

I'm developing my own picture viewer and in the process of creating an image cropping method. It does work with my current code. However, the application is dynamically resizing the image to fit the user's screen. So when it is resized, the calculated X.Y coordinates of the image are incorrect. I'm not very good at math, so I don't know how to calculate that.
This is the code that I am using
internal static Int32Rect GetCrop()
{
var cropArea = cropppingTool.CropTool.CropService.GetCroppedArea();
var x = Convert.ToInt32(cropArea.CroppedRectAbsolute.X);
var y = Convert.ToInt32(cropArea.CroppedRectAbsolute.Y);
var width = Convert.ToInt32(cropArea.CroppedRectAbsolute.Width);
var height = Convert.ToInt32(cropArea.CroppedRectAbsolute.Height);
return new Int32Rect(x, y, width, height);
}
The cropArea variable is from my own modified version of https://github.com/dmitryshelamov/UI-Cropping-Image. It is a Rect that returns X and Y coordinates and width and height from the user drawn square, used to select cropping area of image.
I have the variables for resized image width and height, and the original pixel width and pixel height of the images. The cropping UI uses the resized variables, to fit on the user's screen.
For clarity, the image size is calculated as so, with image control set to Stretch.Fill
double width = sourceBitmap.PixelWidth;
double height = sourceBitmap.PixelHeight;
double maxWidth = Math.Min(SystemParameters.PrimaryScreenWidth - 300, width);
double maxHeight = Math.Min(SystemParameters.PrimaryScreenHeight - 300, height);
var aspectRatio = Math.Min(maxWidth / width, maxHeight / height);
width *= aspectRatio;
height *= aspectRatio;
image.Width = width;
image.Height = height;
So the question is, how do I calculate the offset between rendered size and actual pixel size?
If I understand this: you've calculated a ratio named aspectRatio to scale the image from it's actual size to the size of the screen. You have a cropping tool that gives you coordinates based on the scaled size image, and you want to convert those coordinates so they can be applied to the image's original size.
Assuming the above is right, this should be simple.
If the scaled height and width are calculated by:
scaledWidth = originalWidth * ratio
scaledHeigth = originalHeigth * ratio
Then you can reverse the multiplication by dividing instead:
originalWidth = scaledWidth / ratio
originalHeight = scaledHeight / ratio
This also applies to any coordinates within the image. You can take coordinates from the scaled image, and convert them into coordinates for the original image like so:
originalX = scaledRect.X / ratio
originalY = scaledRect.Y / ratio
originalWidth = scaledRect.Width / ratio
originalHeight = scaledRect.Height / ratio
You'll have to be careful to make sure that none of the values of scaledRect are 0, since division and 0 don't mix. A value of 0 in the scaled coordinate will also translate to 0 in the original coordinate space, so 0 should just stay 0. You can do this with if statements.

When image size change, how do you calculate to counter the real-size coordinate value?

I want to know the coordinates value when the image is stretched from the center.
I know one pixel coordinate in texture image, and I'm using ray cast by matching it to mobile screen.
But I don't know how the coordinate value changes when the image grows.
When images grow, how do you calculate to counter the real-size coordinate value?
The image will increase to 1.33f size.
There may be simpler ways in Unity3D - I don't have any experience there - but this sounds like a fairly simple scaling problem.
You'll need to know the following:
The image coordinates of the centre of the image
This is the vector (width/2, height/2)
The screen coordinates of the centre of the image
Where the center of the image is on the screen
The scaling factor (1.33f in this example)
Given the above you can calculate the pixel being touched using simple math:
public Vector2Int ScaleTouch(Vector2Int imgCentre, Vector2Int dispCentre, float scale, Vector2Int touch)
{
var x = imgCentre.x + (touch.x - dispCentre.x) * scale;
var y = imgCentre.y + (touch.y - dispCentre.y) * scale;
return Vector2Int.RoundToInt(new Vector2(x, y));
}
Or using the methods in Vector2 and Vector2Int you might be able to do this:
public Vector2Int ScaleTouch(Vector2Int imgCentre, Vector2Int dispCentre, float scale, Vector2Int touch)
{
var offset = Vector2.Scale(touch - dispCentre, new Vector2(scale, scale));
return offset + imgCentre;
}
Both assume that your scale is homogeneous in x and y. You could provide a scale vector if you want it to be flexible about scaling in different axes.

Recalculating pixel coordinates after making an image smaller but the same aspect ratio

If I have a PDF page that is 8.5in x 11in # 300 DPI.
It ends up being 2550px x 3300px.
Lets say there are a few X and Y coordinates on the location of a text character from when it was still a PDF such as:
X: 1281.6 and Y: 1022.4
or
1281.6 from the left and 1022.4px from the top
Now if I convert the PDF to an image and I would want the image to be smaller such as 816px x 1056px. This would be same aspect ratio but at 96 dpi instead of 300.
I am trying to figure out what the calculation would be to convert the X and Y coordinates of the text character to their smaller versions.
Like a percentage:
newx = oldx * (newwidth / oldwidth)
newy = oldy * (newheight / oldheight)
Note that if your widths/heights are ints, cast one of them to double - 1000/2000 is 0, which does rather screw up the maths :) (1000.0/2000 or 1000/2000.0 on the other hand is 0.5)

Resizing an image in cm C#

I have an requirement that asks for an image with 10 X 6,88 cm.
I know that I can't simple convert from cm to pixels, cause one pixel size depends on the user display resolution.
I would like to know if there is a way to resize an image to have that size in cm. (I need to keep the image extension also. e.g.: can't convert it to a pdf or other extension)
It really depends on in which resolution the user will print the image (sizes in cm makes little sense other than when printed). If the user wants to make a print in, say 200 dpi, then the image would need to be (10 / 2.54 * 200) by (6.88 / 2.54 * 200) pixels (the division with 2.54 is needed to convert between cm and inches). Which resolution that is needed is highly dependent on what kind of image it is, and the quality requirements of the user.
So just saying "I want to resize to X by Y cm" does not really make sense.
For a code sample on how to make the actual resize once you have figured out the needed size of the image, this SO answer should cover your needs.
Actually, you have to differentiate between the images size on the screen, and the images size on the printout.
usually, you find the formula:
inches = pixels / dpi
so it follows:
pixel = inches * dpi
This is for print, actually.
For the display, replace dpi with ppi, and there you are.
For those (like me) that are not familiar with inches:
inches = pixels / dpi
pixel = inches * dpi
1 centimeter = 0.393700787 inch
pixel = cm * 0.393700787 * dpi
This routine will calculate the pixel-size to have the image display X-cm on the monitor.
But on the printer, you don't have it that easy, since you can't get the DPI as easy as the PPI (bmp.HorizontalResolution & bmp.VerticalResolution).
public static int Cm2Pixel(double WidthInCm)
{
double HeightInCm = WidthInCm;
return Cm2Pixel(WidthInCm, HeightInCm).Width;
} // End Function Cm2Pixel
public static System.Drawing.Size Cm2Pixel(double WidthInCm, double HeightInCm)
{
float sngWidth = (float)WidthInCm; //cm
float sngHeight = (float)HeightInCm; //cm
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(1, 1))
{
sngWidth *= 0.393700787f * bmp.HorizontalResolution; // x-Axis pixel
sngHeight *= 0.393700787f * bmp.VerticalResolution; // y-Axis pixel
}
return new System.Drawing.Size((int)sngWidth, (int)sngHeight);
} // End Function Cm2Pixel
usage would go like this:
public System.Drawing.Image Generate(string Text, int CodeSize)
{
int minSize = Cm2Pixel(2.5); // 100;
if (CodeSize < minSize)
CodeSize = minSize;
if (string.IsNullOrEmpty(Text))
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(CodeSize, CodeSize);
using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp))
{
gfx.Clear(System.Drawing.Color.Black);
using(System.Drawing.Font fnt = new System.Drawing.Font("Verdana", 12, System.Drawing.FontStyle.Bold))
{
double y = CodeSize / 2.0 - fnt.Size;
gfx.DrawString("No Data", fnt, System.Drawing.Brushes.White, 5, (int)y, System.Drawing.StringFormat.GenericTypographic);
} // End Using fnt
} // End using gfx
return bmp;
} // End if (string.IsNullOrEmpty(Text))
...[Generate QR-Code]
return [Generated QR-Code]
}
Image file formats like JPG and TIFF have an EXIF header which has information like horizontal and vertical DPI.
Thus if you get an image that has this metadata, you could verify the printable size.
double DPC = Image_DPI * 0.393700787;
double widthInCm = Image_Width * DPC;
double heightInCm = Image_Height * DPC;
if (widthInCm <= 10 && heightInCm <= 6.88) // do stuff
If you need to resize images to never exceed these printable dimensions, you could do it the other way around, and calculate a DPI ratio that lets the image of dimensions W x H fit within 10cm x 6.88cm bounds.
Kind of what Fredrik is saying:
I would take a nice DPI and require the image to be that resolution or bigger (but is the same aspect ratio) and when exporting/printing the image, resize the image to the DPI used by the other program/printer...
It might be as simple as this: most images store the number of pixels per inch in them. Figure out the number of pixels in each dimension of your image, and divide that by the number of inches (convert from cm). Then use the original bits, just modify the field for the number of pixels per inch (or, more commonly, dots per inch).
So your picture needs to be 3.93" x 2.71". If your image is 393px x 271px, you would set the dpi to 100x100. If your image is 39px x 27px, you would set the dpi to 10x10.
Though probably you'll have to do some resizing, as explained by other answers. :)

Transform pixel height of image to printing size used by graphics object

As part of a print procedure of my application I'm trying to print a list of images scaled down to a specified width and placed one below the other. The problem is I can not figure out how to transform the height in pixels of the images to the height in the units used by the graphics object during printing. How do I calculate the imageHeightPrint variable correctly?
This code snippet is the part of the image printing loop that scales down the image and calculates it's height and the placement of the next image.
Image image = Image.FromStream(imageStream);
// Get proportional correct height
int imageHeight = image.Height * imageWidth / image.Width;
Image imageToPrint = image.GetThumbnailImage(imageWidth, imageHeight, null, IntPtr.Zero);
float imageHeightPrint = e.Graphics.DpiY * imageToPrint.Height / imageToPrint.VerticalResolution;
e.Graphics.DrawImage(imageToPrint, e.MarginBounds.Left, yPos);
yPos += imageHeightPrint;
I found the correct solution my self after dissecting the documentation.
This line:
float imageHeightPrint = e.Graphics.DpiY * imageToPrint.Height / imageToPrint.VerticalResolution;
Should be changed into this:
float imageHeightPrint = imageToPrint.Height /
imageToPrint.VerticalResolution * 100;
The biggest thing I missed was that the height-in-print should be in hundredths of an inch.

Categories

Resources