I want to ask you for help in solving a problem.
I crop the picture with Clone. But there is one detail that affects the operation of the module.
In more details: I have a picture resolution of 1600x900. I need to get a thumb 400x300. Picture 1 is of type 16:9 and the Picture 2 4:3 ratio.
In my version of the solution of the second picture is cut from first. I need the first image smaller, and then cut off. So they look proportionate.
You have to resize your photo at 533x300 and then crop it to 400x300. This will preserve your image ratio.
You need to determine what the deciding factor (height or width) is in your resizing, then resize and finally crop.
Something like this:
thumbHeight = 300;
thumbWidth = 400;
heightRatio = (thumbHeight / img1.Height);
widthRatio = (thumbWidth / img1.Width)
if (heightRatio < widthRatio)
{
resizedHeight = img1.Height * heightRatio;
resizedWidth = img1.Width * heightRatio;
}
else
{
resizedHeight = img1.Height * widthRatio;
resizedWidth = img1.Width * widthRatio;
}
Related
I have a PictureBox inside a Panel, and I have implemented the zoom function with a TrackBar.
When I increase (or decrease) the PictureBox, the position of the image remain fixed on the left side of the PictureBox.
See the example to better understand the problem.
What I want is the possibility to relocate the image compared to the center of the Panel. See the following example
For example I tried to define the PictureBox X origin in this way:
before the zoom I calculate the distance (Δdx) between the origin of the PictureBox (x0) and the center of the Panel (x1).
I increase the distance with the zoom factor (Δdx').
I calculate the new origin of the image (x0') as x1 - Δdx'
I do the same with Y and I define the new PictureBox location with x0' and y0'.
Here the code:
// new image width after the zoom
double width = pbImg.Image.Width + (pbImg.Image.Width * trackbar.Value / 100);
// new image height after the zoom
double height = pbImg.Image.Height + (pbImg.Image.Height * trackbar.Value / 100);
// panel center
int cX = panel.Width / 2;
int cY = panel.Height / 2;
// actual origin for the picturebox
int imgX = pbImg.Location.X;
int imgY = pbImg.Location.Y;
// distance the panel center and the picturebox origin
int distFromXc = cX - imgX;
int distFromYc = cY - imgY;
// new distance with zoom factor
distFromXc = distFromXc + (distFromXc * trackbar.Value / 100);
distFromYc = distFromYc + (distFromYc * trackbar.Value / 100);
// new origin point for the picturebox
int pbX = (cX - distFromXc);
int pbY = (cY - distFromYc);
// new dimension for the picturebox
pbImg.Size = new Size(Convert.ToInt32(width), Convert.ToInt32(height));
// relocate picturebox
Point p = new Point(pbX, pbY);
pbImg.Location = p;
I tried to modify this C# code, but I’m not familiar with it.
In my case I want to manage the Picturebox and the image inside it as the same object (if it’s possible).
What I want is the possibility to increase (or decrease) the Picturebox (and the image inside) but I want the Picturebox to stay centered where it currently is.
The SizeMode of the picture is StretchImage.
The Trackbar has 0% as he minimum value and 100% as the maximum.
The size of the Picturebox, and the image isnside, can be variable, I receive the images from another software.
A zoomed Picturebox can be bigger than Panel, but it’s not a problem, because I can move it.
The problems are the following:
1. If i use the code I wrote above, the reposition seems to work, but the Picturebox isn’t resized.
2. If I use a fixed value for the origin of the Picturebox (for example Point p = new Point(50, 50)), the resize works but obviously the position of the Picturebox is fixed.
This is because you are changing the size of the picturebox and not the size of the image within it. To ensure an image matches the size of the picture box ensure you set the stretchimage sizemode
pbImg.SizeMode = PictureBoxSizeMode.StretchImage
to get it working you could add this line just before you change the size of the picture box, however i recommend setting this on picturebox during its creation.
Refer to : Fit Image into PictureBox
If you want the PictureBox to stay centered where it currently is, and only expand or deflate "in place", then try something like this:
double width = pbImg.Width * trackbar.Value / 100;
double height = pbImg.Height * trackbar.Value / 100;
Rectangle rc = pbImg.Bounds;
rc.Inflate((int)((width - pbImg.Width) / 2), (int)((height - pbImg.Height) / 2));
pbImg.Bounds = rc;
Note that this is all based on the size of the PictureBox itself, NOT the Image within. Not sure what SizeMode you have set for the PB...
---------- EDIT ----------
I'm using StretchImage as SizeMode. Is possible to have the same behavior but without the button? When I move the cursor from left to right the Pb increase and decrease from right to left – Scarj
Of course. Put my code into the ValueChanged() and/or Scroll() events. - Idle_Mind
The original post works off the current size of the PictureBox. You might want to store the original Bounds() of the PB (maybe in the Tag() property) and then always compute the new size based on that instead.
Here's an example of that:
private void Form1_Load(object sender, EventArgs e)
{
pbImg.Tag = pbImg.Bounds;
}
private void button1_Click(object sender, EventArgs e)
{
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
ZoomPB();
}
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
ZoomPB();
}
private void ZoomPB()
{
Rectangle rc = (Rectangle)pbImg.Tag;
double width = rc.Width * trackbar.Value / 100;
double height = rc.Height * trackbar.Value / 100;
rc.Inflate((int)((width - rc.Width) / 2), (int)((height - rc.Height) / 2));
pbImg.Bounds = rc;
}
I have 2 questions:
How to get the display area of a picture inside a picture box with a scale factor?
Example:
I have an image (1000 x 1000), my task is "get an area (600 x 600) of that image".
I create a form, then a panel with a picture box inside, picture box size is 400 x 400, make some code to allow user to drag image inside the box
I load the image into the picture box. Since the desired area is 600 x 600, but my box is 400 x 400 only, so I scale the image with the 0.67 factor.
User will select the desired area by dragging the image arround.
How can I get that area (from the original image)?
And if I allow user to zoom in/out in that picture box, how can I deal with it?
Because the image is scaled in picbox, you can not take the area directly from picbox. The trick is to un-scale the rectangle that the user select and tranform it to the original one.
You need two images:
Bitmap original600x600; //unscaled
Bitmap picBoxImage; //with 400x400 dimensions
when your form loads:
original600x600 = new Bitmap(600, 600);
//Draw the portion of your 1000x1000 to your 600x600 image
....
....
//create the image of your pictureBox
picBoxImage= new Bitmap(400, 400);
//scale the image in picBoxImage
Graphics gr;
gr = Graphics.FromImage(picBoxImage);
gr.DrawImage(original600x600, new Rectangle(0, 0, 400, 400));
gr.Dispose();
gr = null;
pictureBox1.Image = picBoxImage; //If at any time you want to change the image of
//pictureBox1, you dont't draw directly on the control
//but on picBoxImage and then Invalidate()
When the user select a rectangle, lets call it rectangleSelect, on pictureBox1 you need to transform x, y, width, height of rectangle to the original one, the 600x600. You need some simple math:
//scaled unscaled with precision
x becomes -----------> x * (600 / 400) (int)( (double)x * (600D / 400D) )
y becomes -----------> y * (600 / 400) (int)( (double)y * (600D / 400D) )
width becomes -----------> width * (600 / 400) (int)( (double)width * (600D / 400D) )
height becomes -----------> height * (600 / 400) (int)( (double)height * (600D / 400D) )
Hope this helps a little!
I want an image within a PictureBox that will adjust automatically depending on the size of the window but, not larger than the original image. While PictureBoxSizeMode.Zoom almost does this, when the PictureBox is larger than the image it causes the image to pixelate. I'm currently executing this code on resize:
if (pBox.Height * pBox.Height < pBox.Image.Width * pBox.Image.Height) pBox.SizeMode = PictureBoxSizeMode.Zoom;
else pBox.SizeMode = PictureBoxSizeMode.CenterImage;
While this works most of the time, occasionally the image won't revert back to zoom:
Any better way to go about this?
How about setting the maximum size to the image size:
pictureBox1.MaximumSize = pictureBox1.Image.Size;
In Combination with :
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
You should use "if (pBox.Width * pBox.Height < pBox.Image.Width * pBox.Image.Height)" if() Statement. Both dimensions of pBox is taken as height, might cause some problem. Check it
I'm working on some image processing and for debug I'm overlaying colours on the original bitmap.
The problem is the image is rendered in a picture box with SizeMode set to Zoom and invalidating every time I update a pixel is Really slow and just gets slower the larger picturebox is (for the same size image)
What I think might help is if I only invalidate the pixel(s) I've changed but I don't know how convert the co-ordinates of the pixel I've changed into a rectangle rendered on the control. Obviously if the image is being drawn larger than the original image then the rectangle I'm invalidating is going to be more than one pixel
Added a method to get the zoom and padding of the picture pox
private void CalculateZoomAndPadding()
{
Double imageAspect = (Double)pictureBox1.Image.Width / (Double)pictureBox1.Image.Height;
Double pbAspect = (Double)pictureBox1.Width / (Double)pictureBox1.Height;
Boolean heightRestricted = imageAspect < pbAspect;
hPadding = 0;
vPadding = 0;
if (heightRestricted)
{
zoom = (Double)pictureBox1.Height / (Double)pictureBox1.Image.Height;
Double imageWidth = (Double)pictureBox1.Image.Width * zoom;
hPadding = (Double)(pictureBox1.Width - imageWidth) / 2d;
}
else
{
zoom = (Double)pictureBox1.Width / (Double)pictureBox1.Image.Width;
Double imageHeight = (Double)pictureBox1.Image.Height * zoom;
vPadding = (Double)(pictureBox1.Height - imageHeight) / 2d;
}
}
then to invalidate a pixel called invalidate like this:
pictureBox1.Invalidate(new Rectangle(Convert.ToInt32(Math.Floor(x * zoom)) + Convert.ToInt32(hPadding) -1, Convert.ToInt32(Math.Floor(y * zoom)) + Convert.ToInt32(vPadding) -1, PixelSize, PixelSize));
when I first did this I only invalidated the are directly covered by the pixel but found that this was subject to rounding errors so expanded it to include a few extra.
Can you change all the pixels and then just invalidate the image once?
I'd just add a timer that fires 30 or 60 times per second that invalidates the whole control. While there might be a slight delay in updating you shouldn't be able to notice it due to your monitor's refresh rate most likely being 60 Hz only anyway.
Does anyone know how to use the new ASP.Net MVC 3 Html Helper WebImage to crop an uploaded file into a square. I would like to have it centered if possible. I've been banging my head for the last few hours trying to figure this out...any help is appreciated!
The scenario is pretty simple, user can upload an image, the image will then be resized to a square to be used later as a thumbnail in the site.
This worked for me, hope saves some time for others...!
private static void CropImage (HttpPostedFileBase sourceImage) {
var newImage = new WebImage(sourceImage.InputStream);
var width = newImage.Width;
var height = newImage.Height;
if (width > height) {
var leftRightCrop = (width - height) / 2;
newImage.Crop(0, leftRightCrop, 0, leftRightCrop);
}
else if (height > width) {
var topBottomCrop = (height - width) / 2;
newImage.Crop(topBottomCrop, 0, topBottomCrop, 0);
}
//do something with cropped image...
//newImage.GetBytes();
}
I suggest to use Jquery image crop plugin. Because i think not good to crop square automatically because you can remove main part of image, for example if it user photo you can crop his head.
Image crop plugin is easy to use. User just select are that he want to use as preview. At the server side you recive start point coordinates and width/height. For image resize/crop at server side i use image magick. There is wrapper for image magick at .net. Also be care with wrapper because it 32 bit only. I've developed for my needs own wrapper for image magick. But i belive that it can be easy done with .net.
If you still think that autocropping is what you need, i suggest to crop max center squere of image and than recize to size that you want.
Hope this help.
P.S. I don't know but i suppose that such task can't be done using mvc WebImage.
here is a little function that crops image from the center but keeping wanted ratio. I use it for cropping images for galleries and such.
public static WebImage BestUsabilityCrop(WebImage image, decimal targetRatio)
{
decimal currentImageRatio = image.Width/(decimal) image.Height;
int difference;
//image is wider than targeted
if (currentImageRatio > targetRatio)
{
int targetWidth = Convert.ToInt32(Math.Floor(targetRatio * image.Height));
difference = image.Width - targetWidth;
int left = Convert.ToInt32(Math.Floor(difference/(decimal) 2));
int right = Convert.ToInt32(Math.Ceiling(difference/(decimal) 2));
image.Crop(0, left, 0, right);
}
//image is higher than targeted
else if (currentImageRatio < targetRatio)
{
int targetHeight = Convert.ToInt32(Math.Floor(image.Width / targetRatio));
difference = image.Height - targetHeight;
int top = Convert.ToInt32(Math.Floor(difference/(decimal) 2));
int bottom = Convert.ToInt32(Math.Ceiling(difference/(decimal) 2));
image.Crop(top, 0, bottom, 0);
}
return image;
}