I'm trying to write a simple program in WPF where the entire window is taken up by an image whose source is a WriteableBitmap that I draw. Here is the relevant code:
var image = m_Window.CustomImage;
image.Source = new WriteableBitmap(
(int) image.ActualWidth,
(int) image.ActualHeight,
300,
300,
PixelFormats.Bgra32,
null
);
but when I run this I get System.ArgumentException: Value does not fall within the expected range on the constructor. Frustratingly it does not say which value is incorrect. I have tried googling but there have been precious few examples of a WriteableBitmap constructor, and those that do exist are what generated the above code in the first place. Any advice?
The problem is that the ActualWidth and ActualHeight properties of image are 0, which will cause the ArgumentException.
Try setting the values of the values of the pixelWidth and pixelHeight properties to positive integers and see if the exception goes away.
image.Source = new WriteableBitmap(
300,
300,
300,
300,
PixelFormats.Bgra32,
null
);
Related
Alright , i am trying to merge two images(superimpose one image on top of another) using writeablebitmapex library's blit method. And after applying the blit all i am getting is a transparent image with no content.
I would like to superimpose the curtain image on top of the window image.
Source Code :
WriteableBitmap photoWriteableBitMap = await new WriteableBitmap(1,1).FromContent(new Uri("ms-appx:///Curtain1.jpg"));
WriteableBitmap frameWriteableBitMap = await new WriteableBitmap(1, 1).FromContent(new Uri("ms-appx:///Window1.jpg"));
var merge = new WriteableBitmap(750, 750);
merge.Blit(new Rect(0, 0, 100, 100), photoWriteableBitMap, new Rect(0, 0, photoWriteableBitMap.PixelWidth, photoWriteableBitMap.PixelHeight));
merge.Blit(new Rect(0, 0, 200, 200), frameWriteableBitMap, new Rect(0, 0, frameWriteableBitMap.PixelWidth, frameWriteableBitMap.PixelHeight));
// Assign the merged writeable bitmap to the image source.
imgMain.Source = merge;
Expected Image :
Actual Image :
Please let me know what i am doing wrong.
I have found an answer to my solution in case anyone stumbles upon here.
First thing , I was unnecessarily trying to include an extra bitmap(merge) for the desired output.
All I had to do was apply the blit on the window image and set the source and the destination rectangles appropriately.
Below is the final code which works for me ,
WriteableBitmap photoWriteableBitMap = await new WriteableBitmap(1, 1).FromContent(new Uri("ms-appx:///Curtain1.jpg"));
WriteableBitmap frameWriteableBitMap = await new WriteableBitmap(1, 1).FromContent(new Uri("ms-appx:///Window1.jpg"));
frameWriteableBitMap.Blit(new Rect(300, 100, 250, 200), photoWriteableBitMap, new Rect(0, 0, photoWriteableBitMap.PixelWidth , photoWriteableBitMap.PixelHeight));
This is how my final image looks :
I'll get the Out of memory exception on the first row.
XImage image = XImage.FromFile(filePath);
gfx.DrawImage(image, pagePadding, pagePadding + beginDrawYPoint, imageWidth, imageHeight);
gfx.Dispose();
I have no idea where to look for a solution to this problem.
I just hit on this problem too, my solution was to change image.svg to image.png, solved the problem for me.
XImage image = XImage.FromFile(#"wwwroot\icons\122.png");
gfx.DrawImage(image, 250, 250, 100, 25);
I create a WriteableBitmap object, draw a line and try to set it as the source to an Image control. For some reason, the program stops responding and then closes 5 seconds later when I try to set the Source. Anyone have any idea what's wrong? (I am also using WriteableBitmapEx)
WriteableBitmap bit = new WriteableBitmap(400, 400, 96, 96, PixelFormats.Bgr32, null);
WriteableBitmapExtensions.DrawLine(bit, 10, 10, 300, 300, Core.PrimaryColor.ColorValue);
ImageCanvas.Source = bit; // Sets the image to our bitmap, but program crashes for some reason!
When I try your code, it throws an ArgumentException saying
The input WriteableBitmap needs to have the Pbgra32 pixel format. Use
the BitmapFactory.ConvertToPbgra32Format method to automatically
convert any input BitmapSource to the right format accepted by this
class.\r\nParametername: writeableBitmap
Hence this works:
var bitmap = new WriteableBitmap(400, 400, 96, 96, PixelFormats.Pbgra32, null);
WriteableBitmapExtensions.DrawLine(bitmap, 10, 10, 300, 300, Colors.Black);
image.Source = bitmap;
UPDATE: As noted by Anders, you should perhaps use the portable bitmap factory method provided by WriteableBitmapEx to create your bitmap:
var bitmap = BitmapFactory.New(400, 400);
WriteableBitmapExtensions.DrawLine(bitmap, 10, 10, 300, 300, Colors.Black);
image.Source = bitmap;
I am creating an image from a byte array using a UIImageView control. I need to ensure that the max size of the image is 600 x 600. How can I do that? I have tried SizeThatFits() and SizeToFit(), however, that just moves the image around on the screen. I have tried setting the Bound property to new RectangleF(0, 0, 600, 600), however, that also does no good.
You could check UIImage Size property for exceeding your limits. If so, scale it:
const int limit = 600;
if ((View.Frame.Size.Width > limit) || (View.Frame.Size.Height > limit))
{
// Scale as on link above.
}
Alternatively, you could set Frame and ContentMode of your UIImageView to desirable values.
I'm trying to create a JPG from part of my WPF Applications. Like a screenshot, only of individual UIElements. I started here: http://www.grumpydev.com/2009/01/03/taking-wpf-screenshots/
I am using his extension method, which essential allows you to get a byte[] with UIElement.GetJpgImage(). This can then be written using a filestream to a JPG image. If I make a JPG of the whole window, it looks just fine! However, this is not ideal because it just captures what the user sees. Things that are not visible because of the scrollviewer or because their parent was animated to a small size won't show up.
If I take a "screenshot" of, say, a grid that I use for layout:
alt text http://img697.imageshack.us/img697/4233/fullscreenshot2.jpg
I get this crap with a black background. I don't want that. Furthermore, if I've collapsed this grid's height using animation, I won't get anything at all. Those are actually templated checkboxes, they should have black text above them, and the background of the grid should be white. Here's the code that someone else wrote to return the byte[] array that gets written to a filestream:
public static byte[] GetJpgImage(this UIElement source, double scale, int quality)
{
double actualHeight = source.RenderSize.Height;
double actualWidth = source.RenderSize.Width;
double renderHeight = actualHeight * scale;
double renderWidth = actualWidth * scale;
RenderTargetBitmap renderTarget = new RenderTargetBitmap((int) renderWidth, (int) renderHeight, 96, 96, PixelFormats.Pbgra32);
VisualBrush sourceBrush = new VisualBrush(source);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
using (drawingContext)
{
drawingContext.PushTransform(new ScaleTransform(scale, scale));
drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
}
renderTarget.Render(drawingVisual);
JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
jpgEncoder.QualityLevel = quality;
jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
Byte[] _imageArray;
using (MemoryStream outputStream = new MemoryStream())
{
jpgEncoder.Save(outputStream);
_imageArray = outputStream.ToArray();
}
return _imageArray;
}
Somewhere in there, we're getting a black background. Any insight?
EDIT: If I set the grid's background property to white, the screenshot comes out as expected. However, it's not feasible to set everything's background that I need to take a screenshot of.
Just a guess, I would think that a black background would represent portions of the byte array that are not set to anything in this process. The initial zeros in the array would appear as black.
To avoid this, I suggest initializing the array with 0xFF (byte.MaxValue) values.
UPDATED:
From looking at this closer, I think you should draw a white rectangle onto the image before you render the UI element. That ought to work anyway.
Just before this line of code
drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
put something like this
drawingContext.DrawRectangle(Brushes.White, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
Unfortunately the only thing that worked was just setting the element's background in the XAML. I didn't want to do this, but I guess it is what I need to do in this case. Thanks anyway for the suggestion.