Image not visible in a custom canvas (derived class of Canvas) - c#

I have a custom canvas in an application, which is not showing image, in XAML, i write:
<local:MyCanvas>
<local:MyCanvas.LayoutTransform>
<ScaleTransform x:Name="scale" ScaleX="1" ScaleY="1" />
</local:MyCanvas.LayoutTransform>
<Image Source="C:\abc.jpg" />
</local:MyCanvas>
I have tried it on Canvas, and it works, but in the derived class, it doesn't appear, but Visual Studio shows the outline meaning image has been added.
As an alternative, inside MyCanvas:Canvas class, i type:
Image img = new Image();
img.Width = 200;
BitmapImage myBitmapImage = new BitmapImage();
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(#"C:\abc.jpg");
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
img.Source = myBitmapImage;
this.Children.Add(img);
Still not visible. Any ideas?

I have been experimenting with different things and I have been able to add the image by enclosing it in a DrawingVisual, here is the code:
private void addImage (DrawingContext dc)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(#"C:/abc.jpg");
bi.EndInit();
dc.DrawImage(bi, new Rect(new Point(0,0), new Point(200,200)));
}
And by then adding the DrawingVisual to the custom Canvas, here is the code:
DrawingVisual abc = new DrawingVisual();
DrawingContext dc = abc.RenderOpen ();
addImage (dc)
dc.Close();
base.AddVisualChild(abc);
base.addLogicalChild(abc);
Using this method, the image is visible, and it is working fine.
But why isn't it adding to MyCanvas using the previous method?

Related

WPF How to copy a portion of a canvas into an image and overwrite the image file

What I'm trying to do:
Load images from a number of .png files saved to disk (if the file doesn't exist, create a new image and fill it with a given colour)
Add these images to a Canvas (they are the same size as the canvas and are expected to mostly be off screen with a portion overlapping the actual Canvas area)
Draw onto the Canvas using lines, ellipses, etc
(On save) take the Canvas and convert it to a flat image held in memory (let's call it the CanvasImage)
For each image I loaded in step 1, calculate the portion that overlaps the actual Canvas area and copy that portion of the CanvasImage into the appropriate portion of the original image
Save the resulting images to disk, overwriting the existing files
I've had different portions of this working at different times, using code I found by searching for how to do each exact step, but never the full process. I'm mostly struggling with steps 4 to 6 as I don't really understand all the different image-related classes, how you convert between them, and which to use at each step in the process. Though I'm also having some issues with step 1, as I need to be able to overwrite the files at the end.
I've read a lot of the related questions (overwriting images, converting a canvas to an image, copying a portion of an image, etc) and tried the solutions (some of which worked in more simple examples), but I'm struggling to put it all together.
Any help or advice would be greatly appreciated. If there's anything you'd like me to elaborate on I'd be happy to, and if you'd like to see some of the code I can share it (I've just tried a lot of different things so I'm not sure how useful it would be)
I've managed to solve the problem. I'll post the code below for each step I had trouble with in case anyone else will find it useful. The code here is slightly modified to suit the general case.
Step 1: Loading an image from the disk that can be overwritten
public static System.Windows.Controls.Image LoadImage(string filePath)
{
var image = new System.Windows.Controls.Image();
image.Stretch = Stretch.Uniform;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmapImage.UriSource = new Uri(filePath, UriKind.Absolute);
bitmapImage.EndInit();
image.Width = bitmapImage.PixelWidth;
image.Height = bitmapImage.PixelHeight;
image.Source = bitmapImage;
return image;
}
Step 4: Convert canvas to a BitmapImage
public static BitmapImage Convert(Canvas canvas)
{
var sizeRender = new Size(canvas.ActualWidth, canvas.ActualHeight);
var dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(canvas);
ctx.DrawRectangle(vb, null, new Rect(new Point(), sizeRender));
}
var renderBitmap =
new RenderTargetBitmap(
(int)canvas.ActualWidth,
(int)canvas.ActualHeight,
96d,
96d,
PixelFormats.Pbgra32);
renderBitmap.Render(dv);
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(renderBitmap));
BitmapImage bitmap;
using (var stream = new MemoryStream())
{
pngEncoder.Save(stream);
bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze();
}
return bitmap;
}
Step 5: Copy a portion of an image into a different image
public static void SaveImage(Image inputImage, BitmapImage canvasImage, string fileName)
{
... Calculate the portion that overlaps (left, top, width, height) ...
var canvasImageAsBitmap = BitmapConverter.ConvertBitmapImageToBitmap(canvasImage);
var croppingRectangle = new Rectangle(left, top, width, height);
var croppedRegion = canvasImageAsBitmap.Clone(croppingRectangle, canvasImageAsBitmap.PixelFormat);
var image = BitmapConverter.ConvertBitmapImageToBitmap((BitmapImage)inputImage.Source);
var bitmap = new Bitmap((int)inputImage.Width, (int)inputImage.Height);
... Calculate the position of the cropped image in the input image (xPos, yPos) ...
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.DrawImage(image, 0, 0);
graphics.DrawImage(croppedRegion, xPos, yPos);
graphics.Flush();
}
bitmap.Save(fileName);
}
This step relies on the following code to work:
public static Bitmap ConvertBitmapImageToBitmap(BitmapImage bitmapImage)
{
using (MemoryStream memoryStream = new MemoryStream())
{
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
encoder.Save(memoryStream);
Bitmap bitmap = new Bitmap(memoryStream);
return new Bitmap(bitmap);
}
}
Step 6: Overwrite the image file to save in the disk.
This is just the line bitmap.Save(fileName); shown in Step 5, which works due to the implementation of Step 1

DockPanel ImageOption.Image is not showing the image

I'll make it short,
My problem is: The image that i want to set in my DockPanel as icon is not showing.
Here is my Code
DockPanel dock = new DockPanel();
dock.ImageOption.Image = <Bitmap image here>; //
dock.Controls.Add(UserControl1);
UserControl1.MyDockPanel = dock;
Any expert opionion here?
Thanks
You can add image to DockPanel in the cs like this:
DockPanel dock = new DockPanel();
BitmapImage myBitmapImage = new BitmapImage();
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri("...\\ico_48.ico", UriKind.RelativeOrAbsolute);
myBitmapImage.DecodePixelWidth = 2048;
myBitmapImage.EndInit();
Image image = new Image();
image.Source = myBitmapImage;
dock.Children.Add(image);
Content = dock;

Autosize Button with an image

How to make a buttons auto-size with an image instead of fixing a default button size? Thanks really appreciated.
All my buttons are fixed size, I need to have some buttons buttons to be big, some small depending on the image size.
heres my codes:
Button tba = new Button();
tba.FontSize = 19;
tba.Height = 300
tba.MinWidth = 100;
//tba.Height = Double.NaN;
//tba.Width = Double.NaN;
ImageBrush brush = new ImageBrush();
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(#"files.png" + lstQuestion[i].ImageURL.Substring(1), UriKind.Absolute);
bitmap.EndInit();
brush.ImageSource = bitmap;
tba.Background = brush;
wrapPanel1.Children.Add(tba);
To size the button to the image: host the image in an Image and set Image.Strech to None and remove the sizes from your Button:
Button tba = new Button();
Image myImage = new Image();
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(#"files.png" + lstQuestion[i].ImageURL.Substring(1), UriKind.Absolute);
bitmap.EndInit();
myImage.Source = myBitmapImage;
myImage.Stretch = Stretch.None;
tba.Content = myImage;
If you want more than just an image in your Button add the image to panel that will let the image fill the space, e.g. a Grid, then set Button.Content to that panel.
Incidentally in XAML you can just go:
<Button>
<Image Strech="None" Source=".\Water Lilies.jpg"/>
</Button>

How to center an image used as Grid Background through C# code?

I'm trying to set a Grid's backgroud through code.
The Grid has 1000 x 1000 size, the same size of the loaded PNG.
I load this PNG into a Stream, then execute the following code:
using (StreamWrapper wrapper = new StreamWrapper(streamImg))
using (BinaryReader reader = new BinaryReader(wrapper))
{
originalImage = new BitmapImage();
originalImage.BeginInit();
originalImage.CacheOption = BitmapCacheOption.OnLoad;
originalImage.StreamSource = reader.BaseStream;
originalImage.EndInit();
originalImage.Freeze();
}
ib = new ImageBrush() { ImageSource = ConvertToGrayScale(ref originalImage) };
grdQuebraCabeƧa.Background = ib;
private FormatConvertedBitmap ConvertToGrayScale(ref BitmapImage image)
{
FormatConvertedBitmap grayImage = new FormatConvertedBitmap();
grayImage.BeginInit();
grayImage.Source = image;
grayImage.DestinationFormat = PixelFormats.Gray32Float;
grayImage.EndInit();
return grayImage;
}
The following screenshot is the result:
You can see black blocks on lower and right sides.
I want to center the image in the grid.
Is that possible? How can I achieve this result?

WPF Add a png image from resources with C# at runtime

I'm trying to add an image in a stack panel at runtime. My image is in the resources of the application. Here's the code that I have for the moment:
Image image = new Image();
ImageSourceConverter isc = new ImageSourceConverter();
image.Source = isc.ConvertFrom(Properties.Resources.entity16_10) as ImageSource;
image.Height = 16;
image.Width = 16;
panel.Children.Add(image);
I've got a null pointer on the line where I'm trying to use the converter, I don't know if it's the good way of doing this.
Here's how i do it :
object imguri = new Uri("/MyAssembly;Component/MyImageFolder/MyImage.png", UriKind.Relative);
BitmapImage ni = new BitmapImage(imguri);
Image img = new Image();
img.Source = ni;
return img;

Categories