Image added to WPF canvas changes size - c#

As part of an application, I have a canvas object <Canvas Name="canvas"/> into which I am trying to insert the components of a clock as follows
// Add Background
Image bg = new Image();
bg.SetValue(Canvas.ZIndexProperty, 0);
bg.Source = new BitmapImage(new Uri("images/background.png", UriKind.Relative));
canvas.Width = bg.Source.Width;
canvas.Height = bg.Source.Height;
canvas.Children.Add(bg);
// Add second hand
Image hand = new Image();
hand.SetValue(Canvas.ZIndexProperty, 10);
hand.Source = new BitmapImage(new Uri("images/hand.png", UriKind.Relative));
canvas.Children.Add(hand);
The first image (bg) appears correctly but the second one (hand) appears to be scaled (original size is 5 x 61 pixels, interrogating image size after creation shows it has become 6.66 x 84.02 display units)
(bg original is 130 x 130 pixels and shows as 130.4 in display units)
All the answers to my query that I can find (StackOverflow and Google) suggest DPI setting of image but both my images are 96 DPI (according to Paint)
I have tried moving the image declarations into the XAML (not a long term solution) but this makes no difference. I have tried changing the order in which I insert the images with no effect. I have set the canvas width/height explicitly in the XAML - no effect.
I have set the size of the image explicitly - again no effect.
Can anybody tell me what is going on?
added: Compiled using .net 4 on windows7 64bit
Resolved:
Paint was reporting an incorrect DPI setting for the image.
Paint.Net gave me the correct value and by changing this to 96 DPI the problem was resolved

Issue resolved: Paint was reporting an incorrect DPI. Using an alternate paint package (Paint.net) showed the DPI was different. Correcting this setting fixed the issue.

You haven't set Width and Height for the second image and this had probably caused the issue.
You can also try to disable image stretching by adding a line (this should at least not scale the image, even if the control is scaled):
hand.Stretch = Stretch.None;
Update: I've just noticed You've already tried setting the dimensions of the image. Try to set if in the code. I'm currently looking for another possible causes of this problem.
Update II: I see You've found a solution. I'm glad you've made it work :).

Related

How to display pixels 1:1 in a PictureBox

I have a bitmap (from a .bmp file) that is actually a small part of a larger screen dump that I took earlier.
Now I want to display that bitmap in a PictureBox control (WinForms), but I have trouble getting it to display at the same ratio as when it was captured originally.
I assume it has something to do with Windows' DPI setting for my monitor, but how can I shortcut that and make the bitmap be displayed exactly as when captured?
I figured it out! The problem was not WinForms, but the horizontal and vertical resolution associated with the displayed bitmap. When copying the part of the original screendump into a new bitmap (the one that is later assigned to the Image property of the PictureBox), the new bitmap had a different (=default) resolution setting. By changing the resolution setting to match the one from the source bitmap (the original screendump), the problem went away!

WPF - Prevent scaling of Image control + getting Actual Height

Just recently I switched my Windows to 125% DPI scaling mode and found out that my app does things that I don't want it to do.
One of the problems is scaling of the image I am showing in the app. Let's assume it can be any image and for this example let it be a 600-pixel wide one. I want it to stay just like that. I'm ok with scaling the rest of the interface but this one particular Image control has to be exactly as wide as the Image is, and not scaled up to 125% (to 750 pixels). How can I achieve that? Should I change control size after some DPI-related event fires?
Also, the second question is, why WPF is lying to me? When I get ActualWidth it tells me 600 pixels, but Paintbrush isn't lying - I hope - and it shows 750 pixels when I measure width on the screenshot. Should I be checking this value after any particular event so that I get an actual ActualWidth?
Some code:
imgNav.Source = ImageManager.LoadBitmapImage(uri);
BitmapImage bimp = imgNav.Source;
imgNav.Height = bimp.PixelHeight;
imgNav.Width = bimp.PixelWidth;
...
txtFoo.Text = imgNav.ActualWidth.ToString();
Thank you in advance for any suggestions.

Placemark - icon size GEplugin

once agian i need help from all the kind users.
Im using Interop.GEPlugin to develop an application to display certain points on the google earth globe, with different color circels. So far all of that is working, but the problem is the size of this placemark. i want i bigger, like alot!
The code to setting up the placemark is:
KmlIconCoClass icon1 = m_ge.createIcon("low");
icon1.setHref("http://www.wispresort.com/images/easier.jpg");
icon1.setW(3000);
icon1.setH(3000);
var style = m_ge.createStyle("");
style.getIconStyle().setIcon(icon1);
For some reason, when i only add either icon1.setH(3000) its getting higher, but when i add both it just goes back to the original size.. Did i misunderstand something? or is this just a simple mistake in the plug-in??
Hope you can help me, Thanks.
The GE plugin behaves strangley with icon sizes. Even if you provide a large image as an icon, GE attempts to scale that icon down to a default size around 32 pixels. The most effective way I have found to change the size of an icon is with the setScale() method of the kmlIconStyle. The scale is simply a multiplier. If you want a 32px default icon size to bee 3000 pixels, then you can set the scale to about 94 (32x94=3008). kmlIconScale.setScale(94);
KmlIconCoClass icon1 = m_ge.createIcon("low");
icon1.setHref("http://www.wispresort.com/images/easier.jpg");
var style = m_ge.createStyle("");
var iconStyle = style.getIconStyle();
iconStyle.setIcon(icon1);
iconStyle.setScale(98);
The other issue you will face is that GE will automatically scale icons to shrink as you zoom out, so there is so way I have found to make an icon stay at a set size at all scales
Documentation for kmlIconStyle.setScale

WinRT: How do I ensure Images are drawn in a pixel-perfect way on a Canvas?

I am adding Image instances to a Canvas in Windows Runtime environment and my image keeps getting scaled up when in 140 and 180 scale resolution displays, it looks perfect in scale resolution 100. I tried creating 3 PNG images, one for each scale size: 100, 140, 180 but it still scales them up and they look blurry. I created a test image with 4 black pixels on a cyan background and I took a screenshot from the simulator, see how the image is blurry, my original image has just 4 perfect black pixels:
I tried changing the stretch mode of my Image objects, but it does nothing. I'm using this code to add the images at runtime:
var bitmapImage = new BitmapImage();
StorageFile bitmapFile = await StorageFile.GetFileFromApplicationUriAsync(imageUri);
await bitmapImage.SetSourceAsync(await bitmapFile.OpenReadAsync());
Image image = new Image{ Source = bitmapImage};
image.SetValue(Canvas.LeftProperty, x);
image.SetValue(Canvas.TopProperty, y);
canvas.Children.Add(image);
How do I get the images to draw pixel perfectly in the canvas without scaling and at the exact x/y coordinates I want?
I think I have a workaround, but it requires two steps:
First I have to load the image using a more a standard way that doesn't involve getting the file path like so.
var bitmapImage = new BitmapImage(imageUri);
Somehow this must retain more information internally that this image came from a file with the corresponding ResolutionScale for the current display. Thus when it is drawn by the canvas it is not scaled at all. However this only solves half the problem.
The next problem is that the x, y coordinates used to specify where the image is drawn are being scaled so the image is drawn in the wrong place, further than where I wanted. The only thing I can figure to do is unscale them first like so:
var resScale = DisplayInformation.GetForCurrentView().ResolutionScale;
Image image = new Image{ Source = bitmapImage};
image.SetValue(Canvas.LeftProperty, (x * 100.0) / (int)resScale);
image.SetValue(Canvas.TopProperty, (y * 100.0) / (int)resScale);
canvas.Children.Add(image);
The whole thing seems a bit crazy but it seems to work so far... Anyone have a better solution or an explanation why all this is necessary? Seems like the Canvas class needs an unscaled mode that doesn't mess with the images or coordinates across different resolution displays.
UPDATE: This doesn't work perfectly, using a double to store the value results in precision loss and sometimes there are anti-aliasing artifacts. This is not acceptable if you want pixel perfect graphics. I am still looking for a perfect solution.
There are a few more things that might help with your solution.
Use UseLayoutRounding="False" on your image.
Put your Canvas in a full-screen Viewbox, then set the Canvas Width and Height to the screen resolution. You'd use unscaled Canvas.Left/Top values in this case.
Use Direct2D/Direct3D for rendering.
Good luck.
You can change the Stretch property to "None", If you image is still meshed-up:
You should look at what DPI it is saved on. WPF tries to be DPI-independend, so it tries to draw an image of 5"x5" on every monitor the same size. Even when the resolution is higher, it still should be 5"x5" only a high resolution would render(rasterize) the image in higher quality.
Here's some info: http://www.wpflearningexperience.com/?p=41
How do I convert a WPF size to physical pixels?
Here's a piece of xaml code
you can always use scale transform from code behind to scale the images to appropriate amount be it less or more.
<Image Canvas.Left="150" Height="170" Width="170" Visibility="Visible" Stretch="None">
<Image.Source >
<BitmapImage UriSource="ms-appx:///Assets/rollingDieSprite.png"></BitmapImage>
</Image.Source>
<Image.RenderTransform>
<ScaleTransform ScaleX="4" ScaleY="4" x:Name="scaleTfDie"></ScaleTransform>
</Image.RenderTransform>
</Image>
in c# code behind you can go for the following
ScaleTransform sc = new ScaleTransform();
sc.ScaleX = 0.9;
sc.ScaleY = 0.9;
imgDieRolling.RenderTransform = sc;
this will control the scaling . try using fill=none . Let me know if it works.
I found this issue quite problematic as well. I'm creating custom bitmaps and drawing them at different positions on the canvas. I couldn't find a way in the XAML, but I found a way using Direct2D. When you set up your D2DContext, there's a function called SetUnitMode(). The default unit mode is "DIPS" which causes all drawing to be scaled. By switching to PIXELS mode, the system stops scaling the drawing and does everything 1:1.
m_d2dContext->SetUnitMode(D2D1_UNIT_MODE_PIXELS);

Images Scaling Down in draw in C#

Alright guys last little bit of this project I'll ask for help on I promise.
So I go to load the images, works fine however I notice upon loading that the dimensions of the image have been scaled down in the y to 300 (all are a constant value of 433) and up or down from their original width to 600.
I'm using the following method to load them
foreach (string file in Directory.EnumerateFiles(imagePath, "*.JPG"))
{
Image contents = Image.FromFile(file);
treesImage[count] = contents;
count++;
}
and this is the resulting image when I have it loaded.
http://i.stack.imgur.com/Q40kK.png
As you can see the image below the red rectangle is quite small
Any help would be appreciated. If you require any more information please post below and I'll make sure to edit the original question with the relevant information as soon as humanly possible.
EDIT: I am using a simple windows form application and not another graphical framework for my own reasons.
Thanks in advance :)
I'll assume you are using a PictureBox control to display the image.
When someone chooses a tree from your map, you obviously set the PictureBox Image property to the image object referenced by the index in the array. Use the Image object to set the ClientSize of the PictureBox control.
...
Image img = treesImage[idx];
MyPictureBox.SizeMode = PictureBoxSizeMode.Normal;
MyPictureBox.ClientSize = new Size(img.Width,img.Height);
MyPictureBox.Image = img;
...
Alternately you can define one size for your PictureBox and force all the images to be scaled to that size by setting the control SizeMode property to StretchImage declaratively.
I would recommend that you create a simple class (MyImageInfo for example) that would store the Path, Width, and Height of the images found in your first function into a list and then just as before when a user clicks to view an image you set the width and height of the PictureBox and then call the LoadAsync(path) method to get the image. then you aren't storing all images in memory at once, just as you need them since it doesn't look like this requires a lot of quick jumping from image to image.

Categories

Resources