Image compression / resizing is very slow

I am trying to resize an image on a mobile device. (Use of angular 2 based ionic structure 2).

The maximum file size is 5 MB, and some devices take up more images. Therefore, I am currently trying to resize the image using canvas.toDataURL(), but it is very slow. (The application does not respond for 15-20 seconds).

My current resize function is as follows:

private resize(outputFormat, sourceImgObj, quality) {
    let mimeType = "image/jpeg";

    let cvs = document.createElement('canvas');
    cvs.width = sourceImgObj.naturalWidth;
    cvs.height = sourceImgObj.naturalHeight;
    let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0);

    let newImageData = cvs.toDataURL(mimeType, quality/100);
    return newImageData;
}

Which (in my opinion) was founded at that time, if not like jic .

This feature works. In the browser it is decent, but still slow (Chrome). But when you run this function on the device, for example, when you select an image size of 8 MB, the application will basically crash.

/ ?


, cordova-plugin-camera, . base64 ( , ).

+4
2

. , jpeg lossy. , , 8 , , .

, , ( ) , .

, , 8 . toDataURL , .., .

, ...

, (.. ) , :

function resize(sourceImgObj) {
    const mimeType = "image/jpeg"; // would probably be better to keep the one of the file...
    let quality = .92; // default;
    const cvs = document.createElement('canvas');
    const MAX_SIZE = 500; // in px for both height and width
    const w = sourceImgObj.naturalWidth;
    const h = sourceImgObj.naturalHeight;
    let ratio = MAX_SIZE / Math.max(w, h);
    if(ratio > 1){ // if it smaller than our defined MAX_SIZE
      ratio = 1;
      quality = .5; // lower the jpeg quality
      }
    cvs.width = ratio * w;
    cvs.height = ratio * h;
    let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0, cvs.width, cvs.height);

    // note : if it not a problem to convert it to async then toBlob would be a better choice
    let newImageData = cvs.toDataURL(mimeType, quality);
    return newImageData;
}

inp.onchange = e => {
  const MAX_SIZE = 100000; // 100KB
  let img = new Image();
  img.src = URL.createObjectURL(inp.files[0]);
  img.onload = e => {
    // if it not too big, return the image current src
    let dataURL = (inp.files[0].size > MAX_SIZE) ?
    resize(img) : img.src;
    let out = new Image();
    out.src = dataURL;
    document.body.appendChild(out);
    };
  }
<input type="file" id="inp">
Hide result

(ivaro18)

. 50%, . 8,1 600 900 .

resize(sourceImgObj, callback) {
   const mimeType = "image/jpeg";
   let quality = .92; // default;
   const cvs = document.createElement('canvas');
   const MAX_SIZE = 1024; // in px for both height and width
   const w = sourceImgObj.naturalWidth;
   const h = sourceImgObj.naturalHeight;
   let ratio = MAX_SIZE / Math.max(w, h);
   if(ratio > 1) {
       let percentage = (w >= h) ? ((w - MAX_SIZE) / w * 100) : ((h - MAX_SIZE) / h * 100);
       cvs.width = (percentage + 100)/100 * w;
       cvs.height = (percentage + 100)/100 * h;

   } else {
       cvs.width = w * ratio;
       cvs.height = h * ratio;
   }

   let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0, cvs.width, cvs.height);

   let newImageData = cvs.toDataURL(mimeType, quality);
   callback(newImageData);
}
+2

Source: https://habr.com/ru/post/1683407/


All Articles