العمل مع الصور في Rust: تغيير الحجم والقص باستخدام مكتبة image
\n\nRust هي لغة برمجة نظامية حديثة تكتسب شعبية في المهام التي تتطلب أداءً عاليًا وأمانًا. إحدى هذه المهام هي معالجة الصور. في هذه المقالة، سنستعرض بالتفصيل كيفية تغيير حجم (resize) وقص (crop) الصور في Rust باستخدام مكتبة image القوية وسهلة الاستخدام. ستتعلم كيفية تثبيت المكتبة، تحميل الصورة، تطبيق التحويلات، وحفظ النتيجة.
تثبيت وتضمين مكتبة image
\n\nمكتبة image هي المعيار الفعلي للعمل مع الصور النقطية في نظام Rust البيئي. وهي تدعم العديد من التنسيقات (PNG، JPEG، GIF، BMP، WEBP وغيرها) وتوفر مجموعة واسعة من الوظائف للمعالجة.
للبدء، أضف التبعية إلى ملف Cargo.toml:
[dependencies]\nimage = "0.25"\n\nبعد ذلك، يمكنك استيراد الوحدات الضرورية في الكود:
\n\nuse std::path::Path;\nuse image::{open, DynamicImage, GenericImageView, imageops::FilterType};\n\nتحميل وحفظ الصور
\n\nالخطوة الأولى هي تحميل الصورة من ملف. ستقوم المكتبة تلقائيًا بتحديد التنسيق بناءً على الامتداد. لنلق نظرة على مثال أساسي:
\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n // تحميل الصورة\n let img = open("input.jpg")?;\n println!("الحجم: {:?}", img.dimensions());\n // حفظ بتنسيق آخر\n img.save("output.png")?;\n Ok(())\n}\n\nتقوم طريقة open() بإرجاع DynamicImage - وهو تعداد يمكنه تخزين الصورة بأحد التنسيقات الداخلية المتعددة (RGB8، RGBA8، Gray8، إلخ). طريقة dimensions() تُرجع زوجًا (u32, u32) - العرض والارتفاع.
تغيير الحجم (resize)
\n\nتأخذ دالة resize() عرضًا وارتفاعًا جديدين ونوع المرشح. يؤثر المرشح على جودة النتيجة وسرعة التنفيذ. فيما يلي المرشحات الرئيسية:
- \n
- Nearest - سريع ولكن بجودة منخفضة (تقطيع البكسل). \n
- Lanczos3 - جودة عالية ولكنه أبطأ. \n
- CatmullRom - توازن جيد بين السرعة والجودة. \n
- Gaussian - يعمل على تمويه الصورة عند التصغير. \n
مثال لتغيير الحجم إلى 800x600 بكسل:
\n\nuse image::imageops::FilterType;\n\nfn resize_example() -> Result<(), Box<dyn std::error::Error>> {\n let img = open("input.jpg")?;\n let resized = img.resize(800, 600, FilterType::Lanczos3);\n resized.save("resized.jpg")?;\n println!("الحجم الجديد: {:?}", resized.dimensions());\n Ok(())\n}\n\nإذا كنت بحاجة للحفاظ على النسب، استخدم resize_to_fill() (يملأ المنطقة بقص الزوائد) أو resize_to_fit() (يُدرج ضمن الأبعاد المحددة مع إضافة هوامش فارغة). مثال:
// إدراج ضمن مستطيل 400x400 مع الحفاظ على النسب\nlet fitted = img.resize_to_fit(400, 400, FilterType::CatmullRom);\nfitted.save("fitted.jpg")?;\n\n// ملء مستطيل 400x400 مع قص الحواف\nlet filled = img.resize_to_fill(400, 400, FilterType::Lanczos3);\nfilled.save("filled.jpg")?;\n\nقص الصورة (crop)
\n\nيتم القص باستخدام طريقة crop()، والتي تأخذ إحداثيات الزاوية العلوية اليسرى (x, y)، بالإضافة إلى عرض وارتفاع المنطقة. مهم: يجب ألا تتجاوز الإحداثيات والأبعاد حدود الصورة الأصلية، وإلا سيحدث خطأ (panic).
مثال لقص الجزء المركزي بحجم 300x200:
\n\nfn crop_example() -> Result<(), Box<dyn std::error::Error>> {\n let img = open("input.jpg")?;\n let (width, height) = img.dimensions()