admin管理员组

文章数量:1300018

I am trying to press 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 pression 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

  • Tried giving input in hex, buffer, base64 and plain URL string.
  • Since the Android URL contains file:// as prefix I tried to remove them also.

I am trying to press 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 pression 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

  • Tried giving input in hex, buffer, base64 and plain URL string.
  • Since the Android URL contains file:// as prefix I tried to remove them also.
Share Improve this question edited Mar 16, 2020 at 5:03 AmerllicA 32.7k17 gold badges143 silver badges167 bronze badges asked Mar 6, 2020 at 14:57 BadriBadri 1061 gold badge1 silver badge11 bronze badges 3
  • 2 I used github./bamlab/react-native-image-resizer with quality to press image – tuledev Commented Mar 10, 2020 at 4:32
  • Yes, i am currently using that but i wanted to migrate to mozjpeg to reduce file size. – Badri Commented Mar 10, 2020 at 6:54
  • The issue is almost certainly something with the encoding (assuming the file is being read correctly). Because mozjpeg expects the file to be binary encoded maybe something like Buffer.from(data, 'utf8') as readFile from react-native-fs is utf8 by default. – Trobol Commented Mar 16, 2020 at 2:39
Add a ment  | 

4 Answers 4

Reset to default 2

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,
  pressFormat,
  quality
)
  .then( resizedImageUri => {

    // the resizedImageUri is accessible here to use.

  }).catch( err => {

  // Catch any error here.

});

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 press it. maybe this library has a good press 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,
  pressImageQuality: 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.

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

Expo has a ponent that does exactly this: Image Manipulator

本文标签: javascriptImage compression in reactnativeStack Overflow