I have taken a photo and saved it, but I need to do image processing on it. I tried using the following code, but WritableBitmap does not accept a bitmap, it needs a stream.
var writeableBitmap = new WritableBitmap(bitmap);
Here is the code:
CameraCaptureUI cam = new CameraCaptureUI();
var capturedImage = await cam.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (capturedImage != null)
{
var img = new BitmapImage();
img.SetSource(await capturedImage.OpenReadAsync());
}
This should do the trick - You need to use the OpenAsync instead.
var dialog = new CameraCaptureUI();
var file = await dialog.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (file != null)
{
var stream = await file.OpenAsync(FileAccessMode.Read);
var img = new BitmapImage();
img.SetSource(stream);
AccountPictureImage.Source = img;
}
Related
I have a small png image I like to show in an imageview using Xamarin.Android.
I am downloading the file using the following code:
private void Download()
{
var url = "https://hns.d7u.de/v4/images/hvvstoerungen_facebook.png";
var directory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/myapp/";
var fileName = url.Substring(url.LastIndexOf("/") +1);
var path = directory + fileName;
System.Net.WebClient wC = new System.Net.WebClient();
wC.Headers.Add(System.Net.HttpRequestHeader.AcceptEncoding, "gzip");
wC.DownloadDataCompleted += WC_DownloadDataCompleted;
wC.DownloadDataAsync(new Uri(url), path);
}
private void WC_DownloadDataCompleted(object sender, System.Net.DownloadDataCompletedEventArgs e)
{
var path = e.UserState.ToString();
var bytes = e.Result;
if (File.Exists(path))
File.Delete(path);
if (!File.Exists(path))
File.WriteAllBytes(path, bytes);
}
It is stored at /data/user/0/myapp/files/hns/hvvstoerungen_facebook.png and a File.Exists(...) returns a true for that path. So I am sure, that the file is downloaded and it exists.
When I want to show it in the ImageView, I do it like this:
if (System.IO.File.Exists(imageFilePath))
{
Android.Net.Uri andrUri = Android.Net.Uri.Parse(imageFilePath);
ImageIcon.SetImageURI(andrUri);
//Also not working:
//Bitmap bitmap = BitmapFactory.DecodeFile(imageFilePath);
//ImageIcon.SetImageBitmap(bitmap);
//And also not working:
//Android.Net.Uri andrUri = Android.Net.Uri.Parse(imageFilePath);
//Bitmap bmp = BitmapFactory.DecodeStream(Android.App.Application.Context.ContentResolver.OpenInputStream(andrUri));
//ImageIcon.SetImageBitmap(bmp);
}
The Output windows shows the following when the image should be shown:
02-01 23:41:24.770 E/Drawable(19815): Unable to decode stream:
android.graphics.ImageDecoder$DecodeException: Failed to create image
decoder with message 'unimplemented'Input contained an error. 02-01
23:41:24.770 W/ImageView(19815): resolveUri failed on bad bitmap uri:
/data/user/0/myapp/files/hns/hvvstoerungen_facebook.png
But I cannot figured out what exactly this means.
One additional thing is: If I run the app in a brand new Android Emulator instance, this image and all other of its kind are not shown.
If I run the app in an old Android Emulator instance, where the app was already running before but on Android.Forms basis, the old images that were known by the old project are shown while the newly downloaded images are not. All images are in the same folder and I cannot see any differences between them.
Does anyone has an Idea?
Edit:
My working version has the following Download() Method instead:
private void Download()
{
var noCompression = new string[] { ".png", ".jpg", ".jpeg", ".gif", ".zip", ".7z", ".mp3", ".mp4" };
var url = "https://hns.d7u.de/v4/images/hvvstoerungen_facebook.png";
var directory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/myapp/";
var fileName = url.Substring(url.LastIndexOf("/") +1);
var path = directory + fileName;
System.Net.WebClient wC = new System.Net.WebClient();
if (!noCompression.Contains(url.Substring(url.LastIndexOf('.'))))
wC.Headers.Add(System.Net.HttpRequestHeader.AcceptEncoding, "gzip");
wC.DownloadDataCompleted += WC_DownloadDataCompleted;
wC.DownloadDataAsync(new Uri(url), path);
}
You could try the code below.
Download the image from Url:
public Bitmap GetImageBitmapFromUrl(string url)
{
Bitmap imageBitmap = null;
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
return imageBitmap;
}
Usage:
bitmap = GetImageBitmapFromUrl("https://hns.d7u.de/v4/images/hvvstoerungen_facebook.png");
And save the image as png:
void ExportBitmapAsPNG(Bitmap bitmap)
{
var folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
filePath = System.IO.Path.Combine(folderPath, "test.png");
var stream = new FileStream(filePath, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Png, 100, stream);
stream.Close();
}
Usage:
ExportBitmapAsPNG(bitmap);
Check the file exists or not and set into the imageview:
if (File.Exists(filePath))
{
Bitmap myBitmap = BitmapFactory.DecodeFile(filePath);
imageview.SetImageBitmap(myBitmap);
}
I'm using Xamarin forms, and in my application has a button to share the problem that is being in my android application I got doing with Intent but in my application ios'm not knowing how to do, someone could help me?
using android
public async Task<bool> Share(ImageSource image)
{
Intent shareIntent = new Intent(Intent.ActionSend);
bitmapToShare = await GetBitmap (image);
if (bitmapToShare != null) {
CreateDirectoryForPictures("Xpto");
var filePath = System.IO.Path.Combine (dir.AbsolutePath, string.Format("xpto_{0}.png",Guid.NewGuid()));
var stream = new FileStream (filePath, FileMode.Create);
bitmapToShare.Compress (Bitmap.CompressFormat.Png, 100, stream);
stream.Close ();
Java.IO.File file = new Java.IO.File (filePath);
shareIntent.SetType ("image/*");
shareIntent.PutExtra (Intent.ExtraStream, Android.Net.Uri.FromFile (file));
shareIntent.AddFlags (ActivityFlags.GrantReadUriPermission);
Forms.Context.StartActivity (Intent.CreateChooser (shareIntent, "Compartilhar"));
}
return true;
}
private static async Task ShareImageAsyc(ImageSource image, string message, string url = null)
{
var handler = image.GetHandler();
if (handler == null) return;
var uiImage = await handler.LoadImageAsync(image);
var items = new List<NSObject> { new NSString(message ?? string.Empty) };
if (!url.IsNullOrEmpty())
items.Add(new NSString(url));
items.Add(uiImage);
var controller = new UIActivityViewController(items.ToArray(), null);
UIApplication.SharedApplication.KeyWindow.RootViewController.GetTopViewController()
.PresentViewController(controller, true, null);
}
From: https://github.com/jimbobbennett/JimLib.Xamarin/blob/master/JimLib.Xamarin.ios/Sharing/Share.cs
In a Rails environment, I want to manipulate an image after it has been uploaded. I do not need to change the image, but I want to present it to the user based on parameters in the URL.
Any suggestions?
It means after uploading completed you need to show image, you can show imaged using javascript and jquery, i have done this in sample project like following way
function showThumbnail(files){
for(var i=0;i< files.length;i++){
var file = files[i];
var imageType = /image.*/
if(!file.type.match(imageType)){
alert("Not an image");
}
var image = document.createElement("img");
var thumbnail = document.getElementById("thumbnail");
image.file = file;
if(file.type.match(imageType)) {
if((thumbnail.hasChildNodes() == true)){
thumbnail.removeChild(thumbnail.firstChild);
thumbnail.appendChild(image);
}else
{
thumbnail.appendChild(image);
}
}
var reader = new FileReader()
reader.onload = (function(aImg){
return function(e){
aImg.src = e.target.result;
};
}(image))
var ret = reader.readAsDataURL(file);
var canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
image.onload= function(){
ctx.drawImage(image,75,75);
$(".uploadedPhoto").addClass('whiteBG');
$(".uploadtxt").html(file.name);
}
}
}
**I have an air app for iOS I have been developing. I am trying to capture a picture, save the file to the storage directory (not Camera Roll), and save the file name in an sqlite db.
I have tried so many different variations of this, but when it comes to writing the filestream to save the app hangs. Testing on iPad 3. Does ANYONE have a suggestion? This has been driving me nuts for days. I have searched the web but I am stumped.**
public var temp:File; // File Object to save name in database
protected function selectPicture():void
{
myCam = new CameraUI();
myCam.addEventListener(MediaEvent.COMPLETE, onComplete);
myCam.launch(MediaType.IMAGE);
}
protected function onComplete(event:MediaEvent):void {
//imageProblem.source = event.data.file.url;
var cameraUI:CameraUI = event.target as CameraUI;
var mediaPromise:MediaPromise = event.data;
var mpLoader:Loader = new Loader();
mpLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMediaPromiseLoaded);
mpLoader.loadFilePromise(mediaPromise);
}
private function onMediaPromiseLoaded(e:Event):void
{
var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo;
mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded);
this.imageProblem.source = mpLoaderInfo.loader;
var stream:FileStream = new FileStream();
stream.addEventListener(Event.COMPLETE, showComplete);
stream.addEventListener(IOErrorEvent.IO_ERROR, showError);
try{
this.messages.text = "Starting";
stream.open( temp, FileMode.WRITE );
stream.writeBytes(mpLoaderInfo.bytes);
stream.close();
}catch(e:Error){
this.messages.text = e.message;
}
}
protected function showError(e:IOErrorEvent):void{
this.messages.text = e.toString();
}
protected function showComplete(e:Event):void{
this.messages.text = "Completed Writing";
this.imgName.text = temp.url;
imagefile = temp;
deleteFlag = 1;
}
Application hangs due to you are trying to use file operation in Sync mode.
You need to use Async Mode operation instead of sync mode file operation.
stream.openAsync( temp, FileMode.WRITE );
Try with this
var stream:FileStream = new FileStream();
stream.addEventListener(Event.COMPLETE, showComplete);
stream.addEventListener(IOErrorEvent.IO_ERROR, showError);
stream.openAsync( temp, FileMode.WRITE );
stream.writeBytes(mpLoaderInfo.bytes);
stream.close();
Note when using async operation you need not use try catch.For handling error listen IOErrorEvent will catch if any error occurs.
I finally got this to work, I added comments below in the code to explain why it wasn't working.
public var temp:File;
protected function selectPicture():void
{
myCam = new CameraUI();
myCam.addEventListener(MediaEvent.COMPLETE, onComplete);
myCam.launch(MediaType.IMAGE);
}
protected function onComplete(event:MediaEvent):void {
//imageProblem.source = event.data.file.url;
var cameraUI:CameraUI = event.target as CameraUI;
var mediaPromise:MediaPromise = event.data;
var mpLoader:Loader = new Loader();
mpLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMediaPromiseLoaded);
mpLoader.loadFilePromise(mediaPromise);
}
private function onMediaPromiseLoaded(e:Event):void
{
var mpLoaderInfo:LoaderInfo = e.target as LoaderInfo;
mpLoaderInfo.removeEventListener(Event.COMPLETE, onMediaPromiseLoaded);
this.imageProblem.source = mpLoaderInfo.loader;
/// Here was the solution
var bitmapDataA:BitmapData = new BitmapData(mpLoaderInfo.width, mpLoaderInfo.height);
bitmapDataA.draw(mpLoaderInfo.content,null,null,null,null,true);
/// I had to cast the loaderInfo as BitmapData
var bitmapDataB:BitmapData = resizeimage(bitmapDataA, int(mpLoaderInfo.width / 4), int(mpLoaderInfo.height/ 4)); // function to shrink the image
var c:CameraRoll = new CameraRoll();
c.addBitmapData(bitmapDataB);
var now:Date = new Date();
var f:File = File.applicationStorageDirectory.resolvePath("IMG" + now.seconds + now.minutes + ".jpg");
var stream:FileStream = new FileStream()
stream.open(f, FileMode.WRITE);
// Then had to redraw and encode as a jpeg before writing the file
var bytes:ByteArray = new ByteArray();
bytes = bitmapDataB.encode(new Rectangle(0,0, int(mpLoaderInfo.width / 4) , int(mpLoaderInfo.height / 4)), new JPEGEncoderOptions(80), bytes);
stream.writeBytes(bytes,0,bytes.bytesAvailable);
stream.close();
this.imgName.text = f.url;
imagefile = f;
deleteFlag = 1;
}
i use the following code:
protected function videoDisplay_playheadUpdateHandler(event:mx.events.VideoEvent):void
{
if(!captured && videoDisplay.playheadTime>=0){
capture();
}
}
private function capture():void
{
var bmpData:BitmapData = new BitmapData(videoDisplay.width, videoDisplay.height);
bmpData.draw(videoDisplay);
captured = true;
store(...); //????????
}
in order to capture a frame from a videoDisplay object
1) is it correct or am i doing something wrong?
2) what can i do to store the bmpData as .jpg at my computer?
i am using flex4.5 and it is an air app...
any ideas??
Thanks in advance!!
The following code should help you
var jpegEncoder:JPEGEncoder = new JPEGEncoder(90);
var jpgSource:BitmapData = new BitmapData(videoDisplay.width,videoDisplay.height);
jpgSource.draw(this);
var fileReference:FileReference = new FileReference();
fileReference.save(jpegEncoder.encode(jpgSource),"videoImage.jpg");
To use jpeg encode you need to have to import
import mx.graphics.codec.JPEGEncoder;
The above changes should be enough to allow the user to take a snapshot of a running video.
Please note, that with this the user will be prompted to select the location of the file.
Incase you want a silent save, let me know, I will put up the required code.
Somewhere in your application keep an image tag as follows.Most apt place should be just below the video.
<mx:Image scaleContent="true" width="150" height="120" maintainAspectRatio="false" id="myScaledSnapshot"/>
Now with this done, do the following changes in your code:
private function capture(filename:String):void
{
var bitmapData:BitmapData = new BitmapData(videoDisplay.width, videoDisplay.height);
bitmapData.draw(videoDisplay,new Matrix());
var bitmap : Bitmap = new Bitmap(bitmapData);
var jpg:JPEGEncoder = new JPEGEncoder();
var ba:ByteArray = jpg.encode(bitmapData);
myImageSnapshot.source=ba;
var jpegEncoder:JPEGEncoder = new JPEGEncoder(50);
var imageSnapshot:ImageSnapshot = ImageSnapshot.captureImage(this.myImageSnapshot,90,jpegEncoder);
var imageByteArray:ByteArray = imageSnapshot.data;
var newImage:File = File.desktopDirectory.resolvePath("KioskThumbs/"+filename+".jpg");
fileStream = new FileStream();
fileStream.open(newImage, FileMode.UPDATE);
fileStream.writeBytes(imageByteArray);
fileStream.close();
captured = true;
}
The above code really doesnt do anything special.
Its just using an image 'component' from flex, making it do the work for scaling the Video image, then taking the snapshot of this resized image component, and then writing it into a file.
My capture at last is:
private function capture(filename:String):void
{
var bitmapData:BitmapData = new BitmapData(videoDisplay.width, videoDisplay.height);
bitmapData.draw(videoDisplay,new Matrix());
var bitmap : Bitmap = new Bitmap(bitmapData);
var jpg:JPEGEncoder = new JPEGEncoder();
var ba:ByteArray = jpg.encode(bitmapData);
var newImage:File = File.desktopDirectory.resolvePath("KioskThumbs/"+filename+".jpg");
fileStream = new FileStream();
fileStream.open(newImage, FileMode.UPDATE);
fileStream.writeBytes(ba);
fileStream.close();
captured = true;
}
it works fine except the fact that i want to scale the photo lets say to 150 width 120height and not BitmapData(videoDisplay.width,videoDisplay.height); what can i do to solve that?
Thanks a lot all of you!