Merge two image in windows universal 8.1 - c#

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.

Related

Put an image on another image

I'm currently using the below code to put an image on top of another image
Stream stream = client.OpenRead(some URL here);
Bitmap baseimg = (Bitmap)System.Drawing.Image.FromStream(stream);
Bitmap ovlimg = (Bitmap)System.Drawing.Image.FromFile("fanmade.png");
var finalImage = new Bitmap(baseimg.Width, baseimg.Height);
var graphics = Graphics.FromImage(finalImage);
graphics.CompositingMode = CompositingMode.SourceOver;
graphics.DrawImage(baseimg, 0, 0);
graphics.DrawImage(ovlimg, 0, 0);
finalImage.Save("1.png", System.Drawing.Imaging.ImageFormat.Png);
However, the file size turns out to be a lot bigger than expected from 6-9 Mb to 16Mb. So I'm trying to find a more efficient way that would make the file size smaller while still keeping the image quality
Here are both the images
The Base IMG (Changes based on the user input but here's an example): https://pasteboard.co/K6hCXng.png
The overlay IMG: https://pasteboard.co/K6hDvIc.png

WPF: Image control of a CroppedBitmap as BitmapImage is still uncropped Image (Conversion Problem?)

I am trying to Crop a BitmapImage in my WPF application StageWindow.Stage using the CroppedBitmap class.
When saving the new cropped image to file JpegBitmapEncoder I can see the correctly cropped image. CroppedBitmap Crop
However I actually want to save the cropped image into a List\<BitmapImage\> for later use in another WPF image control. That list contains BitmapImages already so changing it to CroppedBitmaps would not suffice.
to be able to store the new croppedBitmap I use something like this:
BitmapImage xx = CroppedBitmap1 as BitmapImage;
when setting an WPF image control to the new BitmapImage (ExpectedCroppedImage) it still displays the CroppedBitmaps original source image without the crop.
I suspect the code above to delete the crop attribute from the new BitmapImage because the BitmapImage itself has no attributes for the cropped Area. But how can I save only the cropped part into a new BitmapImage?
I have been searching around but it seems CroppedBitmap should do the trick I just dont know how to convert it back in the correct manner.
Here is the Code for clarification:
//Stage is the WPF image element that im reading the source image from.
ImageSource StageWindowImageSource = StageWindow.Stage.Source;
CroppedBitmap Crop = new CroppedBitmap((BitmapSource)StageWindowImageSource, new Int32Rect(0,0,50,50));
ExpectedCroppedImage = Crop.Source as BitmapImage;
JpegBitmapEncoder jpg = new JpegBitmapEncoder();
jpg.Frames.Add(BitmapFrame.Create(Crop));
FileStream fp = new FileStream("F:/Crop.jpg", FileMode.Create, FileAccess.Write);
jpg.Save(fp);
fp.Close();
The line
ExpectedCroppedImage = Crop.Source as BitmapImage;
does not return the cropped bitmap, but the original one from which the crop was taken, i.e. the Source bitmap.
Besides that, you don't need any conversion from CroppedBitmap to BitmapImage.
Instead, use a base class of BitmapImage and CroppedBitmap as element type of the List, i.e. use a List<BitmapSource> or List<ImageSource> for your collection.
Now you can assign instances of any class derived from the element type.
List<BitmapSource> images = ...
CroppedBitmap croppedImage = new CroppedBitmap(...);
images.Add(croppedImage);
BitmapImage someOtherImage = new BitmapImage(...);
images.Add(someOtherImage);
private void MyMethod()
{
ImageSource StageWindowImageSource = img.Source;
CroppedBitmap Crop = new CroppedBitmap((BitmapSource) StageWindowImageSource, new Int32Rect(20, 20, 150, 110));
img2.Source = GetImage(Crop, new JpegBitmapEncoder());
}
private BitmapImage GetImage(BitmapSource source, BitmapEncoder encoder)
{
var image = new BitmapImage();
using (var sourceMs = new MemoryStream())
{
encoder.Frames.Add(BitmapFrame.Create(source));
encoder.Save(sourceMs);
sourceMs.Position = 0;
using (var destMs = new MemoryStream(sourceMs.ToArray()))
{
image.BeginInit();
image.StreamSource = destMs;
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
image.Freeze();
}
}
return image;
}

Move BoundingRect of InkStroke to 0;0

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

WPF Rectangle FIll imagebrush not updating

I am developing a WPF application, a messenger client. The user should be able to change his avatar image. When he right-clicks his avatar, a open file dialog appears and there he can select the image he wants. After he has made his decision I delete his current avatar and copy the new one in the same place with the same name. The avatar image is a rectangle with an imagebrush fill. The problem is that the image does not update until I restart the application. Here is the piece of code used to load the new image.
if (x.ShowDialog() == true)
{
ImageBrush img = new ImageBrush();
BitmapImage bit = new BitmapImage();
Bitmap bmp = new Bitmap(x.FileName);
System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "/data/images/avatar/x.png");
bmp.Save(System.IO.Directory.GetCurrentDirectory() + "/data/images/avatar/x.png", System.Drawing.Imaging.ImageFormat.Png);
bit.BeginInit();
bit.CacheOption = BitmapCacheOption.OnLoad;
bit.UriSource = new Uri(#"pack://siteoforigin:,,,/data/images/avatar/x.png");
bit.EndInit();
img.ImageSource = bit;
ProfileImage.Fill = img;
}
I hope you can help me solve this issue or offer me some alternatives. Thank you all!
In order to make BitmapImage reload the image file (with identical file path), you could set the BitmapCreateOptions.IgnoreImageCache option:
bit.BeginInit();
bit.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bit.CacheOption = BitmapCacheOption.OnLoad;
bit.UriSource = new Uri(#"pack://siteoforigin:,,,/data/images/avatar/x.png");
bit.EndInit();
img.ImageSource = bit;

WPF: "edit" image and save

I want to do something like that: open an image in the <image> tag and add some other tags on it, for example green rectangle. After that I want to save it like image with rectangle on some part of it. In general user should drag&drop rectangle and could resize it. But the question is: How can I save it? I suppose that I should save parent tag for all of them, for example <grid> or <canvas> but is it possible?
Transform transform = myCanvas.LayoutTransform;
myCanvas.LayoutTransform = null; Size size = new Size(myCanvas.Width,myCanvas.Height); myCanvas.Measure(size);
myCanvas.Arrange(new Rect(size));
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d,PixelFormats.Pbgra32);
renderBitmap.Render(myCanvas);
using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
myCanvas.LayoutTransform = transform;
For a detailed explanation (and the source of the above code), see this blog post:
http://denisvuyka.wordpress.com/2007/12/03/wpf-diagramming-saving-you-canvas-to-image-xps-document-or-raw-xaml/
You can save as PNG, JPG, etc depending on the encoder that you use

Categories