Skip to content

Commit 08fde0d

Browse files
committed
fix: image leaks
1 parent bd1e40e commit 08fde0d

26 files changed

Lines changed: 570 additions & 590 deletions

File tree

crates/canvas-2d/src/image_bitmap.rs

Lines changed: 69 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![allow(dead_code)]
22
use std::sync::Arc;
33

4-
use skia_safe::{surfaces, EncodedImageFormat};
4+
use skia_safe::surfaces;
55

66
use canvas_core::image_asset::ImageAsset;
77

@@ -201,91 +201,90 @@ pub(crate) fn create_image_bitmap_internal(
201201
resize_height: f32,
202202
output: &ImageAsset,
203203
) {
204-
let mut out_width = image.width() as f32;
205-
let mut out_height = image.height() as f32;
204+
let img_w = image.width() as f32;
205+
let img_h = image.height() as f32;
206206

207-
if resize_width <= 0. && resize_height > 0. {
208-
out_width = image.width() as f32 + resize_height / image.height() as f32;
209-
}
210-
211-
if resize_height <= 0. && resize_width > 0. {
212-
out_height = image.height() as f32 + resize_width / image.width() as f32;
213-
}
207+
// Only one of resize_width / resize_height being set means proportional scale.
208+
let (mut out_width, mut out_height) = (img_w, img_h);
214209

215210
if resize_width > 0. && resize_height > 0. {
216211
out_width = resize_width;
217212
out_height = resize_height;
213+
} else if resize_width > 0. {
214+
let ratio = resize_width / img_w;
215+
out_width = resize_width;
216+
out_height = img_h * ratio;
217+
} else if resize_height > 0. {
218+
let ratio = resize_height / img_h;
219+
out_width = img_w * ratio;
220+
out_height = resize_height;
218221
}
219222

220-
let source_rect;
221-
222-
match rect {
223-
None => {
224-
source_rect =
225-
skia_safe::Rect::from_xywh(0., 0., image.width() as f32, image.height() as f32);
226-
}
227-
Some(rect) => {
228-
source_rect = skia_safe::Rect::from_xywh(rect.0, rect.1, rect.2, rect.3);
223+
let source_rect = match rect {
224+
None => skia_safe::Rect::from_xywh(0., 0., img_w, img_h),
225+
Some(r) => {
226+
let sr = skia_safe::Rect::from_xywh(r.0, r.1, r.2, r.3);
229227
if resize_width == 0. && resize_height == 0. {
230-
out_width = rect.1;
231-
out_height = rect.2;
228+
out_width = sr.width();
229+
out_height = sr.height();
232230
}
231+
sr
233232
}
234-
}
233+
};
234+
235+
let alpha_type = ImageBitmapPremultiplyAlpha::from(premultiply_alpha).into();
236+
let color_space = ImageBitmapColorSpaceConversion::from(color_space_conversion).to_color_space();
235237

236238
let image_info = skia_safe::ImageInfo::new(
237239
(source_rect.width() as i32, source_rect.height() as i32),
238240
skia_safe::ColorType::RGBA8888,
239-
ImageBitmapPremultiplyAlpha::from(premultiply_alpha).into(),
240-
ImageBitmapColorSpaceConversion::from(color_space_conversion).to_color_space(),
241+
alpha_type,
242+
color_space,
241243
);
242244

243-
match surfaces::raster(&image_info, Some((source_rect.width() * 4.) as usize), None) {
244-
None => {}
245-
Some(mut surface) => {
246-
let canvas = surface.canvas();
247-
if flip_y {
248-
canvas.translate(skia_safe::Vector::new(0., source_rect.height()));
249-
canvas.scale((1., -1.));
250-
}
245+
let mut surface = match surfaces::raster(&image_info, Some((source_rect.width() * 4.) as usize), None) {
246+
None => return,
247+
Some(s) => s,
248+
};
251249

252-
let mut paint = skia_safe::Paint::default();
253-
paint.set_anti_alias(true);
254-
255-
surface
256-
.canvas()
257-
.draw_image(&image, (source_rect.x(), source_rect.y()), Some(&paint));
258-
259-
let image = surface.image_snapshot();
260-
261-
if image.width() != out_width as i32 && image.height() != out_height as i32 {
262-
let resize_info = image_info.with_dimensions((out_width as i32, out_height as i32));
263-
264-
let mut bytes = vec![0_u8; (out_width * out_height * 4.) as usize];
265-
if let Some(pixel_map) = skia_safe::Pixmap::new(
266-
&resize_info,
267-
bytes.as_mut_slice(),
268-
(out_width * 4.) as usize,
269-
) {
270-
let _ = image.scale_pixels(
271-
&pixel_map,
272-
ImageBitmapResizeQuality::from(resize_quality).to_quality(),
273-
None,
274-
);
275-
276-
let data = pixel_map.encode(EncodedImageFormat::PNG, 75);
277-
278-
if let Some(data) = data {
279-
output.load_from_bytes(data.as_slice());
280-
};
281-
}
282-
} else {
283-
let encoded = image.encode(None, EncodedImageFormat::PNG, 75);
284-
285-
if let Some(encoded) = encoded {
286-
output.load_from_bytes(encoded.as_bytes());
287-
}
288-
}
250+
{
251+
let canvas = surface.canvas();
252+
if flip_y {
253+
canvas.translate(skia_safe::Vector::new(0., source_rect.height()));
254+
canvas.scale((1., -1.));
255+
}
256+
let mut paint = skia_safe::Paint::default();
257+
paint.set_anti_alias(true);
258+
canvas.draw_image(&image, (-source_rect.x(), -source_rect.y()), Some(&paint));
259+
}
260+
261+
let snapshot = surface.image_snapshot();
262+
let needs_resize = snapshot.width() != out_width as i32 || snapshot.height() != out_height as i32;
263+
264+
if needs_resize {
265+
let resize_info = image_info.with_dimensions((out_width as i32, out_height as i32));
266+
let row_bytes = (out_width * 4.) as usize;
267+
let mut pixels = vec![0_u8; out_height as usize * row_bytes];
268+
269+
if let Some(pixel_map) = skia_safe::Pixmap::new(&resize_info, pixels.as_mut_slice(), row_bytes) {
270+
let _ = snapshot.scale_pixels(
271+
&pixel_map,
272+
ImageBitmapResizeQuality::from(resize_quality).to_quality(),
273+
None,
274+
);
275+
}
276+
output.load_from_raw_bytes_rgba(out_width as u32, out_height as u32, pixels);
277+
} else {
278+
let row_bytes = (snapshot.width() * 4) as usize;
279+
let mut pixels = vec![0_u8; snapshot.height() as usize * row_bytes];
280+
let read_info = skia_safe::ImageInfo::new(
281+
snapshot.dimensions(),
282+
skia_safe::ColorType::RGBA8888,
283+
alpha_type,
284+
None,
285+
);
286+
if snapshot.read_pixels(&read_info, pixels.as_mut_slice(), row_bytes, (0, 0), skia_safe::image::CachingHint::Allow) {
287+
output.load_from_raw_bytes_rgba(snapshot.width() as u32, snapshot.height() as u32, pixels);
289288
}
290289
}
291290
}
@@ -492,7 +491,7 @@ pub fn create_image_asset_encoded_raw(
492491
premultiply_alpha,
493492
color_space_conversion,
494493
resize_quality,
495-
resize_height,
496494
resize_width,
495+
resize_height,
497496
))) as i64
498497
}

0 commit comments

Comments
 (0)