optimize image compression conditions and error handling

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
This commit is contained in:
ゆめ 2024-11-20 05:10:28 -06:00
parent 4c98ae337b
commit 5df98f8f05
No known key found for this signature in database
2 changed files with 73 additions and 69 deletions

View file

@ -58,11 +58,13 @@ pub fn postprocess_webp_image(
pub fn postprocess_png_image(data: &[u8], opt: &ImageOptions) -> ImageResult<Option<DynamicImage>> {
let dec = PngDecoder::new(Cursor::new(data))?;
if !dec.is_apng()? && opt.requested_resize() {
let apng = dec.is_apng()?;
if !apng && opt.requested_resize() {
return Ok(Some(postprocess_static_image(data, opt)?));
}
if opt.static_ == Some(true) {
if apng && opt.static_ == Some(true) {
let first_frame = match dec.apng()?.into_frames().next() {
Some(Ok(frame)) => frame,
_ => return Ok(None),

View file

@ -18,7 +18,7 @@ use image::{
gif::{GifEncoder, Repeat},
jpeg::JpegEncoder,
},
Frames, ImageFormat,
Frames, GenericImageView, ImageFormat,
};
use sniff::SniffingStream;
@ -312,63 +312,63 @@ where
ImageFormat::WebP
};
if options.format.is_none() {
if mime.starts_with("image/png") || mime.starts_with("image/apng") {
let result = sandboxed!(sandbox =>
image_processing::postprocess_png_image(&buf, &options)
.map_err(|e| {
ErrorResponse::postprocess_failed(e.to_string().into())
}))?;
if mime.starts_with("image/png") || mime.starts_with("image/apng") {
let result = sandboxed!(sandbox =>
image_processing::postprocess_png_image(&buf, &options)
.map_err(|e| {
ErrorResponse::postprocess_failed(e.to_string().into())
}))?;
return match result {
Some(img) => {
Ok(MediaResponse::ProcessedStaticImage(StaticImage {
data: img,
format: output_static_format,
compression: options.compression_level(),
is_https,
})
.with_timing_info(TIME_TO_FIRST_BYTE_KEY, ttfb)
.with_opt_timing_info(SLURP_TIMING_KEY, Some(slurp_dur))
.with_timing_info(TIMING_KEY, begin.elapsed()))
}
None => Ok(MediaResponse::Buffer {
data: buf,
content_type: Some("image/png".into()),
}
return match result {
None => Ok(MediaResponse::Buffer {
data: buf,
content_type: Some("image/png".into()),
}
.with_timing_info(TIME_TO_FIRST_BYTE_KEY, ttfb)
.with_opt_timing_info(SLURP_TIMING_KEY, Some(slurp_dur))
.with_timing_info(TIMING_KEY, begin.elapsed())),
Some(img) => {
Ok(MediaResponse::ProcessedStaticImage(StaticImage {
data: img,
format: output_static_format,
compression: options.compression_level(),
is_https,
})
.with_timing_info(TIME_TO_FIRST_BYTE_KEY, ttfb)
.with_opt_timing_info(SLURP_TIMING_KEY, Some(slurp_dur))
.with_timing_info(TIMING_KEY, begin.elapsed())),
};
}
if mime.starts_with("image/webp") {
let result = sandboxed!(sandbox =>
image_processing::postprocess_webp_image(&buf, &options)
.map_err(|e| {
ErrorResponse::postprocess_failed(e.to_string().into())
}))?;
.with_timing_info(TIMING_KEY, begin.elapsed()))
}
};
}
if mime.starts_with("image/webp") {
let result = sandboxed!(sandbox =>
image_processing::postprocess_webp_image(&buf, &options)
.map_err(|e| {
ErrorResponse::postprocess_failed(e.to_string().into())
}))?;
return match result {
Some(img) => {
Ok(MediaResponse::ProcessedStaticImage(StaticImage {
data: img,
format: output_static_format,
compression: options.compression_level(),
is_https,
})
.with_timing_info(TIME_TO_FIRST_BYTE_KEY, ttfb)
.with_opt_timing_info(SLURP_TIMING_KEY, Some(slurp_dur))
.with_timing_info(TIMING_KEY, begin.elapsed()))
}
None => Ok(MediaResponse::Buffer {
data: buf,
content_type: Some("image/webp".into()),
}
return match result {
None => Ok(MediaResponse::Buffer {
data: buf,
content_type: Some("image/webp".into()),
}
.with_timing_info(TIME_TO_FIRST_BYTE_KEY, ttfb)
.with_opt_timing_info(SLURP_TIMING_KEY, Some(slurp_dur))
.with_timing_info(TIMING_KEY, begin.elapsed())),
Some(img) => {
Ok(MediaResponse::ProcessedStaticImage(StaticImage {
data: img,
format: output_static_format,
compression: options.compression_level(),
is_https,
})
.with_timing_info(TIME_TO_FIRST_BYTE_KEY, ttfb)
.with_opt_timing_info(SLURP_TIMING_KEY, Some(slurp_dur))
.with_timing_info(TIMING_KEY, begin.elapsed())),
};
}
.with_timing_info(TIMING_KEY, begin.elapsed()))
}
};
}
let result = sandboxed!(sandbox => image_processing::postprocess_static_image(
@ -602,29 +602,31 @@ impl IntoResponse for StaticImage {
let mut buf = BufWriter::new(Cursor::new(Vec::new()));
if self.compression == CompressionLevel::None {
if self.compression == CompressionLevel::None
|| self.data.dimensions().0 * self.data.dimensions().1 <= 256 * 256
{
self.data.write_to(&mut buf, self.format).unwrap();
} else {
match self.format {
#[cfg(feature = "lossy-webp")]
ImageFormat::WebP => {
let enc = match webp::Encoder::from_image(&self.data) {
Ok(enc) => enc,
match webp::Encoder::from_image(&self.data) {
Ok(enc) => {
let webp = match self.compression {
CompressionLevel::Low => enc.encode(80.),
CompressionLevel::Med => enc.encode(60.),
CompressionLevel::High => enc.encode(40.),
CompressionLevel::Max => enc.encode(25.),
_ => enc.encode(100.0),
};
buf.write_all(&webp).unwrap();
}
Err(e) => {
return ErrorResponse::postprocess_failed(e.to_string().into())
.into_response();
log::warn!("webp compression failed: {:?}", e);
self.data.write_to(&mut buf, self.format).unwrap();
}
};
let webp = match self.compression {
CompressionLevel::Low => enc.encode(80.),
CompressionLevel::Med => enc.encode(60.),
CompressionLevel::High => enc.encode(40.),
CompressionLevel::Max => enc.encode(25.),
_ => enc.encode(100.0),
};
buf.write_all(&webp).unwrap();
}
ImageFormat::Jpeg => {
let mut enc = JpegEncoder::new_with_quality(