I'm working with Windows Phone 8/C# Silverlight and using code similar to this to render text:
TextBlock drawStringInstance = new TextBlock();
drawStringInstance.Text = str;
drawStringInstance.Opacity = 1;
drawStringInstance.Measure(new Size(1000000, 1000000));
WriteableBitmap wb = new WriteableBitmap((int)drawStringInstance.ActualWidth, height);
wb.Render(drawStringInstance, null);
wb.Invalidate();
Notice that I don't save the image and draw it directly so there shouldn't be any saving artifacts. If I just place the text block I get much crisper text with less aliasing as such (left is the "good" rendering):
Is there something I can do to improve this or is this an inherent issue with the approach of WriteableBitmap.Render()?
I think you're not supposed to render elements that are not in the visual tree. In fact , your code does not render anything on my emulator.
Just add the textblock somewhere on the page (perhaps set the margin to -1000 so that it does not show) , then render it.
Related
Hi so I'm making an app for Windows 10 that requires a user to choose an image and it's going to crop the image to 310*128. I got the file picker code already. But I want to know how to actually crop and save the image and display in image box. I already have the xaml page done
With Lumia Imaging SDK you can both crop the selected image and resize the image. In this answer I assume you actually want to crop, but from the text I could just as well guess you really just want to resize.
For crop, use the CropEffect from Lumia.Imaging.Transforms. Set the CropArea property on it to the object, and then render it. If you are rendering straight to the XAML page I recommend using a SwapChainPanel object in XAML and a SwapChainPanelRenderer to render on it.
Given that you are loading a StorageFile and rendering to a SwapChainPanel your code might look like something like this:
StorageFile file = ...
using (var source = new StorageFileImageSource(file))
using (var crop = new CropEffect(source, new Rect(0, 0, 310, 128))
using (var renderer = new SwapChainPanelRenderer(crop, YourSwapChainPanel))
{
await renderer.RenderAsync();
}
Question
How can I scale an image in XAML quickly without anti-aliasing applied?
Background
I am trying to make a pixel editor as a Windows 8 XAML/C# app. I'm using c#/XAML because most of my experience is with c#/WPF.
Method 1: WriteableBitmap + Image control. Originally, I used a WriteableBitmap to store and edit an image. That image is displayed in a resized XAML Image control. The problem is that the image does not get scaled properly because of anti-aliasing. (XAML does not seem to provide the BitmapScalingOptions that are available in WPF)
Method 2: Redrawn WriteableBitmap + Image control. Next I tried writing my own scaling, where I take my original image and write to a larger WriteableBitmap so that the scaled image is pixelated. The scaled image is then presented inside a XAML Image control. This process is slow and inefficient.
Method 3: SharpDX + Direct2d ?? I am pretty sure a solution exists somewhere between SharpDx, SurfaceImageSource, and Direct2d. Event still, I can't quite figure out how to display a SharpDx.WIC.Bitmap inside a Windows.UI.Xaml Image control, and am generally getting lost in the documentation.
What exactly is a recommended setup for achieving my desired end? Are there c# samples available which might point me in the right direction?
I don't know if you mean by scaling it by resizing it with the mouse or just with a button click to auto scale to a predetermined size.
But the thing you can do is to use an Image panel and then, just set it to image.Stretch = Stretch.Fill; so if you override and create a method for the Resize event of the Image Panel, your image will take the size to fill the Image panel.
I'm trying to dynamically place content with one of the items being an image. I can get the image to load to the grid, but while the labels all align nicely, the image appears in the middle of the screen. I don't believe I'm doing this right, I'm wondering if I should be using a list? But, I'm open for suggestions. Currently I'm writing the labels with enough left margin space to separate them, but when the image renders it appears in the middle of the window.
...
Uri imguri = new Uri("/MyName;Component/Resources/myimage.png", UriKind.RelativeOrAbsolute);
BitmapImage ni = new BitmapImage(imguri);
gridEvents.Children.Add(new Label { Content = "Travel:", Margin = new Thickness(300, 0, 0, 0), FontSize = 18 });
gridEvents.Children.Add(new Image() { Source = ni, Height = 15, Width = 15 });
...
I believe the problem is similar to how I'm forcing the labels position with a hard coded margin. I'm new to wpf, so if you know of a better way - I'm ready to learn.
Image appears in the middle of the grid because you didn't set any positioning properties, like margin or align. Position in the center of the grid is just default behavior.
Actually you'd better use ItemsControl or ListView. To better understand ItemsControl read this series of articles.
I have just started learning C# and Visual Studio trying to work both on books and on sample code.
I am aware that tis is not a very brilliant question, but this is the problem that I am trying to solve. I have a windows form and I need to show an image in a Picture box contained in a tableLayoutPanel. The simple problem is that the images I have to load could have several sizes and a typical image is not completely shown within the allocated space: only the area that fits the container is shown, the rest of the image is cutted off. I have to show the image in its entirety, i do not have to resize it. I have already set the autosize property, but this does not seems to work.
Here some code in the form.cs
string imageName = openFileDialog1.FileName; // Get the image name
// Read the image
try
{
img = ( Bitmap) Image .FromFile(imageName);
}
catch
{
MessageBox.Show("oooops" , Text, MessageBoxButtons.OK, MessageBoxIcon .Hand);
}
pictureBox1.Image = img; // show the image
and then in the private void InitializeComponent() found in the form.designer.cs:
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
...
this.pictureBox1 = new System.Windows.Forms.PictureBox();
...
this.tableLayoutPanel1.Controls.Add(this.pictureBox1, 1, 1);
...
this.tableLayoutPanel1.Controls.Add(this.pictureBox1, 1, 1);
...
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.034863F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 2.388038F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 88.5771F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(784, 762);
...
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
Have you any hint about how to show the whole image?
Even using slidbars would be ok, but notwhithstanding the fact that the container has autoscroll = true, nothing happens and the image is still truncated.
Thanks for any help
The autoscroll property in the tableLayout control manage the scrolling of the whole table, including all the child controls. When the image is too big to fit within the picture control box, the autoscroll = yes property show slidebars allowing to slide all the content packed in the table layout control, not the individual image cell. Picture box does not have an autoscroll property, because autoscroll is, as far as I understand, a container's property; to slide the image in its own assigned space an intermediate container should be used, I guess.
My question was not a good question. It is rooted in my confusion about the containment hierarchy and relevant properties, more than in a genuine lack of knowledge or notions. Well, there is always room to improve ...
I'm trying to get started with WPF in c#.
I set a Canvas as the content of a window, then I create another Canvas and put it as a child of the first Canvas (together with other elements, such as buttons and labels). Everything runs fine until I create an Image object and add it dynamically to the inner Canvas:
Image m_Img = new Image
{
Name = "img1",
Width = cvWindow.Width,
Height = dUsefulHeight,
Stretch = Stretch.Uniform
};
m_Img.Source = new BitmapImage(
new Uri(xMap.SelectSingleNode("#image").FirstChild.Value,
UriKind.RelativeOrAbsolute));
Canvas.SetLeft(m_Img, 0);
Canvas.SetTop(m_Img, 0);
double d = m_Img.Source.Width;
cvWindow.Children.Add(m_Img);
Here m_Img is the image I create, cvWindow is the inner Canvas. The source of the image is a PNG file, extracted from an XML file (the string returned is correct).
The odd behaviour is here: if I comment out the line
double d = m_Img.Source.Width;
the Image is not displayed anymore, although other controls in the Canvas (such as labels and buttons) are correctly displayed.
I don't need the width of the source image, so the compiler tells me that variable is never used.
I updated Visual Studio 2010 to the last SP1, but the behaviour remained. Google doesn't help either. I came to think that the Width property may have a getter method that triggers some action, but cannot solve the puzzle.
Edit: Same thing happens using another property of Source (e.g. Height). If I access at least one property, the image displays ok.
I finally discovered what happens: the Image control needs that the properties DecodePixelWidth and DecodePixelHeight of the Source are set to the correct values.
Once the Source is created, those values are not set, and the Image is not drawn. Upon first access to any property of the BitmapImage that serves as source the image is actually decoded and those properties are set to the final width and height of the decoded image (so the Image can be drawn).
I can solve this by setting those values by hand (with a cast to int) like this
BitmapImage bs1 = new BitmapImage();
bs1.BeginInit();
bs1.UriSource = new Uri(
xMap.SelectSingleNode("#image").FirstChild.Value,
UriKind.RelativeOrAbsolute);
bs1.EndInit();
bs1.DecodePixelHeight = (int)bs1.Height;
bs1.DecodePixelWidth = (int)bs1.Width;
m_Img.Source = bs1;
but I think I will re-design my views with a better separation (views in XAML, model and viewmodel via code).
This bit is also mentioned in the second note in http://msdn.microsoft.com/en-us/library/ms747027.aspx
When you specify the size of an image with either Width or Height, you should also set either DecodePixelWidth or DecodePixelHeight to the same respective size.
Don't define your views via code - use XAML,
even if you are trying to creating dynamic views, using XAML is much more clean
and using a good designer app (e.g. Blend), you'll notice things that you didn't consider.
Some things that you didn't consider are that .Width is not necessary equal to .ActalWidth.
Default widths are usually double.NaN (which means auto-width).
Use bindings, bind width of A to width of B, use margin, padding or value converters to make width A binded to width of B - const.
Use layout panels (e.g. Grid, StackPanel, DockPanel) to make alignment of multiple controls simple (and binding free).
Also, prefer using standard naming conventions (e.g. no m_).