64 is 2^6(6 bits). This means that every char(8 bits) contains only 6 bits of information. So in order to convey the same amount of information base64 requires 33.3% more bits compared to binary.

The only thing you can do is reduce the size of the original image before you apply base64, this will reduce the size of the base64 string by the same ratio.

Answer from Jonathan Laperle on Stack Overflow
🌐
GitHub
gist.github.com › profiprog › 88327d5cb4599b1370d1252d262dd42e
Simple compressing base64 string in JavaScript · GitHub
let compressedImg = imgCur.split('').reduce((o, c) => { if (o[o.length - 2] === c && o[o.length - 1] < 35) o[o.length - 1]++; else o.push(c, 0); return o; },[]).map(_ => typeof _ === 'number' ? _.toString(36) : _).join(''); This code replace a every consecutive equaly chars by single char and by count of chars minus one. Count of chars is desired to take only one char place and javascript natively supports to convert number into string by using max.
Discussions

javascript - how to compress a base64 image to custom size - Stack Overflow
I send/receive my image by using base64. I have a base64 string and I want to compress it to my size. for example I want to reduce photo size to 100kb. Is it possible? More on stackoverflow.com
🌐 stackoverflow.com
javascript - Reduce size of image when converted to Base64 - Stack Overflow
I am using the File reader in JavaScript,i need to Post my image to WebApi and convert it into byte Array and save it in server,Its working fine,Now my problem is base64 string increasing the size of image, Let say if i upload image of 30Kb, it is storing has 389Kb in server,How i can save in same size or reduce ... More on stackoverflow.com
🌐 stackoverflow.com
javascript - How do we compress the size of a base64 image in Node.js? - Stack Overflow
I receive a base64 encoded response from the api, which has huge no.of characters (data). So i want to scale/reduce the size of this base64 image. What's the best way to do that? More on stackoverflow.com
🌐 stackoverflow.com
javascript - Compressing base64 data uri images - Stack Overflow
Problem I'm creating multiple charts that are then sent to the server to create a PDF. This data can get large. Question What is the best way to compress and send the image data to the server More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 4
40

You can use canvas, put image into it, scale it and get image src with new base64 code.

Here's the function doing that, it returns promise object, as image needs to be loaded (cached) first before drawing canvas out of it and getting its encoded src.

function resizeBase64Img(base64, width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext("2d");
    var deferred = $.Deferred();
    $("<img/>").attr("src", "data:image/gif;base64," + base64).load(function() {
        context.scale(width/this.width,  height/this.height);
        context.drawImage(this, 0, 0); 
        deferred.resolve($("<img/>").attr("src", canvas.toDataURL()));               
    });
    return deferred.promise();    
}

Can be used like this:

resizeBase64Img(oldBase64, 100, 100).then(function(newImg){
    $("body").append(newImg);
});

here's the jsfiddle

2 of 4
24

A non-jquery solution based on @paulitto 's answer for future googlers like me:

/**
 * Resize a base 64 Image
 * @param {String} base64 - The base64 string (must include MIME type)
 * @param {Number} newWidth - The width of the image in pixels
 * @param {Number} newHeight - The height of the image in pixels
 */
function resizeBase64Img(base64, newWidth, newHeight) {
    return new Promise((resolve, reject)=>{
        const canvas = document.createElement("canvas");
        canvas.width = newWidth;
        canvas.height = newHeight;
        let context = canvas.getContext("2d");
        let img = document.createElement("img");
        img.src = base64;
        img.onload = function () {
            context.scale(newWidth/img.width,  newHeight/img.height);
            context.drawImage(img, 0, 0); 
            resolve(canvas.toDataURL());               
        }
    });
}

Use it like:

resizeBase64Img(basedata, 50, 50).then((result)=>{
    console.log("After resize: "+result);
});

Note that this function returns a base64 string. To get an <img>, you can use something like

resizeBase64Img(basedata, 50, 50).then((result)=>{
    let img = document.createElement("img");
    img.onload = ()=>{
        // do something with the img
    }
    img.src = result;
});

Example:

function resizeBase64Img(base64, newWidth, newHeight) {
    return new Promise((resolve, reject)=>{
        const canvas = document.createElement("canvas");
        canvas.width = newWidth;
        canvas.height = newHeight;
        let context = canvas.getContext("2d");
        let img = document.createElement("img");
        img.src = base64;
        img.onload = function () {
            context.scale(newWidth/img.width,  newHeight/img.height);
            context.drawImage(img, 0, 0); 
            resolve(canvas.toDataURL());               
        }
    });
}

let base64 = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QCgRXhpZgAATU0AKgAAAAgABQEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAAEyAAIAAAAUAAAAWodpAAQAAAABAAAAbgAAAAAAAABgAAAAAQAAAGAAAAABMjAyMDoxMjozMSAwOTozODoxNwAAA6ABAAMAAAABAAEAAKACAAMAAAABAEwAAKADAAMAAAABADIAAAAAAAD/4QyJaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjUuMCI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjAtMTItMzFUMDk6Mzg6MTctMDU6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTEyLTMxVDA5OjM4OjE3LTA1OjAwIj4gPGRjOnRpdGxlPiA8cmRmOkFsdD4gPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5DaXR5c2NhcGVfYW5kX3NreWxpbmVfYnlfdGhlX0NvcGVuaGFnZW5fTGFrZXMsX0Rlbm1hcmtfLV8oMzYwMTgxMDk5NTYpPC9yZGY6bGk+IDwvcmRmOkFsdD4gPC9kYzp0aXRsZT4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHhtcE1NOmFjdGlvbj0icHJvZHVjZWQiIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFmZmluaXR5IFBob3RvIChOb3YgIDYgMjAyMCkiIHhtcE1NOndoZW49IjIwMjAtMTItMzFUMDk6MzY6MjktMDU6MDAiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InByb2R1Y2VkIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAoTm92ICA2IDIwMjApIiBzdEV2dDp3aGVuPSIyMDIwLTEyLTMxVDA5OjM4OjE3LTA1OjAwIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+/+0BkFBob3Rvc2hvcCAzLjAAOEJJTQPtAAAAAAAQAGAAAAABAAIAYAAAAAEAAjhCSU0D8gAAAAAACgAA////////AAA4QklNBAQAAAAAAFQcAVoAAxslRxwCAAACAAQcAgUAQENpdHlzY2FwZV9hbmRfc2t5bGluZV9ieV90aGVfQ29wZW5oYWdlbl9MYWtlcyxfRGVubWFya18tXygzNjAxODE4QklNBAYAAAAAAAcACAAAAAMBADhCSU0ECAAAAAAAEAAAAAEAAAJAAAAC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";

document.body.append("Before: ");
let before = document.createElement("img");
before.src = base64;
document.body.appendChild(before);

resizeBase64Img(base64, 20, 20).then(resized=>{
  document.body.append("After: ");
  let img = document.createElement("img");
  img.src = resized;
  document.body.appendChild(img);
});
img {
  display: block;
}

🌐
CodePen
codepen.io › andersdn › pen › VKPrgg
base64 resize
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Top answer
1 of 1
7

This was a fun challenge cuz it involved a binary search until it finds the right size. I'm not going to advice you to solve this with base64 instead of blob cuz you should really handle it as binary (blob) otherwise it takes up ~33% more data as base64

This code includes resizing that you can set a max width/hight and still be able to keep the aspect ratio and auto quality lookup until it finds the correct quality to match the MAX_SIZE

console.log('Downloading lorem ipsum image to simulate a file from user input')

fetch('https://picsum.photos/1920/1080/?random')
.then(res => res.blob())
.then(blob => {
  const img = new Image()
  img.src = URL.createObjectURL(blob)

  console.log(`Original image size (at 1920x1080) is: ${blob.size} bytes`)
  console.log('URL to original image:', img.src)
  
  img.onload = () => resize(img, 'jpeg').then(blob => {
    console.log('Final blob size', blob.size)
    console.log('Final blob url:', URL.createObjectURL(blob))

    console.log('\nNow with webp\n')

    resize(img, 'webp').then(blob => {
      console.log('Final blob size', blob.size)
      console.log('Final blob url:', URL.createObjectURL(blob))
    })
  })
}) 


const MAX_WIDTH = 1280
const MAX_HEIGHT = 720
const MAX_SIZE = 100000 // 100kb

async function resize(img, type = 'jpeg') {
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  
  ctx.drawImage(img, 0, 0)
  
  let width = img.width
  let height = img.height
  let start = 0
  let end = 1
  let last, accepted, blob
  
  // keep portration
  if (width > height) {
    if (width > MAX_WIDTH) {
      height *= MAX_WIDTH / width
      width = MAX_WIDTH
    }
  } else {
    if (height > MAX_HEIGHT) {
      width *= MAX_HEIGHT / height
      height = MAX_HEIGHT
    }
  }
  canvas.width = width
  canvas.height = height
  console.log('Scaling image down to max 1280x720 while keeping aspect ratio')
  ctx.drawImage(img, 0, 0, width, height)
  
  accepted = blob = await new Promise(rs => canvas.toBlob(rs, 'image/'+type, 1))
  
  if (blob.size < MAX_SIZE) {
    console.log('No quality change needed')
    return blob
  } else {
    console.log(`Image size after scaling ${blob.size} bytes`)
    console.log('Image sample after resizeing with losseless compression:', URL.createObjectURL(blob))
  }
  
  // Binary search for the right size
  while (true) {
    const mid = Math.round( ((start + end) / 2) * 100 ) / 100
    if (mid === last) break
    last = mid
    blob = await new Promise(rs => canvas.toBlob(rs, 'image/'+type, mid))
        console.log(`Quality set to ${mid} gave a Blob size of ${blob.size} bytes`)
    if (blob.size > MAX_SIZE) { end = mid }
    if (blob.size < MAX_SIZE) { start = mid; accepted = blob }
  }

  return accepted
}

PS/warning Canvas don't do any good compression, if you paint a jpg picture on a canvas element and get the image back with no resizing, manipulation quality loss or changing the format toBlob('image/jpg', cb, 1) then you will most definitely get a larger file back since they probably already are well compressed and canvas dose none. I only change the quality & max width/height to reduce the size with the canvas api. You would need some compressor to reduce it even more without quality loss.

Another thing you will lose are some image metadata like geolocation and other useful EXIF data. maybe you want that or you don't

  • jsfiddle demonstration of file increase with canvas
  • imageoptim
  • squoosh.app
  • zopfli
  • pngcrush
🌐
GitHub
gist.github.com › ORESoftware › ba5d03f3e1826dc15d5ad2bcec37f7bf
resizing an image on the front-end before sending to a server · GitHub
It works fine if you add an "onload" listener on "img" in "resizeImage(base64Str)" function and move the rest part of function inside the onload function.
🌐
Stack Overflow
stackoverflow.com › questions › 41610480 › reduce-size-of-image-when-converted-to-base64
javascript - Reduce size of image when converted to Base64 - Stack Overflow
Converting to Base64 definitely has some impact on the size and the performance. Depending on the actual data that you are sending applying gzip compression to those raw bytes could even further strip down the size.
🌐
CodeProject
codeproject.com › Questions › 563793 › CompressingplusBase64plusStrings
Compressing Base64 Strings
March 18, 2013 - Language selection significantly impacts the beginner experience as some languages prove more approachable than others. Python's readability and versatility make it a popular first language for general software learning. JavaScript enables immediate visible results through web development, motivating visual learners.
Find elsewhere
🌐
npm
npmjs.com › package › resize-base64
resize-base64 - npm
A function that resizes a base64 image. Latest version: 1.0.12, last published: 9 years ago. Start using resize-base64 in your project by running `npm i resize-base64`. There are 6 other projects in the npm registry using resize-base64.
      » npm install resize-base64
    
Published: Dec 27, 2016
Version: 1.0.12
🌐
YouTube
youtube.com › giv
Reduce base64 image file size | JavaScript - YouTube
In this video I'll show you how you can reduce the file size of any image in base64 using JavaScript in the frontend before sending to server.Link to CODE: h...
Published: April 22, 2021
Views: 18K
🌐
npm
npmjs.com › package › compress-base64
compress-base64 - npm
January 28, 2025 - A library for compressing base64 in browser environment.
      » npm install compress-base64
    
Published: Apr 12, 2026
Version: 7.1.0
🌐
ServiceNow Community
servicenow.com › community › developer-forum › how-can-i-lower-the-quality-and-size-of-an-image-in-base64 › m-p › 1393367
How can I lower the quality and size of an image in base64
March 15, 2022 - In either case, you wouldn't be able to just change a few characters to accomplish this...most, if not all solutions involve taking the base64, loading it in a canvas, making the tweaks to it (lowering resolution or whatever) and then grabbing the new base64 for use. Example: https://stackoverflow.com/questions/20379027/javascript-reduce-the-size-and-quality-of-image-with-ba...
Top answer
1 of 2
1

Well, base64 is just a text representation of some bytes.

First, you need to transform it into the buffer with bytes. E.g. like this:

const imageBuffer = Buffer.from(yourString, 'base64');

Then you should either save it on a disk and use some other tools like imagemagick to transform it:

fs.writeFileSync('your-image.png', imageBuffer); // in case you know it's PNG, ofc
// transform somehow, probably invoking third-party tool using child_process.execSync

Or you may use libs like Sharp to optimize the image in that buffer. Here's an example from the repo:

sharp(inputBuffer)
  .resize(320, 240)
  .toFile('output.webp', (err, info) => { ... });

Depending on the type of the image you manipulate and on the transformations you're trying to do, you may need different tools, not only Sharp, but also Gifsicle or Guetzli.

Years ago my team created a small CLI tool for optimizing images for our needs. The tool does not solve your problem, but maybe its code, where we work with different encoders, can help you somehow:

https://github.com/funbox/optimizt/blob/master/lib/optimize.js

2 of 2
0

Install library npm install sharp

Conversion to image, resize as you need, and then convert to base64

let arrData = `${imageBase64}`.split(',');
var imgBuffer = Buffer.from(arrData[1], 'base64');
const sharp = require('sharp');
let bufferImgCompressed = await sharp(imgBuffer)
.resize({ width: 100, height: 200 })
.toBuffer()
.then(data => { return data; })
.catch(err => { console.log('Error on compress'); });

let imgBase64Compressed = bufferImgCompressed.toString('base64');

The use of ${imageBase64}.split(',') is because to convert base64 to buffer the string should not to contains the 'data:image/...'

🌐
DEV Community
dev.to › konstantinstanmeyer › image-compression-in-javascripttypescript-dc9
Image Compression in JavaScript/TypeScript - DEV Community
December 4, 2023 - The following approach allows for increased file compression, inherently lowering file size as well as an added ability to store images in Base64-encoded strings if desired.
Top answer
1 of 3
54

Maybe string compression is the solution for you. This converts the data to byte arrays.

There are multiple implementations and algorithms around, for instance

  • LZMA-JS A standalone JavaScript implementation of the Lempel-Ziv-Markov chain (LZMA) compression algorithm.

    my_lzma = new LZMA("./lzma_worker.js");
    my_lzma.compress("This is my compression test.", 1, function on_compress_complete(result) {
        console.log("Compressed: " + result);
        my_lzma.decompress(result, function on_decompress_complete(result) {
            console.log("Decompressed: " + result);
        }, function on_decompress_progress_update(percent) {
            console.log("Decompressing: " + (percent * 100) + "%");
        });
    }, function on_compress_progress_update(percent) {
        console.log("Compressing: " + (percent * 100) + "%");
    });
    
  • lz-string: JavaScript compression, fast!

    var str = "This is my compression test.";
    console.log("Size of sample is: " + str.length);
    var compressed = LZString.compress(str);
    console.log("Size of compressed sample is: " + compressed.length);
    str = LZString.decompress(compressed);
    console.log("Sample is: " + str);
    
2 of 3
13

I needed to generate thumbnails from larger pictures. I decided to solve my version of this problem with the HTML5 Canvas technique. I am using GWT so my code is:

//Scale to size
public static String scaleImage(Image image, int width, int height) {

    Canvas canvasTmp = Canvas.createIfSupported();
    Context2d context = canvasTmp.getContext2d();

    canvasTmp.setCoordinateSpaceWidth(width);
    canvasTmp.setCoordinateSpaceHeight(height);

    ImageElement imageElement = ImageElement.as(image.getElement());

    context.drawImage(imageElement, 0, 0, width, height);

    //Most browsers support an extra option for: toDataURL(mime type, quality) where quality = 0-1 double.
    //This is not available through this java library but might work with elemental version?
    String tempStr = canvasTmp.toDataUrl("image/jpeg");

    return tempStr;
}

If you are using JS you can probably get the idea:

  • Make a canvas the size of the desired output image
  • draw the input image on the canvas in the new size
  • call canvas.toDataURL("mime-type", quality)

You can use any mime-type I think, but for me the jpeg one was the smallest and was comparable to results of my desktop image program.

My GWT would not let me do the quality parameter (and I'm not 100% sure how widely supported it is in which browsers), but that was OK because the resulting images were quite small. If you leave the mime-type blank it defaults to png which in my case was 3-4x larger than jpeg.

🌐
CodePen
codepen.io › Holy-Fire › pen › VNRZme
LZString Base64 compress and decompress
Converts between plaintext and Base64, LZ-compressed strings....