Skip to content

Instantly share code, notes, and snippets.

@soiqualang
Forked from profiprog/simple-compressing.md
Created February 28, 2020 02:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soiqualang/29006aec5b79da35efe904a390d9da51 to your computer and use it in GitHub Desktop.
Save soiqualang/29006aec5b79da35efe904a390d9da51 to your computer and use it in GitHub Desktop.
Simple compressing base64 string in JavaScript

Story

In needed include base64 encoded simple image into HTML page in two formats:

1st as PNG format has length 196 characters and looks like this:

iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAWElEQVR42mNkwA/qgbgRnwJGAgb8BwI7RkbGw5QYUAs0oGXUAPwGgKKqgYF0ANLTyAi1xhZI2WOYzsjYDJTbC2QewGHIwcERBsPcgHqgAX8pMQAcxfhyIwATTkxL+hgX2QAAAABJRU5ErkJggg==

2nd as CUR format has length 1536 characters and looks like this:

AAACAAEAEBAAAAcABwBoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///z0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////98AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////98AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///z3///98////fP///3z///98////fAAAAP////+8////fP///3z///98////fP///3z///98////PQAAAH8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////98AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////98AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////PQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/38AAP5/AAD+fwAA/n8AAP5/AAD+fwAA/n8AAIAAAAAAAQAA/n8AAP5/AAD+fwAA/n8AAP5/AAD+fwAA/v8AAA==

CUR format is amost 8 times bigger than PNG. And as you can see CUR format has repeating many characters. Therefore I used next simple technique to compress that.

Compressing

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. 36-base format, therefore max length of consecutive equaly chars can be max. 35 characters. Compresed string has only 556 characters (which is about 36.2% of source size) and looks like:

A2C0A1E0A0E0B0A3c0A0B0w0B0o0B0A2F0g0A2C0g0A3Q0A3I0A4E0A0I0A6Q0A0Q0AzAtP0/2z000AzAzA5H0/39080AzAzA5D0/4f0AzAzA6/430w0AzAzA5P0/39080AzAzA5D0/4f0AzAzA6/430w0AzA5P0/2z030/29080/3f0P0/230z0/29080/3f0A3P0/3+080/3f0P0/230z0/29080/3f0P0/230z0/29080/3P0Q0A2H080A2D0/0A3/0w0A2P080A2D0/0A3/0w0A2P080A2D0/0A3/0w0A2P080A2D0/0A3/0w0A2P080A2D0/0A3f0w0AzA9/430w0AzAzA5P0/39080AzAzA5D0/4f0AzAzA6/430w0AzAzA5P0/39080AzAzA5D0/4P0Q0AzAzA5f0w0AzA5/03080A1P050/0A1D0+0f0w0A1/0n080A1P050/0A1D0+0f0w0A1/0n080A1I0A6Q0A1/0n080A1P050/0A1D0+0f0w0A1/0n080A1P050/0A1D0+0f0w0A1/0v080A2=1

Decompressing

let decompressedImgCur = compressedImgCur
  .split('').map((c,i,a)=>i%2?undefined:new Array(2+parseInt(a[i+1],36)).join(c)).join('');
  • As you can see, decompressing code is even simpler than compressing one.
  • Is intenationaly written in compressed way because it's length (88 chars) should be included in calculation of compression rate.
  • So true compression rate is (556 + 88) / 1536 which is almost 42%.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment