We're trying to resize images in memory in a PCL project since the Forms.Labs CameraMediaStorageOptions
for the max dimension is broken for now. We found this example which is fantastically simple, but doesn't work. http://developer.xamarin.com/samples/XamFormsImageResize/
public static byte[] ResizeImage (byte[] imageData, float width, float height)
{
byte[] result = null;
#if __IOS__
result = ResizeImageIOS ( imageData, width, height );
#endif
#if __ANDROID__
result = ResizeImageAndroid ( imageData, width, height );
#endif
#if WINDOWS_PHONE
result = ResizeImageWinPhone ( imageData, width, height );
#endif
return result;
}
If we debug this with Android, it skips over the #if __ANDROID__
and ends up returning null. Any idea what could be causing this? Is it normal behaviour?
Here's extra information in case:
We call it this way:
private async Task<byte[]> TakePicture ()
{
//TODO: The picture lags, is it cropped? BUG https://github.com/XLabs/Xamarin-Forms-Labs/issues/528
try {
MediaFile _mediaFile = await this._mediaPicker.TakePhotoAsync(new CameraMediaStorageOptions {
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
byte[] test = StreamToByteArray(_mediaFile.Source);
return ImageResizer.ResizeImage (test, 400, 400);
} catch (System.Exception ex) {
//DisplayAlert ("Exception", ex.Message, "OK");
return null;
}
}
The ImageResizer class:
using System;
using System.IO;
#if __IOS__
using System.Drawing;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
#endif
#if __ANDROID__
using Android.Graphics;
#endif
#if WINDOWS_PHONE
using Microsoft.Phone;
using System.Windows.Media.Imaging;
#endif
namespace Klaim
{
public static class ImageResizer
{
static ImageResizer ()
{
}
public static byte[] ResizeImage (byte[] imageData, float width, float height)
{
byte[] result = null;
#if __IOS__
result = ResizeImageIOS ( imageData, width, height );
#endif
#if __ANDROID__
result = ResizeImageAndroid ( imageData, width, height );
#endif
#if WINDOWS_PHONE
result = ResizeImageWinPhone ( imageData, width, height );
#endif
return result;
}
#if __IOS__
public static byte[] ResizeImageIOS (byte[] imageData, float width, float height)
{
UIImage originalImage = ImageFromByteArray (imageData);
//create a 24bit RGB image
using (CGBitmapContext context = new CGBitmapContext (IntPtr.Zero,
(int)width, (int)height, 8,
(int)(4 * width), CGColorSpace.CreateDeviceRGB (),
CGImageAlphaInfo.PremultipliedFirst)) {
RectangleF imageRect = new RectangleF (0, 0, width, height);
// draw the image
context.DrawImage (imageRect, originalImage.CGImage);
MonoTouch.UIKit.UIImage resizedImage = MonoTouch.UIKit.UIImage.FromImage (context.ToImage ());
// save the image as a jpeg
return resizedImage.AsJPEG ().ToArray ();
}
}
public static MonoTouch.UIKit.UIImage ImageFromByteArray(byte[] data)
{
if (data == null) {
return null;
}
MonoTouch.UIKit.UIImage image;
try {
image = new MonoTouch.UIKit.UIImage(MonoTouch.Foundation.NSData.FromArray(data));
} catch (Exception e) {
Console.WriteLine ("Image load failed: " + e.Message);
return null;
}
return image;
}
#endif
#if __ANDROID__
public static byte[] ResizeImageAndroid (byte[] imageData, float width, float height)
{
// Load the bitmap
Bitmap originalImage = BitmapFactory.DecodeByteArray (imageData, 0, imageData.Length);
Bitmap resizedImage = Bitmap.CreateScaledBitmap(originalImage, (int)width, (int)height, false);
using (MemoryStream ms = new MemoryStream())
{
resizedImage.Compress (Bitmap.CompressFormat.Jpeg, 100, ms);
return ms.ToArray ();
}
}
#endif
#if WINDOWS_PHONE
public static byte[] ResizeImageWinPhone (byte[] imageData, float width, float height)
{
byte[] resizedData;
using (MemoryStream streamIn = new MemoryStream (imageData))
{
WriteableBitmap bitmap = PictureDecoder.DecodeJpeg (streamIn, (int)width, (int)height);
using (MemoryStream streamOut = new MemoryStream ())
{
bitmap.SaveJpeg(streamOut, (int)width, (int)height, 0, 100);
resizedData = streamOut.ToArray();
}
}
return resizedData;
}
#endif
}
}