How to display Windows.Graphics.Imaging.BitmapDecoder in WinJS? - windows-8

I am trying to make an app that applies filter effects on images. From FilePicker I can get a IRandomAccessStream and I can convert it to BitmapDecoder. But I am not sure how to diplay the bitmap data as image? I do not want to use the file name or path, just want to display the BitmapData as an image. What control should I use in WinJS and how to do it?

Convert an IInputStream or IRandomAccessStream to an image with MSApp.createStreamFromInputStream() and URL.createObjectURL():
var path = Windows.Storage.ApplicationData.current.localFolder.path + "\\thing.jpg";
Windows.Storage.StorageFile.getFileFromPathAsync(path).then(function (file) {
file.openAsync(Windows.Storage.FileAccessMode.read).then(function (randomStream) {
// Convert the stream to MS-Stream.
var msStream = MSApp.createStreamFromInputStream("image/jpeg", randomStream);
var imageUrl = URL.createObjectURL(msStream);
var img = document.getElementById("theImage");
img.src = imageUrl;
}, onError);
}, onError);
The HTML should look like this:
<img id="theImage" src="#" />

These MSDN blogs explain the following process in more detail
http://goo.gl/izCdf
http://goo.gl/OLgfn
I found a way to create a BitmapEncoder from a BitmapDecoder. That encoder can be used to create a in memory stream that can be displayed in a field.
internal async Task<InMemoryRandomAccessStream> applyFilterInternal()
{
inputStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(inputStream);
var memStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
var encoder = await Windows.Graphics.Imaging.BitmapEncoder.CreateForTranscodingAsync(memStream, decoder);
encoder.BitmapTransform.ScaledWidth = 640;
encoder.BitmapTransform.ScaledHeight = 480;
encoder.BitmapTransform.Rotation = Windows.Graphics.Imaging.BitmapRotation.Clockwise90Degrees;
// Fant is a relatively high quality interpolation algorithm.
encoder.BitmapTransform.InterpolationMode = Windows.Graphics.Imaging.BitmapInterpolationMode.Fant;
// Attempt to generate a new thumbnail from the updated pixel data.
// Note: Only JPEG, TIFF and JPEG-XR images support encoding thumbnails.
encoder.IsThumbnailGenerated = true;
await encoder.FlushAsync();
return memStream;
}
public IAsyncOperation<InMemoryRandomAccessStream> applyFilter()
{
Task<InMemoryRandomAccessStream> from = applyFilterInternal();
IAsyncOperation<InMemoryRandomAccessStream> to = from.AsAsyncOperation();
return to;
}
To display this -
filter.applyFilter().then(function (memStream) {
var msStream = MSApp.createStreamFromInputStream("image/jpeg", memStream);
var imageURL = URL.createObjectURL(msStream);
id("imageInput").src = imageURL;
});

Related

Send Image to the API using image path that stored in local database

I am trying to send image to the API, I have multiple local storage image path which is stored in local
database sqlite and I have to upload these image on one click. in the
local database. replace _mediaFile = await CrossMedia.Current.TakePhotoAsync
with _mediaFile = Image_Path_From_Database
The datatobesync it contain multiple local storage image path from local dat
conn = await DependencyService.Get().GetConnection();
List datatobesync = new List();
datatobesync = (from c in conn.Table<CDCInfo>()
where c.SyncStatus == 0 && c.UserName == Settings.Username
select new CDCInfo
{
PhotoPath = c.PhotoPath,
}
I have a string image path but I am not sure about how
to use this
Using MediaPlugin for opening a gallery or camera. After selecting the
picture I set that picture to _mediafile and added to the content and send it to the API.
Detail Here
these lines of code gets image from the gallery or camra (using MediaPlugin) in a
mediaFile and send it to the API
private MediaFile _mediaFile;
_mediaFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.
StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg",
AllowCropping = true,
PhotoSize = PhotoSize.Medium
});
var content = new MultipartFormDataContent();
content.Add(new StreamContent(_mediaFile.GetStream()),"\"Files\"", $"\"{_mediaFile.path}\"");
var httpClnt = new HttpClient();
result = await httpClnt.PostAsync(Urle, content);
How can I add image to the content using database path and send it to the API without using MediaPlugin.
I am trying to do something like
foreach (var item in datatobesync)
{
try
{
HttpClient client = new HttpClient();
MultipartFormDataContent content = new
MultipartFormDataContent();
content.Add(new
StreamContent("Here I want to user item.PhotoPath Image path from the database".GetStream()),"\"Files\"",
$"\"{item.PhotoPath}\"");
var httpClnt = new HttpClient();
result = await httpClnt.PostAsync(Urle, content);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I dont know how to use image path at this line
content.Add(new StreamContent(How_to_User_ImagePath_Her.GetStream()),"\"Files\"",
$"\"{item.PhotoPath}\"");
How to get GetStram() of image path

How to generate the Thumbnail of the PDF first page in Xamarin Forms

I'm using the Syncfusion PDF viewer for Xamarin Forms to display a collection of PDF files and it seems the conversion from PDF to PNG (to extract the first page (the cover) of the PDF file to show it, to the user, into a carousel) didn't work in Xamarin [see https://www.syncfusion.com/kb/9112/how-to-convert-pdf-to-png]
I wonder if there is a way to convert PDF into PNG on the Xamarin platform or if I should convert it on the server side.
Thank you.
You can export PDF pages to images without using Syncfusion PDF Viewer control by consuming the PdfRenderer , CGPDFDocument, and PdfDocument classes.
Xamarin.Forms.Android:
//initialize PDFRenderer by passing PDF file from location.
PdfRenderer renderer = new PdfRenderer(GetSeekableFileDescriptor());
int pageCount = renderer.PageCount;
for(int i=0;i<pageCount;i++)
{
// Use `openPage` to open a specific page in PDF.
Page page = renderer.OpenPage(i);
//Creates bitmap
Bitmap bmp = Bitmap.CreateBitmap(page.Width, page.Height, Bitmap.Config.Argb8888);
//renderes page as bitmap, to use portion of the page use second and third parameter
page.Render(bmp, null, null, PdfRenderMode.ForDisplay);
//Save the bitmap
SaveImage(bmp);
page.Close();
}
//Method to retrieve PDF file from the location
private ParcelFileDescriptor GetSeekableFileDescriptor()
{
ParcelFileDescriptor fileDescriptor = null;
try
{
string root = Android.OS.Environment.ExternalStorageDirectory.ToString()+ "/Syncfusion/sample.pdf";
fileDescriptor = ParcelFileDescriptor.Open(new Java.IO.File(root),ParcelFileMode.ReadOnly
);
}
catch (FileNotFoundException e)
{
}
return fileDescriptor;
}
Xamarin.Forms.iOS:
public void ConvertToImage(Stream fileStream) //Pass PDF stream
{
MemoryStream stream = new MemoryStream();
// Create memory stream from file stream.
fileStream.CopyTo(stream);
// Create data provider from bytes.
CGDataProvider provider = new CGDataProvider(stream.ToArray());
try
{
//Load a PDF file.
m_pdfDcument = new CGPDFDocument(provider);
}
catch (Exception)
{
}
//Get PDF's page and convert as image.
using (CGPDFPage pdfPage = m_pdfDcument.GetPage(2))
{
//initialise image context.
UIGraphics.BeginImageContext(pdfPage.GetBoxRect(CGPDFBox.Media).Size);
// get current context.
CGContext context = UIGraphics.GetCurrentContext();
context.SetFillColor(1.0f, 1.0f, 1.0f, 1.0f);
// Gets page's bounds.
CGRect bounds = new CGRect(pdfPage.GetBoxRect(CGPDFBox.Media).X, pdfPage.GetBoxRect(CGPDFBox.Media).Y, pdfPage.GetBoxRect(CGPDFBox.Media).Width, pdfPage.GetBoxRect(CGPDFBox.Media).Height);
if (pdfPage != null)
{
context.FillRect(bounds);
context.TranslateCTM(0, bounds.Height);
context.ScaleCTM(1.0f, -1.0f);
context.ConcatCTM(pdfPage.GetDrawingTransform(CGPDFBox.Crop, bounds, 0, true));
context.SetRenderingIntent(CGColorRenderingIntent.Default);
context.InterpolationQuality = CGInterpolationQuality.Default;
// Draw PDF page in the context.
context.DrawPDFPage(pdfPage);
// Get image from current context.
pdfImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
}
}
// Get bytes from UIImage object.
using (var imageData = pdfImage.AsPNG())
{
imageBytes = new byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, imageBytes, 0, Convert.ToInt32(imageData.Length));
//return bytes;
}
//Create image from bytes.
imageStream = new MemoryStream(imageBytes);
//Save the image. It is a custom method to save the image
Save("PDFtoImage.png", "image/png", imageStream);
}
Xamarin.Forms.UWP
public async void ConvertToImage(Stream fileStream) //Pass PDF stream
{
StorageFile file = null;
//Creates file picker to choose PDF file.
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.FileTypeFilter.Add(".pdf");
filePicker.ViewMode = PickerViewMode.Thumbnail;
filePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
filePicker.SettingsIdentifier = "picker1";
filePicker.CommitButtonText = "Open Pdf File";
//Open file picker option
file = await filePicker.PickSingleFileAsync();
// Load selected PDF file from the file picker.
PdfDocument pdfDocument = await PdfDocument.LoadFromFileAsync(file);
if (pdfDocument != null && pdfDocument.PageCount > 0)
{
for (int pageIndex = 0; pageIndex < pdfDocument.PageCount; pageIndex++)
{
//Get page from a PDF file.
var pdfPage = pdfDocument.GetPage((uint)pageIndex);
if (pdfPage != null)
{
//Create temporary folder to store images.
StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;
//Create image file.
StorageFile destinationFile = await KnownFolders.CameraRoll.CreateFileAsync(Guid.NewGuid().ToString() + ".jpg");
if (destinationFile != null)
{
IRandomAccessStream randomStream = await destinationFile.OpenAsync(FileAccessMode.ReadWrite);
//Crerate PDF rendering options
PdfPageRenderOptions pdfPageRenderOptions = new PdfPageRenderOptions();
pdfPageRenderOptions.DestinationWidth = (uint)(300);
// Render the PDF's page as stream.
await pdfPage.RenderToStreamAsync(randomStream, pdfPageRenderOptions);
await randomStream.FlushAsync();
//Dispose the random stream
randomStream.Dispose();
//Dispose the PDF's page.
pdfPage.Dispose();
}
}
}
}
}
I work for Syncfusion.

Windows Phone 8.1 Media Capture Rotated Incorrectly

I'm having great difficulty getting my captured image to be rotated correctly, the bitmapencoder class doesn't seem to be doing anything.
private async Task CapturePhoto()
{
ImageEncodingProperties pIEPEncoder = ImageEncodingProperties.CreateJpeg();
InMemoryRandomAccessStream pIMSCapture = new InMemoryRandomAccessStream();
using (pIMSCapture)
{
await cMCeCapture.CapturePhotoToStreamAsync(pIEPEncoder, pIMSCapture);
pIMSCapture.Seek(0);
BitmapDecoder pBDrDecoder = await BitmapDecoder.CreateAsync(pIMSCapture);
BitmapEncoder pBErEncoder = await BitmapEncoder.CreateForTranscodingAsync(pIMSCapture, pBDrDecoder);
pBErEncoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
pBErEncoder.BitmapTransform.Rotation = ConvertDegreesToBitmapRotation(cIntRotationDegrees);
await pBErEncoder.FlushAsync();
BitmapImage pBIeCapture = new BitmapImage();
pIMSCapture.Seek(0);
await pBIeCapture.SetSourceAsync(pIMSCapture);
CaptureImage.Source = pBIeCapture;
CaptureImage.Stretch = Stretch.Uniform;
CaptureImage.Width = LayoutRoot.ActualWidth;
CaptureImage.Height = LayoutRoot.ActualHeight;
}
await CleanupCameraAsync();
}
Any ideas how to fix this? The camera API seems to be my nemesis as of late, so frustrating to get anything working how I would like.
I have found an alternative solution and that's to use the WritableBitmapEx class obtained from here,
https://writeablebitmapex.codeplex.com/
This actually does what it's supposed to do, unlike the BitmapEncoder class for some reason. Plus it's super easy to use. Although flipping Horizontal seems to flip Vertical instead, not entirely sure why but it works anyway. I just switched Horizontal and Vertical over.
private async Task CapturePhoto()
{
ImageEncodingProperties pIEPEncoder = ImageEncodingProperties.CreateJpeg();
InMemoryRandomAccessStream pIMSCapture = new InMemoryRandomAccessStream();
using (pIMSCapture)
{
await cMCeCapture.CapturePhotoToStreamAsync(pIEPEncoder, pIMSCapture);
if(!cBlnExternalCamera)
{
pIMSCapture.Seek(0);
BitmapImage pBIeCapture = new BitmapImage();
await pBIeCapture.SetSourceAsync(pIMSCapture);
pIMSCapture.Seek(0);
WriteableBitmap pWBpBitmap = new WriteableBitmap(pBIeCapture.PixelWidth, pBIeCapture.PixelHeight);
await pWBpBitmap.SetSourceAsync(pIMSCapture);
if (cIntRotationDegrees != 0)
pWBpBitmap = pWBpBitmap.Rotate(cIntRotationDegrees);
if (cBlnMirroringPreview)
pWBpBitmap = pWBpBitmap.Flip(cDInDisplayInformation.CurrentOrientation == DisplayOrientations.Landscape || cDInDisplayInformation.CurrentOrientation == DisplayOrientations.LandscapeFlipped ? WriteableBitmapExtensions.FlipMode.Vertical : WriteableBitmapExtensions.FlipMode.Horizontal);
CaptureImage.Source = pWBpBitmap;
CaptureImage.Stretch = Stretch.Uniform;
CaptureImage.Width = LayoutRoot.ActualWidth;
CaptureImage.Height = LayoutRoot.ActualHeight;
}
else
{
pIMSCapture.Seek(0);
BitmapImage pBIeCapture = new BitmapImage();
await pBIeCapture.SetSourceAsync(pIMSCapture);
CaptureImage.Source = pBIeCapture;
CaptureImage.Stretch = Stretch.Uniform;
CaptureImage.Width = LayoutRoot.ActualWidth;
CaptureImage.Height = LayoutRoot.ActualHeight;
}
}
await CleanupCameraAsync();
}

How to save the photo captured with Camera in Picture Library

I used below code to capture photo but not sure how to save it in Picture Library or Folder in Picture Library. Would appreciate your help on this.
CameraCaptureUI camera = new CameraCaptureUI();
camera.PhotoSettings.CroppedAspectRatio = new Size(16, 9);
StorageFile photo = await camera.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo != null)
{
BitmapImage bmp = new BitmapImage();
IRandomAccessStream stream = await photo.OpenAsync(FileAccessMode.Read);
bmp.SetSource(stream);
ImageSource.Source = bmp;
ImageSource.Visibility = Visibility.Visible;
StorageFolder storageFolder = KnownFolders.PicturesLibrary;
??? not sure :
var imagefile = await KnownFolders.PicturesLibrary.CreateFileAsync("MyPhoto.jpeg", CreationCollisionOption.ReplaceExisting);
photo.CopyAsync(storageFolder,imagefile);
}
Here you go. You must have to set camera and picture library access capability in manifest.
CameraCaptureUI camera = new CameraCaptureUI();
camera.PhotoSettings.CroppedAspectRatio = new Size(16, 9);
StorageFile photo = await camera.CaptureFileAsync(CameraCaptureUIMode.Photo);
//By default the photo will be stored at location
//%localappdata%\Packages\APP_PACKAGE_ID\TempState
if (photo != null)
{
//await photo.MoveAsync(KnownFolders.PicturesLibrary);
//OR
await photo.MoveAsync(KnownFolders.PicturesLibrary, "DesiredPhotoName" + photo.FileType, NameCollisionOption.GenerateUniqueName);
}

WinRT No mapping for the Unicode character exists in the target multi-byte code page

I am trying to read a file in my Windows 8 Store App. Here is a fragment of code I use to achieve this:
if(file != null)
{
var stream = await file.OpenAsync(FileAccessMode.Read);
var size = stream.Size;
using(var inputStream = stream.GetInputStreamAt(0))
{
DataReader dataReader = new DataReader(inputStream);
uint numbytes = await dataReader.LoadAsync((uint)size);
string text = dataReader.ReadString(numbytes);
}
}
However, an exeption is thrown at line:
string text = dataReader.ReadString(numbytes);
Exeption message:
No mapping for the Unicode character exists in the target multi-byte code page.
How do I get by this?
I managed to read file correctly using similar approach to suggested by duDE:
if(file != null)
{
IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
}
Can somebody please elaborate, why my initial approach didn't work?
Try this instead of string text = dataReader.ReadString(numbytes):
dataReader.ReadBytes(stream);
string text = Convert.ToBase64String(stream);
If, like me, this was the top result when search for the same error regarding UWP, see the below:
The code I had which was throwing the error (no mapping for the unicode character exists..):
var storageFile = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(fileToken);
using (var stream = await storageFile.OpenAsync(FileAccessMode.Read))
{
using (var dataReader = new DataReader(stream))
{
await dataReader.LoadAsync((uint)stream.Size);
var json = dataReader.ReadString((uint)stream.Size);
return JsonConvert.DeserializeObject<T>(json);
}
}
What I changed it to so that it works correctly
var storageFile = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(fileToken);
using (var stream = await storageFile.OpenAsync(FileAccessMode.Read))
{
T data = default(T);
using (StreamReader astream = new StreamReader(stream.AsStreamForRead()))
using (JsonTextReader reader = new JsonTextReader(astream))
{
JsonSerializer serializer = new JsonSerializer();
data = (T)serializer.Deserialize(reader, typeof(T));
}
return data;
}