imageControl.Source (C# UWP) - c#

I writing app for uwp
I have PCL, where is method for opening Camera, taking photo and saving it.
Here is code for method in PCL.
public async void PhotoTake()
{
CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo == null)
{
return;
}
StorageFolder destinationFolder =
await ApplicationData.Current.LocalFolder.CreateFolderAsync("ProfilePhotoFolder", CreationCollisionOption.OpenIfExists);
await photo.CopyAsync(destinationFolder, "ProfilePhoto.jpg", NameCollisionOption.ReplaceExisting);
await photo.DeleteAsync();
IRandomAccessStream stream = await photo.OpenAsync(FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap.Convert(softwareBitmap,
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied);
SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);
}
In xaml I have Image. I need to display photo in this Image.
As I understood I need to write smth like this imageControl.Source = bitmapSource;
But my when I write it I have
Error CS0103 The name 'bitmapSource' does not exist in the current context
Here is my xaml.cs file
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
CameraOpening cam = new CameraOpening();
cam.PhotoTake();
imageControl.Source = bitmapSource;
}
}
How I hadle this error?
Thank's

bitmapSource is a local variable inside your method. You can't access it from outside.
Change the method's return type from void to Task<SoftwareBitmapSource> and delete the image file after creating the bitmap:
public async Task<SoftwareBitmapSource> PhotoTake()
{
var captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
var bitmapSource = new SoftwareBitmapSource();
if (photo != null)
{
var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(
"ProfilePhotoFolder", CreationCollisionOption.OpenIfExists);
await photo.CopyAsync(folder, "ProfilePhoto.jpg",
NameCollisionOption.ReplaceExisting);
using (var stream = await photo.OpenAsync(FileAccessMode.Read))
{
var decoder = await BitmapDecoder.CreateAsync(stream);
var softwareBitmap = await decoder.GetSoftwareBitmapAsync();
var softwareBitmapBGR8 = SoftwareBitmap.Convert(
softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);
}
await photo.DeleteAsync();
}
return bitmapSource;
}
Then await the method call. As this can't be done in the Page's contructor, you may do it in a Loaded event handler:
public MainPage()
{
this.InitializeComponent();
Loaded += async (o, e) =>
{
var cam = new CameraOpening();
imageControl.Source = await cam.PhotoTake();
};
}

Related

how to convert StorageFile (png image) to transparent PNG Bitmap in c#?

I am making a UWP app where i want to pick a user signature scanned by the user and make the picture transparent.
now first things first:
I am using FileOpenPicker to pick the storage file.
Work tried by me
public async void Button_AddSign_Click(object sender, RoutedEventArgs e)
{
try
{
var _filePicker = new FileOpenPicker();
_filePicker.SuggestedStartLocation = PickerLocationId.Desktop;
_filePicker.ViewMode = PickerViewMode.Thumbnail;
_filePicker.FileTypeFilter.Add(".png");
IStorageFile _file = await _filePicker.PickSingleFileAsync();
StorageFolder storageFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync(CurrentUser);
if (_file != null)
{
StorageFile storageFile = await _file.CopyAsync(storageFolder, "Signature.png");
await MakeSignTransparentAsync(storageFile);
}
}
catch{Exception ex}
}
public static async Task MakeSignTransparentAsync(StorageFile Inputfile)
{
var memStream = new InMemoryRandomAccessStream();
using (IRandomAccessStream fileStream = await Inputfile.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(memStream, decoder);
encoder.BitmapTransform.ScaledWidth = 600;
encoder.BitmapTransform.ScaledHeight = 200;
await encoder.FlushAsync();
memStream.Seek(0);
fileStream.Seek(0);
fileStream.Size = 0;
await RandomAccessStream.CopyAsync(memStream, fileStream);
memStream.Dispose();
}
Bitmap bmp;
using (MemoryStream ms = new MemoryStream(memStream)) //Getting an error at this line
{
bmp = new Bitmap(ms);
}
bmp.MakeTransparent();
bmp.Save(bmpInput.Path + "test.png", ImageFormat.Png);
}
Error:
Argument 1: cannot convert from 'Windows.Storage.Streams.InMemoryRandomAccessStream' to 'byte[]
Any help is appreciated.
If there is another way around other than this that is also appreciated.
Found a solution using a library ImageMagick
using ImageMagick;
public static async Task MakeSignTransparentAsync(StorageFile bmpInput)
{
using (var img = new MagickImage(bmpInput.Path))
{
// -fuzz XX%
img.ColorFuzz = new Percentage(10);
// -transparent white
img.Transparent(MagickColors.White);
img.Write(bmpInput.Path);
}
}

How to get IRandomAccessStream from StorageFile

First I declared
private MediaCapture _mediaCapture;
StorageFile capturedPhoto;
IRandomAccessStream imageStream;
Second I am capturing
var lowLagCapture = await _mediaCapture.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8));
var capturedPhoto = await lowLagCapture.CaptureAsync();
await lowLagCapture.FinishAsync();
Third I am setting the image source:
var softwareBitmap = capturedPhoto.Frame.SoftwareBitmap;
SoftwareBitmap softwareBitmapBGRB = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
await bitmapSource.SetBitmapAsync(softwareBitmapBGRB);
image.Source = bitmapSource;
How can i get imageStream? I used CaptureElement tool in xaml .
It's quite simple, the question is what do you want to do with that IRandomAccessStreem. Below is some code I think you'll need:
public void HandleImageFileOperations(StorageFile file)
{
if (file != null)
{
//converts the StorageFile to IRandomAccessStream
var stream = await file.OpenAsync(FileAccessMode.Read);
//creates the stream to an Image just in-case you want to show it
var image = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
image.SetSource(stream);
//creates the image into byte array just in-case you need it to store the image
byte[] bitmapImageBytes = null;
var reader = new Windows.Storage.Streams.DataReader(stream.GetInputStreamAt(0));
bitmapImageBytes = new byte[stream.Size];
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(bitmapImageBytes);
}
}

Save Photo in media library windows phone 8.1

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();
}
}

Cropping Image with Xamlcropcontrol for UI and WriteableBitmapEx

For the past week I've been researching as much as i can on how to add the ability to crop a profile image in my windows store app. So far I have looked at the Microsoft solution to this but have decided to go a different route. I downloaded a control from NuGet called XamlCropControl. It works pretty well for the UI and even give me information like Original Height/Width The position of the cropped top/bottom/left/right/width/height all within the xaml control. my question is as how to take that information and crop the the image using WriteableBitmapEx. So far this is my code and i'm having a problem.
private async void ProfilePhotoImageClick(object sender, TappedRoutedEventArgs e)
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
using (Windows.Storage.Streams.IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(fileStream);
BackgroundLogo.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
PhotoUploadCropper.Opacity = 1;
PhotoUploadCropper.ImageSource = bitmapImage;
ProfileSetupStackPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
imagetoResize = bitmapImage;
}
}
}
BitmapImage imagetoResize;
private void AcceptPhotoImageCropClick(object sender, RoutedEventArgs e)
{
WriteableBitmap bmp = new WriteableBitmap(0,0).FromContent(imagetoResize);
var croppedBmp = bmp.Crop(0, 0, bmp.PixelWidth / 2, bmp.PixelHeight / 2);
croppedBmp.SaveToMediaLibrary("ProfilePhoto.jpg");
}
PhotoUploadCropper is the xamlcropcontrol.
This is the information from xamlcropcontrol
This is the problem im having
It tells me there is no deffinition for FromContent if i have the (imagetoResize) there but if i remove it i get no error. After all the cropping is done it will be uploading to azure blob storage which i have already setup.
Edit: Works like this.
private async void ProfilePhotoImageClick(object sender, TappedRoutedEventArgs e)
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read))
{
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
fileclone = file;
BackgroundLogo.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
PhotoUploadCropper.IsEnabled = true;
PhotoUploadCropper.Opacity = 1;
PhotoUploadCropper.ImageSource = bitmapImage;
ProfileSetupStackPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
}
}
StorageFile fileclone;
async Task<WriteableBitmap> LoadBitmap(StorageFile file)
{
int cropx = PhotoUploadCropper.CropTop;
int cropy = PhotoUploadCropper.CropLeft;
int cropW = PhotoUploadCropper.CropWidth;
int cropH = PhotoUploadCropper.CropHeight;
using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read))
{
var bmp = await BitmapFactory.New(1, 1).FromStream(fileStream);
var croppedBmp = bmp.Crop(cropy, cropx, cropW, cropH);
var resizedcroppedBmp = croppedBmp.Resize(200, 200, WriteableBitmapExtensions.Interpolation.Bilinear);
return resizedcroppedBmp;
}
}
private async void AcceptPhotoImageCropClick(object sender, RoutedEventArgs e)
{
var CroppedBMP = await CropBitmap(fileclone);
using (IRandomAccessStream fileStream = new InMemoryRandomAccessStream())
{
string filename = Path.GetRandomFileName() + ".JPG";
var file = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync(filename, CreationCollisionOption.GenerateUniqueName);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
Stream pixelStream = CroppedBMP.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, 0, pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)CroppedBMP.PixelWidth, (uint)CroppedBMP.PixelHeight, 96.0, 96.0, pixels);
await encoder.FlushAsync();
}
ProfilePhotoButtonsGrid.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
BackgroundLogo.Visibility = Windows.UI.Xaml.Visibility.Visible;
PhotoUploadCropper.IsEnabled = false;
PhotoUploadCropper.Opacity = 0;
ProfileSetupStackPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
if (fileStream != null)
{
UploadFile(file);
}
}
}
You will have to use the WBX WinRT APIs for this. Looks like you are trying the WP / Silverlight methods.
Try this:
async Task<WriteableBitmap> LoadBitmap(string path)
{
Uri imageUri = new Uri(BaseUri, path);
var bmp = await BitmapFactory.New(1, 1).FromContent(imageUri);
return bmp;
}
Note it takes an URI. In your case you can rather use the IRandomAccessStream directly:
var bmp = await BitmapFactory.New(1, 1).FromStream(fileStream);

How to Set Background Image from IsolatedStorage

I am loading a BitmapImage from IsolatedStorage and would like to set the value to the background of MainPage. I am not sure how to properly do this?
TombstoningHelper.cs
public async Task StorePhoto(Stream photoStream, string fileName)
{
// persist data into isolated storage
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream current = await file.OpenStreamForWriteAsync())
{
await photoStream.CopyToAsync(current);
}
}
public async Task<BitmapImage> RetrievePhoto(string fileName)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
Stream imageStream = await file.OpenStreamForReadAsync();
//Check if file exists
// display the file as image
BitmapImage bi = new BitmapImage();
bi.SetSource(imageStream);
return bi;
}
MainPage.xaml.cs
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
//Set Page Theming
ImageBrush ib = new ImageBrush();
TombstoningHelper tsh = new TombstoningHelper();
if (Settings.TransparentBackground.Value == null)
ib.ImageSource = new BitmapImage(new Uri("/Assets/Graphics/" + Settings.Background.Value, UriKind.Relative)); //No Error
else
ib.ImageSource = tsh.RetrievePhoto(Constants.BackgroundImageName); //Error occurs here
LayoutRoot.Background = ib;
I am getting an error above stating Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Windows.Media.Imaging.BitmapImage>' to 'System.Windows.Media.ImageSource.
You need to use the await keyword since your Helper's methods are asynchronous.
else
ib.ImageSource = await tsh.RetrievePhoto(Constants.BackgroundImageName);
You should use await statement, like this:
ib.ImageSource = await tsh.RetrievePhoto(Constants.BackgroundImageName);

Categories