use std::error::Error;
use tinify::{ResizeMethod, ResizeOptions, Tinify};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
println!("📏 Tinify: Resizing Images Example");
println!("====================================");
let api_key = std::env::var("TINIFY_API_KEY")
.unwrap_or_else(|_| "XZmVxmxJxbx4PZbHyxwX74v8N0LLtvqq".to_string());
let client = Tinify::new(api_key)?;
println!("✅ Client initialized");
create_test_image("resize_input.png").await?;
let source = client.source_from_file("resize_input.png").await?;
println!("✅ Source image loaded");
println!("\n🔄 Example 1: Scale method (maintains aspect ratio)");
let scale_options = ResizeOptions {
method: ResizeMethod::Scale,
width: Some(150),
height: None, };
match source.resize(scale_options).await {
Ok(mut result) => {
result.to_file("resized_scale.png").await?;
println!(" ✅ Scaled image saved to resized_scale.png");
if let Some(width) = result.image_width() {
println!(" 📐 New width: {}px", width);
}
if let Some(height) = result.image_height() {
println!(" 📐 New height: {}px", height);
}
}
Err(e) => println!(" ❌ Scale resize error: {}", e),
}
println!("\n📦 Example 2: Fit method (fits within dimensions)");
let fit_options = ResizeOptions {
method: ResizeMethod::Fit,
width: Some(200),
height: Some(200),
};
let source2 = client.source_from_file("resize_input.png").await?;
match source2.resize(fit_options).await {
Ok(mut result) => {
result.to_file("resized_fit.png").await?;
println!(" ✅ Fit-resized image saved to resized_fit.png");
if let Some(width) = result.image_width() {
println!(" 📐 Fit width: {}px", width);
}
if let Some(height) = result.image_height() {
println!(" 📐 Fit height: {}px", height);
}
}
Err(e) => println!(" ❌ Fit resize error: {}", e),
}
println!("\n🎯 Example 3: Cover method (covers entire area, may crop)");
let cover_options = ResizeOptions {
method: ResizeMethod::Cover,
width: Some(100),
height: Some(100),
};
let source3 = client.source_from_file("resize_input.png").await?;
match source3.resize(cover_options).await {
Ok(mut result) => {
result.to_file("resized_cover.png").await?;
println!(" ✅ Cover-resized image saved to resized_cover.png");
if let Some(width) = result.image_width() {
println!(" 📐 Cover width: {}px", width);
}
if let Some(height) = result.image_height() {
println!(" 📐 Cover height: {}px", height);
}
}
Err(e) => println!(" ❌ Cover resize error: {}", e),
}
println!("\n🖼️ Example 4: Thumb method (intelligent cropping for thumbnails)");
let thumb_options = ResizeOptions {
method: ResizeMethod::Thumb,
width: Some(80),
height: Some(80),
};
let source4 = client.source_from_file("resize_input.png").await?;
match source4.resize(thumb_options).await {
Ok(mut result) => {
result.to_file("resized_thumb.png").await?;
println!(" ✅ Thumbnail saved to resized_thumb.png");
if let Some(width) = result.image_width() {
println!(" 📐 Thumb width: {}px", width);
}
if let Some(height) = result.image_height() {
println!(" 📐 Thumb height: {}px", height);
}
}
Err(e) => println!(" ❌ Thumb resize error: {}", e),
}
println!("\n⚠️ Example 5: Error handling for invalid dimensions");
let invalid_options = ResizeOptions {
method: ResizeMethod::Fit,
width: Some(0), height: Some(100),
};
let source5 = client.source_from_file("resize_input.png").await?;
match source5.resize(invalid_options).await {
Ok(_) => println!(" ❌ Unexpected success with invalid dimensions"),
Err(e) => println!(" ✅ Correctly caught invalid dimensions: {}", e),
}
println!("\n🎉 Resize examples completed!");
cleanup_files(&[
"resize_input.png",
"resized_scale.png",
"resized_fit.png",
"resized_cover.png",
"resized_thumb.png",
])
.await;
Ok(())
}
async fn create_test_image(filename: &str) -> Result<(), Box<dyn Error>> {
let png_data = create_test_png_data();
tokio::fs::write(filename, png_data).await?;
println!("✅ Created test image: {}", filename);
Ok(())
}
fn create_test_png_data() -> Vec<u8> {
vec![
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x08, 0x06, 0x00, 0x00, 0x00, 0x70, 0xE2, 0x95, 0x25, 0x00, 0x00, 0x00, 0x19, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9C, 0x62, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE,
0x42, 0x60, 0x82,
]
}
async fn cleanup_files(files: &[&str]) {
for file in files {
if tokio::fs::metadata(file).await.is_ok() {
let _ = tokio::fs::remove_file(file).await;
}
}
}