العمل مع الصور في Rust: تغيير الحجم والقص باستخدام مكتبة image

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

العمل مع الصور في Rust: تغيير الحجم والقص باستخدام مكتبة image

\n\n

Rust هي لغة برمجة نظامية حديثة تكتسب شعبية في المهام التي تتطلب أداءً عاليًا وأمانًا. إحدى هذه المهام هي معالجة الصور. في هذه المقالة، سنستعرض بالتفصيل كيفية تغيير حجم (resize) وقص (crop) الصور في Rust باستخدام مكتبة image القوية وسهلة الاستخدام. ستتعلم كيفية تثبيت المكتبة، تحميل الصورة، تطبيق التحويلات، وحفظ النتيجة.

\n\n

تثبيت وتضمين مكتبة image

\n\n

مكتبة image هي المعيار الفعلي للعمل مع الصور النقطية في نظام Rust البيئي. وهي تدعم العديد من التنسيقات (PNG، JPEG، GIF، BMP، WEBP وغيرها) وتوفر مجموعة واسعة من الوظائف للمعالجة.

\n\n

للبدء، أضف التبعية إلى ملف Cargo.toml:

\n\n
[dependencies]\nimage = "0.25"
\n\n

بعد ذلك، يمكنك استيراد الوحدات الضرورية في الكود:

\n\n
use std::path::Path;\nuse image::{open, DynamicImage, GenericImageView, imageops::FilterType};
\n\n

تحميل وحفظ الصور

\n\n

الخطوة الأولى هي تحميل الصورة من ملف. ستقوم المكتبة تلقائيًا بتحديد التنسيق بناءً على الامتداد. لنلق نظرة على مثال أساسي:

\n\n
fn 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) - العرض والارتفاع.

\n\n

تغيير الحجم (resize)

\n\n

تأخذ دالة resize() عرضًا وارتفاعًا جديدين ونوع المرشح. يؤثر المرشح على جودة النتيجة وسرعة التنفيذ. فيما يلي المرشحات الرئيسية:

\n\n
    \n
  • Nearest - سريع ولكن بجودة منخفضة (تقطيع البكسل).
  • \n
  • Lanczos3 - جودة عالية ولكنه أبطأ.
  • \n
  • CatmullRom - توازن جيد بين السرعة والجودة.
  • \n
  • Gaussian - يعمل على تمويه الصورة عند التصغير.
  • \n
\n\n

مثال لتغيير الحجم إلى 800x600 بكسل:

\n\n
use 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() (يُدرج ضمن الأبعاد المحددة مع إضافة هوامش فارغة). مثال:

\n\n
// إدراج ضمن مستطيل 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).

\n\n

مثال لقص الجزء المركزي بحجم 300x200:

\n\n
fn crop_example() -> Result<(), Box<dyn std::error::Error>> {\n    let img = open("input.jpg")?;\n    let (width, height) = img.dimensions()                    

توصيات