Improve image rendering under rotation when exporting to PNG (#1547)

This commit is contained in:
Tom Binford 2023-06-24 05:28:02 -07:00 committed by GitHub
parent 622cef8e00
commit fa42a26f6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 11 additions and 5 deletions

View File

@ -489,13 +489,19 @@ fn render_image(
let view_height = size.y.to_f32(); let view_height = size.y.to_f32();
let aspect = (image.width() as f32) / (image.height() as f32); let aspect = (image.width() as f32) / (image.height() as f32);
let scale = ts.sx.max(ts.sy); // For better-looking output, resize `image` to its final size before painting it to `canvas`.
let w = (scale * view_width.max(aspect * view_height)).ceil() as u32; // See https://github.com/typst/typst/issues/1404#issuecomment-1598374652 for the math.
let theta = f32::atan2(-ts.kx, ts.sx);
// To avoid division by 0, choose the one of { sin, cos } that is further from 0.
let prefer_sin = theta.sin().abs() > std::f32::consts::FRAC_1_SQRT_2;
let scale_x =
f32::abs(if prefer_sin { ts.kx / theta.sin() } else { ts.sx / theta.cos() });
let w = (scale_x * view_width.max(aspect * view_height)).ceil() as u32;
let h = ((w as f32) / aspect).ceil() as u32; let h = ((w as f32) / aspect).ceil() as u32;
let pixmap = scaled_texture(image, w, h)?; let pixmap = scaled_texture(image, w, h)?;
let scale_x = view_width / pixmap.width() as f32; let paint_scale_x = view_width / pixmap.width() as f32;
let scale_y = view_height / pixmap.height() as f32; let paint_scale_y = view_height / pixmap.height() as f32;
let paint = sk::Paint { let paint = sk::Paint {
shader: sk::Pattern::new( shader: sk::Pattern::new(
@ -503,7 +509,7 @@ fn render_image(
sk::SpreadMode::Pad, sk::SpreadMode::Pad,
sk::FilterQuality::Nearest, sk::FilterQuality::Nearest,
1.0, 1.0,
sk::Transform::from_scale(scale_x, scale_y), sk::Transform::from_scale(paint_scale_x, paint_scale_y),
), ),
..Default::default() ..Default::default()
}; };

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 168 KiB