Move BoundingRect of InkStroke to 0;0 - c#

How can I nove BoundingRect to coordinates: X=0;Y=0?
I need to save every InkStroke painted by user on InkCanvas as image separetly in Windows Universal App.
To save final image I'm using Win2D, but this just save cropped Canvas from <0,0> to <BoundingRectHeight,BoundingRectWidth>...
private async Task SaveToImage(string id, InkStroke stroke, float width, float height)
{
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget offscreen = new CanvasRenderTarget(device, width, height, 96);
using (CanvasDrawingSession ds = offscreen.CreateDrawingSession())
{
ds.Clear(Colors.Transparent);
ds.DrawInk(new InkStroke[] { stroke });
}
StorageFile f = await ApplicationData.Current.LocalFolder.CreateFileAsync(id + ".png", CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream output = await f.OpenAsync(FileAccessMode.ReadWrite))
{
await offscreen.SaveAsync(output, CanvasBitmapFileFormat.Png);
await output.FlushAsync();
}
}

I realized that this approach is probably wrong.
So, I decide to do this way:
Draw given stroke into Offscreen canvas by Win2D
Offscreen canvas save into InMememoryRandomAccessStream
Crop given stream into WritableBitmap
Open StorageFile for read/write
Create BitmapEncoder and set Pixel data from WriteableBitmap
Full example you can found at my GitHub

Related

ScreenShot in WPF

I am having two control image view and canvas.
Over image i am drawing rectangle.While taking screenshot i am only getting image not the rectangle.
Using below code i am getting black image
int Width = (int)canvas1.RenderSize.Width;
int Height = (int)canvas1.RenderSize.Height;
RenderTargetBitmap renderTargetBitmap =
new RenderTargetBitmap(Width, Height, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(canvas1);
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (Stream fileStream = File.Create(filePath))
{
pngImage.Save(fileStream);
}
if i am replacing canvas with image only image is coming.
How to take screenshot containing both the controls ?
have a no-op after the render call for the render to be completed before taking the screenshot.
Also am assuming you are able to view the drawn rectangle in the viewport
and it is only not appearing in the screenshot. If not make sure the color of the rectangle is distinct against the image background.
renderTargetBitmap.Render(canvas1);
//no-op for rendering to complete before taking screenshot.
_dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { }));
//screenshot code here.

Merge two image in windows universal 8.1

I have 1.png (150x150 size) and 2.png (150x150 size). I use this code for make a stackpanel (310x150 size):
StackPanel mygrid = new StackPanel();
mygrid.Orientation = Orientation.Horizontal;
Image myimage1 = new Image();
myimage1.Width = 150; myimage1.Height = 150;
myimage1.Source = new BitmapImage(new Uri(#"ms-appx:///assets/1.png", UriKind.RelativeOrAbsolute));
Image myimage2 = new Image();
myimage2.Width = 150; myimage2.Height = 150;
myimage2.Source = new BitmapImage(new Uri(#"ms-appx:///assets/2.png", UriKind.RelativeOrAbsolute));
mygrid.Children.Add(myimage1);
mygrid.Children.Add(myimage2);
Then I convert this stackpanel to Image:
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(mygrid, 310, 150);
I want to save this image in "ms-appx:///assets/3.png" (like this name) and use that. In this way, I merge two image to one image But I can't save them to 3.png. How can I do that?
If this is not a good way to merge two picture in one picture, Is it possible to help me?
Update: I'm sorry but question has problems and it is deleted. I can't delete it because there is answer on it. Thanks for helping me.
I think you are using generally the wrong approach to do this. I would load the 2 images into WriteableBitmaps and then blend them with the WriteableBitmapEx library
Having said that, here is how you can save the WriteableBitmap as png, taken from here:
// Save the writeableBitmap object to JPG Image file
IStorageFile saveFile = todo;// insert your code for opening the file here
IRandomAccessStream stream = await savefile.OpenAsync(FileAccessMode.ReadWrite);
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
// Get pixels of the WriteableBitmap object
Stream pixelStream = renderTargetBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
// Save the image file with jpg extension
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableBitmap.PixelWidth, (uint)writeableBitmap.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
You try to save the image as ms-appx:///assets/3.png that won't work as you can't save the image in the application package.
You need to save it to somewhere where your app has write access to.

Draw a bitmap in WPF

I am trying to draw some string to bitmap at certain position and copy a barcode bitmap to the new bitmap.I have not done with graphics before so i don't know where to start.
Can anyone guide me on this?my output of the bitmap is a receipt like.
Here is a solution. Please make a grid or canvas and put the barcode image and use a label with desired text and put the label on desired location relative to barcode grid. So, trick is you can immediately take screenshot of this grid using following code.Then, you are done.
public void ConvertToBitmapSource(UIElement element)
{
var target = new RenderTargetBitmap(
(int)element.RenderSize.Width, (int)element.RenderSize.Height,
96, 96, PixelFormats.Pbgra32);
target.Render(element);
var encoder = new PngBitmapEncoder();
var outputFrame = BitmapFrame.Create(target);
encoder.Frames.Add(outputFrame);
using (var file = File.OpenWrite("TestImage.png"))
{
encoder.Save(file);
}
}

The fastest way to convert canvas to the writeablebitmap in WPF?

I currently have one writeablebitmap image and canvas with drawings and I want to send the images to the peer.In order to reduce the bandwidth, I would like to convert canvas to the writeablebitmap, thus I can blit both the images to a new writeablebitmap. The problem is I cannot find a good way to convert the canvas.
Therefore, I would like to ask if there is a direct way to convert the canvas to a writeablebitmap class.
This is taken from this blog post but instead of writing to a file, it writes to a WriteableBitmap.
public WriteableBitmap SaveAsWriteableBitmap(Canvas surface)
{
if (surface == null) return null;
// Save current canvas transform
Transform transform = surface.LayoutTransform;
// reset current transform (in case it is scaled or rotated)
surface.LayoutTransform = null;
// Get the size of canvas
Size size = new Size(surface.ActualWidth, surface.ActualHeight);
// Measure and arrange the surface
// VERY IMPORTANT
surface.Measure(size);
surface.Arrange(new Rect(size));
// Create a render bitmap and push the surface to it
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(
(int)size.Width,
(int)size.Height,
96d,
96d,
PixelFormats.Pbgra32);
renderBitmap.Render(surface);
//Restore previously saved layout
surface.LayoutTransform = transform;
//create and return a new WriteableBitmap using the RenderTargetBitmap
return new WriteableBitmap(renderBitmap);
}

How do I overlay an image in .NET

I have a .png image i wish to overlay on a base image.
My overlay image contains just a red slant line. I need to get the red line overlayed on the base image at the same co-ordinate as it is in overlay image.
The problem is I do not have the co-ordinates location.
I need to find it programmatically with C#. The overlay image will always be transparent or of white background. What code to find the line co-ordinates from overlay image?
You can create new image, render background image first and then render overlay image over it. Since overlay has alpha channel and line is placed where it should be (i mean there is opaque space on top and left side of line) you do not need coordinates. Illustration code:
Image imageBackground = Image.FromFile("bitmap1.png");
Image imageOverlay = Image.FromFile("bitmap2.png");
Image img = new Bitmap(imageBackground.Width, imageBackground.Height);
using (Graphics gr = Graphics.FromImage(img))
{
gr.DrawImage(imageBackground, new Point(0, 0));
gr.DrawImage(imageOverlay, new Point(0, 0));
}
img.Save("output.png", ImageFormat.Png);
If you are using WPF, why not use a path for your overlay instead of an image if it is a simple line? This would allow it to scale to any size, and has methods for manipulating its dimensions.
If you are using Winforms, there are some similar graphics drawing capabilities you might leverage. Getting the dimensions of the image should be easy, assuming you're using a PictureBox, the following properties should suffice:
myPictureBox.Top
myPictureBox.Bottom
myPictureBox.Left
myPictureBox.Right
Similarly, for a WPF Image:
myImage.Margin
I already needed to create a blank space around an image and I used the ImageFactory library to do that.
Here is the code. I guess you are capable to figure out how to adjust to your needs.
public static Image ResizedImage(Image image, int desiredWidth, int desiredHeight)
{
Image res = (Bitmap)image.Clone();
Image resizedImage;
ImageLayer imageLayer = new ImageLayer();
try
{
if (res != null)
{
//white background
res = new Bitmap(desiredWidth, desiredHeight, res.PixelFormat);
//image to handle
using (var imgf = new ImageFactory(true))
{
imgf
.Load(image)
.Resize(new ResizeLayer(new Size(desiredWidth, desiredHeight),
ResizeMode.Max,
AnchorPosition.Center,
false));
resizedImage = (Bitmap)imgf.Image.Clone();
}
//final image
if (resizedImage != null)
{
imageLayer.Image = resizedImage;
imageLayer.Size = new Size(resizedImage.Width, resizedImage.Height);
imageLayer.Opacity = 100;
using (var imgf = new ImageFactory(true))
{
imgf
.Load(res)
.BackgroundColor(Color.White)
.Overlay(imageLayer);
res = (Bitmap)imgf.Image.Clone();
}
}
}
}
catch (Exception ex)
{
ex.Message;
}
return res;
}

Categories