Compressing base64 data uri images

一个人想着一个人 提交于 2019-11-29 23:04:25

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);
    
Jesse Adamson

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.

I finally got this working with fairly large files.

To do it, I used lz-string, as shown above.

There is one issue though, which is that sending UTF-16 data via ajax is deprecated, so.. it doesn't work. The fix is to convert to and from UTF-16 and UTF-8.

Here's the conversion code I'm using. I'm not sure what the standard endian is, btw:

var UTF = {};

UTF.U16to8 = function(convertMe) {
var out = "";
  for(var i = 0; i < convertMe.length; i++) {
      var charCode = convertMe.charCodeAt(i);
      out += String.fromCharCode(~~(charCode/256));
      out += String.fromCharCode(charCode%256);
    }
  return out;
}

UTF.U8to16 = function(convertMe) {
  var out = ""
  for(var i = 0; i < convertMe.length; i += 2) {
    var charCode = convertMe.charCodeAt(i)*256;
    charCode += convertMe.charCodeAt(i+1);
    out += String.fromCharCode(charCode)
  }
  return out;
}

If you're using Node.js, this code works on both sides. If not, you'll have to write your own version of these converters for the server side.

Phew! What a day this was.

This is not much of a satifying answer, but there are probably no libraries that give the result you want.

You say that resizing is not an option, but then, what is? Only lossless compression? Base64 strings represent a compressed image already, I don't think any libraries will provide lossless compression.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!