On the process of optimizing picture matting with canvas

Posted by dmyst3 on Sun, 16 Jan 2022 04:33:14 +0100

Premise: the work involves IPTV Set-top Box EPG development business. Normal IPTV Set-top Box video playback calls the Mediaplayer component encapsulated by the manufacturer, which is different from ordinary video playback. The rendered video window belongs to the underlying rendering of Android system, and the html page element is not a layer. It will be blocked by dom element when playing under the document stream. To play the video correctly, you must keep the dom document stream completely transparent in the video area. Therefore, the canvas solution is used and recorded here.

Conventional normal operation

The traditional EPG page will reserve a video playback window when generating the background image. In short, it is to make a partially transparent PNG image as the base image, similar to the following:

Disadvantages: fixed layout, too rigid, limiting the video playback area.

Because the EPG page developed by me is not fixed typesetting and is intelligently arranged for the background management system, the EPG page is completely flexible and configurable. Any place may be a video playback area, and the traditional solution can not meet this demand.

Solution

Set an img tag, introduce the background image, turn the image into canvas for local transparency (matting) when calling video playback, and restore the background image after video playback.

Note: css code is ignored

	<img id="imgurl" src="xxx.jpg" /> 
	<script>
		var bg = document.getElementById("imgurl");
		// When calling video playback, start matting
		bg2canvas(bg, 30, 40, 200, 160);
		function bg2canvas(bg, left, top, width, height){
			var canvas = document.createElement("canvas");
			canvas.width = 1280;
    		canvas.height = 720;
    		var content = canvas.getContext("2d");
    		content.drawImage(bg, 0, 0);
    		var imgData = content.getImageData(left, top, width, height);
    		for (var i = 0, len = imgData.data.length; i < len; i += 4) {
	      		// Change the transparency of each pixel
      			imgData.data[i + 3] = 0;
	    	}
	    	content.putImageData(imgData, left, top);
	    	bg.src = canvas.toDataURL();
	    	bg.onload = undefined;
    	}
    	// When the video playback ends
    	bg.src = "xxx.jpg";
	</script>
Disadvantages: some set-top boxes with poor performance are extremely slow in the implementation process. The investigation found that they are implementing transparent loops and canvas The todataurl() process took too long
Optimizing bg2canvas() method 1

Query the canvas document and find that the canvas becomes transparent. You can call the clearRect() API

	function bg2canvas(bg, left, top, width, height){
		var canvas = document.createElement("canvas");
		canvas.width = 1280;
    	canvas.height = 720;
    	var content = canvas.getContext("2d");
    	content.drawImage(bg, 0, 0);
    	// delete
    	/* var imgData = content.getImageData(left, top, width, height);
    	for (var i = 0, len = imgData.data.length; i < len; i += 4) {
	      		// Change the transparency of each pixel
      			imgData.data[i + 3] = 0;
	    	}
	    content.putImageData(imgData, left, top); */
	    
	    content.clearRect(left, top, width, height); /* newly added */ 
	    bg.src = canvas.toDataURL();
	    bg.onload = undefined;
    }
Disadvantages: it does save some performance problems, but canvas The todataurl () method still takes too long.
Optimizing bg2canvas() method 2

Since the last step is to turn to pictures, which consume performance, just don't turn to pictures, and directly render the graphics in the form of canvas when the page is loaded.

	<canvas id="canvas"></canvas>
	<script>
	// Rendering canvas graphics
	var oimg = new Image();
  	oimg.src = "../pic/d/7b9ded875fac44208b8f9e5e90c8a21d.JPG";
	var cvs = document.querySelector("#canvas");
	var context = cvs.getContext("2d");
  	oimg.onload = function () {
    	cvs.width = 1280;
    	cvs.height = 720;
    	context.drawImage(this, 0, 0, 1280, 720);
  	};
  	
  	// When the video is playing, matting
  	context.clearRect(30, 40, 200, 160);
	</script>
Improved performance, perfect

Topics: Javascript Front-end html5 canvas