Drawing an image from svg url in wpf C# - c#

This is the URL with image-https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/acid.svg
What I have tried
Sample 1-
-I am using SharpVectors package
public void DrawImage()
{
Image svgImage = new Image();
WpfDrawingSettings settings = new WpfDrawingSettings();
settings.IncludeRuntime = false;
settings.TextAsGeometry = true;
FileSvgReader converter = new FileSvgReader(settings);
DrawingGroup drawing = converter.Read(new Uri("https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/acid.svg"));
if (drawing != null)
{
svgImage.Source = new DrawingImage(drawing);
}
}
sample 1 works perfectly but it's latency is very high, So I wanted to improve the performance.
Sample 2 - I tried using bitmap to improve performance below is code, but the issue is I need to download the image or store in folder and use as path as string which works fine but my condition is my URLs are coming form JSON file in .SVG format, they are dynamic and I am not using any .XAMl files for UI.
UI built in code behind programmatically.
Is there any other way I can display SVG image in WPF?
public void DrawImage()
{
Image dynamicImage = new Image();
dynamicImage.Width = 300;
dynamicImage.Height = 200;
stcdock.Children.Add(dynamicImage);
WpfDrawingSettings settings = new WpfDrawingSettings();
settings.IncludeRuntime = true;
settings.TextAsGeometry = false;
string svgTestFile = #"\Downloads\acid.svg";
StreamSvgConverter converter = new StreamSvgConverter(settings);
MemoryStream memStream = new MemoryStream();
if (converter.Convert(svgTestFile, memStream))
{
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = memStream;
bitmap.EndInit();
dynamicImage.Source = bitmap;
}
}

.svg are not nativly supported in wpf.
https://www.nuget.org/packages/svg
This package promisses to add this functionality.

Related

Xamarin Forms Byte[] to Image Source not showing

Hi all I have a byte[] which I save from the Xamarin Essentials Media Picker, I want to display the image on my XAML page so all I have is a blank XAML page with a StackLayout and in my code I do the following:
Stream stream = new MemoryStream(filebyte);
var imageSource = ImageSource.FromStream(() => stream);
Image test = new Image();
test.Source = imageSource;
test.WidthRequest = 50;
test.HeightRequest = 50;
ImageStack.Children.Add(test);
but when the page loads nothing is there. i'm I missing something. I have even tried this on a fresh project using the latest version of Xamarin Forms and Xamarin Essential's
imgByteArray is Byte[], using following code to add image by behind code.
var stream1 = new MemoryStream(imgByteArray);
image.Source = ImageSource.FromStream(() => stream1);
image.WidthRequest = 50;
image.HeightRequest = 50;
imagestack.Children.Add(image);
Update:
Adding one image in Forms, setting Build action as Embedded resource, then converting this image into byte[], using this byte[] for Image to show. I have no problem.
var image = new Xamarin.Forms.Image();
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] imgByteArray = null;
var s = assembly.GetManifestResourceStream("FormsSample.f19.png");
if (s != null)
{
var length = s.Length;
imgByteArray = new byte[length];
s.Read(imgByteArray, 0, (int)length);
var stream1 = new MemoryStream(imgByteArray);
image.Source = ImageSource.FromStream(() => stream1);
image.WidthRequest = 50;
image.HeightRequest = 50;
imagestack.Children.Add(image);
}

How to override(use) BitmapFrame.Thumbnail property in WPF C#?

Hello! The problem is? that I've got a multipage Tiff file to show, and I use
BitmapFrame.Thumbnail property to show small size thumbnail of every frame(page) of my multipage Tiff file. But< for some reason? the property returns null. Please, give step by step description, of how this should be done?
I've already tried to create my own BitmapSource thumbnail with this method:
public static BitmapImage GetThumbnail(BitmapFrame bitmapFrame)
{
try
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
MemoryStream memorystream = new MemoryStream();
BitmapImage tmpImage = new BitmapImage();
encoder.Frames.Add(bitmapFrame);
encoder.Save(memorystream);
tmpImage.BeginInit();
tmpImage.CacheOption = BitmapCacheOption.OnLoad;
tmpImage.StreamSource = new MemoryStream(memorystream.ToArray());
File.WriteAllBytes( $"{Path.GetTempFileName()}.jpg", memorystream.ToArray());
tmpImage.UriSource = new Uri($"{Path.GetTempFileName()}.jpg");
tmpImage.DecodePixelWidth = 80;
tmpImage.DecodePixelHeight = 120;
tmpImage.EndInit();
memorystream.Close();
return tmpImage;
}
catch (Exception ex)
{
return null;
throw ex;
}
}
then I convert the result to BitmapSource and create a list of BitmapFrames using:
List<BitmapFrame> tiffImageList = new List<BitmapFrame>();
tiffImageList.Add(new TiffImage() { index = imageIndex, image = BitmapFrame.Create(frame, (BitmapSource)GetThumbnail(frame))});
In the end I try to get property, but it returns null:
foreach (var tiffImage in tiffImageList)
{
Image image = new Image();
image.Source = tiffImage.image.Thumbnail;
}
I ran into a similar issue, modifying with the SDK PhotoViewerDemo example. Some valid jpg's are shown as white square thumbnails.
I think I found why the question code does not work. Ivan's question provides a correct constructor of BitmapFrame, but the functions have to create a BitmapSource, not a BitmapImage.
C# BitmapFrame.Thumbnail property is null for some images
I got it working with the function provided in that topic, using Ivan's call to the constructor, using the two bitmapsource arguments.
Code in the SDK example I now use is..
private BitmapSource CreateBitmapSource(Uri path)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = path;
bmpImage.EndInit();
return bmpImage;
}
private BitmapSource CreateThumbnail(Uri path)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = path;
bmpImage.DecodePixelWidth = 120;
bmpImage.EndInit();
return bmpImage;
}
// it has to be plugged in here,
public Photo(string path)
{
Source = path;
_source = new Uri(path);
// replaced.. Image = BitmapFrame.Create(_source);
// with this:
Image = BitmapFrame.Create(CreateBitmapSource(_source),CreateThumbnail(_source));
Metadata = new ExifMetadata(_source);
}

QR code rendering with ZXing.Net.Mobile in Xamarin.Forms app

I'm trying to use ZXing.Net.Mobile to display a QR code as an image.
I'm having difficulty getting the byte[] returned from BarcodeWriter.Writer(...) into an image for display.
i.e. this does not display an image
public class BarcodePage : ContentPage
{
public BarcodePage()
{
Image image = new Image();
image.Source = ImageSource.FromStream(() =>
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new EncodingOptions
{
Height = 200,
Width = 600
}
};
var bitmapBytes = writer.Write ("Some text");
return new MemoryStream(bitmapBytes);
});
Content = image;
}
}
The bitmapBytes byte array looks like it has reasonable values in the debugger, how can I turn that into an image for display?
If I change the Image.Source assignment to:
image.Source = ImageSource.FromUri(new Uri("http://i.imgur.com/q0aIYvC.png"));
then it does correctly display the image, so I know the problem isn't with the Forms layout, etc.
Workaround
At the moment, I'm doing conversion to a MemoryStream in the native, e.g. in Android I have:
public class BuildQrCodes_Android : IBuildQrCodes
{
public async Task<MemoryStream> ImageStreamForAsync(string text)
{
var writer = new BarcodeWriter
{
Format = ZXing.BarcodeFormat.QR_CODE,
Options = new EncodingOptions
{
Height = 600,
Width = 600
}
};
var bitmap = writer.Write(text);
var stream = new MemoryStream();
await bitmap.CompressAsync(Bitmap.CompressFormat.Png, 100, stream);
stream.Position = 0;
return stream;
}
}
and then over in the Xamarin Forms side, I have
IBuildQrCodes qrBuilder = /* Service lookup */
var stream = await qrBuilder.ImageStreamForAsync("the text to encode");
return ImageSource.FromStream(() => new MemoryStream(stream.ToArray()));
which is doing what I want, so it's an acceptable workaround.
I am not sure what widget "Content" in your code represents, but assigning your "image" to a Form View's Image Class that is a member of your ContentPage should do the trick.
In XAML, you would create an Image within your ContentPage, i.e. like in one of the Form's samples.
Otherwise, dynamically create an Image class widget, add it your layout via AddView for your ContentPage.

how to rotate image in File in C# & WPF application

I have WPF and C# application. which captures the images and Save in to file(*.jpg).
I have the image path and i want to rotate image saved in File through the c# code.
and Save the Rotated image in same file.
How can i do that?
Use the rotate flip method.
E.g.:
Bitmap bitmap1 = (Bitmap)Bitmap.FromFile(#"C:\test.jpg");
bitmap1.RotateFlip(RotateFlipType.Rotate180FlipNone);
bitmap1.Save(#"C:\Users\Public\Documents\test rotated.jpg");
you can use my method:
BitmapImage rotateImage(string filename,int angle)
{
WIA.ImageFile img = new WIA.ImageFile();
img.LoadFile(filename);
WIA.ImageProcess IP = new WIA.ImageProcess();
Object ix1 = (Object)"RotateFlip";
WIA.FilterInfo fi1 = IP.FilterInfos.get_Item(ref ix1);
IP.Filters.Add(fi1.FilterID, 0);
Object p1 = (Object)"RotationAngle";
Object pv1 = (Object)angle;
IP.Filters[1].Properties.get_Item(ref p1).set_Value(ref pv1);
img = IP.Apply(img);
File.Delete(filename);
img.SaveFile(filename);
BitmapImage imagetemp = new BitmapImage();
using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
imagetemp.BeginInit();
imagetemp.CacheOption = BitmapCacheOption.OnLoad;
imagetemp.StreamSource = stream;
imagetemp.EndInit();
}
return imagetemp;
}
usage:
string filename = System.AppDomain.CurrentDomain.BaseDirectory + "4.jpg";
image.Source = rotateImage(filename,90);

Rendering an image at runtime in WPF

I have posted several questions related to this problem I am having and I am starting to believe this cannot be done. Here is the back story.
I have an ASP.NET application from which I want to generate a .png image. This .png image needs to be constructed from either XAML or a WPF Visual Tree. Because of this, I must generate the .png image in an STA thread. Everything works fine until my XAML/WPF Visual Tree includes an Image (as in a System.Windows.Controls.Image). My .png file gets generated correctly except the Image element does not show the referenced picture. The referenced picture is located at a remote URL. No errors or exceptions are thrown.
How do I create a .png image from some XAML/WPF Visual Tree that includes a System.Windows.Controls.Image element? The resulting .png must include the picture referenced in the Image element. I have tried the following code in a variety of ways:
string address = "http://imgtops.sourceforge.net/bakeoff/o-png24.png";
WebClient webClient = new WebClient();
byte[] imageContent = webClient.DownloadData(address);
Image image = new Image();
using (MemoryStream memoryStream = new MemoryStream(imageContent))
{
BitmapImage imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.StreamSource = memoryStream;
imageSource.EndInit();
image.Source = imageSource;
}
// Set the size
image.Height = 200;
image.Width = 300;
// Position the Image within a Canvas
image.SetValue(Canvas.TopProperty, 1.0);
image.SetValue(Canvas.LeftProperty, 1.0);
Canvas canvas = new Canvas();
canvas.Height = 200;
canvas.Width = 300;
canvas.Background = new SolidColorBrush(Colors.Purple);
canvas.Children.Add(image);
// Create the area
Size availableSize = new Size(300, 200);
frameworkElement.Measure(availableSize);
frameworkElement.Arrange(new Rect(availableSize));
// Convert the WPF representation to a PNG file
BitmapSource bitmap = RenderToBitmap(frameworkElement);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
// Generate the .png
FileStream fileStream = new FileStream(filename, FileMode.Create);
encoder.Save(fileStream);
public BitmapSource RenderToBitmap(FrameworkElement target)
{
int actualWidth = 300;
int actualHeight = 200;
Rect boundary = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(actualWidth, actualHeight, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext context = drawingVisual.RenderOpen())
{
VisualBrush visualBrush = new VisualBrush(target);
context.DrawRectangle(visualBrush, null, new Rect(new Point(), boundary.Size));
}
renderBitmap.Render(drawingVisual);
return renderBitmap;
}
Thank you for your help.
You are rendering the output bitmap correctly, it is just the input bitmap you are screwwing up :).
BitmapImage requires access to the StreamSource property until it fires the DownloadCompleted event, but the 'using' block Dispose()s of the MemoryStream before it has a chance! You could simply unwrap the MemoryStream from the using block and let the GC handle it (if you do, I would recommend setting the BitmapImage.CacheOption to BitmapCacheOption.None, so it uses the stream directly, rather than a copy), but I would use the UriSource property and wait for the DownloadComplete event before rendering.

Categories

Resources