আমি কয়েক বছর আগে এই সমস্যাটি মোকাবিলা করেছি এবং গিথুবটিতে আমার সমাধানটি https://github.com/rossturner/HTML5- আইমেজ আপলোডার হিসাবে আপলোড করেছি
রবার্টকের উত্তরটি মজিলা হ্যাকস ব্লগ পোস্টে প্রস্তাবিত সমাধানটি ব্যবহার করে , তবে আমি দেখতে পেলাম যে এটি 2: 1 নয় (বা এর একাধিক) স্কেলের আকার পরিবর্তন করার সময় এটি সত্যই দুর্বল চিত্রের মান দিয়েছে। আমি বিভিন্ন চিত্রের আকার পরিবর্তনকারী অ্যালগরিদমগুলির সাথে পরীক্ষা শুরু করেছিলাম, যদিও বেশিরভাগ শেষ ধীর হয়ে গেছে অন্যথায় মানের দিক থেকেও দুর্দান্ত ছিল না।
অবশেষে আমি এমন একটি সমাধান নিয়ে এসেছি যা আমি বিশ্বাস করি যে দ্রুত সম্পাদন করে এবং এতে খুব ভাল পারফরম্যান্সও রয়েছে - এক্স টার্গেটের ভিত্তিতে 2: 1 অনুপাতের ভিত্তিতে 1 ক্যানভাস থেকে অন্য কাজ করে অনুলিপি করার জন্য মজিলা সমাধানটি দ্রুত কাজ করে এবং চিত্রের মানের ক্ষতি না করে কাজ করে works পিক্সেল প্রশস্ত এবং 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
আসল দিক অনুপাতটি বজায় রেখে একটি চিত্রকে প্রশস্ত আকারে স্কেল করে । উন্নয়নের সময় এটি আইপ্যাড / আইফোন সাফারিতে প্রধান ডেস্কটপ ব্রাউজারগুলি (আই 9 +, ফায়ারফক্স, ক্রোম) ছাড়াও কাজ করেছিল তাই আমি আশা করি এটি আজও এইচটিএমএল 5 এর বিস্তৃত গ্রহণের কারণে সামঞ্জস্যপূর্ণ হবে। নোট করুন যে ক্যানভাস.টো.ডাটাআরএল () কলটি মাইম টাইপ এবং চিত্রের গুণমান নিয়েছে যা আপনাকে গুণমান এবং আউটপুট ফাইল ফর্ম্যাটটিকে নিয়ন্ত্রণ করতে দেয় (আপনি যদি চান তবে ইনপুট থেকে আলাদা)।
এটি কেবলমাত্র বিন্দুতে আবশ্যক নয় ওরিয়েন্টেশন সম্পর্কিত তথ্য বজায় রাখে, এই মেটাডাটা সম্পর্কে জ্ঞান ছাড়াই চিত্রটিকে পুনরায় আকার দেওয়া হয় এবং সে হিসাবে সংরক্ষণ করা হয়, ওরিয়েন্টেশনের জন্য চিত্রের মধ্যে কোনও মেটাডেটা হারাতে হবে যার অর্থ ট্যাবলেট ডিভাইসে নেওয়া চিত্রগুলি "উল্টোদিকে" ছিল এগুলি হিসাবে উপস্থাপন করা হয়েছে, যদিও সেগুলি ডিভাইসের ক্যামেরা ভিউফাইন্ডারে উল্টানো হত। যদি এটি উদ্বেগজনক হয় তবে এই ব্লগ পোস্টটিতে কীভাবে এটি সম্পাদন করতে হবে তার একটি ভাল গাইড এবং কোড উদাহরণ রয়েছে, যা আমি নিশ্চিত যে উপরের কোডটিতে একীভূত হতে পারে।