Exemplos de Processamento de Imagem Web Rust

Exemplos de processamento de imagem Web Rust incluindo leitura/gravação, redimensionamento e conversão de formato

💻 Ler/Gravar Imagem rust

🟢 simple ⭐⭐

Ler e salvar arquivos de imagem usando o crate image

⏱️ 20 min 🏷️ rust, web, image processing
Prerequisites: Basic Rust, image crate
// Web Rust Image Read/Save Examples
// Basic image file operations
//
// Add to Cargo.toml:
// [dependencies]
// image = "0.24"

use image::{DynamicImage, ImageError, io::Reader as ImageReader};
use std::path::Path;

// 1. Read Image

/// Read image from file path
fn read_image(path: &str) -> Result<DynamicImage, ImageError> {
    let img = ImageReader::open(path)?.decode()?;
    Ok(img)
}

/// Read image from bytes
fn read_image_from_bytes(data: &[u8]) -> Result<DynamicImage, ImageError> {
    let img = image::load_from_memory(data)?;
    Ok(img)
}

/// Read image with format hint
fn read_image_with_format(path: &str, format: image::ImageFormat) -> Result<DynamicImage, ImageError> {
    let img = ImageReader::with_format(std::fs::File::open(path)?, format).decode()?;
    Ok(img)
}

// 2. Save Image

/// Save image to file (auto-detect format from extension)
fn save_image(img: &DynamicImage, path: &str) -> Result<(), ImageError> {
    img.save(path)?;
    Ok(())
}

/// Save image with specific format
fn save_image_with_format(img: &DynamicImage, path: &str, format: image::ImageFormat) -> Result<(), ImageError> {
    img.save_with_format(path, format)?;
    Ok(())
}

/// Save image with quality (for JPEG)
fn save_image_jpeg_quality(img: &DynamicImage, path: &str, quality: u8) -> Result<(), ImageError> {
    let encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(
        &mut std::fs::File::create(path)?,
        quality
    );
    img.write_with_encoder(encoder)?;
    Ok(())
}

// 3. Image Information

/// Get image dimensions
fn get_image_dimensions(img: &DynamicImage) -> (u32, u32) {
    img.dimensions()
}

/// Get image color type
fn get_image_color_type(img: &DynamicImage) -> String {
    format!("{:?}", img.color())
}

/// Get image file size
fn get_image_file_size(path: &str) -> Result<u64, std::io::Error> {
    Ok(std::fs::metadata(path)?.len())
}

// 4. Batch Operations

/// Read multiple images
fn read_multiple_images(paths: &[&str]) -> Vec<Result<DynamicImage, ImageError>> {
    paths.iter().map(|&path| read_image(path)).collect()
}

/// Save multiple images
fn save_multiple_images(images: &[(&DynamicImage, &str)]) -> Vec<Result<(), ImageError>> {
    images.iter().map(|(img, path)| save_image(img, path)).collect()
}

// 5. Image Validation

/// Check if file is valid image
fn is_valid_image(path: &str) -> bool {
    ImageReader::open(path).is_ok() && ImageReader::open(path).and_then(|r| r.decode()).is_ok()
}

/// Get supported formats for a file
fn get_image_format(path: &str) -> Option<image::ImageFormat> {
    Path::new(path)
        .extension()
        .and_then(|ext| ext.to_str())
        .and_then(|ext| image::ImageFormat::from_extension(ext))
}

// 6. Create Basic Images

/// Create new blank image
fn create_blank_image(width: u32, height: u32, color: [u8; 3]) -> DynamicImage {
    image::RgbImage::new(width, height).into()
}

/// Create solid color image
fn create_solid_color_image(width: u32, height: u32, r: u8, g: u8, b: u8) -> DynamicImage {
    let img: image::RgbImage = image::RgbImage::from_fn(width, height, |_, _| {
        image::Rgb([r, g, b])
    });
    img.into()
}

// 7. Image from Raw Data

/// Create image from raw RGB bytes
fn image_from_rgb_bytes(data: &[u8], width: u32, height: u32) -> Result<DynamicImage, ImageError> {
    let img: image::RgbImage = image::RgbImage::from_raw(width, height, data.to_vec())
        .ok_or(ImageError::Parameter(ErrorKind::DimensionError))?;
    Ok(img.into())
}

/// Create image from raw RGBA bytes
fn image_from_rgba_bytes(data: &[u8], width: u32, height: u32) -> Result<DynamicImage, ImageError> {
    let img: image::RgbaImage = image::RgbaImage::from_raw(width, height, data.to_vec())
        .ok_or(ImageError::Parameter(ErrorKind::DimensionError))?;
    Ok(img.into())
}

// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Web Rust Image Read/Save Examples ===\n");

    // 1. Create a test image
    println!("--- 1. Create Test Image ---");
    let test_img = create_solid_color_image(200, 200, 100, 150, 200);
    save_image(&test_img, "test_output.png")?;
    println!("Created and saved test image");

    // 2. Read image
    println!("
--- 2. Read Image ---");
    let img = read_image("test_output.png")?;
    let (width, height) = get_image_dimensions(&img);
    println!("Image dimensions: {}x{}", width, height);
    println!("Color type: {}", get_image_color_type(&img));

    // 3. Save in different formats
    println!("
--- 3. Save in Different Formats ---");
    save_image_with_format(&img, "output.jpg", image::ImageFormat::Jpeg)?;
    save_image_with_format(&img, "output.bmp", image::ImageFormat::Bmp)?;
    save_image_with_format(&img, "output.png", image::ImageFormat::Png)?;
    println!("Saved in JPG, BMP, and PNG formats");

    // 4. JPEG quality
    println!("
--- 4. JPEG Quality ---");
    save_image_jpeg_quality(&img, "output_high.jpg", 90)?;
    save_image_jpeg_quality(&img, "output_low.jpg", 30)?;
    println!("Saved high and low quality JPEGs");

    // 5. File sizes
    println!("
--- 5. File Sizes ---");
    println!("PNG: {} bytes", get_image_file_size("output.png")?);
    println!("JPEG (high): {} bytes", get_image_file_size("output_high.jpg")?);
    println!("JPEG (low): {} bytes", get_image_file_size("output_low.jpg")?);

    // 6. Read from bytes
    println!("
--- 6. Read from Bytes ---");
    let bytes = std::fs::read("test_output.png")?;
    let img_from_bytes = read_image_from_bytes(&bytes)?;
    println!("Read image from {} bytes", bytes.len());

    // 7. Validation
    println!("
--- 7. Validation ---");
    println!("test_output.png is valid: {}", is_valid_image("test_output.png"));
    println!("Format: {:?}", get_image_format("test_output.png"));

    println!("
=== All Image Read/Save Examples Completed ===");
    Ok(())
}

💻 Redimensionamento de Imagem rust

🟡 intermediate ⭐⭐⭐

Redimensionar e escalonar imagens usando vários métodos de interpolação

⏱️ 25 min 🏷️ rust, web, image processing
Prerequisites: Intermediate Rust, image crate
// Web Rust Image Scaling Examples
// Image resizing and scaling operations
//
// Add to Cargo.toml:
// [dependencies]
// image = "0.24"

use image::{DynamicImage, imageops, FilterType};

// 1. Basic Resizing

/// Resize image to exact dimensions
fn resize_exact(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize(width, height, FilterType::Lanczos3)
}

/// Resize maintaining aspect ratio
fn resize_aspect_ratio(img: &DynamicImage, max_width: u32, max_height: u32) -> DynamicImage {
    img.resize(max_width, max_height, FilterType::Lanczos3)
}

/// Resize to fit within bounds
fn resize_to_fit(img: &DynamicImage, max_width: u32, max_height: u32) -> DynamicImage {
    img.resize(max_width, max_height, FilterType::Lanczos3)
}

// 2. Advanced Scaling

/// Scale by factor
fn scale_by_factor(img: &DynamicImage, factor: f32) -> DynamicImage {
    let (width, height) = img.dimensions();
    let new_width = (width as f32 * factor) as u32;
    let new_height = (height as f32 * factor) as u32;
    img.resize(new_width, new_height, FilterType::Lanczos3)
}

/// Scale to width (maintain aspect ratio)
fn scale_to_width(img: &DynamicImage, target_width: u32) -> DynamicImage {
    let (width, height) = img.dimensions();
    let ratio = target_width as f32 / width as f32;
    let new_height = (height as f32 * ratio) as u32;
    img.resize(target_width, new_height, FilterType::Lanczos3)
}

/// Scale to height (maintain aspect ratio)
fn scale_to_height(img: &DynamicImage, target_height: u32) -> DynamicImage {
    let (width, height) = img.dimensions();
    let ratio = target_height as f32 / height as f32;
    let new_width = (width as f32 * ratio) as u32;
    img.resize(new_width, target_height, FilterType::Lanczos3)
}

// 3. Thumbnail Generation

/// Generate thumbnail
fn generate_thumbnail(img: &DynamicImage, size: u32) -> DynamicImage {
    img.thumbnail(size, size)
}

/// Generate thumbnail with exact dimensions (crop if needed)
fn generate_thumbnail_exact(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize_exact(width, height, FilterType::Lanczos3)
}

/// Generate thumbnail with padding
fn generate_thumbnail_pad(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize_to_fill(width, height, FilterType::Lanczos3)
}

// 4. Filter Types

/// Resize with nearest neighbor (fast, low quality)
fn resize_nearest(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize(width, height, FilterType::Nearest)
}

/// Resize with triangle (moderate quality)
fn resize_triangle(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize(width, height, FilterType::Triangle)
}

/// Resize with Gaussian (smooth)
fn resize_gaussian(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize(width, height, FilterType::Gaussian)
}

/// Resize with CatmullRom (sharp)
fn resize_catmull(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    img.resize(width, height, FilterType::CatmullRom)
}

// 5. Special Scaling Operations

/// Resize to fit width, keeping aspect ratio
fn resize_fit_width(img: &DynamicImage, target_width: u32) -> DynamicImage {
    scale_to_width(img, target_width)
}

/// Resize to fit height, keeping aspect ratio
fn resize_fit_height(img: &DynamicImage, target_height: u32) -> DynamicImage {
    scale_to_height(img, target_height)
}

/// Resize and crop to exact dimensions
fn resize_crop(img: &DynamicImage, width: u32, height: u32) -> DynamicImage {
    let (orig_width, orig_height) = img.dimensions();

    // Calculate aspect ratios
    let orig_ratio = orig_width as f32 / orig_height as f32;
    let target_ratio = width as f32 / height as f32;

    if orig_ratio > target_ratio {
        // Crop width
        let new_height = ((orig_width as f32 / target_ratio) as u32).min(orig_height);
        let cropped = img.crop(
            0,
            (orig_height - new_height) / 2,
            orig_width,
            new_height
        );
        cropped.resize(width, height, FilterType::Lanczos3)
    } else {
        // Crop height
        let new_width = ((orig_height as f32 * target_ratio) as u32).min(orig_width);
        let cropped = img.crop(
            (orig_width - new_width) / 2,
            0,
            new_width,
            orig_height
        );
        cropped.resize(width, height, FilterType::Lanczos3)
    }
}

// 6. Batch Resizing

/// Resize multiple images to same size
fn resize_batch(images: &[&DynamicImage], width: u32, height: u32) -> Vec<DynamicImage> {
    images.iter().map(|img| resize_exact(img, width, height)).collect()
}

/// Create multiple sizes from one image
fn create_multiple_sizes(img: &DynamicImage, sizes: &[u32]) -> Vec<(u32, DynamicImage)> {
    sizes.iter().map(|&size| {
        (size, generate_thumbnail(img, size))
    }).collect()
}

// 7. Smart Resizing

/// Resize with max dimension (maintain aspect ratio)
fn resize_max_dimension(img: &DynamicImage, max_dim: u32) -> DynamicImage {
    let (width, height) = img.dimensions();
    if width > height {
        scale_to_width(img, max_dim)
    } else {
        scale_to_height(img, max_dim)
    }
}

/// Resize with min dimension (maintain aspect ratio)
fn resize_min_dimension(img: &DynamicImage, min_dim: u32) -> DynamicImage {
    let (width, height) = img.dimensions();
    if width < height {
        scale_to_width(img, min_dim)
    } else {
        scale_to_height(img, min_dim)
    }
}

// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Web Rust Image Scaling Examples ===\n");

    // Create test image
    use image::RgbImage;
    let test_img: DynamicImage = RgbImage::from_fn(800, 600, |x, y| {
        let r = ((x as f32 / 800.0) * 255.0) as u8;
        let g = ((y as f32 / 600.0) * 255.0) as u8;
        let b = 128;
        image::Rgb([r, g, b])
    }).into();

    println!("Original: {}x{}", test_img.width(), test_img.height());

    // 1. Basic resize
    println!("
--- 1. Basic Resize ---");
    let resized = resize_exact(&test_img, 400, 300);
    println!("Resized to: {}x{}", resized.width(), resized.height());

    // 2. Scale to width
    println!("
--- 2. Scale to Width ---");
    let scaled_width = scale_to_width(&test_img, 300);
    println!("Scaled to width 300: {}x{}", scaled_width.width(), scaled_width.height());

    // 3. Scale to height
    println!("
--- 3. Scale to Height ---");
    let scaled_height = scale_to_height(&test_img, 200);
    println!("Scaled to height 200: {}x{}", scaled_height.width(), scaled_height.height());

    // 4. Scale by factor
    println!("
--- 4. Scale by Factor ---");
    let scaled_down = scale_by_factor(&test_img, 0.5);
    let scaled_up = scale_by_factor(&test_img, 1.5);
    println!("Scaled by 0.5: {}x{}", scaled_down.width(), scaled_down.height());
    println!("Scaled by 1.5: {}x{}", scaled_up.width(), scaled_up.height());

    // 5. Thumbnails
    println!("
--- 5. Thumbnails ---");
    let thumb = generate_thumbnail(&test_img, 150);
    println!("Thumbnail 150x150: {}x{}", thumb.width(), thumb.height());

    // 6. Different filters
    println!("
--- 6. Different Filters ---");
    let nearest = resize_nearest(&test_img, 200, 150);
    let lanczos = resize_exact(&test_img, 200, 150);
    println!("Nearest: {}x{}", nearest.width(), nearest.height());
    println!("Lanczos: {}x{}", lanczos.width(), lanczos.height());

    // 7. Multiple sizes
    println!("
--- 7. Multiple Sizes ---");
    let sizes = create_multiple_sizes(&test_img, &[50, 100, 150, 200, 300]);
    for (size, img) in sizes {
        println!("Size {}: {}x{}", size, img.width(), img.height());
    }

    // 8. Smart resizing
    println!("
--- 8. Smart Resizing ---");
    let max_dim = resize_max_dimension(&test_img, 400);
    let min_dim = resize_min_dimension(&test_img, 300);
    println!("Max dimension 400: {}x{}", max_dim.width(), max_dim.height());
    println!("Min dimension 300: {}x{}", min_dim.width(), min_dim.height());

    // 9. Resize and crop
    println!("
--- 9. Resize and Crop ---");
    let cropped = resize_crop(&test_img, 300, 300);
    println!("Cropped to square: {}x{}", cropped.width(), cropped.height());

    println!("
=== All Image Scaling Examples Completed ===");
    Ok(())
}

💻 Conversão de Formato de Imagem rust

🟡 intermediate ⭐⭐⭐

Converter entre diferentes formatos de imagem como JPG, PNG, BMP, WebP

⏱️ 20 min 🏷️ rust, web, image processing
Prerequisites: Intermediate Rust, image crate
// Web Rust Image Format Conversion Examples
// Convert images between different formats
//
// Add to Cargo.toml:
// [dependencies]
// image = "0.24"

use image::{DynamicImage, ImageFormat, DynamicImage::*};
use std::path::Path;

// 1. Basic Format Conversion

/// Convert image to different format
fn convert_format(img: &DynamicImage, output_path: &str, format: ImageFormat) -> Result<(), image::ImageError> {
    img.save_with_format(output_path, format)?;
    Ok(())
}

/// Convert with automatic format detection
fn convert_auto_format(img: &DynamicImage, output_path: &str) -> Result<(), image::ImageError> {
    img.save(output_path)?;
    Ok(())
}

/// Convert PNG to JPEG
fn png_to_jpeg(input_path: &str, output_path: &str) -> Result<(), image::ImageError> {
    let img = image::open(input_path)?;
    img.save_with_format(output_path, ImageFormat::Jpeg)?;
    Ok(())
}

/// Convert JPEG to PNG
fn jpeg_to_png(input_path: &str, output_path: &str) -> Result<(), image::ImageError> {
    let img = image::open(input_path)?;
    img.save_with_format(output_path, ImageFormat::Png)?;
    Ok(())
}

// 2. Conversion with Options

/// Convert to JPEG with quality
fn to_jpeg_with_quality(img: &DynamicImage, output_path: &str, quality: u8) -> Result<(), image::ImageError> {
    let mut output = std::fs::File::create(output_path)?;
    let encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, quality);
    img.write_with_encoder(encoder)?;
    Ok(())
}

/// Convert to PNG with compression
fn to_png_with_compression(img: &DynamicImage, output_path: &str, compression: image::codecs::png::CompressionType) -> Result<(), image::ImageError> {
    let mut output = std::fs::File::create(output_path)?;
    let encoder = image::codecs::png::PngEncoder::new_with_compression(&mut output, compression);
    img.write_with_encoder(encoder)?;
    Ok(())
}

/// Convert to PPM
fn to_ppm(img: &DynamicImage, output_path: &str) -> Result<(), image::ImageError> {
    img.save_with_format(output_path, ImageFormat::Pnm)?;
    Ok(())
}

// 3. Batch Conversion

/// Convert multiple images to same format
fn convert_batch(input_paths: &[&str], output_dir: &str, format: ImageFormat) -> Result<Vec<Result<(), image::ImageError>>, std::io::Error> {
    std::fs::create_dir_all(output_dir)?;
    Ok(input_paths.iter().map(|path| {
        let img = image::open(path);
        match img {
            Ok(img) => {
                let filename = Path::new(path).file_stem().unwrap().to_str().unwrap();
                let ext = extension_from_format(format);
                let output_path = format!("{}/{}.{}", output_dir, filename, ext);
                convert_format(&img, &output_path, format)
            },
            Err(e) => Err(e)
        }
    }).collect())
}

/// Get file extension from format
fn extension_from_format(format: ImageFormat) -> &'static str {
    match format {
        ImageFormat::Png => "png",
        ImageFormat::Jpeg => "jpg",
        ImageFormat::Bmp => "bmp",
        ImageFormat::WebP => "webp",
        _ => "png"
    }
}

// 4. Format-Specific Conversions

/// Convert to BMP (lossless)
fn to_bmp(img: &DynamicImage, output_path: &str) -> Result<(), image::ImageError> {
    img.save_with_format(output_path, ImageFormat::Bmp)?;
    Ok(())
}

/// Convert to WebP if available
fn to_webp(img: &DynamicImage, output_path: &str) -> Result<(), image::ImageError> {
    img.save_with_format(output_path, ImageFormat::WebP)?;
    Ok(())
}

/// Convert to ICO
fn to_ico(img: &DynamicImage, output_path: &str) -> Result<(), image::ImageError> {
    img.save_with_format(output_path, ImageFormat::Ico)?;
    Ok(())
}

/// Convert to TIFF
fn to_tiff(img: &DynamicImage, output_path: &str) -> Result<(), image::ImageError> {
    img.save_with_format(output_path, ImageFormat::Tiff)?;
    Ok(())
}

// 5. Color Space Conversions

/// Convert to grayscale
fn to_grayscale(img: &DynamicImage) -> DynamicImage {
    img.grayscale()
}

/// Convert to black and white (binary)
fn to_black_and_white(img: &DynamicImage, threshold: u8) -> DynamicImage {
    let gray = img.to_luma8();
    let binary: image::GrayImage = image::GrayImage::from_fn(gray.width(), gray.height(), |x, y| {
        let pixel = gray.get_pixel(x, y)[0];
        let value = if pixel > threshold { 255 } else { 0 };
        image::Luma([value])
    });
    DynamicImage::ImageLuma8(binary)
}

/// Invert colors
fn invert_colors(img: &DynamicImage) -> DynamicImage {
    img.invert()
}

// 6. Alpha Channel Handling

/// Remove alpha channel (convert to RGB)
fn remove_alpha(img: &DynamicImage) -> DynamicImage {
    img.to_rgb8().into()
}

/// Add alpha channel (convert to RGBA)
fn add_alpha(img: &DynamicImage) -> DynamicImage {
    img.to_rgba8().into()
}

/// Apply transparency mask
fn apply_alpha_mask(img: &DynamicImage, mask: &DynamicImage) -> Result<DynamicImage, image::ImageError> {
    let mut rgba = img.to_rgba8();
    let mask_gray = mask.to_luma8();

    for (x, y, pixel) in rgba.enumerate_pixels_mut() {
        if let Some(mask_pixel) = mask_gray.get_pixel_checked(x, y) {
            pixel[3] = mask_pixel[0];
        }
    }

    Ok(DynamicImage::ImageRgba8(rgba))
}

// 7. Format Validation

/// Detect format from file
fn detect_format(path: &str) -> Option<ImageFormat> {
    ImageFormat::from_path(path).ok()
}

/// Check if format supports transparency
fn supports_transparency(format: ImageFormat) -> bool {
    matches!(format, ImageFormat::Png | ImageFormat::WebP | ImageFormat::Ico)
}

/// Check if format is lossy
fn is_lossy_format(format: ImageFormat) -> bool {
    matches!(format, ImageFormat::Jpeg | ImageFormat::WebP)
}

// 8. Conversion Utilities

/// Auto-convert based on input format
fn auto_convert(input_path: &str, output_path: &str) -> Result<(), image::ImageError> {
    let img = image::open(input_path)?;
    img.save(output_path)?;
    Ok(())
}

/// Convert with format preservation check
fn convert_safe(input_path: &str, output_path: &str) -> Result<bool, image::ImageError> {
    let input_format = detect_format(input_path).unwrap();
    let output_format = detect_format(output_path).unwrap();

    if input_format == output_format {
        return Ok(false); // No conversion needed
    }

    // Check for loss of transparency
    if !supports_transparency(output_format) {
        let img = image::open(input_path)?;
        if img.color().has_alpha() {
            // Remove alpha before saving
            let rgb = remove_alpha(&img);
            rgb.save(output_path)?;
            return Ok(true);
        }
    }

    auto_convert(input_path, output_path)?;
    Ok(true)
}

// 9. Special Conversions

/// Convert to grayscale JPEG
fn to_grayscale_jpeg(img: &DynamicImage, output_path: &str, quality: u8) -> Result<(), image::ImageError> {
    let gray = to_grayscale(img);
    to_jpeg_with_quality(&gray, output_path, quality)?;
    Ok(())
}

/// Convert to thumbnail JPEG
fn to_thumbnail_jpeg(img: &DynamicImage, output_path: &str, size: u32, quality: u8) -> Result<(), image::ImageError> {
    let thumb = img.thumbnail(size, size);
    to_jpeg_with_quality(&thumb, output_path, quality)?;
    Ok(())
}

// Usage Examples
fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Web Rust Image Format Conversion Examples ===\n");

    // Create test image with RGBA
    use image::RgbaImage;
    let test_img: DynamicImage = RgbaImage::from_fn(400, 300, |x, y| {
        let r = ((x as f32 / 400.0) * 255.0) as u8;
        let g = ((y as f32 / 300.0) * 255.0) as u8;
        let b = 128;
        let a = 255;
        image::Rgba([r, g, b, a])
    }).into();

    // Save test image
    test_img.save("test_rgba.png")?;
    println!("Created test image");

    // 1. Basic conversions
    println!("
--- 1. Basic Conversions ---");
    convert_format(&test_img, "output.jpg", ImageFormat::Jpeg)?;
    convert_format(&test_img, "output.bmp", ImageFormat::Bmp)?;
    convert_format(&test_img, "output.ppm", ImageFormat::Pnm)?;
    println!("Converted to JPG, BMP, PPM");

    // 2. JPEG with quality
    println!("
--- 2. JPEG Quality Levels ---");
    to_jpeg_with_quality(&test_img, "high.jpg", 90)?;
    to_jpeg_with_quality(&test_img, "medium.jpg", 60)?;
    to_jpeg_with_quality(&test_img, "low.jpg", 30)?;
    println!("Created JPEGs with 90%, 60%, 30% quality");

    // 3. PNG compression
    println!("
--- 3. PNG Compression ---");
    to_png_with_compression(&test_img, "fast.png", image::codecs::png::CompressionType::Fast)?;
    to_png_with_compression(&test_img, "best.png", image::codecs::png::CompressionType::Best)?;
    println!("Created PNGs with Fast and Best compression");

    // 4. Grayscale conversion
    println!("
--- 4. Grayscale Conversion ---");
    let gray = to_grayscale(&test_img);
    gray.save("grayscale.jpg")?;
    println!("Created grayscale JPEG");

    // 5. Black and white
    println!("
--- 5. Black and White ---");
    let bw = to_black_and_white(&test_img, 128);
    bw.save("blackwhite.png")?;
    println!("Created black and white image");

    // 6. Invert colors
    println!("
--- 6. Invert Colors ---");
    let inverted = invert_colors(&test_img);
    inverted.save("inverted.png")?;
    println!("Created color-inverted image");

    // 7. Alpha handling
    println!("
--- 7. Alpha Channel ---");
    let no_alpha = remove_alpha(&test_img);
    no_alpha.save("no_alpha.jpg")?;
    println!("Removed alpha for JPEG conversion");

    // 8. Format detection
    println!("
--- 8. Format Detection ---");
    println!("test_rgba.png format: {:?}", detect_format("test_rgba.png"));
    println!("output.jpg format: {:?}", detect_format("output.jpg"));

    // 9. Format properties
    println!("
--- 9. Format Properties ---");
    println!("PNG supports transparency: {}", supports_transparency(ImageFormat::Png));
    println!("JPEG supports transparency: {}", supports_transparency(ImageFormat::Jpeg));
    println!("JPEG is lossy: {}", is_lossy_format(ImageFormat::Jpeg));
    println!("PNG is lossy: {}", is_lossy_format(ImageFormat::Png));

    // 10. Thumbnail conversion
    println!("
--- 10. Thumbnail JPEG ---");
    to_thumbnail_jpeg(&test_img, "thumb.jpg", 150, 70)?;
    println!("Created 150x150 thumbnail JPEG");

    println!("
=== All Image Format Conversion Examples Completed ===");
    Ok(())
}