العمل مع الصور في Rust: نظرة عامة على المكتبات وأمثلة عملية
Rust هي لغة برمجة أنظمة حديثة تكتسب شعبية في المجالات التي تتطلب أداءً عاليًا وموثوقية. معالجة الصور ليست استثناءً: حيث يقدم نظام Rust البيئي العديد من المكتبات الناضجة لتحميل الصور ومعالجتها وتحويلها وتحليلها. في هذه المقالة، سنستعرض الأدوات الرئيسية: image، fast_image_resize و photon-rs، وسنقدم أمثلة كود للمهام النموذجية.
المكتبة الأساسية: image
crate image (الإصدار 0.25.x) هو المعيار الفعلي للعمل مع الصور في Rust. يدعم قراءة وكتابة العديد من التنسيقات: PNG، JPEG، BMP، GIF، TIFF، WebP وغيرها. توفر المكتبة هياكل بيانات مناسبة لتمثيل الصور (DynamicImage، RgbImage، GrayImage) ومجموعة واسعة من العمليات: تغيير الحجم، القص، التدوير، المرشحات، تحويل مساحات الألوان.
مثال على تحميل وحفظ صورة مع تغيير الحجم:
use image::{DynamicImage, GenericImageView, imageops::FilterType};
fn resize_image(input_path: &str, output_path: &str, new_width: u32, new_height: u32) { let img = image::open(input_path).expect("فشل فتح الصورة"); let resized = img.resize_exact(new_width, new_height, FilterType::Lanczos3); resized.save(output_path).expect("فشل حفظ الصورة"); println!("تم تغيير حجم الصورة وحفظها في {}", output_path);}
fn main() { resize_image("input.jpg", "output.png", 800, 600);}تدعم مكتبة image أيضًا العمل المباشر مع البكسلات. على سبيل المثال، يمكن الوصول إلى كل بكسل وتغيير لونه:
use image::{GenericImage, Rgba};
fn invert_colors(path: &str) { let mut img = image::open(path).expect("خطأ في الفتح"); for (x, y, pixel) in img.enumerate_pixels_mut() { let inverted = Rgba([ 255 - pixel[0], 255 - pixel[1], 255 - pixel[2], pixel[3], ]); img.put_pixel(x, y, inverted); } img.save("inverted.png").unwrap();}تغيير الحجم عالي الأداء: fast_image_resize
إذا كانت مهمتك هي تغيير حجم الصور بشكل متكرر بأقصى سرعة، فانظر إلى crate fast_image_resize. يستخدم تعليمات SIMD (SSE، AVX2، NEON) وخوارزميات محسّنة (Lanczos، Catmull-Rom، Mitchell). تعمل المكتبة مباشرة مع مصفوفات البكسلات الخام، مما يقلل من النفقات العامة.
مثال على استخدام fast_image_resize:
use fast_image_resize as fr;use image::GenericImageView;
fn resize_fast(input_path: &str, output_path: &str, new_width: u32, new_height: u32) { // تحميل الصورة عبر image let img = image::open(input_path).expect("خطأ في الفتح"); let (width, height) = img.dimensions(); let rgba = img.to_rgba8();
// إنشاء تمثيل لـ fast_image_resize let src_view = fr::ImageView::new(&rgba, width, height, fr::PixelType::U8x4); let mut dst_image = fr::Image::new(new_width, new_height, fr::PixelType::U8x4); let mut dst_view = dst_image.view_mut();
// إعداد أداة تغيير الحجم let mut resizer = fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::Lanczos3)); resizer.resize(&src_view, &mut dst_view).expect("خطأ في تغيير الحجم");
// حفظ النتيجة عبر image let result_img = image::RgbaImage::from_raw(new_width, new_height, dst_image.into_vec()).unwrap(); result_img.save(output_path).unwrap();}وفقًا للاختبارات، يمكن أن يكون fast_image_resize أسرع بمقدار 2-5 مرات من تغيير الحجم القياسي