我正在使用canvas和cordova为移动设备创建一个非常基本的图像编辑器。 不幸的是,当涉及画布时,javascript是内存的猪,这会导致一切都在移动设备上彻底崩溃。
我正在使用cropperjs来处理裁剪。 (如果你有更好的,请告诉我)。 Cropper仅允许使用base 64数据URL检索图像,这些URL似乎是巨大的内存浪费。 裁剪完图像后,我需要重新显示它以便再次裁剪。 奖励是图像根据裁剪方式变为黑白。这部分工作得非常好,但是再次将内存大小加倍,因为它最终使用从画布中提取的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使用量。 有没有更好的方法将修改后的图像存储在内存中?更小的东西?或者,有没有办法制作一个新的临时文件并加载?或者我完全走错了轨道?
-Bindind67的答案
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>
- 编辑 看起来使用画布代替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]);
}
}
答案 0 :(得分:1)
画布可以用作图像,是HTML图像元素。无需从画布转换为图像只是为了显示结果。
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();
}
答案 1 :(得分:1)
var img = new Image();
//img.crossOrigin = "Anonymous";
img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
img.onload = function() {
draw(this);
};
function draw(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');
window['zoomctx'] = document.getElementById('zoom').getContext('2d');
var smoothbtn = document.getElementById('smoothbtn');
var toggleSmoothing = function(event) {
zoomctx.imageSmoothingEnabled = this.checked;
zoomctx.mozImageSmoothingEnabled = this.checked;
zoomctx.webkitImageSmoothingEnabled = this.checked;
zoomctx.msImageSmoothingEnabled = this.checked;
};
smoothbtn.addEventListener('change', toggleSmoothing);
var zoom = function(event) {
var x = event.layerX;
var y = event.layerY;
zoomctx.drawImage(canvas,
Math.abs(x - 100),
Math.abs(y - 100),
200, 200,
0, 0,
200, 200);
};
canvas.addEventListener('mousemove', zoom);
function CROP_IT (e){
//this line will collect all data from canvas
window["IMAGE_CROPED"] = zoomCanvas.toDataURL();
localStorage.setItem( "savedImageData", zoomCanvas.toDataURL("image/png") );
alert(IMAGE_CROPED)
}
canvas.addEventListener('click', CROP_IT , false);
}
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas -->
<canvas id="canvas" width="300" height="227"></canvas>
<canvas id="zoom" width="300" height="227"></canvas>
<div>
<label for="smoothbtn">
<input type="checkbox" name="smoothbtn" checked="false" id="smoothbtn">
Enable image smoothing
</label>