This is my current application GUI, its still not been finalized as I am just trying to get the main functions to work (This is for self practice),
https://www.dropbox.com/s/gtsz5k4mtpkuva5/appLatest.png?dl=0
At first when I was trying to save the image it was saving the whole canvas (printCanvas) then I learnt it was possible to "crop" the rendered image, but now my image is 480 x 480.
I am just wondering, how would I know increase the resolution of the image, I would like to to be able to be printed on something like A3?
Here is my current code, for the Rendering / Cropping of the image,
private static void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)
{
var renderTargetBitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 92, 92, PixelFormats.Pbgra32);
renderTargetBitmap.Render(visual);
var crop = new CroppedBitmap(renderTargetBitmap, new Int32Rect(610, 130, 480, 480));
var bitmapFrame = BitmapFrame.Create(renderTargetBitmap);
encoder.Frames.Add(BitmapFrame.Create(crop));
using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
{
encoder.Save(fileStream);
}
}
Thanks for any insight you can provide!
Related
I have a WPF app which saves out a thumbnail image as png. The code works well enough but when I open the image is very blurry. The image that it grabs comes from the canvas itself. The canvas changes its width and height depending on the image I'm loading. The desired thumbnail size will be 200 x 200 (pixels).
Here is my code
public void CreateThumbail(Canvas canvas, string filename)
{
RenderTargetBitmap rtb = new RenderTargetBitmap(
(int)canvas.ActualWidth,
(int)canvas.ActualHeight,
96, //dip X
96, //dpi Y
PixelFormats.Pbgra32);
rtb.Render(canvas);
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(CreateResizedImage(rtb, 200, 200, 0));
using (var filestream = System.IO.File.Create(filename))
{
pngImage.Save(filestream);
}
}
private static BitmapFrame CreateResizedImage(ImageSource source, int width, int height, int margin)
{
var rect = new Rect(margin, margin, width, height);
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
group.Children.Add(new ImageDrawing(source, rect));
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
drawingContext.DrawDrawing(group);
var resizedImage = new RenderTargetBitmap(
(int)rect.Width, (int)rect.Height,// Resized dimensions
96, 96, // Default DPI values
PixelFormats.Pbgra32); // Default pixel format
resizedImage.Render(drawingVisual);
return BitmapFrame.Create(resizedImage);
}
I saved out the image before I resize it and it looks crisp and sharp. yet when I save out the thumbnail it's ugly and blurry. What am I doing wrong? Am I over-engineering this? Many thanks in advance.
Probably you need to respect the original dimensions of the image. For instance an image that is 400x400 will downscale to 200x200 quite nicely, but an image that is 235x235 will not.
This doesn't consider images that are not square to begin with.
You might try reducing the image height and width by a good factor (I would start by halving) repeatedly until the image is smaller than 200x200 and then padding it with white or transparent.
Image processing can be quite hard. It's not something I'm an expert in either so I'd probably try a 3rd party library like this one I just found on google: https://imageprocessor.org/
This thing has been driving me crazy.
I have a Visiblox chart. which I'm currently exporting as a PNG using the following code:
var chart = this.CalibrationChartVisibility == Visibility.Visible ? this.calibrationChart : this.residualChart;
var transform = chart.LayoutTransform;
chart.LayoutTransform = null;
var width = (int)chart.ActualWidth;
var height = (int)chart.ActualHeight;
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(chart);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
var stream = new MemoryStream();
encoder.Save(stream);
stream.Position = 0;
chart.LayoutTransform = transform;
return stream.ToArray();
and I get something like this:
But now I need to also need to export it as a JPEG. I thought it would be simple, just change the encoder but this is what I get:
I've tried this:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/31ac62d4-399b-4f2e-a9b9-749efe7528b6/rendertargetbitmap-to-file-problem?forum=wpf
and this:
http://www.grumpydev.com/2009/01/03/taking-wpf-screenshots/
and this:
Get a bitmap image from a Control view
and ervey sugestion on this post:
How to save image using JpegBitmapEncoder
or this one:
saving WPF InkCanvas to a JPG - image is getting cropped
and everything else which crossed my mind, but the outcome is still the same.
There must be something I'm overlooking but I have no idea what it is.
To sum up comments this seems to be a background issue as PNG, attached to this question, has everything transparent apart from chart lines and since JPEG does not support transparency all that is transparent will be black.
Simpliest solution would be to set background of chart to some color
Disclaimer: I provided this answer for the System.Drawing.Image from ImageSource in Resources question and was going to vote to close this question as a duplicate of the other, but couldn't because the question author didn't accept the answer.
In WPF, every UI element extends the Visual Class which Provides rendering support in WPF. There is also a RenderTargetBitmap Class that has a Render Method that takes a Visual object as an input parameter. So you could set your ImageSource as the Source property of an Image and simply render the Image to a Bitmap image:
Image yourImageObject = new Image();
yourImageObject.Source = yourImageSource;
RenderTargetBitmap renderTargetBitmap =
new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
renderTargetBitmap.Render(yourImageObject);
// Save to .png file
PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder();
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (Stream stream = File.Create(filepath))
{
pngBitmapEncoder.Save(stream);
}
As this is well documented on the internet, I won't bother to repeat the whole story here. To find out the full story, please see the How to Render Bitmap or to Print a Visual in WPF page from the Dot NET Tricks website, which will also help you with your printing requirement.
UPDATE >>>
Ok, so most of this applies to you in just the same way, except that you'd want to use a JpegBitmapEncoder object instead. This example from the linked page shows another way to save a JPEG image:
int width = 128;
int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];
// Define the image palette
BitmapPalette myPalette = BitmapPalettes.Halftone256;
// Creates a new empty image with the pre-defined palette
BitmapSource image = BitmapSource.Create(
width,
height,
96,
96,
PixelFormats.Indexed1,
myPalette,
pixels,
stride);
FileStream stream = new FileStream("new.jpg", FileMode.Create);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.FlipHorizontal = true;
encoder.FlipVertical = false;
encoder.QualityLevel = 30;
encoder.Rotation = Rotation.Rotate90;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
Please let me know if you have any problems.
Maybe it's a stupid question, but I have some problems with finding the proper answer:S
How to get frames as Bitmap's or Image's (or something similar) from DrawingGroup? I don't actually know how to bite it. I tried to look for it in the Internet, but had problems with finding something useful.
If you need an image to be used as the Source of an Image control, you could simply put the drawing into a DrawingImage:
var drawing = ...
var drawingImage = new DrawingImage(drawing);
image.Source = drawingImage;
If the question is about creating a BitmapSource (i.e. something that can be encoded by a BitmapEncoder via a BitmapFrame), there is no direct conversion. You have to put the image into an intermediate Image control and render that control into a RenderTargetBitmap, which is a BitmapSource:
var drawing = ...
var drawingImage = new DrawingImage(drawing);
var image = new Image { Source = drawingImage };
var bitmap = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);
image.Arrange(new Rect(0, 0, bitmap.Width, bitmap.Height));
bitmap.Render(image);
I have a situation where I want to convert some XAML to an image, so I created a RichTextBox and then took the image of it. Now problem is that words in image is blurred, any idea how I might be able to fix it?
public System.Drawing.Bitmap ConvertXamltoImage(string XamlString, int Width, int Height)
{
RichTextBox AdContentRichTextBox = new RichTextBox() { Width = Width, Height = Height };
AdContentRichTextBox.BorderThickness = new Thickness(0);
XmlReader _XmlReader = XmlReader.Create(new StringReader(XamlString));
AdContentRichTextBox.Document = XamlString;
var size = new Size(Width, Height);
AdContentRichTextBox.Measure(size);
AdContentRichTextBox.Arrange(new Rect(size));
RenderTargetBitmap bmp = new RenderTargetBitmap(Width, Height, 300, 300, PixelFormats.Pbgra32);
bmp.Render(AdContentRichTextBox);
DrawingVisual _drawingVisual = new DrawingVisual();
using (DrawingContext _drwaingContext = _drawingVisual.RenderOpen())
{
VisualBrush _visualBrush = new VisualBrush(AdContentRichTextBox);
}
PngBitmapEncoder _png = new PngBitmapEncoder();
_png.Frames.Add(BitmapFrame.Create(bmp));
System.Drawing.Bitmap _tempBitmap = null;
using (Stream _fileStream = new MemoryStream())
{
_png.Save(_fileStream);
_tempBitmap = new System.Drawing.Bitmap(_fileStream);
_fileStream.Flush();
}
return _tempBitmap;
}
Hmmmm..there could be lots of things all interacting here:
1st
"Grayscale fall back - if ClearType is disabled or one is rendering text in certain situations where the ClearType algorithm cannot be run, WPF will use a grayscale rendering algorithm to antialias the rendered text."
Rendering Text to a RenderTargetBitmap seems to be one of those situations....(the renderer switches from a hardware to a software path).
2nd
In addition NET 4 switched the default scaling algorithm from high-quality (Fant) to low-quality (Bi-Linear).....now that shouldn't come into play here as it doesn't look like you are scaling the bitmap in any way...but you never know what's going on inside. It's possible to switch the scaler back to the higher quality one.
http://www.olsonsoft.com/blogs/stefanolson/post/Workaround-for-low-quality-bitmap-resizing-in-WPF-4.aspx
3rd
You may need to take into account the parent container of the RichTextBox...see last link below, mentions it can distort the font rendering.
Problems with rendering text as bitmaps using WPF
Some ideas on how to work around this are:
render the RichTextBox at a higher resolution e.g. 600dpi, and then scale down the bitmap (probably will make no difference)
capture the screen....difficult or not practical if your visual is offscreen/obscured, etc.
See related links:
http://windowsclient.net/wpf/white-papers/wpftextclarity.aspx
WPF RenderTargetBitmap downscaling text ClearType to GreyScale
WPF RenderTargetBitmap downscaling TextRenderMode to GreyScale
WPF text rendering inconsistencies
I am loading an image using the the PhotoChooserTask on Windows Phone 7. After loading the photo, I want to be able to immediately resize the photo whilst keeping it aspect ratio and this is without displaying the image in the UI, then save the to the IsolatedStorage.
So far, I have something like this:
private void SaveToIsolatedStorage(Stream imageStream, string fileName)
{
using (var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var fileStream = myIsolatedStorage.CreateFile(fileName))
{
var wbBarcodeImage = new WriteableBitmap(100, 100);
wbBarcodeImage.SetSource(imageStream);
wbBarcodeImage.Resize(100, 100, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
wbBarcodeImage.SaveJpeg(fileStream, 100, 100, 0, 85);
}
}
}
It's resizing the image, but I am unable to figure out how to keep the aspect ratio of the image.
You can query the image properties for height and width and determine aspect ration. If you then know either height or width, you can calculate the other value. Your need to add querying these properties to your code and then a little math.