How to optimise an Image in React Native

43,307

Solution 1

https://github.com/bamlab/react-native-image-resizer provides an API to resize local images.

It allows you to specify:

  • Max dimensions (whilst preserving aspect ratio) and;
  • Output quality (for JPEG only)

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.
});

Solution 2

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);

Solution 3

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 }
};

Solution 4

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);
  }
}

Share:
43,307

Related videos on Youtube

Learner
Author by

Learner

I live to learn and I love to live.

Updated on October 12, 2021

Comments

  • Learner
    Learner over 2 years

    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?

  • Jujunol
    Jujunol over 6 years
    This library contains native code. If you're going to use it then you'll have to "eject" your app.
  • Afsara
    Afsara about 6 years
    @Learner any solution for iOS images captured from camera ?
  • user3480687
    user3480687 almost 3 years
    How to use the place of compressFormat?
  • Ayush Kumar
    Ayush Kumar over 2 years
    This is a great way of compressing images. Cool huh.
  • CrackerKSR
    CrackerKSR over 2 years
    @user3480687 use 'PNG' or 'JPG' for compressFormat. check its index.d.ts file of module to know more about parameters