Badri
Badri

Reputation: 106

Image compression in react-native

I am trying to compress images with mozjpeg when I implemented it in node.js according to the docs it worked fine.

const input = fs.readFileSync("in.ppm");
const out = mozjpeg.encode(input, { quality: 85 });

I need to do the compression on the client-side, so I tried to do the same with react-native since react-native doesn't contain core node modules such as fs, I need to go for a third party library react-native-fs for file reading.

When I tried to execute mozjpeg.encode(input, { quality: 85 }); in react-native it throws Unrecognized input file format --- perhaps you need -targa

server-side implementation

const mozjpeg = require("mozjpeg-js");
const fs = require("fs");

const input = fs.readFileSync(filePath);
const out = mozjpeg.encode(input, { quality: 85 });
console.error(out.stderr);
fs.writeFileSync("out.jpg", out.data);

client-side implementation

fs.readFile(image.path).then(data => {
    const out = mozjpeg.encode(data, { quality: 85 });
    console.log(out);
}

Here is the list of thing I tried

Upvotes: 6

Views: 10766

Answers (4)

oldo.nicho
oldo.nicho

Reputation: 2289

Expo has a component that does exactly this: Image Manipulator

Upvotes: 0

AmerllicA
AmerllicA

Reputation: 32472

Also, there is another good React-Native image crop picker library that purpose is grabbing some images and cropping them but it has a good ability to compress it. maybe this library has a good compress algorithm like mozjpeg.

It can open camera, open gallery or use a constant image, even you can turn of cropping:

ImagePicker.openCamera({
  width: 300,
  height: 400,
  compressImageQuality: 0.2
}).then(image => {
  // do what you want
}).catch(e => {
  // handle error
});

Good to config and it has many options for tuning. I hope it helps you.

Upvotes: 2

AmerllicA
AmerllicA

Reputation: 32472

Actually I don't know about mozjpeg but I prefer to use pure JavaScript way on the environment of problem to solve my problem.

I guess your thought fell in one-way bios, leave away the NodeJS solution, you are in the react-native environment so use React Native Compress Image or React Native Image Resizer.

Based on my experiences I prefer to use the second one, the React Native Image Resizer.

After install, use it like below:

ImageResizer.createResizedImage(
  imageUri,
  newWidth,
  newHeight,
  compressFormat,
  quality
)
  .then( resizedImageUri => {

    // the resizedImageUri is accessible here to use.

  }).catch( err => {

  // Catch any error here.

});

Upvotes: 2

Mohsen
Mohsen

Reputation: 1555

You can find in mozjpeg-js doc that the input argument is:

a typed array or buffer of data


fs.readFile return type in client-side (react-native-fs) is Promise<string> and return contents. (Doc)

But in server-side (fs), fs.readFileSync return buffer object. (Doc)


So you can change string to a typed array with this function:

function str2ta(str) {
  var bufView = new Uint16Array(str.length*2); // 2 bytes for each char
  for (var i=0, strLen=str.length; i<strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return bufView;
}

Upvotes: 1

Related Questions