How to get IRandomAccessStream from StorageFile - c#

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

Related

How can set image according to format in SimplePdfViewerControl in UWP

When I tried to view image in PdfViewer with Letter Format then Image is bluring. while when I tried viewing without defined format then picture is clear.
My Code
private async void Load(PdfDocument pdfDoc)
{
try
{
PdfPages.Clear();
for (uint i = 0; i < pdfDoc.PageCount; i++)
{
BitmapImage image = new BitmapImage();
var page = pdfDoc.GetPage(i);
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
//PdfPageRenderOptions pdfPageRenderOptions = new PdfPageRenderOptions();
{
await page.RenderToStreamAsync(stream);
await image.SetSourceAsync(stream);
}
PdfPages.Add(image);
}
}
This Code Belong to Format set
StorageFile ImageFile;
var storageFolder = await KnownFolders.GetFolderForUserAsync(null, KnownFolderId.PicturesLibrary);
StorageFolder projectFolder = await storageFolder.CreateFolderAsync(imageLocation, CreationCollisionOption.OpenIfExists);
StorageFile file = await projectFolder.GetFileAsync(item);
if (file == null) return;
var Stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
IRandomAccessStream stream = await file.OpenReadAsync();
Stream imageStream = stream.AsStreamForRead();
BitmapImage sourceImage = new BitmapImage();
PdfBitmap image = new PdfBitmap(imageStream);
PdfSection section1 = doc.Sections.Add();
section1.PageSettings.Size = PdfPageSize.Letter;
page = section1.Pages.Add();
PdfGraphics graphics = page.Graphics;
//Draw the image
if (fileType == Constants.PrescriptionType.Prescription.GetHashCode())
graphics.DrawImage(image, 0, 0, page.Graphics.ClientSize.Width, page.Graphics.ClientSize.Height);
else
graphics.DrawImage(image, 0, 0, page.Graphics.ClientSize.Width, page.Graphics.ClientSize.Height);
Thank You

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

imageControl.Source (C# UWP)

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

Windows 8 How to open a BitmapImage as a stream?

In a Windows 8 app, how do I convert a BitmapImage to a Stream? I have a List of BitmapImages and I'm going to use that List to upload each image to a server and I need to use a Stream to do that. So is there a way to convert each individual BitmapImage into a Stream?
No, there isn't. You need to track the original sources or use a WriteableBitmap instead.
Retrieve the bitmap image:
public async void ContinueFileOpenPicker(FileOpenPickerContinuationEventArgs args)
{
if (args.Files.Count > 0)
{
var imageFile = args.Files[0] as StorageFile;
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
ImageControl.Source = bitmapImage;
await _viewModel.Upload(imageFile);
}
}
}
Create the file stream:
internal async Task Upload(Windows.Storage.StorageFile file)
{
var fileStream = await file.OpenAsync(FileAccessMode.Read);
fileStream.Seek(0);
var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
Globals.MemberId = ApplicationData.Current.LocalSettings.Values[Globals.PROFILE_KEY];
var userName = "Rico";
var sex = 1;
var url = string.Format("{0}{1}?memberid={2}&name={3}&sex={4}", Globals.URL_PREFIX, "api/Images", Globals.MemberId, userName,sex);
byte[] image = new byte[fileStream.Size];
await UploadImage(image, url);
}
Create a memory stream from the image:
public async Task UploadImage(byte[] image, string url)
{
Stream stream = new System.IO.MemoryStream(image);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
Uri resourceAddress = null;
Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
request.Content = streamContent;
var httpClient = new Windows.Web.Http.HttpClient();
var cts = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
}

Rotating images in WinRT

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

Categories