I want to add a piece of text into an image in UWP. When I use the Microsoft.Graphics.Canvas.Text in win2D, it just created an image with Text. So how could I add a text into an existed image? Thanks.Like this
As #Trey's comment, we should be able to use Win2d in UWP.
To install Win2D.uwp, run the following command in the Package Manager Console
Install-Package Win2D.uwp
We should be able use the CanvasBitmap.LoadAsync method to load a bitmap from a stream. Then we can use the CanvasRenderTarget.CreateDrawingSession method to return a new drawing session that we can use it to draw the image and text to the drawing session.
At last we should be able to write the CanvasRenderTarget to the file.
For example:
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
var sourceFile = await picker.PickSingleFileAsync();
if (sourceFile == null) { return; }
var device = CanvasDevice.GetSharedDevice();
var image = default(CanvasBitmap);
using (var s = await sourceFile.OpenReadAsync())
{
image = await CanvasBitmap.LoadAsync(device, s);
}
var offscreen = new CanvasRenderTarget(
device, (float)image.Bounds.Width, (float)image.Bounds.Height, 96);
using (var ds = offscreen.CreateDrawingSession())
{
ds.DrawImage(image, 0, 0);
ds.DrawText("Hello world", 10, 10, Colors.Blue);
}
var displayInformation = DisplayInformation.GetForCurrentView();
var savepicker = new FileSavePicker();
savepicker.FileTypeChoices.Add("png", new List<string> { ".png" });
var destFile = await savepicker.PickSaveFileAsync();
using (var s = await destFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, s);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)offscreen.Size.Width,
(uint)offscreen.Size.Height,
displayInformation.LogicalDpi,
displayInformation.LogicalDpi,
offscreen.GetPixelBytes());
await encoder.FlushAsync();
}
Related
I search in web but I not found any solution to take a screenshot an UI element (in bitmap by example) in UWP - Universal Windows Platform.
You may use Render XAML to bitmap
Some Sample Code here:
// Render to an image at the current system scale and retrieve pixel contents
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(RenderedGrid);
var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
var savePicker = new FileSavePicker();
savePicker.DefaultFileExtension = ".png";
savePicker.FileTypeChoices.Add(".png", new List<string> { ".png" });
savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
savePicker.SuggestedFileName = "snapshot.png";
// Prompt the user to select a file
var saveFile = await savePicker.PickSaveFileAsync();
// Verify the user selected a file
if (saveFile == null)
return;
// Encode the image to the selected file on disk
using (var fileStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
DisplayInformation.GetForCurrentView().LogicalDpi,
DisplayInformation.GetForCurrentView().LogicalDpi,
pixelBuffer.ToArray());
await encoder.FlushAsync();
}
Sample Example
https://code.msdn.microsoft.com/windowsapps/XAML-render-to-bitmap-dd4f549f
I'm getting photo path from a list view and showing image in detail screen.
Detail page Code is here.
//Imaged is my image control in Xaml.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var imagePath = e.Parameter as string;
imaged.Source = new BitmapImage(new Uri(imagePath, UriKind.RelativeOrAbsolute));
var imgsource = imaged.Source;
}
I want to save this picture in media Library, by clicking save button event.
Here is my Save button event code.
private async void ApplicationBarIconButton_Click_SaveToPictures(object sender, RoutedEventArgs e)
{
FileSavePicker picker = new FileSavePicker();
// picker.FileTypeChoices.Add("PNG File", new List<string>() { ".png" });
picker.FileTypeChoices.Add("JPEG image", new string[] { ".jpg" });
picker.FileTypeChoices.Add("PNG image", new string[] { ".png" });
picker.FileTypeChoices.Add("BMP image", new string[] { ".bmp" });
picker.DefaultFileExtension = ".png";
picker.SuggestedFileName = "bomdiaimg";
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
StorageFile file = await picker.PickSaveFileAsync();
// StorageFile file = await picker.PickSaveFileAndContinue();
if (file != null)
{
RenderTargetBitmap renderTargetBitMap = new RenderTargetBitmap();
await renderTargetBitMap.RenderAsync(imaged, (int)imaged.Width, (int)imaged.Height);
var pixels = await renderTargetBitMap.GetPixelsAsync();
using (IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, randomAccessStream);
byte[] bytes = pixels.ToArray();
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)renderTargetBitMap.PixelWidth, (uint)renderTargetBitMap.PixelHeight, 96, 96, bytes); await encoder.FlushAsync();
}
}
}
I'm not able to save picture the error is that
Here the error is an exception.
StorageFile file = await picker.PickSaveFileAsync();
SOme times green line under this method "which shows that use picksavefile and continue" But when I use this method then error display. not able to understand this issue. how can I save my picture in media library
The SaveJpeg method is an extension method from the namespace System.Windows.Media.Imaging.Extensions. Add a using at the top of the source file:
using System.Windows.Media.Imaging.Extensions;
And, possibly you meant to use System.Windows.Media.Imaging.WriteableBitmap instead of Windows.UI.Xaml.Media.Imaging.WriteableBitmap?
You maybe want use RenderTargetBitMap for save control image. Please check this example code.
FileSavePicker picker = new FileSavePicker();
picker.FileTypeChoices.Add("JPG File", new List<string>() { ".jpg" });
StorageFile file = await picker.PickSaveFileAsync(); if (file != null)
{
RenderTargetBitmap renderTargetBitMap = new RenderTargetBitmap();
//With this method we can make our XAML elements in an image. await
renderTargetBitMap.RenderAsync(grdRender, (int)grdRender.Width, (int)grdRender.Height);
var pixels = await renderTargetBitMap.GetPixelsAsync();
using (IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, randomAccessStream);
byte[] bytes = pixels.ToArray();
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)renderTargetBitMap.PixelWidth, (uint)renderTargetBitMap.PixelHeight, 96, 96, bytes); await encoder.FlushAsync();
}
}
I am developing an universal app, in my shared code i am trying to download the image from net and save the image to LocalFolder.
I am using HttpClient to download the images from user given urls and reading the client response to save the image. I am using below code to save, but couldn't able to find Writeable SaveJpeg method.
HttpResponseMessage response = await httpClient.GetAsync(imageUri);
await Task.Run(async () =>
{
if (response.IsSuccessStatusCode)
{
// save image locally
StorageFolder folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists);
BitmapImage bmp = new BitmapImage();
var buffer = await response.Content.ReadAsBufferAsync();
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
DataWriter writer = new DataWriter(ras.GetOutputStreamAt(0));
writer.WriteBuffer(buffer);
bmp.SetSource(ras);
}
});
What is the best way to save the imageresponse to localfolder with image quality % (for both WP and Windows).
You should save the stream directly instead of saving the BitmapImage.
Something like this.
var ras = new InMemoryRandomAccessStream();
var writer = new DataWriter(ras);
writer.WriteBuffer(buffer);
await writer.StoreAsync();
var inputStream = ras.GetInputStreamAt(0);
// you can still use this to display it on the UI though
//bmp.SetSource(ras);
// write the picture into this folder
var storageFile = await folder.CreateFileAsync("image1.jpg", CreationCollisionOption.GenerateUniqueName);
using (var storageStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
await RandomAccessStream.CopyAndCloseAsync(inputStream, storageStream.GetOutputStreamAt(0));
}
Update
You can use BitmapEncoder and when pass in property dpi values in SetPixelData.
using (var storageStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, storageStream);
var pixelStream = yourWriteableBitmap.PixelBuffer.AsStream();
var pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)yourWriteableBitmap.PixelWidth, (uint)yourWriteableBitmap.PixelHeight, 48, 48, pixels);
await encoder.FlushAsync();
}
I have a Windows 8 app in which I want to rotate an image file.
In shot, I want to open an image file, rotate it and save the content back to the file.
Is that possible in WinRT? If so, how? Thanks.
Update:
Base on Vasile's answer, I could do some work on this. However I'm not sure what to do next:
public static async Task RotateImage(StorageFile file)
{
if (file == null)
return;
var data = await FileIO.ReadBufferAsync(file);
// create a stream from the file
var ms = new InMemoryRandomAccessStream();
var dw = new DataWriter(ms);
dw.WriteBuffer(data);
await dw.StoreAsync();
ms.Seek(0);
// find out how big the image is, don't need this if you already know
var bm = new BitmapImage();
await bm.SetSourceAsync(ms);
// create a writable bitmap of the right size
var wb = new WriteableBitmap(bm.PixelWidth, bm.PixelHeight);
ms.Seek(0);
// load the writable bitpamp from the stream
await wb.SetSourceAsync(ms);
wb.Rotate(90);
//How should I save the image to the file now?
}
Ofcourse it is possible. You can do it yourself with a pixel manipulation and create a new WriteableBitmapObject or, you could reuse the already implemented functionality from the WriteableBitmapEx (WriteableBitmap Extensions). You can get it via NuGet.
Here you can find a description of the implemented functionality which it offers, and few short samples.
Use this to save WriteableBitmap to StorageFile
private async Task<StorageFile> WriteableBitmapToStorageFile(WriteableBitmap writeableBitmap)
{
var picker = new FileSavePicker();
picker.FileTypeChoices.Add("JPEG Image", new string[] { ".jpg" });
StorageFile file = await picker.PickSaveFileAsync();
if (file != null && writeableBitmap != null)
{
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(
BitmapEncoder.JpegEncoderId, stream);
Stream pixelStream = writeableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)writeableBitmap.PixelWidth, (uint)writeableBitmap.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
}
return file;
}
else
{
return null;
}
}
I want to share the screenshot of the app on Twitter, Facebook, etc. This is my code: it saves the picture, but doesn't open the share media task. I know the problem is in the path :{
var wb = new WriteableBitmap(LayoutRoot, new TranslateTransform());
using (var mediaLibrary = new MediaLibrary()) {
using (var stream = new MemoryStream()) {
var fileName = string.Format("{0}.jpg", DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss"));
wb.SaveJpeg(stream, wb.PixelWidth, wb.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
mediaLibrary.SavePicture(fileName, stream);
shareMediaTask = new ShareMediaTask();
shareMediaTask.FilePath = fileName;
shareMediaTask.Show();
}
}
How can I get the saved picture's path?
Isn't it possible to just simply take a screenshot and share it without saving it on the phone?
To get the real path for the MediaLibrary file, you'll need to use the GetPath() extension method, something like;
using Microsoft.Xna.Framework.Media.PhoneExtensions;
...
var picture = mediaLibrary.SavePicture(fileName, stream);
shareMediaTask = new ShareMediaTask();
shareMediaTask.FilePath = picture.GetPath();
shareMediaTask.Show();
For sharing the screen shot it is not required to save the image , in windows 8.1 it is very easy.
Here is the code, enjoy!
async void dataTransferMgr_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
DataRequest request = args.Request;
request.Data.Properties.Title = "Title";
request.Data.Properties.Description = "brief description";
request.Data.SetText("detailed information");
RandomAccessStreamReference imageStreamRef = await ScreenshotToStreamReferenceAsync(yourChartControlName);
request.Data.Properties.Thumbnail = imageStreamRef;
request.Data.SetBitmap(imageStreamRef);
}
private async Task ScreenshotToStreamAsync(FrameworkElement element, IRandomAccessStream stream)
{
var renderTargetBitmap = new Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(element);
var pixelBuffer = await renderTargetBitmap.GetPixelsAsync();
var dpi = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi;
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
dpi,
dpi,
pixelBuffer.ToArray());
await encoder.FlushAsync();
}
private async Task<RandomAccessStreamReference> ScreenshotToStreamReferenceAsync(FrameworkElement element)
{
var ms = new InMemoryRandomAccessStream();
await ScreenshotToStreamAsync(element, ms);
ms.Seek(0);
return RandomAccessStreamReference.CreateFromStream(ms);
}