Is it possible to compress an image that has been converted from base64 string to binary?

976 Views Asked by At

I have an app that should create a thumbnail from large images. So I need to compress the image and for that I'm using the package imagemin.

I get the input from the user as a base64 string, and then on my server, I convert it using Buffer.from(base64string, "base64").

The issue is that the output from imagemin is not compressed at all. No error is thrown, but the image is not compressed. Although it works perfectly when I pass untouched binary data (such as from an image.jpg file), it seems to not be possible to use binary data that has been converted from base64 strings.

my code:

const imagemin = require("imagemin");
const imageminJpegtran = require("imagemin-jpegtran");
const imageminMozjpeg = require("imagemin-mozjpeg");
const imageminPngquant = require("imagemin-pngquant");
const fs = require("fs");

const myPic = () => {
  return new Promise((resolve, reject) => {
    fs.readFile("/image.txt", (err, data) => {
      if (err) throw err;
      resolve(Buffer.from(data, "base64"));
    });
  });
};

const waitMyPic = async () => {
  const picBuff = await myPic();
  return picBuff;
};

waitMyPic().then((res) => {
  console.log("Original File Size: " + Math.round(res.length / 1024));

  const compressImg = async (res) => {
    const files = await imagemin.buffer(res, {
      plugins: [
        imageminJpegtran(),
        imageminMozjpeg({
          quality: [10],
        }),
        imageminPngquant({ quality: [0.1, 0.12] }),
      ],
    });
    return files;
  };
  compressImg(res).then((data) => {
    console.log("Compressed File Size: " + Math.round(res.length / 1024));
    fs.writeFile("/image2.txt", data, (err, data) => {
      if (err) throw err;
    });
  });
});

note that in this code I'm reading a .txt file that has the base64 string of an image, and then I'm converting it to binary so I can use it in the imagemin function. This is for testing only, in the real situation the base64 strings would be served by the user and sent to the server through POST requests.

Any thoughts on this?

I'm not attached to imagemin at all, I could use another solution if someone points out a better approach. All I want to do is to compress an image as much as I can without making it unrecognizable, so I can create thumbnails that will be used in the blog "posts catalog".

2

There are 2 best solutions below

0
On

Yup with the help imageminMozjpeg plugin I able to reduce the size by 1/10 example code below

import imagemin from "imagemin";
import imageminMozjpeg from "imagemin-mozjpeg";
const ogBuffer = Buffer.from(base64String, "base64");
const buffer = await imagemin.buffer(ogBuffer, {
  plugins: [imageminMozjpeg({ quality: 50 })],
});
0
On

Sure just do pass the result from Buffer.from(data, 'base64') as the argument to imagemin.buffer(result, . Make sure that data is just the base64 data itself and does not include the metadata i.e. "data:image/png;base64,"