Since the creators update came out, uwp can use svg images as briefly explained here (minute 3).
I have this svg (48x48) and i can use it fine, if (and only if) i set the image's width&height to 48 and the strech to none:
<Image Source="ms-appx:///Assets//check.svg" Height="48" Width="48" Stretch="None"/>
If i set the stretch to fill, the image disappears. If i increase the width and height i can see that the icon is pinned to the upper left corner of the image (screenshot with a different svg but same size). Isn't Stretch=Fill and a fixed height/width the intended way to scale an image?
It looks to my as if the stretching algorithm does not grasp that my svg is supposed to be 48x48. Am i doing it wrong, or are there workarounds?
Okay, so here is how I solved this!
YouTube Video for this!
Open the SVG file
The SVG file Width and Height - set these to auto!
I've been having the same issue all morning and was about to completely give up on Svg support, seems mad that you can't get a scalable format to scale properly...
But, I had one more go and I think I've worked this out.
It seems that you need to tell the SvgImageSource to rasterize at the SVG's original design size and then get the Image to scale it. Not sure it's a particularly helpful approach, but certainly solves it as of build 15063.
<Image Width="24" Stretch="Uniform" VerticalAlignment="Center">
<Image.Source>
<SvgImageSource UriSource="ms-appx:///Assets/salesorder.folder.plain.svg"
RasterizePixelHeight="48"
RasterizePixelWidth="48" />
</Image.Source>
</Image>
So if the SVG was 48x48 we turn it into a bitmap at 48x48 using the RasterizePixelHeight and RasterizePixelWidth values and then the image scales that to 24x24.
Hope that helps.
Update
I just re-read your question and realised that you were looking to increase the scale whereas I've been working to decrease it. Looks as though the technique still works, but as you scale up you're going to lose any sharpness of image due to the bitmap scale process. I think this points to a fundamental flaw in the current implementation. They seem to be rendering the svg as a bitmap, and we have to tell it the original size to get it to render properly, and then they allow the bitmap code to do the rest of the work.
I think it's somewhat debateable whether this is true support or an odd half way house. Somewhere someone suggested that Adobe Illustrator can generate XAML paths, I think I'm going to look at that to see whether I can get a better quality output, shame though because I really like Inkscape :-(
For me, it worked with modifying SVG file like this:
Add appropriate preserveAspectRatio property to svg tag. For me it was "xMinYMin meet".
Set viewbox property of svg tag to this template "0 0 ActualHeight ActualWidth", in my case it was "0 0 1050 805".
Set height and width of svg tag to "auto".
Now svg element is relative to Height, Width and Stretch properties you provide in your XAML page or view.
It might be needed to rebuild the project for XAML Designer to take effect.
SVG File:
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 1050 805" width="auto" height="auto" ... > ... </svg>
XAML File:
<Image
Width="200"
Source="ms-appx:///Assets/Photos/Illustrations/sample.svg"
Stretch="UniformToFill" />
For me it works only if you set RasterizePixelHeight and RasterizePixelWidth to the svg original resolution (e.g. document properties in Inkscape).
For me it worked without setting those Properties, but adding preserveAspectRatio="xMinYMin" to the <svg ...> tag and deleting width and height from the <svg ...> tag.
Related
I was developing an UWP app. I am using UWP "Image" control to show images in my app. All images are loaded properly most of the time. But occasionally few images not loading properly. Sometimes it is loaded in cropped version and sometimes loaded a black box which is never set from app. My code to set image:
XAML:
<Image x:Name="FavoritePen"
Source="{Binding FavPenSource, Mode=OneWay}"
Height="44"
Width="44"
Margin="0,10,10,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"/>
CS:
private string favPenSource =
"ms-appx:///Assets/Images/NoteList/ic_main_tb_favorite_on.svg";
public string FavPenSource
{
get
{
return favPenSource;
}
set
{
SetProperty(ref favPenSource, value);
}
}
Black box loaded:
Wrong image loaded with cropped version:
Additionally, this is a very rare case, may be 1/100 frequency.
I googled and tried many solutions but it didn't help. I found that some people faced same issue but didn't find a proper solution yet. (Issue_1 , Issue_2, Issue_3 , Issue_4)
Can anyone please help me to solve the issue!!
Add View Box element, This is the x, y coordinates of the image inside the element along with the height and width. The default size is 300×150 size. Since I do not see the full container source, check if the SVG element is not beyond the parent container. You can remove the Horizontal/Vertical Alignment.
Sometimes it is loaded in cropped version and sometimes loaded a black box which is never set from app. My code to set image:
The problem is the svg file has been specified height and width property, when you render them with fix size image control, the svg content will display beyond the bound.
For this problem, please edit svg content and set it's height and width property as auto
<svg width="auto" height="auto" viewBox="0 0 469 476" version="1.1" xmlns="http://www.w3.org/2000/svg">
I want to optimize the memory usage in my WPF app.
I want to load from the disk an jpg image and show it with its real size.
And then I want to show 5 cropped square section of the original image loaded from the disk.
(No resize is applied on any image).
I want to do all this by loading the original image once and sharing that data among the image controls, in such a way that no memory is wasted and all controls fetch data from the same memory location.
I tried by using a memory stream object but in the end due to some convertions between bitmap and bitmapimage I ended up copying the data.
I found an interesting way to crop an image from a BitmapImage here that I think will solve your problem. Doing it this way, you can display all of your images just using a single BitmapImage
In your xaml your full resolution image would just be a regular image element, but your cropped images would be a rectangle element using an image brush with a specific viewbox. Just define the rectangle with the height and width of the cropped image that you want, and then the viewbox is defined as "x y width height" (in my example it is "10 20 100 200") and remember that x starts at 0 for left and is positive moving right, and y starts at 0 for the top and is positive moving down.
<Image Source="{Binding Image}"></Image>
<Rectangle Height="200" Width="100">
<Rectangle.Fill>
<ImageBrush ViewboxUnits="Absolute" Viewbox="10,20,100,200" ImageSource="{Binding Image}"></ImageBrush>
</Rectangle.Fill>
</Rectangle>
Note that the binding for the Image and the ImageBrush are the same, so you only need to define Image once, and it is used across both elements.
Wherever you look in Windows 10, there are circles. It's fairly easy to make images circular, but camera is a bit different. Is there a simple XAML way to clip the camera stream in a CaptureElement to make it a circle?
I tried putting it in a border, but CaptureElement doesn't care about its borders. I also tried using the Clip property, but it can only clip to RectangleGeometry.
One way would certainly be to grab CaptureElement frames, transforming them to images (frame by frame) and applying to Image element, and then clipping the image, but it seems like that would have awful performance.
Is there something in the framework to make this really simple, but I'm not seeing it?
Well after seeing that might be the background is always black of the Canvas DirectX the only way I see is:
1.- Clip a rectangle with an ellipse in Inkscape for instance.
2.- Copy to Expression Design and Ctrl-Shift-C (to copy XAML)
3.- Place inside a ViewBox only the path generated
<Grid Width="300" Height="300">
<CaptureElement Name="PreviewControl" Stretch="Uniform" Width="280" Height="280" />
<Viewbox Width="280" Height="280">
<Path Width="813.701" Height="813.701" Canvas.Left="-33.3503" Canvas.Top="-45.3503" Stretch="Fill" Fill="#FF800080" Data="F1 M -33.3503,-45.3503L -33.3503,768.35L 780.35,768.35L 780.35,-45.3503L -33.3503,-45.3503 Z M 373.54,158.095C 485.863,158.095 576.985,249.137 576.985,361.54C 576.985,473.863 485.863,564.985 373.54,564.985C 261.137,564.985 170.095,473.863 170.095,361.54C 170.095,249.137 261.137,158.095 373.54,158.095 Z "/>
</Viewbox>
</Grid>
With that you can place an image in the path or a solid color, that's the only way I see to do it. Hope it helps
I have an image element in one xaml that is accessed and displayed on a different xaml. Interestingly the image automatically resizes itself to fit the grid while also maintaining the aspect ratio.
However I have Path elements that serve as borders to the images. When the Path elements are displayed they display at their normal size and I just cannot get them fit the image as borders no matter how I set the dimensions, whether it's programmatically or in xaml. These Path elements are imported from an Adobe Illustrator file.
This is how the code from XAML files looks,
<ImageDisplay.xaml>
<grid>
<image name="imageToDisplay"/>
</grid>
</ImageDisplay.xaml>
<ImageBorder.xaml>
<Path Element 1>
<Path Element 2>
<Path Element 3>
<Path Element 4>
</ImageBorder.xaml>
<SubMain.xaml>
<local:ImageDisplay />
<local:ImageBorder />
<otherelements />
</SubMain.xaml>
<Main.xaml>
<SubMain.xaml />
<SubMain.xaml />
<SubMain.xaml />
</Main.xaml>
So in the Main.xaml the SubMain.xaml is allotted a certain width and height and the ImageDisplay elements re-size and fit themselves perfectly without the help of code. But the same does not happen for ImageBorder element. What might I be doing wrong here?
You can use ActualWidth and ActualHeight of the image after it autoresizes and set the width and height of paths.
Image class
Path class
How do you get the REAL position of objects in silverlight?
I have a header image centered on the screen. When I make the browser window smaller, obviously, the header's left side goes off the screen. Finding out the actual position is good to know if you want to position objects on top of the image.
I capture the Content_Resized and I run a little test:
if (App.Current.Host.Content.ActualWidth > header.Width)
{
TEST = Canvas.GetLeft(header);
}
else
{
TEST = Canvas.GetLeft(header);
}
TEST always returns zero.
EDIT: header sits on a grid instead of a canvas. "Well, there is your problem..." So a better question might be this. How would I get the margins of an image sitting on a grid?
I probably should just answer the question but how to find the position of an element relative to another is probably something that has been answered before (by myself and others) here and elsewhere on the tinternet.
However if your goal is to place an item over an image then place the image in a Grid and then add the item as child of the Grid. That way you assign the relative position over the image as the margin of the item and let Silverlight's layout system do the rest.
As a general rule if you feel that you need to write code to move stuff about when the size of things change then unless you are writing a custom panel or something you're probably not using Silverlight layout system properly.
Edit:
Try this experiment:-
<Grid x:Name="LayoutRoot">
<Grid x:Name="headerContainer" Margin="50, 60, 0, 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image Source="YourLargeImage" />
<Image Source="YourSmallerImage" HorizontalAlignment="Center" VerticalAlignment="Top" />
</Grid>
</Grid>
Now try changing the inner grid's Margin to move its position around the screen. Note the smaller image always remains at the top center of the large image.
I got it working.
First of all, these images are on a grid, not a canvas. But switching the grid to a canvas caused lots of other problems one of which is that I could not have the header image centered like before.
The solution was to change the margin of the smaller image sitting on top of the larger header image when the content resized like this:
blankbarimage.Margin = new Thickness((App.Current.Host.Content.ActualWidth - header.Width) / 2, 0, 0, 0);
and, by the way, you create a content resized method like this:
App.Current.Host.Content.Resized += new EventHandler(Content_Resized);
So, to answer my own question, the way you get the REAL position of object in silverlight is (if they are on a grid) by looking at their margin settings.