I'm working on an imaging app using the nokia imaging SDK 1.1. A task seeming fairly simple (let the user choose an image and apply some filters to it) currently blocks me, for 2 days now.
I've written hundreds of lines and reviewd all the Nokia Dev Samples (which, most of the time, are very well-strcutured, but too complex for an imaging SDK starter like me) but I always get the following exception:
{System.NullReferenceException: Invalid pointer at Nokia.Graphics.Imaging.BitmapRenderer.RenderAsync()
This is the code (I've reduced the part where the filters are passed so just an empty FilterEffect is passed on for simplicity):
PhotoChooserTask task = new PhotoChooserTask();
task.Completed += async (result,choosen) =>
{
Stream stream = choosen.ChosenPhoto;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(stream);
WriteableBitmap bitmap = new WriteableBitmap(bitmapImage);
WriteableBitmapRenderer renderer = new WriteableBitmapRenderer(new FilterEffect(), bitmap, OutputOption.PreserveAspectRatio);
await renderer.RenderAsync();
};
task.ShowCamera = true;
task.Show();
So if I understood everything well, the app is crashing because some kind of invalid pointer is passed on, but the bitmap it valid - or at least the size of it is correct, so I guess, the data has been passed on, as well.
Anyway, here is the stacktrace
at Nokia.Graphics.Imaging.BitmapRenderer.RenderAsync()
at Nokia.Graphics.Imaging.WriteableBitmapRenderer.<<RenderAsync>b__0>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at RealtimeFilterDemo.MainPage.<<ShutterButton_Tap>b__1a>d__1c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__0(Object state)
You're not setting a source image for the FilterEffect, and instead passing the source stream directly into the target WriteableBitmap for some reason.
When you kick off the RenderAsync operation, the FilterEffect Source property is null, and this is what causes the exception. You should pass an image source into either the FilterEffect constructor, or set its Source property.
I recommend a StreamImageSource since you've got a System.IO.Stream with the image data.
Conceptually, this is how to think of it:
chosen photo stream -> StreamImageSource -> FilterEffect -> WriteableBitmapRenderer -> the writeable bitmap
And more concretely:
using(var streamSource = new StreamImageSource(stream))
using(var filterEffect = new FilterEffect(streamSource, filters))
using(var writeableBitmapRenderer = new WriteableBitmapRenderer(filterEffect, writeableBitmap))
{
await writeableBitmapRenderer.RenderAsync();
....
}
Related
I try to have an object with some immutable properties which initiate at the constructor and won't be able to change after initiation. Those properties then only have getter method. Since I want this object can be shared with other classes, I save it to the SharedObject class called saveIt().
All work fine when running the app on iOS (I do not test it on Android yet) except that if I completely shutdown the app from memory and reopen it, those properties' without setter are lost. The code is as below:
var rooms:ArrayCollection = saveData.read("rooms") as ArrayCollection;
if (!roomExists) {
var room:Room;
room = new Room(myID, myName, maxRoomSize);
room.name = rm.name;
room.timestamp = new Date();
room.joinUrl = rm.joinUrl;
room.attendeeUrl = rm.attendeeUrl;
room.attendees = conferenceParameters.metadata.hasOwnProperty("attendees") ? conferenceParameters.metadata["attendees"] : null;
rooms.addItem(room);
}
saveIt.save("rooms", rooms);
I found if I assign a dummy setter for each of the immutable properties i.e.
function set myID(s:String):void{}
then it can be safely saved even I shutdown the app. Since I can't find any information about this code behavior, so I'd like to look for opinions here!!
I am working on a map control in windows phone 8. I have declared a MapPolyLine field variable
private MapPolyline _line;
After initializing my Main Page I add this to my Map control.
_line = new MapPolyline();
_line.StrokeColor = Colors.Red;
_line.StrokeThickness = 5;
Map.MapElements.Add(_line);
On the PositionChanged event I check for this condition.
if (_line.Path.Count > 0)
and then update the Map accordingly with this line.
i.e.
var previousPoint = _line.Path.Last();
var distance = coord.GetDistanceTo(previousPoint);`
var coord = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);
Map.Center = coord;
_line.Path.Add(coord);
But I get Unauthorized Access, cross thread exception.
So I tried to put all my code including the 'if' condition under this
Dispatcher.BeginInvoke(() =>
{
// Update Map
});
Now the exception is not thrown, but when I hover my mouse over _line.Path.Count, it still throws an exception, but the only difference is that it is not thrown.
Is it because I have not yet moved or changed my location?. Dont know but any help on the same please, anyone?.
Thanks In Advance.
I'm a newbie to monodroid and I have two killers here I wish someone can help me to resolve:
I have a monodrid app which uploads an image to a web service, the images comes from the device camera or the Pictures gallery.
First thing is I use the following code to take a picture from the device camera:
var intent = new Intent(MediaStore.ActionImageCapture);
var availableActivities = this.PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
if (availableActivities != null && availableActivities.Count > 0)
{
var dir = new Java.IO.File(
Android.OS.Environment.GetExternalStoragePublicDirectory(
Android.OS.Environment.DirectoryPictures), "myapp");
if (!dir.Exists())
{
dir.Mkdirs();
}
_file = new Java.IO.File(dir, String.Format("image-{0}.jpg", Guid.NewGuid()));
StaticDataHolder.ImageUri = Android.Net.Uri.FromFile(_file);
intent.PutExtra(MediaStore.ExtraOutput, Android.Net.Uri.FromFile(_file));
StartActivityForResult(intent, RESULT_CAMERA_CAPTURE);
}
And this code to read scaled Bitmap from StaticDataHolder.ImageUri into an ImageView control so the user can confirm weather to use the selected image or not:
Bitmap largeBitmap = null;
try
{
image.SetImageBitmap(null);
if (Bitmap != null)
{
Bitmap.Recycle();
Bitmap.Dispose();
}
largeBitmap = MediaStore.Images.Media.GetBitmap(ContentResolver, StaticDataHolder.ImageUri);
Bitmap = GetScaledImage(largeBitmap);
SetImageFromBitmap(image, Bitmap);
return true;
}
catch (Java.Lang.OutOfMemoryError)
{
return false;
}
finally
{
if (largeBitmap != null)
{
largeBitmap.Recycle();
largeBitmap.Dispose();
}
}
The second issue is when the user confirm the selected image weather its taken from the camera or picked from the gallery, I create a new Bitmap to be compressed and sent to a web service which I host using the following code:
byte[] buffer = null;
MemoryStream ms = null;
Bitmap bmp = null;
ms = new MemoryStream();
bmp = MediaStore.Images.Media.GetBitmap(ContentResolver, StaticDataHolder.ImageUri);
bmp.Compress(Bitmap.CompressFormat.Jpeg, 60, ms);
buffer = ms.GetBuffer();
ms.Dispose();
bmp.Recycle();
bmp.Dispose();
and then I pass the buffer to the web service method.
This code will work perfectly the first time I start the app, But when I try to load a second image I get OutOfMemoryError exception and the image is not loaded.
How i can load a Bitmap and dispose it probably so I can avoid this exception?.
Please note that every step here is managed via separate activities:
1.Take or choose a photo activity.
2.Confirm the selected photo activity.
3.Load the selected photo and send it to the web service activity.
As far as I know the activity is disposed when finished so by default all resources used in it will also be disposed but in my case its appears to be not!.
I have searched it for 3 days with no luck, any help would be much appreciated.
Bitmaps in general are a pain on Android since they live in the native heap and are not directly garbage collected, well in Android < 2.3.x at least. Have you tried using BitmapFactory?
For example:
var opts = new BitmapFactory.Options() { InPurgeable = true, InInputShareable = true };
var bitmap = BitmapFactory.DecodeFile (pathToBitmap, opts);
Will cause the result bitmap to be purgeable from memory when needed (http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html)
I'm using this to show the callstack:
throw new Error("show me");
But I'd like to print a longer (deeper) stack because the current one do not show me what I need.
If you don't see more with Error.getStackTrace(), it's probably because there is nothing more in the stack. Except for private internal player calls like [Render] etc.
Look at the deepest item in the call stack, it's probably an event handler of some sort. If so, you can't dig deeper than that.
You can get the stack trace as a string and log it to a file or show it in a text field.
var e:Error = new Error();
var trace:String = e.getStackTrace();
someTextField.text = trace;
Edit:
Using Flash Develop I threw an error and was able to see more than 17 steps of the stack trace :
Error
at Main/func14()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:100]
at Main/func13()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:93]
at Main/func12()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:88]
at Main/func11()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:83]
at Main/func10()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:78]
at Main/func9()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:73]
at Main/func8()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:68]
at Main/func7()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:63]
at Main/func6()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:58]
at Main/func5()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:53]
at Main/func4()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:49]
at Main/func3()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:44]
at Main/func2()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:39]
at Main/func1()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:34]
at Main/onCreationComplete()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:29]
at Main/___Main_Application1_creationComplete()[C:\Users\SGU\Desktop\barisu\misc\flex4test\src\Main.mxml:5]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:13152]
at mx.core::UIComponent/set initialized()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:1818]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:842]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.y\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]
I'm using WriteableBitmapEx in a WinRT project. I load an image into a WriteableBitmap from the users Picture library. However, I cannot then immediately write to that image, if I do, it will be overwritten with the image itself (it seems like it's Async loading the image and then it's overwritting my drawing on top of it). I don't know how to stop it from doing that (I tried using Await on the SetSource but that's not an Async method).
I've used an "Await Task.Delay(1000)" and that works, but it seems hacky because 1000ms may or may not be enough time.. I would like it to wait until the bitmap is loaded before proceeding.
Can anyone seem off the top what I'm doing wrong or suggest how I can ensure the WriteableBitmap is loaded from the pictures library before doing any processing? Here's the example code snippet I created:
Dim file = Await picker.PickSingleFileAsync
If file Is Nothing Then
Exit Sub
End If
Dim wbm As New WriteableBitmap(1, 1)
wbm.SetSource(Await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
' If I don't have this, the DrawLine will not show up, if I do, it will.
Await Task.Delay(1000)
wbm.DrawLine(1, 1, 255, 255, Colors.Green)
wbm.Invalidate()
ImageMain.Source = wbm
This method loads an image from the app's content, decodes it and passes back an ready-to-use WriteableBitmap.
Taken from the WriteableBitmapEx library:
/// <summary>
/// Loads an image from the applications content and fills this WriteableBitmap with it.
/// </summary>
/// <param name="bmp">The WriteableBitmap.</param>
/// <param name="uri">The URI to the content file.</param>
/// <returns>The WriteableBitmap that was passed as parameter.</returns>
public static async Task<WriteableBitmap> FromContent(this WriteableBitmap bmp, Uri uri)
{
// Decode pixel data
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
var decoder = await BitmapDecoder.CreateAsync(await file.OpenAsync(FileAccessMode.Read));
var transform = new global::Windows.Graphics.Imaging.BitmapTransform();
var pixelData = await decoder.GetPixelDataAsync(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb);
var pixels = pixelData.DetachPixelData();
// Copy to WriteableBitmap
bmp = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
using (var bmpStream = bmp.PixelBuffer.AsStream())
{
bmpStream.Seek(0, SeekOrigin.Begin);
bmpStream.Write(pixels, 0, (int)bmpStream.Length);
return bmp;
}
}
BTW, WinRT is now officially supported by WriteableBitmapEx. ;)
http://kodierer.blogspot.de/2012/05/one-bitmap-to-rule-them-all.html
The OpenAsync returning just means the stream is available, not that the data is actually read from it. It seems like you would therefore want to both open + read first and then you would be fine.
Since Filip pointed out that ReadAsync would require you to create and pass in a buffer first, I've updated the below snippet to use DataReader to actually load the stream into the byte array after doing OpenReadAsync to get the IRandomAccessStream.
var randomAccessStream = await file.OpenReadAsync();
var dataReader = new DataReader(randomAccessStream);
await dataReader.LoadAsync(randomAccessStream.Size);
byte[] imageBytes;
dataReader.ReadBytes(out imageBytes);
wbm.SetSource(new MemoryStream(imageBytes));
I don't think WB has the events that BitmapImage does to wait for it to open. I would try using BitmapDecoder/CreateAsync/GetPixelDataAsync/DetachPixelData and copy resulting byte array to the WB's pixel buffer instead of calling wb.SetSource(). Then maybe call wb.Invalidate(). Or maybe just replace the Delay call with an Invalidate one.