i got a problem with image scaling in C#.
I have a picture Box with given Size : e.g. width = 800px height = 600px
I am loading different images into that picture box, small ones ( 400x400) and big ones (800+ x 600+)
My images are getting resized if they do not fit into box. But they are always resized to MAX width and height of PictureBox. So the aspect ratio is destroyed.
Can anybody help to identify / fix the problem?
Classes:
Form1.cs
ImageHandling.cs (commented out)
ImageUtilities.cs
Examples:
Problem 1:
My Version
vs
Original Source
Problem 2:
My Version
vs
Original Source
How i want it:
Solution
this.PictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
Set that property to your PictureBox and the size of the image will increased or decreased to fit the PictureBox maintaining the size ratio.
For more info: http://msdn.microsoft.com/en-us/library/system.windows.forms.picturebox.sizemode.aspx
I handled this by resetting the SizeMode on the PictureBox's resize method.
This is, essentially, the same answer as above, but it's formatted much better.
private void ScaleImage()
{
if (pbInfo.Image == null)
return;
if (pbInfo.Image.Width > pbInfo.Width || pbInfo.Image.Height > pbInfo.Height)
pbInfo.SizeMode = PictureBoxSizeMode.Zoom;
else
pbInfo.SizeMode = PictureBoxSizeMode.Normal;
}
Related
my canvas is 1920*1080 and I'm adding an image that its width is 200 and height is 200 too,
I want the image to go to the top right corner, and after setting the following code and running the application
I see that the image overflows the canvas:
Image img = new Image();
img.Source = SOURCE;
img.Width = 200;
img.Height = 200;
screen.Canvas.Children.Add(img); // I have already created screen obj and a canvas before
img.SetValue(Canvas.LeftProperty, 1720);
img.SetValue(Canvas.TopProperty, 0);
after I checked it manually, I saw that if I put the Canvas.Left 1350 it fit the target,
but I can't understand why it happens
...................
And about the canvas parent:
it's in the window and I maximize the window at startup also I'm using the code below in its window constructor to maximize the canvas too:
var resolution = Screen.PrimaryScreen.Bounds;
Canvas.Width = resolution.Width; // i put the name of the canvas, Canvas :)
Canvas.Height = resolution.Height;
.................
another update:
I find out however I get the screen size 1920x1080 but the real size is 1536x864 so can anyone help how to get the real screen size? :)
So the problem was I wasn't setting the actual width and height for my canvas,
when I use the resolution width and height, what I get is 1920x1080 but also I checked in my display setting that I have 125% scale so it makes the size 1536x864 so I got this number with RenderSize:
screen.Canvas.Width = screen.RenderSize.Width;
screen.Canvas.Height = screen.RenderSize.Height;
And also it's worth mentioning that if you use it in the constructor the RenderSize will be 0
Why my resolution of Thinkpad T450s is 1536px width?
I want to load an image and put it into a viewbox. The image is displayed correctly, but, when I'm going to get it's width and height, it's both NaN.
This is my image load code :
Image img = new Image();
img.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("1.png");
Viewbox vb = new Viewbox();
vb.Width = img.Width;
vb.Height = img.Height;
vb.Child = img;
cnv.Children.Add(vb);
The reason I want to get the image width and height is so I could resize it (via viewbox resize) later inside the application.
Any idea how to get the image dimension?
And this is how I'm going to resize it (via mouse wheel)
private void cnv_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (vb != null)
{
vb.Width += Mouse.MouseWheelDeltaForOneLine;
vb.Height += Mouse.MouseWheelDeltaForOneLine;
}
}
And it returns error and said that vb.Width is not a valid value.
Questions to sum this up :
How to get the image width / height in wpf?
How to resize the viewbox (which will also result in image resize) via mouse wheel? For example, if I scroll up the wheel, the width and height is added by 1, and if I scroll down the wheel, the width and height is reduced by 1.
Thank you
P.S. Viewbox vb; and Image img; is a global variable, I just shorten the script down.
P.S.S. I know if the Viewbox width and height initialized by a number, lets say 100 and 100, it will work, I just wanna know how to get the image original size.
EDIT :
The resize can be achieved by detecting whether it's scrolled up or down by detecting e.Delta > 0 or e.Delta < 0
(Source : http://social.msdn.microsoft.com/Forums/vstudio/en-US/170c4fd0-1441-4d83-903d-594af75f8fb4/detect-mouse-scroll)
It seems as though the Image object is not fully loaded at that stage. I believe that you can use the Width and Height properties of the ImageSource class instead. That should be fully loaded at this stage.
ImageSource.Width Property
ImageSource.Height Property
For other users, you can also possibly find the values that you want from the ActualWidth and ActualHeight properties of the Image class (inherited from the FrameworkElement class) instead of the more usual Width and Height properties.
FrameworkElement.ActualHeight Property
FrameworkElement.ActualWidth Property
The image original size can only be obtained in Pixels while your WPF controls are measured in Device Independent Pixels so you're going to have to make a translation from Pixels to Device Independent Pixels and back wherever necessary.
That said, to obtain the width and height for a png file, you can load it into a BitmapImage instead of Image and query the PixelWidth and PixelHeight properties for the BitmapImage.
Again, be aware that this is the only place in your code where you're going to be dealing with Pixels, all Width and Height properties (including ActualWidth and ActualHeight, only set after the control is fully rendered) are measured in Device Independent Pixels. This can be misleading because in a lot of situations this happens to be a 1:1 conversion but this is not guaranteed to be the case.
More info can be found here: http://msdn.microsoft.com/en-us/library/windows/desktop/ff684173%28v=vs.85%29.aspx
Before I go into my question, let me explain my setup:
First: I have a PictureBox that holds a Bitmap which is generated at runtime. This Bitmap can be different widths but always the same height.
Second: PictureBoxes do not support scrolling, therefore, I have the PictureBox docked in a panel. Initially, I had used the panel's autoscroll feature, but abandoned that after I discovered through this article that PictureBoxes have a size limit. I also learned that it's better to instead have small PictureBoxes and only draw what needs to be seen instead of the whole image.
Third: So I added a HScrollBar, which is fine and dandy, but I can't seem to figure out the math behind how big to make the scroller. I tried setting the maximum of the scrollbar to the length of the bitmap, but as you can see the size of the scroller is much smaller in mine than the one Windows puts in if I use the autoscroll feature.
My question is, what is the math behind the scroller size and how do I emulate that in my custom scrollbar?
Let me know if my question is unclear and I will try my best to make it more understandable. And thanks in advance for your help!
I figured out what was the problem. Perhaps I should have tried a little longer. :)
The answer lies in the LargeChange property. I let the Maximum at the total width of the bitmap and then set the LargeChange to the width of what I wanted to show. (i.e. the width of the PictureBox)
The size of the "scroller" is determined by the ratio of the value of LargeChange to the value of Maximum. For example, if the width to show (LargeChange) is 100 and the total width (Maximum) is 300 then the "scroller" size will be 1/3 of the scrollbar length. (100/300).
I got same problem too and tried to figure it out, I have a panel which contain another panel inside it called panelChild, and the default scrollbar is small, I need lager scrollbar, so I use HScrollBar to do that (display over-top of default scrollbar), I post my solution here, may be it helpful to someone
public Form() {
InitializeComponent();
hScrollBar.Maximum = panelChild.Width;
hScrollBar.LargeChange = panel.Width; // panel which contain panelChild, and this hScrollBar will same as panel scrollbar
hScrollBar.Scroll += HScrollBar_Scroll;
}
private void HScrollBar_Scroll(object sender, ScrollEventArgs e)
{
int diference = e.OldValue - e.NewValue;
foreach (Control c in panel.Controls)
{
c.Location = new Point(c.Location.X + diference, c.Location.Y);
}
}
I added the GestureListener to an image i'm trying to have zoom like this Stack Overflow answer here: How to zoom in and zoom out Images in WP7?
The problem is that the image does not ever stop zooming, and covers other controls on the page. This covers a few important buttons on the page.
In addition, it allows the image to get so small that it's very hard to make it bigger, and allows the image to go so far off the screen where it's too hard to bring it back.
My goal is to:
Keep the image in the Grid Row it's assigned to, to not cover other controls.
Prevent the width/height of the image from getting to small
Prevent the Width/height of getting too big
Prevent the image from being dragged off the screen.
Is there a way to solve this? The Width/Height of the Image object are not modified by the GestureListener, so I cannot simply do
Image i = sender as Image;
if (i.Height == TOO_BIG)
return;
...
This blog post shows how to implement Pinch/Zoom scaling on an image: http://alvaropeon.wordpress.com/2011/03/10/implementing-pinch-to-zoom-images-in-wp7/ The solution presented there is to limit at 4x the original size, but you could whatever you want. If you want to constrain it to it's parent, then just get the ActualWidth and ActualHeight of the parent as use those as your limits.
I ended up fixing this and getting it work perfectly with the code from the following blog:
http://www.frenk.com/2011/03/windows-phone-7-correct-pinch-zoom-in-silverlight/
It's a very impressive set of functions for Pinch/Zoom. The issue I had about the image covering other controls was fixed by adding clipping to the Grid, which is detailed here:
http://www.codeproject.com/Articles/36495/Silverlight-ClipToBounds-Can-I-Clip-It-Yes-You-Can.aspx
I guess you can do it by restricting transform.ScaleX and transform.ScaleY in the below event handler.if initialScale < somelength ,then only do the code.
private void OnPinchDelta(object sender, PinchGestureEventArgs e)
{
transform.Rotation = initialAngle + e.TotalAngleDelta;
transform.ScaleX = initialScale * e.DistanceRatio;
transform.ScaleY = initialScale * e.DistanceRatio;
}
I have a couple of pictureboxes that need to be resized by aspect ratio when the window size changes. I assumed I can anchor the width, but set the height manually (i.e. anchor the left, right, and top edges; but not the bottom.) However, my control won't resize if I try changing the Size property. Why wouldn't that work? How can I resize my control?
private void Form1_Resize(object sender, System.EventArgs e)
{
int oldWidth = 1280;
int oldHeight = 1024;
int newWidth = webcamPictureBox.Size.Width; // this is auto-resized w/ window; becomes 591
int newHeight = (oldHeight * newWidth) / oldWidth; // this is calculated manually; becomes 472
// Control won't resize if I change the Size property
// Size property stays the same
this.webcamPictureBox.Size = new Size(newWidth, newHeight);
this.thumbnailPictureBox.Size = new Size(newWidth, newHeight);
}
You could be running into one of a few problems, I suppose:
What's the SizeMode of the PictureBox? Is it AutoSize, StretchImage, or something like that? It should probably be Normal for what you want to do.
Are you sure you have your anchoring set up correctly?
Did you debug and check the final size of the picture boxes you're trying to resize? You should verify that it's what you expect and that the form has been repainted.
These are just some ideas; your code along is not enough to provide a great response.
It's difficult to answer this question definitively with the information you've posted.
Windows forms controls problems are difficult to debug by nature because of all the controls that might be affecting what you're doing. First off, you'll want to try debugging this on your own on a form with as few controls as possible. Are there any circumstances under which the resizing behaves properly?
That said, is the Dock property set on these controls? They definitely won't resize if they're set to DockStyle.Fill.
Thanks for the ideas -- they pointed me on the right track! Everything was set up as they should be, except the TableLayoutPanel they were in was constraining their sizes. I determined this by noticing the pictureboxes' size values were simply uneditable, both in runtime and in the designer.
So I set TableLayoutPanel's AutoSize to true, and it works great!