- In this blog, we are going to look how to compress image/photo in Nativescript(Angular) well of course without any plugins ! in Android
- Here we are going to get images via photo and camera plugin and compress it before displaying
- If you are a {N} pro just hope on to here, for getting the complete working sample code on GitHub
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++;
}
-
Use fromFile(path: string): Promise to load an ImageSource instance from the specified file asynchronously.
var imageFromLocalFile: ImageSource = <ImageSource>fromFile(image);
-
The method toBase64String(format: "png" | "jpeg" | "jpg", quality?: number): string converts the image to base64 encoded string, using the provided image format and quality. The supported formats are png, jpeg, and jpg. The quality parameter is optional and defaults to maximum quality,and find the file size as number
var b64 = imageFromLocalFile.toBase64String('jpg', 90); var fileSize = b64.replace(/\=/g, '').length * 0.75;
-
the method loadFromBase64() loads this instance from the specified base64 encoded string asynchronously.
@param source The Base64 string to load the image from.
imageFromLocalFile.loadFromBase64(b64);
-
The method saveToFile() converts the image to base64 encoded string, using the provided image format and quality.
@param format The format (encoding) of the image.
@param quality Optional parameter, specifying the quality of the encoding. Defaults to the maximum available quality. Quality varies on a scale of 0 to 100.
var saved = imageFromLocalFile.saveToFile(image, 'jpg', 10);
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)!