3

I'm having difficulty with JpegBitmapEncoder since it is creating an image that is placed in black rectangle. and I don't have the solution for fix.

 private void SaveImage(Canvas canvas, string fileName)
    {
        SaveFileDialog s = new SaveFileDialog();
        s.FileName = "Pic";
        s.DefaultExt = ".jpg";
        s.Filter = "JPG files (.jpg)|*.jpg";

        Nullable<bool> result = s.ShowDialog();
        if (result == true)
        {
            RenderTargetBitmap renderBitmap = new RenderTargetBitmap(6646, 3940, 2000d, 2000d, PixelFormats.Pbgra32);

            canvas.Measure(new Size((int)canvas.Width, (int)canvas.Height));
            canvas.Arrange(new Rect(new Size((int)canvas.Width, (int)canvas.Height)));

            renderBitmap.Render(canvas);

            string filename = s.FileName;
            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderBitmap));

            using (FileStream file = File.Create(filename))
            {
                encoder.Save(file);
            }
        }
    }

with this code i get:

enter image description here

but when i use PngBitmap Encoder this doesn't happen. Can anyone shine a light? How do I remove the black rectangle or perhaps fill it by increasing the dimensions of the picture?

Clemens
  • 123,504
  • 12
  • 155
  • 268
MicroDev92
  • 169
  • 1
  • 15

1 Answers1

5

.png supports transparency, whereas .jpg doesn't. I suspect that the background of your canvas is transparent, and as it doesn't know what to do with it it just leaves the pixels default (0,0,0) i.e. black. Png defaults to (0,0,0,0), which is transparent black.

Or, your canvas isn't the same dimensions as the image (your create your image with hardcoded width & height, rather than use the Width and Height of your canvas). As it's larger, it only renders the parts where the canvas actually covers.

If it's the first case, try setting your canvas Background="White" to your canvas so it renders all of it with no transparency. If it's the second, try creating a Rectangle the dimensions of your image with the appropriate Fill="White" and rendering that first before your canvas. Something like this:

Rectangle fillBackground = new Rectangle {
    Width = 6646,
    Height = 3940,
    Fill=Brushes.White
}

renderBitmap.Render(fillBackground);
renderBitmap.Render(canvas);

Some advice, you shouldn't really use Width and Height, these can be NAN for a control that's layout is determined by it's parent. You should actually use Canvas.ActualWidth and Canvas.ActualHeight or Canvas.RenderSize.Width/Height. This will actually reflect the on-screen size all the time.

Also, to calculate the size of your output image adjusting for your DPI choice you can use the following:

RenderTargetBitmap renderBitmap = new RenderTargetBitmap(Width * DPI/96, 
                                                         Height * DPI/96, 
                                                         DPI, DPI, PixelFormats.Pbgra32);
Joe
  • 6,773
  • 2
  • 47
  • 81
  • This is actually good, and it solves the problem, the problem was i had a border(that i forgot about) around the canvas(canvas is actually the size of the picture xD), so when I fill the border with white, it actually does the trick! Tnx alot! – MicroDev92 Jan 12 '17 at 22:04
  • No problem, I've been wrestling with exporting images/screenshots all week and just happened to have hit this exact issue! – Joe Jan 12 '17 at 22:10
  • First example doesn't work for me - only last "Render()" works – VladStepu2001 Jan 24 '22 at 15:11