| 1 |
1 |
|
use askama::Template; |
|
2 |
+ |
use image::ImageDecoder; |
| 2 |
3 |
|
use askama_web::WebTemplate; |
| 3 |
4 |
|
use axum::{ |
| 4 |
5 |
|
extract::{DefaultBodyLimit, Multipart, Path, Query, State}, |
|
| 424 |
425 |
|
} |
| 425 |
426 |
|
} |
| 426 |
427 |
|
|
|
428 |
+ |
// --- Image processing --- |
|
429 |
+ |
|
|
430 |
+ |
fn process_image(data: &[u8]) -> Result<Vec<u8>, String> { |
|
431 |
+ |
let reader = image::ImageReader::new(std::io::Cursor::new(data)) |
|
432 |
+ |
.with_guessed_format() |
|
433 |
+ |
.map_err(|e| format!("Failed to read image: {}", e))?; |
|
434 |
+ |
let mut decoder = reader |
|
435 |
+ |
.into_decoder() |
|
436 |
+ |
.map_err(|e| format!("Failed to create decoder: {}", e))?; |
|
437 |
+ |
let orientation = decoder.orientation().unwrap_or(image::metadata::Orientation::NoTransforms); |
|
438 |
+ |
let mut img = image::DynamicImage::from_decoder(decoder) |
|
439 |
+ |
.map_err(|e| format!("Failed to decode image: {}", e))?; |
|
440 |
+ |
img.apply_orientation(orientation); |
|
441 |
+ |
let mut output = Vec::new(); |
|
442 |
+ |
let encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, 75); |
|
443 |
+ |
img.write_with_encoder(encoder) |
|
444 |
+ |
.map_err(|e| format!("JPEG encoding failed: {}", e))?; |
|
445 |
+ |
Ok(output) |
|
446 |
+ |
} |
|
447 |
+ |
|
| 427 |
448 |
|
// --- Multipart parsing --- |
| 428 |
449 |
|
|
| 429 |
450 |
|
struct WineFormData { |
|
| 459 |
480 |
|
let field_name = field.name().unwrap_or("").to_string(); |
| 460 |
481 |
|
match field_name.as_str() { |
| 461 |
482 |
|
"image" => { |
| 462 |
|
- |
let content_type = field.content_type().unwrap_or("application/octet-stream").to_string(); |
| 463 |
483 |
|
let bytes = field.bytes().await.map_err(|e| format!("Failed to read image: {}", e))?; |
| 464 |
484 |
|
if !bytes.is_empty() { |
| 465 |
|
- |
image = Some(bytes.to_vec()); |
| 466 |
|
- |
image_mime = Some(content_type); |
|
485 |
+ |
let processed = process_image(&bytes)?; |
|
486 |
+ |
image = Some(processed); |
|
487 |
+ |
image_mime = Some("image/jpeg".to_string()); |
| 467 |
488 |
|
} |
| 468 |
489 |
|
} |
| 469 |
490 |
|
"name" => name = field.text().await.unwrap_or_default(), |