File size: 4,748 Bytes
cca0cf3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | /**
* @fileoverview Image Compressor & Thumbnail Generator Engine
* @module utils/image-compressor
* @description محرك معالجة وضغط الصور وتوليد الصور المصغرة محلياً عبر Canvas لتحسين سرعة الإرسال وتقليل استهلاك الذاكرة.
*/
(global => {
'use strict';
/**
* كائن معالجة وضغط الصور
*/
const ImageCompressor = {
/**
* ضغط الصورة وتقليص أبعادها للحد الأقصى المسموح (1200px) مع الحفاظ على نسبة العرض للارتفاع
* @param {File|Blob} file - ملف الصورة المراد ضغطه
* @param {number} maxSize - أقصى بُعد مسموح به (افتراضياً 1200px)
* @param {number} quality - جودة ضغط الـ JPEG (من 0.1 إلى 1.0)
* @returns {Promise<Blob>} الـ Blob المضغوط
*/
compressImage: function(file, maxSize = 1200, quality = 0.85) {
return new Promise((resolve) => {
if (!(file instanceof Blob)) {
resolve(file);
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const canvas = document.createElement('canvas');
let width = img.width;
let height = img.height;
if (width > height) {
if (width > maxSize) {
height = Math.round(height * (maxSize / width));
width = maxSize;
}
} else {
if (height > maxSize) {
width = Math.round(width * (maxSize / height));
height = maxSize;
}
}
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.drawImage(img, 0, 0, width, height);
}
canvas.toBlob((blob) => {
resolve(blob || file);
}, 'image/jpeg', quality);
};
img.onerror = () => resolve(file);
};
reader.onerror = () => resolve(file);
});
},
/**
* @param {File|Blob} fileBlob
* @param {number} thumbSize
* @param {number} quality
* @returns {Promise<Blob>}
*/
generateThumbnail: function(fileBlob, thumbSize = 120, quality = 0.80) {
return new Promise((resolve) => {
if (!(fileBlob instanceof Blob)) {
resolve(fileBlob);
return;
}
const reader = new FileReader();
reader.readAsDataURL(fileBlob);
reader.onload = (event) => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = thumbSize;
canvas.height = thumbSize;
const ctx = canvas.getContext('2d');
if (ctx) {
const minDim = Math.min(img.width, img.height);
const sx = (img.width - minDim) / 2;
const sy = (img.height - minDim) / 2;
ctx.drawImage(img, sx, sy, minDim, minDim, 0, 0, thumbSize, thumbSize);
}
canvas.toBlob((blob) => {
resolve(blob || fileBlob);
}, 'image/jpeg', quality);
};
img.onerror = () => resolve(fileBlob);
};
reader.onerror = () => resolve(fileBlob);
});
}
};
global.FritreeImageCompressor = ImageCompressor;
})(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this); |