diff --git a/crates/resvg/src/image.rs b/crates/resvg/src/image.rs index 0c631905..4f315a10 100644 --- a/crates/resvg/src/image.rs +++ b/crates/resvg/src/image.rs @@ -86,7 +86,25 @@ mod raster_images { let options = DecoderOptions::default().jpeg_set_out_colorspace(ColorSpace::RGBA); let mut decoder = zune_jpeg::JpegDecoder::new_with_options(data, options); - let img_data = decoder.decode().ok()?; + decoder.decode_headers().ok()?; + let output_cs = decoder.get_output_colorspace()?; + + let img_data = { + let data = decoder.decode().ok()?; + match output_cs { + ColorSpace::RGBA => data, + // `set_output_color_space` is not guaranteed to actually always set the output space + // to RGBA (its docs say "we do not guarantee the decoder can convert to all colorspaces"). + // In particular, it seems like it doesn't work for luma JPEGs, + // so we convert them manually. + ColorSpace::Luma => data + .into_iter() + .flat_map(|p| [p, p, p, 255]) + .collect::>(), + _ => return None, + } + }; + let info = decoder.info()?; let size = tiny_skia::IntSize::from_wh(info.width as u32, info.height as u32)?; diff --git a/crates/resvg/tests/integration/render.rs b/crates/resvg/tests/integration/render.rs index 7838e8cf..c8a38505 100644 --- a/crates/resvg/tests/integration/render.rs +++ b/crates/resvg/tests/integration/render.rs @@ -1101,7 +1101,9 @@ use crate::render; #[test] fn structure_image_embedded_gif() { assert_eq!(render("tests/structure/image/embedded-gif"), 0); } #[test] fn structure_image_embedded_jpeg_as_image_jpeg() { assert_eq!(render("tests/structure/image/embedded-jpeg-as-image-jpeg"), 0); } #[test] fn structure_image_embedded_jpeg_as_image_jpg() { assert_eq!(render("tests/structure/image/embedded-jpeg-as-image-jpg"), 0); } +#[test] fn structure_image_embedded_jpeg_luma() { assert_eq!(render("tests/structure/image/embedded-jpeg-luma"), 0); } #[test] fn structure_image_embedded_jpeg_without_mime() { assert_eq!(render("tests/structure/image/embedded-jpeg-without-mime"), 0); } +#[test] fn structure_image_embedded_png_luma() { assert_eq!(render("tests/structure/image/embedded-png-luma"), 0); } #[test] fn structure_image_embedded_png() { assert_eq!(render("tests/structure/image/embedded-png"), 0); } #[test] fn structure_image_embedded_svg_with_text() { assert_eq!(render("tests/structure/image/embedded-svg-with-text"), 0); } #[test] fn structure_image_embedded_svg_without_mime() { assert_eq!(render("tests/structure/image/embedded-svg-without-mime"), 0); } diff --git a/crates/resvg/tests/tests/structure/image/embedded-jpeg-luma.png b/crates/resvg/tests/tests/structure/image/embedded-jpeg-luma.png new file mode 100644 index 00000000..774242fd Binary files /dev/null and b/crates/resvg/tests/tests/structure/image/embedded-jpeg-luma.png differ diff --git a/crates/resvg/tests/tests/structure/image/embedded-jpeg-luma.svg b/crates/resvg/tests/tests/structure/image/embedded-jpeg-luma.svg new file mode 100644 index 00000000..7f17fcec --- /dev/null +++ b/crates/resvg/tests/tests/structure/image/embedded-jpeg-luma.svg @@ -0,0 +1,8 @@ + + Embedded JPEG with luma + + + + + diff --git a/crates/resvg/tests/tests/structure/image/embedded-png-luma.png b/crates/resvg/tests/tests/structure/image/embedded-png-luma.png new file mode 100644 index 00000000..c43970e2 Binary files /dev/null and b/crates/resvg/tests/tests/structure/image/embedded-png-luma.png differ diff --git a/crates/resvg/tests/tests/structure/image/embedded-png-luma.svg b/crates/resvg/tests/tests/structure/image/embedded-png-luma.svg new file mode 100644 index 00000000..8aa77383 --- /dev/null +++ b/crates/resvg/tests/tests/structure/image/embedded-png-luma.svg @@ -0,0 +1,8 @@ + + Embedded PNG with luma + + + + +