javascript - HTML Canvas 和内存使用

标签 javascript html cordova canvas cropperjs

我正在使用 Canvas 和 Cordova 为移动设备制作一个非常基本的图像编辑器。 不幸的是,当涉及 Canvas 时,JavaScript 会占用大量内存,这会导致所有内容在移动设备上彻底崩溃。

我正在使用cropperjs来处理裁剪。 (如果您有更好的,请告诉我)。 Cropper 只允许使用 Base 64 数据 URL 检索图像,这似乎会浪费大量内存。 裁剪图像后,我需要重新显示它以再次裁剪。 一个好处是图像根据裁剪方式变成黑白。该部分工作得很好,但可能会再次使内存大小加倍,因为它最终使用从 Canvas 中提取的 dataURL。

页面上的按钮调用此函数。这似乎就是麻烦开始的地方。

var originalImage = document.createElement('img');
var cropper;
    function finish() {            
        var data=cropper.getCroppedCanvas().toDataURL();
        originalImage.onload = function () {
            cropper.replace(originalImage, false);
            cropper.clear();
            originalImage.onload=undefined;
        };
        originalImage.src=data;

    }

我猜测最终的问题是 dataURL 太大了,即使不在 DOM 中也会消耗内存。这段代码会导致 chrome 和 firefox 为 600kb 的照片增加大约 700mb 的 RAM 使用量。 有没有更好的方法将修改后的图像存储在内存中?更小的东西?或者,有没有办法创建一个新的临时文件并加载它?或者我完全走错了路?

-Blindman67 答案的编辑

const originalImage = document.createElement('canvas');
originalImage.ctx = originalImage.getContext("2d");
var cropper; //cropper is created and destroyed on image load, so I can't use const?
function finish() {                
    const cropped = cropper.getCroppedCanvas();
    originalImage.width = cropped.width;
    originalImage.height = cropped.height;
    originalImage.ctx.drawImage(cropped,0,0);
    cropper.clear();
    cropper.replace(originalImage , false); //errors, TypeError: t.match is not a function, cropper.min.js (line 11, col 4244)
}

从文件上传加载图像的代码

    $('#file').on('change', function (ev) {            
        var f = ev.target.files[0];
        var fr = new FileReader();

        fr.onload = function (ev2) {
            console.dir(ev2);
            if (cropper !== undefined) {
                cropper.destroy();
            }

            //Probably something wrong with this part
            $('#img').on("load",function(){
                originalImage.width = this.width;
                originalImage.height = this.height;
                originalImage.ctx.drawImage(document.getElementById("img"),0,0);
            }).attr('src', ev2.target.result);
            //^^^^^

            //obvious I've been at this awhile, efficiency went down the tubes \/
            var image = document.getElementById("img");
            var options = {
                viewMode: 0,
                dragMode: 'crop',
                responsive: true,
                autoCrop: false,
                movable: false,
                scalable: false,
                zoomable: false,
                zoomOnTouch: false,
                zoomOnWheel: false,
                ready: cropReady
            };
            cropper = new Cropper(image, options);
        };

        fr.readAsDataURL(f);
    });

页面本身基本上是

<div >
    <img id="img" style="max-width: 100%; max-height: 100%"/>
</div>

-编辑 看起来使用 Canvas 代替 imgs 效果很好。

html:

<div class="span-filler">
    <img id="img" style="max-width: 100%; max-height: 650px"/>
    <canvas id="originalImg" style="display:none;max-width: 100%;max-height: 100%;">Please use Chrome or Firefox
    </canvas>
</div>

脚本

var cropper;
var gBrightness = 0;
var orgImg = document.getElementById("originalImg");
function finish() {
    cropper.replace(orgImg, true); //doesn't need to data URL oddly
    var data = cropper.getCroppedCanvas();
    orgImg.width = data.width;
    orgImg.height = data.height;
    orgImg.getContext("2d").drawImage(data, 0, 0);
    cropper.replace(orgImg.toDataURL("Image/jpeg"), false); //does need it
    cropper.clear();
}
$('#file').on('change', function (ev) {
    var f = ev.target.files[0];
    var fr = new FileReader();

    fr.onload = function (ev2) {
        console.dir(ev2);
        if (cropper !== undefined) {
            cropper.destroy();
        }
        $('#img').attr('src', ev2.target.result);
        var image = document.getElementById("img");
        var options = {
            viewMode: 0,
            dragMode: 'crop',
            responsive: true,
            autoCrop: false,
            movable: false,
            scalable: false,
            zoomable: false,
            zoomOnTouch: false,
            zoomOnWheel: false,
            ready: cropReady
        };
        cropper = new Cropper(image, options);
    };

    fr.readAsDataURL(f);
});
function cropReady() {

    var data = cropper.getCroppedCanvas();
    orgImg.width = data.width;
    orgImg.height = data.height;
    orgImg.getContext("2d").drawImage(data, 0, 0);

    processImage(); //converts to black and white using web workers
}

//still looking for efficiencies here
function processImage(brightness) {
    var canvas = document.createElement('canvas');

    var ctx = canvas.getContext("2d");
    canvas.width = orgImg.width;
    canvas.height = orgImg.height;

    var imgPixels;
    var imgPixelsSrc = orgImg.getContext("2d").getImageData(0, 0, orgImg.width, orgImg.height);


    var myWorker = new Worker('js/image_editor/imageWorker.js');

    myWorker.onmessage = function (e) {
        imgPixels = e.data[0];
        gBrightness = e.data[2];

        ctx.putImageData(imgPixels, 0, 0);
        cropper.replace(canvas.toDataURL("image/jpeg"), true);
    };
    if (brightness === undefined) {
        myWorker.postMessage([imgPixelsSrc, true]);
    } else {
        myWorker.postMessage([imgPixelsSrc, false, brightness]);
    }
}

最佳答案

Canvas 可以用作图像,是一个 HTML 图像元素。无需仅仅为了显示结果就从 Canvas 转换为图像。

const originalImage = document.createElement('canvas');
originalImage.ctx = originalImage.getContext("2d");
const cropper;
function finish() {            
    // check documentation to ensure cropper
    // is not creating a copy but rather
    // is returning just a reference
    const cropped = cropper.getCroppedCanvas();        
    originalImage.width = cropped.width;
    originalImage.height = cropped.height;
    originalImage.ctx.drawImage(cropped,0,0);
    cropper.clear();
}

关于javascript - HTML Canvas 和内存使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44699756/

相关文章:

javascript - 阻止移动网络代理注入(inject) JavaScript

javascript - 在 for 循环中修改对象(异步/等待)

javascript - jQuery UI 对话框问题

ios - 如何在面向公众的网站上使用 oauth 保护 iOS 企业分发?

javascript - 如何使用 hasOwnProperty 检查属性?

javascript - iframe 内容并不总是加载

android - 来自 Cordova 插件的未捕获异常

javascript - Windows Phone 8 Cordova HTML5 App 上的触摸会忽略具有较高 z-index 的图层

php - 如何使用 php 更新 SQLite 表中的数据?

javascript - 在回发期间维护多个 div 的切换状态