العمل مع الصور باستخدام TypeScript: تغيير الحجم (resize) والقص (crop)
في تطوير الويب الحديث، تعد معالجة الصور من جانب العميل مهمة شائعة. TypeScript، بفضل الكتابة الصارمة والتكامل مع واجهات برمجة التطبيقات الحديثة للمتصفح، يسمح بإجراء عمليات resize (تغيير الحجم) و crop (القص) بأمان وكفاءة. في هذه المقالة، سنناقش طريقتين: استخدام Canvas API الأصلي والعمل مع مكتبات الخادم sharp و jimp لـ Node.js.
1. Canvas API: معالجة من جانب العميل بدون تبعيات
يعتبر HTMLCanvasElement في المتصفح أسهل طريقة للتعامل مع الصور. لا يتطلب تثبيت حزم إضافية ويعمل في أي متصفح حديث.
1.1. تغيير الحجم (resize) عبر Canvas
الفكرة الأساسية هي رسم الصورة الأصلية على canvas بأبعاد جديدة، ثم تصدير النتيجة.
function resizeImage( source: HTMLImageElement, targetWidth: number, targetHeight: number): Promise<Blob> { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas'); canvas.width = targetWidth; canvas.height = targetHeight; const ctx = canvas.getContext('2d'); if (!ctx) { reject(new Error('Canvas context not supported')); return; } // رسم الصورة بالأبعاد الجديدة ctx.drawImage(source, 0, 0, targetWidth, targetHeight); // التصدير إلى Blob (التنسيق الافتراضي هو PNG) canvas.toBlob((blob) => { if (blob) resolve(blob); else reject(new Error('Failed to create blob')); }, 'image/jpeg', 0.9); // يمكن تحديد التنسيق والجودة });}هام: عند تكبير الصورة (upscale)، قد تتدهور الجودة - يستخدم canvas الاستيفاء الثنائي الخطي. هذا مقبول للمعاينات، لكنه غير مناسب للطباعة.
1.2. القص (crop) بالإحداثيات
يتطلب القص تحديد منطقة مستطيلة من الصورة الأصلية.
function cropImage( source: HTMLImageElement, x: number, y: number, width: number, height: number): Promise<Blob> { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); if (!ctx) { reject(new Error('Canvas not supported')); return; } // قص جزء من الصورة الأصلية ctx.drawImage(source, x, y, width, height, 0, 0, width, height); canvas.toBlob((blob) => { if (blob) resolve(blob); else reject(new Error('Blob creation failed')); }, 'image/png'); });}نصيحة: تأكد دائمًا من أن الإحداثيات x, y, width, height لا تتجاوز حدود الصورة الأصلية، وإلا سيعيد canvas مناطق فارغة.
2. المعالجة من جانب الخادم: sharp و jimp
إذا كنت تعمل في بيئة Node.js و TypeScript، فإن مكتبات sharp (C++ native، أداء عالي) و jimp (JS خالص، عبر المنصات) هي الحلول القياسية.
2.1. التثبيت والاستيراد
// التثبيت// npm install sharp// npm install jimp
import sharp from 'sharp';import Jimp from 'jimp';2.2. تغيير الحجم (resize) باستخدام sharp
async function resizeWithSharp( inputPath: string, outputPath: string, width: number, height: number): Promise<void> { await sharp(inputPath) .resize(width, height, { fit: 'cover', // 'cover' - يقص الزائد، 'contain' - يضمن الاحتواء position: 'center' // نقطة المرجع عند القص }) .toFile(outputPath);}تحدد المعلمة fit استراتيجية الاحتواء:
cover—