Reputation: 2649
Photos captured via camera are too large for efficient upload and download in React native.
Is there an api or library to compress a PNG image file in React Native?
Upvotes: 32
Views: 64079
Reputation: 1302
If you are using react-native-image-picker for uploading images, you can set maxWidth, maxHeight or quality of image for reducing the size.
const options = {
title: 'Select Picture',
storageOptions: {
skipBackup: true,
path: 'images',
},
maxWidth: 500,
maxHeight: 500,
quality: 0.5,
};
ImagePicker.showImagePicker(options, resolve, reject);
Upvotes: 26
Reputation: 2649
https://github.com/bamlab/react-native-image-resizer provides an API to resize local images.
It allows you to specify:
API
import ImageResizer from 'react-native-image-resizer';
ImageResizer.createResizedImage(
imageUri,
newWidth,
newHeight,
compressFormat,
quality,
)
.then(resizedImageUri => {
// resizeImageUri is the URI of the new image that can now be displayed, uploaded...
})
.catch(err => {
// Oops, something went wrong. Check that the filename is correct and
// inspect err to get more details.
});
Upvotes: 14
Reputation: 3373
My custom solution for image compression in react-native based on image size.
import * as ImageManipulator from 'expo-image-manipulator';
export default async function ImageCompress(image, { width, height }) {
const compressSizer = size => {
const MB = size / Math.pow(1024, 2);
if (Math.round(MB) === 0) return 1;
if (Math.round(MB) === 1) return 0.9;
if (Math.round(MB) === 2) return 0.8;
if (Math.round(MB) === 3) return 0.7;
if (Math.round(MB) === 4) return 0.6;
if (Math.round(MB) >= 5) return 0.5;
if (Math.round(MB) >= 10) return 0.4;
if (Math.round(MB) >= 15) return 0.3;
if (Math.round(MB) >= 20) return 0.2;
if (Math.round(MB) >= 25) return 0.1;
};
const imageManipulator = async (image, { width, height }) => {
const response = await fetch(image);
const blob = await response.blob();
const compress = compressSizer(blob.size);
let resize;
if (height === width) resize = { height: 480, width: 480 };
else if (height > width) resize = { height: 480 };
else resize = { width: 720 };
const compressedPhoto = await ImageManipulator.manipulateAsync(
image,
[{ resize }],
{
compress,
format: ImageManipulator.SaveFormat.JPEG,
},
);
return compressedPhoto.uri;
};
try {
return await imageManipulator(image, { width, height });
} catch (error) {
console.log(error);
}
}
Upvotes: 6
Reputation: 1386
You could use expo-image-manipulator:
import { manipulateAsync, SaveFormat } from 'expo-image-manipulator';
const compressImage = async (uri, format = SaveFormat.JPEG) => { // SaveFormat.PNG
const result = await manipulateAsync(
uri,
[{ resize: { width: 1200 } }],
{ compress: 0.7, format }
);
return { name: `${Date.now()}.${format}`, type: `image/${format}`, ...result };
// return: { name, type, width, height, uri }
};
Upvotes: 7