Nativescript Image Compression

Imports

The necessary imports to be included in the .ts file are

import * as imagepicker from 'nativescript-imagepicker';
import * as camera from 'nativescript-camera';
import { ImageAsset } from 'tns-core-modules/image-asset';
import { Image } from 'tns-core-modules/ui/image';
import { ImageSource, fromFile } from 'tns-core-modules/image-source';

Image upload via camera and gallery

via camera:

The plugin used here is nativescript-camera for more information refer
the uploadFromCamera() function gets the camera image as imagesource after getting the android camera permissions from the .requestPermissions() methord,just neglect the this.imageUpload(localPath,this.cameraImage,'fromCamera'); for now

  uploadFromCamera() {
        var options = {
            width: 300,
            height: 300,
            keepAspectRatio: false,
            saveToGallery: true
        };
        camera
            .requestPermissions()
            .then(() =>
                camera
                    .takePicture(options)
                    .then(imageAsset => {
                        this.cameraImage = imageAsset;
                        var image = new Image();
                        image.src = imageAsset;
                        imageAsset.getImageAsync(imagesource => {
                            let localPath = imageAsset.android;

                            this.index =
                                this.imgArray.push({
                                    imageurl: '',
                                    uploaded: false,
                                    url: '',
                                    name: '',
                                    tag: '',
                                    thumburl: ''
                                }) - 1;

                            this.imageUpload(
                                localPath,
                                this.cameraImage,
                                'fromCamera'
                            );
                        });
                    })
                    .catch(function(e) {
                        console.log('catch in camera', e);
                    })
            )
            .catch(function(e) {
                console.log(e);
            });
    }

via gallery

The plugin used here is nativescript-imagepicker for more information refer
the uploadFromgallery() function gets the camera image as imagesource after getting the android gallery permissions from the .authorize() methord,just neglect the this.imageUpload(localPath,this.cameraImage,'fromCamera'); for now

    uploadFromgallery() {
        let context = imagepicker.create({
            mode: 'single'
        });
        this.startSelection(context);
    }
    private startSelection(context) {
        context
            .authorize()
            .then(() => {
                this.imageAssets = [];
                this.imageSrc = null;
                return context.present();
            })
            .then(selection => {
                this.index = this.imgArray.length;
                selection.forEach(select => {
                    this.imageSrc = select;

                    let options = {
                        width: this.previewSize,
                        heigth: this.previewSize
                    };
                    this.imageSrc.options = options;
                    this.imageSrc.keepAspectRatio = false;
                    this.cameraImage = this.imageSrc;
                    this.imgArray.push({
                        imageurl: '',
                        uploaded: false,
                        url: '',
                        name: '',
                        tag: '',
                        thumburl: ''
                    });
                    this.imageUpload(
                        select._android,
                        this.cameraImage,
                        'fromGallery'
                    );
                });
            })
            .catch(function(e) {
                console.log('catch gallery', e);
            });
    }

the coresponding .html file where the uploadFromCamera(),uploadFromgallery() functions wil be called is

<StackLayout>
  <Button
    class="btn btn-primary btn-active"
    id="button"
    text="CAMERA"
    (tap)="uploadFromCamera()"
  ></Button>

  <Button
    class="btn btn-primary btn-active"
    id="button"
    text="GALLERY"
    (tap)="uploadFromgallery()"
  ></Button>
  <ListView [items]="imgArray" height="400">
    <ng-template let-item="item">
      <image
        margin="20"
        [src]="item?.imageurl"
        class="p-t-10"
        stretch="aspectFill"
      ></image>
    </ng-template>
  </ListView>
</StackLayout>

Yeah you guessed it right! :)
this.imageUpload(arg1,arg2,arg3) is the function where we are doing the so called image compression so again in our .ts file we have to include

    private imageUpload(image, photoImage, fromWhere) {
        var imageFromLocalFile: ImageSource = <ImageSource>fromFile(image);
        var b64 = imageFromLocalFile.toBase64String('jpg', 90);
        var fileSize = b64.replace(/\=/g, '').length * 0.75;
        console.log('filesize', fileSize);//file size before compression
         if (Math.round(fileSize).toString().length > 6) { //image size greater than 1mb
        imageFromLocalFile.loadFromBase64(b64);
        var saved = imageFromLocalFile.saveToFile(image, 'jpg', 10);
         }

        // console.log('saved status', saved); //status whether true or false
        var imageFromLocalFile: ImageSource = <ImageSource>fromFile(image);
        var b64 = imageFromLocalFile.toBase64String('jpg');
        var fileSize = b64.replace(/\=/g, '').length * 0.75;
        console.log('filesize after', fileSize);//file size after compression

        this.imgArray[this.index].uploaded = true;

        this.imgArray[this.index].imageurl = photoImage;
        this.index++;
     
    }

well in my case the results were as below:

Type Before Compression After Compression
Image size 1mb 0.5mb

Warning

we can see the quality of the images(color,contrast..etc) decreases to a considerable amount after compression, so give the quality params accordingly

You can get the complete working demo code here

Happy scripting(Yeah scripting native)!

Subscribe to newsletter
Need more tech news? Tune in to our weekly newsletter to get the latest updates