Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions packages/cli/src/opt/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ pub(crate) fn process_image(
source: &Path,
output_path: &Path,
) -> anyhow::Result<()> {
// Copy verbatim if no transform is requested (#5642)
if image_options.format() == ImageFormat::Unknown
&& image_options.size() == ImageSize::Automatic
{
std::fs::copy(source, output_path).with_context(|| {
format!(
"Failed to copy image from {} to {}",
source.display(),
output_path.display()
)
})?;
return Ok(());
}

let mut image = image::ImageReader::new(std::io::Cursor::new(&*std::fs::read(source)?))
.with_guessed_format()
.context("Failed to guess image format")?
Expand Down Expand Up @@ -141,3 +155,49 @@ pub(crate) fn compress_jpg(image: DynamicImage, output_location: &Path) -> anyho
w.write_all(&jpeg_bytes)?;
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

// Write a PNG with detectable chunk/compression to verify byte-for-byte copying
fn write_source_png(path: &Path) {
let file = std::fs::File::create(path).unwrap();
let w = BufWriter::new(file);
let mut encoder = png::Encoder::new(w, 4, 4);
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
encoder.set_compression(png::Compression::Best);
encoder
.add_text_chunk("Comment".to_string(), "dioxus-asset-test".to_string())
.unwrap();
let mut writer = encoder.write_header().unwrap();
// 4x4 RGBA pixels with varied colors.
let mut data = Vec::with_capacity(4 * 4 * 4);
for i in 0..16u8 {
data.extend_from_slice(&[i.wrapping_mul(16), 255 - i, i, 255]);
}
writer.write_image_data(&data).unwrap();
writer.finish().unwrap();
}

// Test for #5642: `asset!()` must copy bytes verbatim
#[test]
fn default_options_preserve_source_bytes() {
let dir = std::env::temp_dir().join(format!("dx-image-opt-test-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let source = dir.join("source.png");
let output = dir.join("output.png");
write_source_png(&source);

process_image(&ImageAssetOptions::default(), &source, &output).unwrap();

assert_eq!(
std::fs::read(&source).unwrap(),
std::fs::read(&output).unwrap(),
"asset!() with default options must copy the source bytes verbatim, not re-encode"
);

std::fs::remove_dir_all(&dir).ok();
}
}