मैंने कुछ साल पहले इस समस्या से निपटा और मेरे समाधान को https://github.com/rossturner/HTML5-ImageUploader के रूप में अपलोड किया
robertc का जवाब मोज़िला हैक्स ब्लॉग पोस्ट में प्रस्तावित समाधान का उपयोग करता है , हालांकि मैंने पाया कि यह वास्तव में खराब छवि गुणवत्ता का था जब 2: 1 (या एक से अधिक) का आकार नहीं था। मैंने एल्गोरिदम का आकार बदलने वाली अलग-अलग छवि के साथ प्रयोग करना शुरू कर दिया, हालांकि अधिकांश का अंत काफी धीमा था या फिर गुणवत्ता में महान नहीं थे।
अंत में मैं एक समाधान के साथ आया था जो मुझे विश्वास है कि जल्दी से निष्पादित होता है और इसमें बहुत अच्छा प्रदर्शन भी है - जैसा कि 1 कैनवस से दूसरे कैनवास पर कॉपी करने का मोज़िला समाधान 2: 1 के अनुपात में छवि गुणवत्ता के नुकसान के बिना जल्दी से काम करता है, जिसे x का लक्ष्य दिया गया है। पिक्सेल चौड़े और y पिक्सेल लम्बे होते हैं, मैं इस कैनवास को आकार देने की विधि का उपयोग करता हूँ जब तक कि चित्र x और 2 x और y और 2 y के बीच न हो । इस बिंदु पर मैं फिर लक्ष्य आकार के आकार के अंतिम "चरण" के लिए एल्गोरिथम छवि का आकार बदल देता हूं। कई अलग-अलग एल्गोरिदम की कोशिश करने के बाद, मैं एक ब्लॉग से लिया गया बिलिनियर इंटरपोलेशन पर बस गया, जो अब ऑनलाइन नहीं है, लेकिन इंटरनेट आर्काइव के माध्यम से सुलभ है, जो अच्छे परिणाम देता है, यहां लागू कोड है:
ImageUploader.prototype.scaleImage = function(img, completionCallback) {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
while (canvas.width >= (2 * this.config.maxWidth)) {
canvas = this.getHalfScaleCanvas(canvas);
}
if (canvas.width > this.config.maxWidth) {
canvas = this.scaleCanvasWithAlgorithm(canvas);
}
var imageData = canvas.toDataURL('image/jpeg', this.config.quality);
this.performUpload(imageData, completionCallback);
};
ImageUploader.prototype.scaleCanvasWithAlgorithm = function(canvas) {
var scaledCanvas = document.createElement('canvas');
var scale = this.config.maxWidth / canvas.width;
scaledCanvas.width = canvas.width * scale;
scaledCanvas.height = canvas.height * scale;
var srcImgData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
var destImgData = scaledCanvas.getContext('2d').createImageData(scaledCanvas.width, scaledCanvas.height);
this.applyBilinearInterpolation(srcImgData, destImgData, scale);
scaledCanvas.getContext('2d').putImageData(destImgData, 0, 0);
return scaledCanvas;
};
ImageUploader.prototype.getHalfScaleCanvas = function(canvas) {
var halfCanvas = document.createElement('canvas');
halfCanvas.width = canvas.width / 2;
halfCanvas.height = canvas.height / 2;
halfCanvas.getContext('2d').drawImage(canvas, 0, 0, halfCanvas.width, halfCanvas.height);
return halfCanvas;
};
ImageUploader.prototype.applyBilinearInterpolation = function(srcCanvasData, destCanvasData, scale) {
function inner(f00, f10, f01, f11, x, y) {
var un_x = 1.0 - x;
var un_y = 1.0 - y;
return (f00 * un_x * un_y + f10 * x * un_y + f01 * un_x * y + f11 * x * y);
}
var i, j;
var iyv, iy0, iy1, ixv, ix0, ix1;
var idxD, idxS00, idxS10, idxS01, idxS11;
var dx, dy;
var r, g, b, a;
for (i = 0; i < destCanvasData.height; ++i) {
iyv = i / scale;
iy0 = Math.floor(iyv);
// Math.ceil can go over bounds
iy1 = (Math.ceil(iyv) > (srcCanvasData.height - 1) ? (srcCanvasData.height - 1) : Math.ceil(iyv));
for (j = 0; j < destCanvasData.width; ++j) {
ixv = j / scale;
ix0 = Math.floor(ixv);
// Math.ceil can go over bounds
ix1 = (Math.ceil(ixv) > (srcCanvasData.width - 1) ? (srcCanvasData.width - 1) : Math.ceil(ixv));
idxD = (j + destCanvasData.width * i) * 4;
// matrix to vector indices
idxS00 = (ix0 + srcCanvasData.width * iy0) * 4;
idxS10 = (ix1 + srcCanvasData.width * iy0) * 4;
idxS01 = (ix0 + srcCanvasData.width * iy1) * 4;
idxS11 = (ix1 + srcCanvasData.width * iy1) * 4;
// overall coordinates to unit square
dx = ixv - ix0;
dy = iyv - iy0;
// I let the r, g, b, a on purpose for debugging
r = inner(srcCanvasData.data[idxS00], srcCanvasData.data[idxS10], srcCanvasData.data[idxS01], srcCanvasData.data[idxS11], dx, dy);
destCanvasData.data[idxD] = r;
g = inner(srcCanvasData.data[idxS00 + 1], srcCanvasData.data[idxS10 + 1], srcCanvasData.data[idxS01 + 1], srcCanvasData.data[idxS11 + 1], dx, dy);
destCanvasData.data[idxD + 1] = g;
b = inner(srcCanvasData.data[idxS00 + 2], srcCanvasData.data[idxS10 + 2], srcCanvasData.data[idxS01 + 2], srcCanvasData.data[idxS11 + 2], dx, dy);
destCanvasData.data[idxD + 2] = b;
a = inner(srcCanvasData.data[idxS00 + 3], srcCanvasData.data[idxS10 + 3], srcCanvasData.data[idxS01 + 3], srcCanvasData.data[idxS11 + 3], dx, dy);
destCanvasData.data[idxD + 3] = a;
}
}
};
यह config.maxWidth
मूल पहलू अनुपात को बनाए रखते हुए, एक चित्र को नीचे की चौड़ाई तक फैलाता है। विकास के समय इसने प्रमुख डेस्कटॉप ब्राउज़र (IE9 +, फ़ायरफ़ॉक्स, क्रोम) के अलावा iPad / iPhone Safari पर काम किया था, इसलिए मुझे उम्मीद है कि यह आज भी HTML5 के व्यापक स्तर को देखते हुए संगत होगा। ध्यान दें कि कैनवस .toDataURL () कॉल एक माइम प्रकार और छवि गुणवत्ता लेता है जो आपको गुणवत्ता और आउटपुट फ़ाइल प्रारूप को नियंत्रित करने की अनुमति देगा (यदि आप चाहें तो इनपुट से भिन्न)।
एकमात्र बिंदु जो इसे कवर नहीं करता है, वह ओरिएंटेशन की जानकारी को बनाए रखता है, इस मेटाडेटा के ज्ञान के बिना छवि को आकार दिया जाता है और इसे बचाया जाता है, जो कि अभिविन्यास के लिए छवि के भीतर किसी भी मेटाडेटा को खो देता है, जिसका अर्थ है कि टैबलेट डिवाइस "उल्टा" पर ली गई छवियां थीं। इस तरह प्रस्तुत किया गया है, हालांकि वे डिवाइस के कैमरे के दृश्यदर्शी में फ़्लिप हो गए होंगे। यदि यह एक चिंता का विषय है, तो इस ब्लॉग पोस्ट में इसे पूरा करने के तरीके के बारे में एक अच्छा मार्गदर्शक और कोड उदाहरण हैं, जो मुझे यकीन है कि उपरोक्त कोड को एकीकृत किया जा सकता है।