I am using the below code to downlaod the picture form a remote url and save to Local storage folder
try
{
var rootFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync( "MyAppName\\CoverPics", CreationCollisionOption.OpenIfExists);
var coverpic_file = await rootFolder.CreateFileAsync(filename, CreationCollisionOption.FailIfExists);
try
{
var httpWebRequest = HttpWebRequest.CreateHttp(coverUrl);
HttpWebResponse response = (HttpWebResponse)await httpWebRequest.GetResponseAsync();
Stream resStream = response.GetResponseStream();
using (var stream = await coverpic_file.OpenAsync(FileAccessMode.ReadWrite))
{
await resStream.CopyToAsync(stream.AsStreamForWrite());
}
response.Dispose();
}
catch //any exceptions happend while saving the picture
{
saved = false;
}
}
catch
{
//https://msdn.microsoft.com/en-us/library/windows/apps/br227250.aspx
//Raise an exception if file already present
saved = true;
}
This code is working for me in most of the cases , but i noticed that for few pictures the image is not downloading completely.
I am callling this function in an async block for more tahn 100 images in a single go inside the foreach loop and in the end few of them are failed downloads
[ Either i can see some invalid file is getting created
or part of image only in downloading and rest of the area i can see a black colour block [ looks like image is corrupted].
Size of all images is less than 1 MB only
Can some one help me to optimize this code or point out the mistake in code so i can able to download all the images completely
I am not seeing any error in my code. But after trying some different ways of downloading and saving a file my code looks like this and
try
{
HttpClient client = new HttpClient(); // Create HttpClient
byte[] buffer = await client.GetByteArrayAsync(coverUrl); // Download file
using (Stream stream = await coverpic_file.OpenStreamForWriteAsync())
stream.Write(buffer, 0, buffer.Length); // Save
}
catch
{
saved = false;
}
And this code is working fine without causing any issues All images are downloading completely and no more issues of black block on images.
If any one can points out the difference with my first code will be really helpful to understood the reason for error
Have you tried using new Windows.Web.Http.HttpClient instead of HttpWebRequest?
Also take a look this SO question :
How do I use the new HttpClient from Windows.Web.Http to download an image?
If you not familiar with HttpClient, I sugest to watch CH9 presentation :
https://channel9.msdn.com/Events/Build/2013/4-092
I tried your download and experienced the same issues.
var myFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("MyFolderPath", CreationCollisionOption.OpenIfExists);
var myFile = await myFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(new Uri(URL), myFile);
await download.StartAsync();
The above exception occurs at line await bitmapImage.SetSourceAsync(fileStream); whenever I tried to retrieve image from local file.
This is the method I'm using for storing and retrieving the image file.
public async Task<BitmapImage> RetrieveImageFromFile(String fileName)
{
try
{
StorageFile localFile = await _storageFolder.GetFileAsync(fileName + "Img");
BitmapImage bitmapImage = new BitmapImage();
using (IRandomAccessStream fileStream = await localFile.OpenAsync(FileAccessMode.Read))
{
await bitmapImage.SetSourceAsync(fileStream);
}
return bitmapImage;
}
catch(Exception e)
{
return null;
}
}
public async void WriteImageToFile(string fileName, IRandomAccessStreamWithContentType stream )
{
StorageFile file = await _storageFolder.CreateFileAsync(fileName + "Img", CreationCollisionOption.ReplaceExisting);
Stream streamToSave = stream.AsStreamForWrite();
using (Stream fileStram = await file.OpenStreamForWriteAsync())
{
streamToSave.CopyTo(fileStram);
}
}
The input stream for the WriteImageToFile method is retrieved from contact.Thumbnail.OpenReadAsync() method
Any help ?
Just turning my comment into an answer since it's been helping people:
The 0x88982f50 error is generally related to a failure to read/decode an image file correctly. Verify your file is formatted properly. Google 88982f50 to see dozens of potentially related fixes, all relating to image file I/O. I never did find a definitive source for the error but this turned out to be my problem as well... Bad file.
Late answer but might save someone else from spending hours hunting this down...
Error code 0x88982f50 is WINCODEC_ERR_COMPONENTNOTFOUND, and it's the Windows Imaging Component's way of saying it can't decode an image file.
Most likely the file is corrupted, or the version of WIC installed in Windows doesn't include a codec needed to decode it.
Microsoft provides zero information about it.
I have a (hopefully) simple question (I don’t have found an answer, that fit’s by all of my searches).
I work with Xamarin.Forms 1.4.1-Pre-1.
In my app, I have:
byte[] AvatarErfassung; // Bytearray, to later update the webservice
var Avatar = new Image { HeightRequest = 71, WidthRequest = 61, HorizontalOptions = LayoutOptions.Start };
Avatar.Source = "SymbolMann.jpg";
where the image "SymbolMann.jpg” is included as project-resource (in each project) and showed on a page (without problems).
I now want to put the image in a byte-array to send it to our webservice.
I don't have found any way to access the image "SymbolMann.jpg" (to load it in a byte-array) or to use (however) the Avatar.Source therefore.
Question:
How to get the image “SymbolMann.jpg” into the byte-array “AvatarErfassung” ?
Thanks for every answer
Hi Dimitris
Thanks for your (fast) replay.
As I wrote, I work with Xamarin.Forms.
The images are stored as resources:
in \Resources\Drawable\ (for Android), \Resources\ (for iOS) and in the root (for WP).
I have to load the image on a content-page.
If I overtake your code, to the line:
var assembly = this.GetType().GetTypeInfo().Assembly;
I have the error-message (translated to English):
“System.Type don’t contain a definition for GetTypeInfo method (is a using missing?)”
Do I have to add a specific using?
You write:
// you can replace "this.GetType()" with "typeof(MyType)", where MyType is any type in your assembly.
What do I have to place as type?
= typeof(????).GetTypeInfo().Assembly:
Thanks for a further reply.
Update #2:
Firts, thanks for your patience…
Unfortunately in VS2013, I don’t find any function “resolve” that shows me the missing using - but I have find out the missing using my self :-)
In the meantime I have added
using System.Reflection;
Now, the line:
var assembly = this.GetType().GetTypeInfo().Assembly;
is resolved and compiled without error
Further, I have changed the type of the .jpg from “Android Resource” to “Embedded Ressource”.
The App then crashes in the line:
long length = s.Length;
as it seems that s is null (I think the jpg is not found)
Further - if I change the type to “Embedded Ressource” - the image is not found any more by Xamarin.Forms (Avatar.Source = "SymbolMann.jpg";)
If I change the type of the .jpg to “Compile” I can’t compile the app.
Error-message:
A namespace can’t contain directly members like fields or methods.
So… what is the correct type to the resource (so that it can be loaded with assembly.GetManifestResourceStream()?
Do I have to add something to the filename (SymbolMann.jpg) so that it will be found?
How do I have to change Avatar.Source = "SymbolMann.jpg" so that it is found (if I change the type from “Android Resource” to anything else)?
Once again my needs:
On a registration-page, default-images (symbols) are showed as avatar for man and woman in a standard-Xamarin.Forms image (avatar.source = “SymbolMann.jpg” / “SymbolFrau.jpg”).
The .jpg’s are stored in the standard-directories for each project (Android, iOS and WP) where the are accessible without problems from the image-object.
The user then can take one of the default-images or load another one over mediapicker.
If the user the tap the button “Register”, I have to create a byte-array from the Image to send it via json to our webservice.
If the user select another image via mediapicker, I have access to the stream, the problem is, to become a byte-array from the default-images (in every platform).
Once again thanks for your help...
You can easily do this, by reading the resource stream from the assembly:
var assembly = this.GetType().GetTypeInfo().Assembly; // you can replace "this.GetType()" with "typeof(MyType)", where MyType is any type in your assembly.
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream("SymbolMann.jpg"))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
}
// Do something with buffer
To get the assembly that holds the embedded resources of your project you need to call the GetTypeInfo method on a type included in that assembly. Hence, typeof(X), where "X" is any type in your assembly. For example, if you are using a custom page called MyCustomPage:
public class MyCustomPage : ContentPage {}
... this is what you would pass: typeof(MyCustomPage)
You need any instance of type Type (this is what the typeof keyword returns basically). The alternative is to call the GetType() method on any object that is included in your project.
Note that you will not be able to get the correct assembly if you call typeof(X) on a type that is not included in your project. Eg. calling typeof(ContentPage).GetTypeInfo().Assembly, would return the assembly that the ContentPage type resides in. Which is not the one that includes your resources. I hope this is not confusing. If it is, please let me know.
Now, the GetTypeInfo method is an extension method included in the System.Reflection namespace. When the text editor in Xamarin Studio does not recognize something, it highlights it with red. Right-clicking on that will give you a Resolve option in the context menu:
If the type or method can be resolved, it will show that option.
More on images in Xamarin Forms here.
Thanks #FredWenger and #Dimitris - here's my solution based on both your answers:
Add your image to the Xamarin Forms (Portable) project wherever you like. I just
went for the root: MyProject\DaffyDuck.jpg
Mark the image as an Embedded Resource (file properties -> build
action)
Call the function referencing the Embedded Resource like this:
ImageDataFromResource("MyProject.DaffyDuck.jpg")
Notice that you need to include the project name to get the assembly name *.
This is the function:
public byte[] ImageDataFromResource(string r)
{
// Ensure "this" is an object that is part of your implementation within your Xamarin forms project
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer = null;
using (System.IO.Stream s = assembly.GetManifestResourceStream(r))
{
if (s != null)
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
}
}
return buffer;
}
If you need to reference the loaded data in an ImageView control do
it thus:
ImageView.Source = ImageSource.FromStream(() => new MemoryStream(imageData));
*NB: If step 3 doesn't work and you want to check your embedded resource names call this: var names = assembly.GetManifestResourceNames(); and see what is listed in your project.
First, many thanks to Dimitris who has guided me to the right direction!
Conclusion:
The base:
I work with VS2013 - update 2, Xamarin.Forms (1.4.1-Pre1) and my app is based on the template “Blank App (Xamarin.Forms Shared)” (not PCL) and I use all platforms (Android, iOS, WP).
On a user-registration-page the user can select an image as avatar (that then later is showed to his postings). There are two default-images (one for male one for female), that are showed, depending of the sex of the user. The user then can overtake one of the default-images or select another image from the media-picker.
The default-images were stored on the default-locations for content-images (for Android e.g. under /Resources/Drawable/).
The images were showed in a XF-Standard-Image-Object with Image-Source = “xxx.jpg”.
This has worked without problems.
The problem:
As the user-data (including avatar) are stored on a SQL-Server (over a Json-web-service), I have to convert the image-data to a byte-array (to send it then with the other data as string to the web-service).
The problem was, to load the images from the default-directories and convert it to a byte-array (whereby the file-access was the problem -> not reachable).
The solution:
Thanks Dimitris, that have guided me in the correct direction, I have implemented the following solution:
In all projects (Android, iOS and WP), I have added a new directory “\Embedded\” (directly under the root).
Then, I have copied my two jpg’s (“SymbolMann.jpg” and "SymbolFrau.jpg”) in this directory (for all Platforms).
Then, I have changed the resource-type to the images from e.g. “AndroidResource” to “Embedded Resource” (for all platforms the same type).
In my Startup-Code to the app (app.cs), I have added:
//
string cNameSpace = "";
switch (Device.OS)
{
case TargetPlatform.WinPhone:
cNameSpace = "MatrixGuide.WinPhone";
break;
case TargetPlatform.iOS:
cNameSpace = "MatrixGuide.iOS";
break;
case TargetPlatform.Android:
cNameSpace = "MatrixGuide.Droid";
break;
}
GV.cEmbeddedAblage = cNameSpace + ".Embedded.";
where GV.cEmbeddedAblage is simply a global variable.
To checkout the namespace-names, I had to right-click the projects for each platform and have a look at the settled namespace-name (can varies in your project).
The .Embedded. is the new created directory (same name on all platforms).
Additionally, I have created global byte-arrays for the male-image (GV.ByteSymbolMann) and for the female-image (GV.ByteSymbolFrau).
In the startup-Code of the registration-page, I have added:
string cFilename = "";
if (GV.ByteSymbolMann == null) // not yet loaded
{
cFilename = GV.cEmbeddedAblage + "SymbolMann.jpg";
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream(cFilename))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
GV.ByteSymbolMann = buffer; // Overtake byte-array in global variable for male
}
}
//
if (GV.ByteSymbolFrau == null) // not yet loaded
{
cFilename = GV.cEmbeddedAblage + "SymbolFrau.jpg";
var assembly = this.GetType().GetTypeInfo().Assembly;
byte[] buffer;
using (Stream s = assembly.GetManifestResourceStream(cFilename))
{
long length = s.Length;
buffer = new byte[length];
s.Read(buffer, 0, (int)length);
GV.ByteSymbolFrau = buffer; // Overtake byte-array in global variable for female
}
}
The code to loading the .jpg into the image-object, I had to change from:
//Avatar.Source = "SymbolMann.jpg"; // Load from default directory
to
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolMann)); // Load (stream) from byte-array
I then takeover the selected byte-array (parallel to showing the image) in a further byte-array (for later upload to the web-service as string)
AvatarErfassung = GV.ByteSymbolMann;
If the user change the selection (e.g. to woman):
Avatar.Source = ImageSource.FromStream(() => new MemoryStream(GV.ByteSymbolFrau));
AvatarErfassung = GV.ByteSymbolFrau;
Note: If the user select another image from mediapicker, I have directly access to the stream, so this was never the problem.
This solution works for all platforms (Android, iOS, WP).
I hope this may help some other users…
And... finally thanks to Dimitris
Adding on to noelicus's answer:
Setup
Add your image to the root folder of the Xamarin.Forms project, e.g. MyProject\pizza.png
In Visual Studio, right-click on the image file and select Build Action -> EmbeddedResource
Code
public byte[] GetImageFromFile(string fileName)
{
var applicationTypeInfo = Application.Current.GetType().GetTypeInfo();
byte[] buffer;
using (var stream = applicationTypeInfo.Assembly.GetManifestResourceStream($"{applicationTypeInfo.Namespace}.fileName"))
{
if (stream != null)
{
long length = stream.Length;
buffer = new byte[length];
stream.Read(buffer, 0, (int)length);
}
}
return buffer;
}
Example
public class MyPage() : ContentPage
{
public MyPage()
{
var imageAsByteArray = GetImageFromFile("pizza.png");
var pizzaImage = new Image();
pizzaImage.Source = ImageSource.FromStream(() => new MemoryStream(imageAsByteArray));
Content = pizzaImage;
}
byte[] GetImageFromFile(string fileName)
{
var applicationTypeInfo = Application.Current.GetType().GetTypeInfo();
byte[] buffer;
using (var stream = applicationTypeInfo.Assembly.GetManifestResourceStream($"{applicationTypeInfo.Namespace}.{fileName}"))
{
if (stream != null)
{
long length = stream.Length;
buffer = new byte[length];
stream.Read(buffer, 0, (int)length);
}
}
return buffer;
}
}
I had a lot of problems getting this to work. My project was already using FFImageLoading elsewhere, and I found this to be the easiest way to load the .png as a stream:
using (var stream = await ImageService.Instance.LoadCompiledResource("resource_image.png").AsPNGStreamAsync())
{
localBitmap = SKBitmap.Decode(stream);
}
Make sure your resource files have the same name in both iOS and Droid projects. They'll probably already have their build action set to 'BundleResource' (iOS) or 'AndroidResource' (Droid).
Sure, you'll have to install the FFImageLoading Nuget, but you'll be glad you did.
I used noelicus given idea and printed all the names from ManifestResourceNames array and I found there my image name as ProjectName.Droid.image_name.jpeg .Then I just changed the method call from assembly.GetManifestResourceStream("image_name.jpg") to assembly.GetManifestResourceStream("ProjectName.Droid.image_name.jpeg").And it worked.
So the correct answer would be :
Store the image in root folder at PCL.
Make it's build action in properties as Embedded resource.
Then print <b><i>var names = assembly.GetManifestResourceNames()</i></b> array which will be a string array and can be printed using
foreach(var data in names){Debug.WriteLine(data);}
There you will see the resource name for image and then use the method
Stream s = assembly.GetManifestResourceStream("resource_name_you_found.format")
I want to perform media transcoding operation in-memory using Media Foundation from a MP3 format to a WAV (PCM) format.
I tried the code as mentioned below:
//Initialize MediaStreamSource with location of MP3 file
var mediaStream = new MediaStreamSource(mp3File);
//Create a "dummy" wav file to attach to IRandomAccessStream
StorageFile _OutputFile2 = await
KnownFolders.VideosLibrary.CreateFileAsync("Test.wav",
CreationCollisionOption.GenerateUniqueName);
IRandomAccessStream iras =
_OutputFile2.OpenAsync(FileAccessMode.ReadWrite).AsTask().Result;
//Setup the transcode operation to convert from MP3 to WAV
_Profile = MediaEncodingProfile.CreateWav(audioEncodingProfile);
var preparedTranscodeResult = await
_Transcoder.PrepareMediaStreamSourceTranscodeAsync(mediaStream, iras,
_Profile);
try
{
if (preparedTranscodeResult.CanTranscode)
{
var progress = new Progress<double>(TranscodeProgress);
await
preparedTranscodeResult.TranscodeAsync().AsTask(_cts.Token,
progress);
}
else
{
TranscodeFailure(preparedTranscodeResult.FailureReason);
}
}
catch (Exception ex)
{
TranscodeError(ex.Message);
}
When trying to transcode, I get the following error:
This object needs to be initialized before the requested operation can
be carried out.
I also referred this link which has a similar issue:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/6156580a-6673-4cf3-b6a9-5853b2a85bf6/what-kind-of-stream-to-feed-into-mediatranscoderpreparestreamtranscodeasync?forum=winappswithnativecode
I am looking for a sample which performs in-memory transcode operation instead of saving it to disk.
Appreciate your help.
Can any of you provide an actual working sample of how to take and save a photo using the MediaCapture element. I've tried looking for an actual solution in MSDN but none of those explanations or code actually describe the process in a simple way.
I need to take a picture and save it to my library (i need to show the correct preview for this), however right now it is rotated 90 degrees and i can't adjust it. I've tried setting the rotation of the video preview and it works for the preview however when i do this the aspect ratio its all wrong and the saved image its not correct.
The examples from channel 9 kind of suck too. I just need a simple implementation...
Im using a Runtime app NOT a silverlight app for Windows Phone 8.1.
I have had the same issue, SetRecordRotation doesn't work for me. I found workaround - take photo and rotate an image, it works great. I use method like that:
private async void CapturePhoto()
{
string photoPath = string.Empty;
ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg();
using (var imageStream = new InMemoryRandomAccessStream())
{
await MediaCapture.CapturePhotoToStreamAsync(format, imageStream);
BitmapDecoder dec = await BitmapDecoder.CreateAsync(imageStream);
BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(imageStream, dec);
enc.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
await enc.FlushAsync();
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile capturefile = await folder.CreateFileAsync("photo.jpg", CreationCollisionOption.GenerateUniqueName);
photoPath = capturefile.Name;
using (var fileStream = await capturefile.OpenAsync(FileAccessMode.ReadWrite))
{
try
{
await RandomAccessStream.CopyAsync(imageStream, fileStream);
}
catch {}
}
}
}
I modified sample of code from article How to capture a photo in your Windows Phone 8.1 Runtime app by Marco Siccardi
http://dotnet.dzone.com/articles/how-capture-photo-your-windows-0
There are two samples posted on the Microsoft github page that are relevant, although they target Windows 10. Still, the APIs should work on 8/8.1.
GetPreviewFrame: This sample will not lock the page rotation, and apply a corrective rotation to the preview stream. It does not use SetPreviewRotation, as that method is more resource-heavy than using the metadata approach. This sample doesn't capture photos (just preview frames)
UniversalCameraSample: This one does capture photos, and supports portrait and landscape orientations. Here is the relevant part:
var stream = new InMemoryRandomAccessStream();
try
{
await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
var photoOrientation = ConvertOrientationToPhotoOrientation(GetCameraOrientation());
await ReencodeAndSavePhotoAsync(stream, photoOrientation);
}
catch (Exception ex)
{
Debug.WriteLine("Exception when taking a photo: {0}", ex.ToString());
}
With:
private static async Task ReencodeAndSavePhotoAsync(IRandomAccessStream stream, PhotoOrientation photoOrientation)
{
using (var inputStream = stream)
{
var decoder = await BitmapDecoder.CreateAsync(inputStream);
var file = await KnownFolders.PicturesLibrary.CreateFileAsync("SimplePhoto.jpeg", CreationCollisionOption.GenerateUniqueName);
using (var outputStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);
var properties = new BitmapPropertySet { { "System.Photo.Orientation", new BitmapTypedValue(photoOrientation, PropertyType.UInt16) } };
await encoder.BitmapProperties.SetPropertiesAsync(properties);
await encoder.FlushAsync();
}
}
}
Have a closer look at the sample to see how to get the orientation of the camera in the first place (a call to it is being made in the first snippet I posted).
Or, if you prefer a video, you can watch the camera session from the recent //build/ conference, which includes a little bit of a walkthrough through some camera samples.
you can change the aspect ratio for your video preview & captured photo by setting in the MediaCapture.VideoDeviceController.
Also, you can set your video preview upright by using the following code.
MediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
I have answered a similar questions in the another post in the link below. Hope it helps.
https://stackoverflow.com/a/29875992/4672579