10

I'm trying to compress image taken from camera to 250kb size in Xamarin.Forms. I found ways to do that in dependency service but I want it without dependency service (pure xamarin.forms code). How could it possible. Can anyone suggest me best approaches you have?

Thanks in advance

Nawnit
  • 362
  • 1
  • 2
  • 14
  • 12
    I don't think there is any way to do it in "pure" forms code unless you want to write all of the image logic from scratch, which would be a huge amount of code. Relying on the highly optimized native image handling capabilities of each platform seems like a much better way to go, even if it does force you to use DI. – Jason Jan 05 '16 at 04:57
  • When you check with object browser of .NET reference library, It is showing System.Drawing portable library. How to import that library? – Naveen Bathina Jan 05 '16 at 14:34
  • 1
    system.drawing lets you use this answer. http://stackoverflow.com/a/24199315/5495701 – Slepz Jan 05 '16 at 16:58
  • @Slepz you are wrong, system.drawing only works on Windows, op is asking for non windows platform "Xamarin". – Akash Kava Jul 14 '16 at 11:12
  • The most important question is wether lossy compression is okay. If it's not, you need to make stronger assumptions about your image (bounded dimensions, for example), or you won't be able to garantuee bounded compressed size. – Volker Schmidt Jul 14 '16 at 15:10

3 Answers3

25

It is a very complicated job since you would need a ton of knowledge about image processing.

Most importantly, re-inventing wheel is a bad move.

http://www.codeproject.com/Articles/83225/A-Simple-JPEG-Encoder-in-C

Take a look of the above code project which only tackles JPEG; not to say TIFF, GIF, BMP etc.

Image compression involves many complex mathematics transforms, like DCT and Huffman.

You will need a whole university semester to learn those basics.


On the other hand, wisely utilizing platform support, you can complete the task within a minute.

BitmapEncoder in Windows Phone.

FileStream stream = new FileStream("new.jpg", FileMode.Create);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.QualityLevel = 30;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);

Bitmap in Android

using (System.IO.Stream stream = System.IO.File.Create(targetFile))
{
    bitmap.Compress(Bitmap.CompressFormat.Jpeg, 30, stream);
}

UIImage in iOS

NSData data = image.AsJPEG(0.3);

Bitmap in .NET framework

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
ImageCodecInfo codec = codecs.First(t => t.FormatID == ImageFormat.Jpeg.Guid);
EncoderParameters parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(Encoder.Quality, 30L);
bitmap.Save("output.jpg", codec, parameters);
Tommy
  • 3,044
  • 1
  • 14
  • 13
6

I also had this same problem. Please check here as I believe you will find the solution.

https://xamarincodes.com/2020/04/05/image-compression-in-xamarin-forms/

I used Xam.Plugin.Media – setting the compression quality to take photos and compress as well.

Here is a sample

private async void cmdCameraPhotograph_Clicked(object sender, EventArgs e)
    {
        if (CrossMedia.Current.IsTakePhotoSupported)
        {
            var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
            {
                Directory = "Photographs",
                SaveToAlbum = true,
                CompressionQuality = 40,
                CustomPhotoSize = 35,
                PhotoSize = PhotoSize.MaxWidthHeight,
                MaxWidthHeight = 2000,
                DefaultCamera = CameraDevice.Rear
            }).ConfigureAwait(true);

            if (file != null)
            {
                
            }
        }
        else
        {
            await DisplayAlert("Not Supported", "Your device does not support this feature.", "OK. Understood")
                .ConfigureAwait(true);
        }
    }

You can also get the file from the Gallery

var file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
            {
                CompressionQuality = 40,
                CustomPhotoSize = 35,
                PhotoSize = PhotoSize.MaxWidthHeight,
                MaxWidthHeight = 2000
            }).ConfigureAwait(true);
1

My application uses a ListView with an image in each item in the list. I am using the following plugin, which has excellent documentation with example code

https://github.com/jamesmontemagno/MediaPlugin

for getting images from camera and gallery. The ListView was coming up slowly with lots of

[Choreographer] Skipped xx frames! The application may be doing too much work on its main thread.

Once I specified the PhotoSize = PhotoSize.Medium and CompressionQuality = 92 to reduce the size of the images the UI is now quite snappy without any noticeable loss of image quality!

charles young
  • 2,269
  • 2
  • 23
  • 38