Learner
Learner

Reputation: 2649

How to optimise an Image in React Native

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

Answers (4)

Shehzad Osama
Shehzad Osama

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

Learner
Learner

Reputation: 2649

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

Upvotes: 14

U.A
U.A

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

Mihail
Mihail

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

Related Questions