mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
fix error handling
This commit is contained in:
parent
dbac50db8f
commit
f0895c6b7b
3 changed files with 75 additions and 56 deletions
|
@ -16,9 +16,6 @@ use image::DynamicImage;
|
|||
use image::ImageDecoder;
|
||||
use image::ImageError;
|
||||
|
||||
use crate::error::image_error_message;
|
||||
use crate::error::DOMExceptionInvalidStateError;
|
||||
|
||||
//
|
||||
// About the animated image
|
||||
// > Blob .4
|
||||
|
@ -32,40 +29,43 @@ use crate::error::DOMExceptionInvalidStateError;
|
|||
//
|
||||
|
||||
pub(crate) trait ImageDecoderFromReader<'a, R: BufRead + Seek> {
|
||||
fn to_decoder(reader: R) -> Result<Self, AnyError>
|
||||
fn to_decoder(
|
||||
reader: R,
|
||||
error_fn: fn(ImageError) -> AnyError,
|
||||
) -> Result<Self, AnyError>
|
||||
where
|
||||
Self: Sized;
|
||||
fn to_intermediate_image(self) -> Result<DynamicImage, AnyError>;
|
||||
fn to_intermediate_image(
|
||||
self,
|
||||
error_fn: fn(ImageError) -> AnyError,
|
||||
) -> Result<DynamicImage, AnyError>;
|
||||
fn get_icc_profile(&mut self) -> Option<Vec<u8>>;
|
||||
}
|
||||
|
||||
pub(crate) type ImageDecoderFromReaderType<'a> = BufReader<Cursor<&'a [u8]>>;
|
||||
|
||||
pub(crate) fn image_decoding_error(
|
||||
error: ImageError,
|
||||
) -> DOMExceptionInvalidStateError {
|
||||
DOMExceptionInvalidStateError::new(&image_error_message(
|
||||
"decoding",
|
||||
&error.to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
macro_rules! impl_image_decoder_from_reader {
|
||||
($decoder:ty, $reader:ty) => {
|
||||
impl<'a, R: BufRead + Seek> ImageDecoderFromReader<'a, R> for $decoder {
|
||||
fn to_decoder(reader: R) -> Result<Self, AnyError>
|
||||
fn to_decoder(
|
||||
reader: R,
|
||||
error_fn: fn(ImageError) -> AnyError,
|
||||
) -> Result<Self, AnyError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match <$decoder>::new(reader) {
|
||||
Ok(decoder) => Ok(decoder),
|
||||
Err(err) => return Err(image_decoding_error(err).into()),
|
||||
Err(err) => return Err(error_fn(err)),
|
||||
}
|
||||
}
|
||||
fn to_intermediate_image(self) -> Result<DynamicImage, AnyError> {
|
||||
fn to_intermediate_image(
|
||||
self,
|
||||
error_fn: fn(ImageError) -> AnyError,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
match DynamicImage::from_decoder(self) {
|
||||
Ok(image) => Ok(image),
|
||||
Err(err) => Err(image_decoding_error(err).into()),
|
||||
Err(err) => Err(error_fn(err)),
|
||||
}
|
||||
}
|
||||
fn get_icc_profile(&mut self) -> Option<Vec<u8>> {
|
||||
|
|
|
@ -89,7 +89,10 @@ where
|
|||
/// Premultiply the alpha channel of the image.
|
||||
pub(crate) fn premultiply_alpha(
|
||||
image: DynamicImage,
|
||||
unmatch: Option<fn(ColorType) -> Result<DynamicImage, AnyError>>,
|
||||
unmatch_color_handler: fn(
|
||||
ColorType,
|
||||
DynamicImage,
|
||||
) -> Result<DynamicImage, AnyError>,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
let color = image.color();
|
||||
match color {
|
||||
|
@ -105,10 +108,7 @@ pub(crate) fn premultiply_alpha(
|
|||
ColorType::Rgba16 => Ok(DynamicImage::ImageRgba16(
|
||||
process_premultiply_alpha(&image.to_rgba16()),
|
||||
)),
|
||||
x => match unmatch {
|
||||
Some(unmatch) => unmatch(x),
|
||||
None => Ok(image),
|
||||
},
|
||||
x => unmatch_color_handler(x, image),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,10 @@ where
|
|||
/// Invert the premultiplied alpha channel of the image.
|
||||
pub(crate) fn unpremultiply_alpha(
|
||||
image: DynamicImage,
|
||||
unmatch: Option<fn(ColorType) -> Result<DynamicImage, AnyError>>,
|
||||
unmatch_color_handler: fn(
|
||||
ColorType,
|
||||
DynamicImage,
|
||||
) -> Result<DynamicImage, AnyError>,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
match image.color() {
|
||||
ColorType::La8 => Ok(DynamicImage::ImageLumaA8(
|
||||
|
@ -232,10 +235,7 @@ pub(crate) fn unpremultiply_alpha(
|
|||
ColorType::Rgba16 => Ok(DynamicImage::ImageRgba16(
|
||||
process_unpremultiply_alpha(&image.to_rgba16()),
|
||||
)),
|
||||
x => match unmatch {
|
||||
Some(unmatch) => unmatch(x),
|
||||
None => Ok(image),
|
||||
},
|
||||
x => unmatch_color_handler(x, image),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -387,7 +387,10 @@ where
|
|||
/// Convert the color space of the image from sRGB to Display-P3.
|
||||
pub(crate) fn srgb_to_display_p3(
|
||||
image: DynamicImage,
|
||||
unmatch: Option<fn(ColorType) -> Result<DynamicImage, AnyError>>,
|
||||
unmatch_color_handler: fn(
|
||||
ColorType,
|
||||
DynamicImage,
|
||||
) -> Result<DynamicImage, AnyError>,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
match image.color() {
|
||||
// The conversion of the lumincance color types to the display-p3 color space is meaningless.
|
||||
|
@ -407,10 +410,7 @@ pub(crate) fn srgb_to_display_p3(
|
|||
ColorType::Rgba16 => Ok(DynamicImage::ImageRgba16(
|
||||
process_srgb_to_display_p3(&image.to_rgba16()),
|
||||
)),
|
||||
x => match unmatch {
|
||||
Some(unmatch) => unmatch(x),
|
||||
None => Ok(image),
|
||||
},
|
||||
x => unmatch_color_handler(x, image),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ where
|
|||
pub(crate) fn to_srgb_from_icc_profile(
|
||||
image: DynamicImage,
|
||||
icc_profile: Option<Vec<u8>>,
|
||||
unmatch: Option<fn(ColorType) -> Result<DynamicImage, AnyError>>,
|
||||
unmatch_color_handler: fn(ColorType, DynamicImage) -> Result<DynamicImage, AnyError>,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
match icc_profile {
|
||||
// If there is no color profile information, return the image as is.
|
||||
|
@ -586,10 +586,7 @@ pub(crate) fn to_srgb_from_icc_profile(
|
|||
ColorType::Rgba16 => {
|
||||
Ok(DynamicImage::ImageRgba16(process_icc_profile_conversion::<_,_,8>(&image,icc_profile,srgb_icc_profile)))
|
||||
}
|
||||
x => match unmatch {
|
||||
Some(unmatch) => unmatch(x),
|
||||
None => Ok(image),
|
||||
},
|
||||
x => unmatch_color_handler(x, image),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@ use image::imageops::overlay;
|
|||
use image::imageops::FilterType;
|
||||
use image::ColorType;
|
||||
use image::DynamicImage;
|
||||
use image::ImageError;
|
||||
use image::RgbaImage;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
@ -111,55 +112,62 @@ fn decode_bitmap_data(
|
|||
) -> Result<DecodeBitmapDataReturn, AnyError> {
|
||||
let (image, width, height, icc_profile) = match image_bitmap_source {
|
||||
ImageBitmapSource::Blob => {
|
||||
fn image_decoding_error(error: ImageError) -> AnyError {
|
||||
DOMExceptionInvalidStateError::new(&image_error_message(
|
||||
"decoding",
|
||||
&error.to_string(),
|
||||
))
|
||||
.into()
|
||||
}
|
||||
let (image, icc_profile) = match &*mime_type {
|
||||
// Should we support the "image/apng" MIME type here?
|
||||
"image/png" => {
|
||||
let mut decoder: PngDecoder<ImageDecoderFromReaderType> =
|
||||
ImageDecoderFromReader::to_decoder(BufReader::new(Cursor::new(
|
||||
buf,
|
||||
)))?;
|
||||
)), image_decoding_error)?;
|
||||
let icc_profile = decoder.get_icc_profile();
|
||||
(decoder.to_intermediate_image()?, icc_profile)
|
||||
(decoder.to_intermediate_image(image_decoding_error)?, icc_profile)
|
||||
}
|
||||
"image/jpeg" => {
|
||||
let mut decoder: JpegDecoder<ImageDecoderFromReaderType> =
|
||||
ImageDecoderFromReader::to_decoder(BufReader::new(Cursor::new(
|
||||
buf,
|
||||
)))?;
|
||||
)), image_decoding_error)?;
|
||||
let icc_profile = decoder.get_icc_profile();
|
||||
(decoder.to_intermediate_image()?, icc_profile)
|
||||
(decoder.to_intermediate_image(image_decoding_error)?, icc_profile)
|
||||
}
|
||||
"image/gif" => {
|
||||
let mut decoder: GifDecoder<ImageDecoderFromReaderType> =
|
||||
ImageDecoderFromReader::to_decoder(BufReader::new(Cursor::new(
|
||||
buf,
|
||||
)))?;
|
||||
)), image_decoding_error)?;
|
||||
let icc_profile = decoder.get_icc_profile();
|
||||
(decoder.to_intermediate_image()?, icc_profile)
|
||||
(decoder.to_intermediate_image(image_decoding_error)?, icc_profile)
|
||||
}
|
||||
"image/bmp" => {
|
||||
let mut decoder: BmpDecoder<ImageDecoderFromReaderType> =
|
||||
ImageDecoderFromReader::to_decoder(BufReader::new(Cursor::new(
|
||||
buf,
|
||||
)))?;
|
||||
)), image_decoding_error)?;
|
||||
let icc_profile = decoder.get_icc_profile();
|
||||
(decoder.to_intermediate_image()?, icc_profile)
|
||||
(decoder.to_intermediate_image(image_decoding_error)?, icc_profile)
|
||||
}
|
||||
"image/x-icon" => {
|
||||
let mut decoder: IcoDecoder<ImageDecoderFromReaderType> =
|
||||
ImageDecoderFromReader::to_decoder(BufReader::new(Cursor::new(
|
||||
buf,
|
||||
)))?;
|
||||
)), image_decoding_error)?;
|
||||
let icc_profile = decoder.get_icc_profile();
|
||||
(decoder.to_intermediate_image()?, icc_profile)
|
||||
(decoder.to_intermediate_image(image_decoding_error)?, icc_profile)
|
||||
}
|
||||
"image/webp" => {
|
||||
let mut decoder: WebPDecoder<ImageDecoderFromReaderType> =
|
||||
ImageDecoderFromReader::to_decoder(BufReader::new(Cursor::new(
|
||||
buf,
|
||||
)))?;
|
||||
)), image_decoding_error)?;
|
||||
let icc_profile = decoder.get_icc_profile();
|
||||
(decoder.to_intermediate_image()?, icc_profile)
|
||||
(decoder.to_intermediate_image(image_decoding_error)?, icc_profile)
|
||||
}
|
||||
"" => {
|
||||
return Err(
|
||||
|
@ -243,25 +251,31 @@ fn apply_color_space_conversion(
|
|||
ColorSpaceConversion::Default => {
|
||||
match image_bitmap_source {
|
||||
ImageBitmapSource::Blob => {
|
||||
fn color_unmatch(x: ColorType) -> Result<DynamicImage, AnyError> {
|
||||
fn unmatch_color_handler(
|
||||
x: ColorType,
|
||||
_: DynamicImage,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
Err(type_error(image_error_message(
|
||||
"apply colorspaceConversion: default",
|
||||
&format!("The color type {:?} is not supported.", x),
|
||||
)))
|
||||
}
|
||||
to_srgb_from_icc_profile(image, icc_profile, Some(color_unmatch))
|
||||
to_srgb_from_icc_profile(image, icc_profile, unmatch_color_handler)
|
||||
}
|
||||
ImageBitmapSource::ImageData => match predefined_color_space {
|
||||
// If the color space is sRGB, return the image as is.
|
||||
PredefinedColorSpace::Srgb => Ok(image),
|
||||
PredefinedColorSpace::DisplayP3 => {
|
||||
fn unmatch(x: ColorType) -> Result<DynamicImage, AnyError> {
|
||||
fn unmatch_color_handler(
|
||||
x: ColorType,
|
||||
_: DynamicImage,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
Err(type_error(image_error_message(
|
||||
"apply colorspace: display-p3",
|
||||
&format!("The color type {:?} is not supported.", x),
|
||||
)))
|
||||
}
|
||||
srgb_to_display_p3(image, Some(unmatch))
|
||||
srgb_to_display_p3(image, unmatch_color_handler)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -278,6 +292,12 @@ fn apply_premultiply_alpha(
|
|||
if !color.has_alpha() {
|
||||
Ok(image)
|
||||
} else {
|
||||
fn unmatch_color_handler(
|
||||
_: ColorType,
|
||||
image: DynamicImage,
|
||||
) -> Result<DynamicImage, AnyError> {
|
||||
Ok(image)
|
||||
}
|
||||
match premultiply_alpha {
|
||||
// 1.
|
||||
PremultiplyAlpha::Default => Ok(image),
|
||||
|
@ -285,7 +305,9 @@ fn apply_premultiply_alpha(
|
|||
// https://html.spec.whatwg.org/multipage/canvas.html#convert-from-premultiplied
|
||||
|
||||
// 2.
|
||||
PremultiplyAlpha::Premultiply => process_premultiply_alpha(image, None),
|
||||
PremultiplyAlpha::Premultiply => {
|
||||
process_premultiply_alpha(image, unmatch_color_handler)
|
||||
}
|
||||
// 3.
|
||||
PremultiplyAlpha::None => {
|
||||
// NOTE: It's not clear how to handle the case of ImageData.
|
||||
|
@ -295,7 +317,7 @@ fn apply_premultiply_alpha(
|
|||
return Ok(image);
|
||||
}
|
||||
|
||||
unpremultiply_alpha(image, None)
|
||||
unpremultiply_alpha(image, unmatch_color_handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue