Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript HTML画布和内存使用_Javascript_Html_Cordova_Canvas_Cropperjs - Fatal编程技术网

Javascript HTML画布和内存使用

Javascript HTML画布和内存使用,javascript,html,cordova,canvas,cropperjs,Javascript,Html,Cordova,Canvas,Cropperjs,我正在使用canvas和cordova为手机制作一个非常基本的图像编辑器。 不幸的是,当涉及到画布时,javascript是内存的猪,这会导致移动设备上的一切彻底崩溃 我正在使用cropperjs处理裁剪。(如果你有更好的,请告诉我)。Cropper只允许使用基本64数据URL检索图像,这似乎是巨大的内存浪费。 一旦图像被裁剪,我需要重新显示它以便再次裁剪。 另一个好处是,根据图像的裁剪方式,图像将变成黑白。这一部分工作得很好,但内存大小可能又增加了一倍,因为它最终使用的是从画布中提取的数据UR

我正在使用canvas和cordova为手机制作一个非常基本的图像编辑器。 不幸的是,当涉及到画布时,javascript是内存的猪,这会导致移动设备上的一切彻底崩溃

我正在使用cropperjs处理裁剪。(如果你有更好的,请告诉我)。Cropper只允许使用基本64数据URL检索图像,这似乎是巨大的内存浪费。 一旦图像被裁剪,我需要重新显示它以便再次裁剪。 另一个好处是,根据图像的裁剪方式,图像将变成黑白。这一部分工作得很好,但内存大小可能又增加了一倍,因为它最终使用的是从画布中提取的数据URL

页面上的按钮调用此函数。问题似乎就从这里开始

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的内存。 有没有更好的方法将修改后的图像存储在内存中?要小一点的吗?或者,有没有办法创建一个新的临时文件并加载它?还是我完全走错了方向

-为盲人67的答案编辑

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>

画布可以用作图像,是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 img=newimage();
//img.crossOrigin=“匿名”;
img.src=https://mdn.mozillademos.org/files/5397/rhino.jpg';
img.onload=函数(){
画(这个);
};
功能图(img){
var canvas=document.getElementById('canvas');
var ctx=canvas.getContext('2d');
ctx.drawImage(img,0,0);
img.style.display='none';
window['zoomCanvas']=document.getElementById('zoom');
窗口['zoomctx']=document.getElementById('zoom').getContext('2d');
var smoothbtn=document.getElementById('smoothbtn');
变量切换平滑=函数(事件){
zoomctx.imageSmoothingEnabled=已选中此项;
zoomctx.mozImageSmoothingEnabled=this.checked;
zoomctx.webkitImageSmoothingEnabled=this.checked;
zoomctx.msImageSmoothingEnabled=已选中此项;
};
smoothbtn.addEventListener('change',toggleSmoothing);
var zoom=函数(事件){
var x=事件.layerX;
var y=event.layerY;
zoomctx.drawImage(画布,
数学abs(x-100),
数学abs(y-100),
200, 200,
0, 0,
200, 200);
};
canvas.addEventListener('mousemove',zoom);
功能裁剪_IT(e){
//此行将从画布收集所有数据
window[“IMAGE_CROPED”]=zoomCanvas.toDataURL();
setItem(“savedImageData”,zoomCanvas.toDataURL(“image/png”);
警报(图像交叉)
} 
canvas.addEventListener('click',CROP_IT,false);
}

  
启用图像平滑

此行没有意义:originalImage.onload=未定义;另外:crapper.replace。如果可能,请发布代码段!使用简单画布裁剪图像的一部分。你可以收集图像数据看看:当我搜索“简单画布”时,我没有发现任何明显的东西。我目前正在使用这个,但如果有更好的,我愿意换成另一个<代码>裁剪器.替换(原始图像,错误)将htmlimage作为第一个参数,将update Color或full作为第二个参数,true仅用于颜色,false用于重新加载。由于理论上图像大小已经改变,因此需要重新加载。进行这些编辑需要花费一些时间,但是,
crapper.replace(originalImage,true)
throws
TypeError:t.match不是crapper.min.js中的函数
。这并不是因为这两个对象都可以传递到
drawImage
,它们是相同的……如果我将dataurl存储在sessionStorage中,并且只将其提供给内存中的图像变量,时间刚好足以加载裁剪器,然后将其清除。那会有帮助吗?还是本地存储?或者两者都会导致同样的问题?@TrevorD你没有空间,在手机上存储空间非常小。我不明白问题是什么。你说crapper.replace抛出了一个错误,为什么要使用它呢。将裁剪后的图像作为画布,只需销毁裁剪器对象并显示画布即可。如果您希望客户端重新启动,则只需重新启动。@TrevorD在文档(github上的readme.md)中指出,裁剪器可以从画布创建“用块元素(容器)包装图像或画布元素”,而且API是松散的,并公开了它使用的画布,因此您可以直接更改它,而不是通过它的接口。当你对一个库有问题时,你应该在阅读完文档后查看代码。虽然这不完全是我需要的,因为这个页面基本上是用来拍摄文档的,所以它需要一个精确的裁剪。它仍然很有趣,可能在其他方面对我有所帮助。所以谢谢:)
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]);
    }
}
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();
}