1
votes

I am using a JS cropper library. Once the cropping is done, the cropper prodives me a canvas so that I can get the data and upload the cropped picture to my server.

Currently it works fine but when converting the canvas to a PNG data url, as I want my output picture to be very large (it's a banner), the upload actually takes a lot of time so I prefer to go with JPEG which seems to compress better large pictures. But JPEG has no alpha channel so it seems I have to replace it with a background (I choose my color: white).

So, can someone tell me how to convert that canvas to a data url in JPEG when the original image is like this:

icon with alpha

It is a cropped picture of a warning icon in PNG. The background is alpha and it has some black drawings.

I have done some attempts but it seems that when I draw a rectangle on the canvas it draws on top of my initial picture. I can't draw the rectangle before the picture gets added because the cropper lib provides me with the canvas already constructed.

canvasToDataUrl(cropper) {
    const ctx = canvas.getContext('2d');
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    return canvas.toDataURL("image/jpeg",1);
},

When I do this I only get a white picture at the end.

If I don't draw a rectangle and I just try to convert to JPEG then I get a black picture.

1

1 Answers

4
votes

Simply create a new canvas where you first draw the background-color, then the wanted canvas image :

function canvasToDataURL(canvas){
    // use cloneNode(true) to get the same width/height as your previous canvas
    var exporter = canvas.cloneNode(true);
    var ctx = exporter.getContext('2d');
    // first fill set our background
    ctx.fillStyle = 'white';
    ctx.fillRect(0,0,exporter.width, exporter.height);
    // yes you can draw a canvas onto a canvas
    ctx.drawImage(canvas, 0,0);
    var dataURL = exporter.toDataURL('image/jpeg');
    return dataURL;
}

// simulate the cropper canvas
var cropper = document.createElement('canvas');
var img = new Image();
img.onload = function(){
  cropper.width = this.width/2;
  cropper.height = this.height/2;
  cropper.getContext('2d').drawImage(this, 0,0);
  // here we pass the canvas, not the img
  result.src = canvasToDataURL(cropper);
  }
img.crossOrigin = 'anonymous';
img.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
body { background-color: ivory; }
<img id="result"/>