mirror of
https://github.com/typst/typst
synced 2025-08-15 15:38:33 +08:00
Wrap whole CustomImage in Arc
This commit is contained in:
parent
8f0cb71db8
commit
a330866ad2
@ -9,7 +9,6 @@ use ecow::{eco_format, EcoString};
|
|||||||
use image::codecs::gif::GifDecoder;
|
use image::codecs::gif::GifDecoder;
|
||||||
use image::codecs::jpeg::JpegDecoder;
|
use image::codecs::jpeg::JpegDecoder;
|
||||||
use image::codecs::png::PngDecoder;
|
use image::codecs::png::PngDecoder;
|
||||||
use image::imageops::rotate180;
|
|
||||||
use image::{
|
use image::{
|
||||||
guess_format, DynamicImage, ImageBuffer, ImageDecoder, ImageResult, Limits, Pixel,
|
guess_format, DynamicImage, ImageBuffer, ImageDecoder, ImageResult, Limits, Pixel,
|
||||||
};
|
};
|
||||||
|
@ -61,26 +61,28 @@ pub(crate) fn handle_image(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around RasterImage so that we can implement `CustomImage`.
|
struct Repr {
|
||||||
#[derive(Clone)]
|
|
||||||
struct PdfImage {
|
|
||||||
/// The original, underlying raster image.
|
/// The original, underlying raster image.
|
||||||
raster: RasterImage,
|
raster: RasterImage,
|
||||||
/// The alpha channel of the raster image, if existing.
|
/// The alpha channel of the raster image, if existing.
|
||||||
alpha_channel: OnceLock<Option<Arc<Vec<u8>>>>,
|
alpha_channel: OnceLock<Option<Vec<u8>>>,
|
||||||
/// A (potentially) converted version of the dynamic image stored `raster` that is
|
/// A (potentially) converted version of the dynamic image stored `raster` that is
|
||||||
/// guaranteed to either be in luma8 or rgb8, and thus can be used for the
|
/// guaranteed to either be in luma8 or rgb8, and thus can be used for the
|
||||||
/// `color_channel` method of `CustomImage`.
|
/// `color_channel` method of `CustomImage`.
|
||||||
actual_dynamic: OnceLock<Arc<DynamicImage>>,
|
actual_dynamic: OnceLock<Arc<DynamicImage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper around RasterImage so that we can implement `CustomImage`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct PdfImage(Arc<Repr>);
|
||||||
|
|
||||||
impl PdfImage {
|
impl PdfImage {
|
||||||
pub fn new(raster: RasterImage) -> Self {
|
pub fn new(raster: RasterImage) -> Self {
|
||||||
Self {
|
Self(Arc::new(Repr {
|
||||||
raster,
|
raster,
|
||||||
alpha_channel: OnceLock::new(),
|
alpha_channel: OnceLock::new(),
|
||||||
actual_dynamic: OnceLock::new(),
|
actual_dynamic: OnceLock::new(),
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,15 +90,15 @@ impl Hash for PdfImage {
|
|||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
// `alpha_channel` and `actual_dynamic` are generated from the underlying `RasterImage`,
|
// `alpha_channel` and `actual_dynamic` are generated from the underlying `RasterImage`,
|
||||||
// so this is enough. Since `raster` is prehashed, this is also very cheap.
|
// so this is enough. Since `raster` is prehashed, this is also very cheap.
|
||||||
self.raster.hash(state);
|
self.0.raster.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomImage for PdfImage {
|
impl CustomImage for PdfImage {
|
||||||
fn color_channel(&self) -> &[u8] {
|
fn color_channel(&self) -> &[u8] {
|
||||||
self.actual_dynamic
|
self.0.actual_dynamic
|
||||||
.get_or_init(|| {
|
.get_or_init(|| {
|
||||||
let dynamic = self.raster.dynamic();
|
let dynamic = self.0.raster.dynamic();
|
||||||
let channel_count = dynamic.color().channel_count();
|
let channel_count = dynamic.color().channel_count();
|
||||||
|
|
||||||
match (dynamic.as_ref(), channel_count) {
|
match (dynamic.as_ref(), channel_count) {
|
||||||
@ -113,20 +115,18 @@ impl CustomImage for PdfImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn alpha_channel(&self) -> Option<&[u8]> {
|
fn alpha_channel(&self) -> Option<&[u8]> {
|
||||||
self.alpha_channel
|
self.0.alpha_channel
|
||||||
.get_or_init(|| {
|
.get_or_init(|| {
|
||||||
self.raster.dynamic().color().has_alpha().then(|| {
|
self.0.raster.dynamic().color().has_alpha().then(|| {
|
||||||
Arc::new(
|
self.0.raster
|
||||||
self.raster
|
.dynamic()
|
||||||
.dynamic()
|
.pixels()
|
||||||
.pixels()
|
.map(|(_, _, Rgba([_, _, _, a]))| a)
|
||||||
.map(|(_, _, Rgba([_, _, _, a]))| a)
|
.collect()
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| &***v)
|
.map(|v| &**v)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bits_per_component(&self) -> BitsPerComponent {
|
fn bits_per_component(&self) -> BitsPerComponent {
|
||||||
@ -134,18 +134,18 @@ impl CustomImage for PdfImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
(self.raster.width(), self.raster.height())
|
(self.0.raster.width(), self.0.raster.height())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn icc_profile(&self) -> Option<&[u8]> {
|
fn icc_profile(&self) -> Option<&[u8]> {
|
||||||
if matches!(
|
if matches!(
|
||||||
self.raster.dynamic().as_ref(),
|
self.0.raster.dynamic().as_ref(),
|
||||||
DynamicImage::ImageLuma8(_)
|
DynamicImage::ImageLuma8(_)
|
||||||
| DynamicImage::ImageLumaA8(_)
|
| DynamicImage::ImageLumaA8(_)
|
||||||
| DynamicImage::ImageRgb8(_)
|
| DynamicImage::ImageRgb8(_)
|
||||||
| DynamicImage::ImageRgba8(_)
|
| DynamicImage::ImageRgba8(_)
|
||||||
) {
|
) {
|
||||||
self.raster.icc().map(|b| b.as_bytes())
|
self.0.raster.icc().map(|b| b.as_bytes())
|
||||||
} else {
|
} else {
|
||||||
// In all other cases, the dynamic will be converted into RGB8 or LUMA8, so the ICC
|
// In all other cases, the dynamic will be converted into RGB8 or LUMA8, so the ICC
|
||||||
// profile may become invalid, and thus we don't include it.
|
// profile may become invalid, and thus we don't include it.
|
||||||
@ -155,7 +155,7 @@ impl CustomImage for PdfImage {
|
|||||||
|
|
||||||
fn color_space(&self) -> ImageColorspace {
|
fn color_space(&self) -> ImageColorspace {
|
||||||
// Remember that we convert all images to either RGB or luma.
|
// Remember that we convert all images to either RGB or luma.
|
||||||
if self.raster.dynamic().color().has_color() {
|
if self.0.raster.dynamic().color().has_color() {
|
||||||
ImageColorspace::Rgb
|
ImageColorspace::Rgb
|
||||||
} else {
|
} else {
|
||||||
ImageColorspace::Luma
|
ImageColorspace::Luma
|
||||||
|
Loading…
x
Reference in New Issue
Block a user