Mobile Image Compression Upload solution

Source: Internet
Author: User

Recently done mobile image upload, found that pictures, especially the image of the iphone photos are about 2M, but in fact the project is not so big, so think of JS in the foreground to compress.

The solution is as follows:

 "One" Get picture data

First get the image data, that is, listen to the Change event of input file, then get to the uploaded file object files, the class array of files to a group, and then a foreach traversal.

Then determine the file type, if not the picture is not processed. If the picture is to instantiate a filereader, read the uploaded file data in base64 format, determine the length of the data, if the picture is greater than 200KB call compress method to compress, otherwise call upload method to upload.

Filechooser.onchange = function () {if (!this.files.length) return;        var files = Array.prototype.slice.call (this.files);            if (Files.length > 9) {alert ("up to 9 images can be uploaded at the same time");        Return            } files.foreach (function (file, i) {if (!/\/(?: jpeg|png|gif)/i.test (File.type)) return;            var reader = new FileReader ();            var li = document.createelement ("Li");            li.innerhtml = ' <div class= ' progress ' ><span></span></div> ';            $ (". Img-list"). Append ($ (LI));                Reader.onload = function () {var result = This.result;                var img = new Image ();                IMG.SRC = result; If the picture size is less than 200kb, upload the IF (result.length <= maxsize) {$ (LI). css ("Background-image", "                    URL ("+ result +") ");                    img = NULL;                    Upload (result, File.type, $ (LI));             Return   }//the picture is loaded and then compresses, then uploads if (Img.complete) {callback ();                } else {img.onload = callback;                    } function callback () {var data = compress (IMG);                    $ (LI). css ("background-image", "url (" + Data + ")");                    Upload (data, File.type, $ (LI));                img = NULL;            }            };        Reader.readasdataurl (file); })    };

 "2" Compressed picture

After getting the picture data, we can do the compress compress the image method. And compressing the picture is not directly drawing the picture to the canvas and then calling the Todataurl on the line.

In iOS, canvas draws a picture with two restrictions:

The first is the size of the picture, if the size of the picture is more than 2 million pixels, the picture can not be drawn to the canvas, the call DrawImage will not error, but you use Todataurl to obtain the image data when the image is empty data.

In addition, the size of the canvas is limited, if the size of the canvas is larger than about 5 million pixels (that is, the width and height product), not only the picture can not be drawn, and nothing else is not drawn.

The first limitation should be handled by tiles. Tile painting, that is, the picture is divided into multiple pieces to the canvas, my code is to split the image into a 1 million-pixel piece of the size, and then drawn to the canvas.

In response to the second limitation, my approach is to properly compress the width of the image, and in my code, for the sake of insurance, the upper limit is 4 million pixels, and if the image is larger than 4 million pixels, it is compressed to less than 4 million pixels. The 4 million-megapixel picture should be enough, and the width and height are 2000x2000.

This solves both limitations on iOS.

In addition to the limitations described above, there are two pits, one is the canvas of the todataurl is only compressed JPG, when the user uploads the image is a PNG, you need to turn to JPG, that is, unified with Canvas.todataurl (' Image/jpeg ', 0.1) , the type is uniformly set to JPEG, and the compression ratio is controlled by itself.

The other is that if a PNG-to-JPG is drawn to the canvas and the canvas has a transparent area, the transparent area turns black when it is turned into a JPG, because the canvas's transparency, like Somer, considers Rgba (0,0,0,0), so turning into JPG becomes rgba ( 0,0,0,1), that is, the transparent background will become black. The solution is to paint a layer of white background on the canvas.

Function Compress (img) {var initsize = img.src.length;        var width = img.width;        var height = img.height;        If the picture is greater than 4 million pixels, calculate the compression ratio and press the size to 4 million VAR ratio;            if ((ratio = width * height/4000000) >1) {ratio = math.sqrt (ratio);            Width/= ratio;        Height/= ratio;        }else {ratio = 1;        } canvas.width = width;        Canvas.height = height;//Floor Ctx.fillstyle = "#fff";        Ctx.fillrect (0, 0, canvas.width, canvas.height);        If the picture pixel is greater than 1 million, use the tile to draw var count; if (count = width * height/1000000) > 1) {count = ~ ~ (math.sqrt (count) +1);//Calculate how many tiles to divide//calculate each block            Tile width and Height var nw = ~ ~ (width/count);            var NH = ~ ~ (height/count);            Tcanvas.width = NW;            Tcanvas.height = NH; for (var i = 0, i < count; i++) {for (var j = 0; J < Count; J + +) {Tctx.drawimage (IMG, I* NW * ratio, J * nh * ratio, NW * ratio, NH * ratio, 0, 0, NW, NH);                Ctx.drawimage (Tcanvas, I * NW, J * NH, NW, NH);        }}}} else {Ctx.drawimage (img, 0, 0, width, height);        }//Minimum compression var ndata = Canvas.todataurl (' Image/jpeg ', 0.1);        Console.log (' Pre-compression: ' + initsize);        Console.log (' after compression: ' + ndata.length ');        Console.log (' compression ratio: ' + ~ ~ (initsize-ndata.length)/initsize) + "%");        Tcanvas.width = Tcanvas.height = Canvas.width = Canvas.height = 0;    return ndata; }

  

 

Mobile Image Compression Upload solution

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.