From e05036bdd1bb1fdc232c5161fb92224a7a8cef8e Mon Sep 17 00:00:00 2001 From: rianhalid Date: Sat, 27 Jan 2024 04:59:32 +0800 Subject: [PATCH 1/5] upgrade image and imageproc --- crate/Cargo.toml | 39 +++++++++++++++++++++++++-------------- crate/src/lib.rs | 8 +++++--- crate/src/multiple.rs | 2 +- crate/src/text.rs | 4 ++-- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/crate/Cargo.toml b/crate/Cargo.toml index 84414da..adb0ac1 100644 --- a/crate/Cargo.toml +++ b/crate/Cargo.toml @@ -8,23 +8,34 @@ readme = "./README.md" repository = "https://github.com/silvia-odwyer/photon" version = "0.3.2" edition = "2021" -exclude = [ - "pkg/*", - "examples/input_images/*" -] +exclude = ["pkg/*", "examples/input_images/*"] homepage = "https://silvia-odwyer.github.io/photon/" [lib] crate-type = ["cdylib", "rlib"] [dependencies] -image = { version = "0.23.12", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"] } -palette="0.6.1" -rand="0.7.2" -imageproc = { version = "0.22.0", default-features = false } -rusttype="0.9.2" -base64="0.13.0" -time="0.3.21" +image = { version = "0.24.8", default-features = false, features = [ + "gif", + "jpeg", + "ico", + "png", + "pnm", + "tga", + "tiff", + "webp", + "bmp", + "hdr", + "dxt", + "dds", + "farbfeld", +] } +palette = "0.6.1" +rand = "0.7.2" +imageproc = { version = "0.23.0", default-features = false } +rusttype = "0.9.2" +base64 = "0.13.0" +time = "0.3.21" wasm-bindgen = { version = "=0.2.85", optional = true } serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" @@ -44,7 +55,7 @@ console_error_panic_hook = { version = "0.1.7", optional = true } wee_alloc = { version = "0.4.2", optional = true } [dev-dependencies] -time="0.3.21" +time = "0.3.21" criterion = "0.3" [[bench]] @@ -69,7 +80,7 @@ features = [ "console", 'CssStyleDeclaration', 'EventTarget', - "Blob" + "Blob", ] optional = true @@ -80,5 +91,5 @@ enable_wasm = [ "web-sys", "js-sys", "node-sys", - "console_error_panic_hook" + "console_error_panic_hook", ] diff --git a/crate/src/lib.rs b/crate/src/lib.rs index e233257..a8aa91e 100644 --- a/crate/src/lib.rs +++ b/crate/src/lib.rs @@ -43,6 +43,7 @@ use base64::{decode, encode}; use image::DynamicImage::ImageRgba8; use image::{GenericImage, GenericImageView}; use serde::{Deserialize, Serialize}; +use std::io::Cursor; #[cfg(feature = "enable_wasm")] use wasm_bindgen::prelude::*; @@ -179,7 +180,7 @@ impl PhotonImage { img = ImageRgba8(img.to_rgba8()); let mut buffer = vec![]; - img.write_to(&mut buffer, image::ImageOutputFormat::Png) + img.write_to(&mut Cursor::new(&mut buffer), image::ImageOutputFormat::Png) .unwrap(); let base64 = encode(&buffer); @@ -193,7 +194,7 @@ impl PhotonImage { let mut img = helpers::dyn_image_from_raw(self); img = ImageRgba8(img.to_rgba8()); let mut buffer = vec![]; - img.write_to(&mut buffer, image::ImageOutputFormat::Png) + img.write_to(&mut Cursor::new(&mut buffer), image::ImageOutputFormat::Png) .unwrap(); buffer } @@ -204,7 +205,8 @@ impl PhotonImage { img = ImageRgba8(img.to_rgba8()); let mut buffer = vec![]; let out_format = image::ImageOutputFormat::Jpeg(quality); - img.write_to(&mut buffer, out_format).unwrap(); + img.write_to(&mut Cursor::new(&mut buffer), out_format) + .unwrap(); buffer } diff --git a/crate/src/multiple.rs b/crate/src/multiple.rs index 1430c55..b7623dd 100644 --- a/crate/src/multiple.rs +++ b/crate/src/multiple.rs @@ -32,7 +32,7 @@ use wasm_bindgen::prelude::*; /// watermark(&mut img, &water_mark, 30_u32, 40_u32); /// ``` #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] -pub fn watermark(img: &mut PhotonImage, watermark: &PhotonImage, x: u32, y: u32) { +pub fn watermark(img: &mut PhotonImage, watermark: &PhotonImage, x: i64, y: i64) { let dyn_watermark: DynamicImage = crate::helpers::dyn_image_from_raw(watermark); let mut dyn_img: DynamicImage = crate::helpers::dyn_image_from_raw(img); image::imageops::overlay(&mut dyn_img, &dyn_watermark, x, y); diff --git a/crate/src/text.rs b/crate/src/text.rs index 3c5e5f9..38b81ad 100644 --- a/crate/src/text.rs +++ b/crate/src/text.rs @@ -35,7 +35,7 @@ use wasm_bindgen::prelude::*; /// draw_text_with_border(&mut img, "Welcome to Photon!", 10_u32, 10_u32); /// ``` #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] -pub fn draw_text_with_border(photon_img: &mut PhotonImage, text: &str, x: u32, y: u32) { +pub fn draw_text_with_border(photon_img: &mut PhotonImage, text: &str, x: i32, y: i32) { let mut image = helpers::dyn_image_from_raw(photon_img).to_rgba8(); let mut image2: DynamicImage = @@ -105,7 +105,7 @@ pub fn draw_text_with_border(photon_img: &mut PhotonImage, text: &str, x: u32, y /// draw_text(&mut img, "Welcome to Photon!", 10_u32, 10_u32); /// ``` #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] -pub fn draw_text(photon_img: &mut PhotonImage, text: &str, x: u32, y: u32) { +pub fn draw_text(photon_img: &mut PhotonImage, text: &str, x: i32, y: i32) { let mut image = helpers::dyn_image_from_raw(photon_img).to_rgba8(); let mut image2: DynamicImage = From ec34c8bda8373ea44ce3ab5953e47ec176eedaf1 Mon Sep 17 00:00:00 2001 From: rianhalid Date: Sat, 27 Jan 2024 05:20:36 +0800 Subject: [PATCH 2/5] add get_bytes_webp() --- crate/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crate/src/lib.rs b/crate/src/lib.rs index a8aa91e..afd00fb 100644 --- a/crate/src/lib.rs +++ b/crate/src/lib.rs @@ -210,6 +210,17 @@ impl PhotonImage { buffer } + /// Convert the PhotonImage to raw bytes. Returns a WEBP. + pub fn get_bytes_webp(&self) -> Vec { + let mut img = helpers::dyn_image_from_raw(self); + img = ImageRgba8(img.to_rgba8()); + let mut buffer = vec![]; + let out_format = image::ImageOutputFormat::WebP; + img.write_to(&mut Cursor::new(&mut buffer), out_format) + .unwrap(); + buffer + } + /// Convert the PhotonImage's raw pixels to JS-compatible ImageData. #[cfg(all(feature = "web-sys", feature = "wasm-bindgen"))] #[allow(clippy::unnecessary_mut_passed)] From 44bce247bfc88f7de1819b2f9a8b053b99bad6a2 Mon Sep 17 00:00:00 2001 From: rianhalid Date: Sat, 27 Jan 2024 05:48:31 +0800 Subject: [PATCH 3/5] remove usage of deprecated to_bytes() and replace with into_bytes() --- crate/src/channels.rs | 2 +- crate/src/conv.rs | 4 ++-- crate/src/effects.rs | 26 ++++++++++++----------- crate/src/helpers.rs | 2 +- crate/src/lib.rs | 12 +++++++---- crate/src/monochrome.rs | 4 ++-- crate/src/multiple.rs | 8 +++---- crate/src/native.rs | 2 +- crate/src/noise.rs | 4 ++-- crate/src/transform.rs | 47 ++++++++++++++++++++++++++--------------- 10 files changed, 65 insertions(+), 46 deletions(-) diff --git a/crate/src/channels.rs b/crate/src/channels.rs index 86c1b58..ca63557 100644 --- a/crate/src/channels.rs +++ b/crate/src/channels.rs @@ -760,7 +760,7 @@ pub fn selective_greyscale(mut photon_image: PhotonImage, ref_color: Rgb) { img.put_pixel(x, y, px); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } diff --git a/crate/src/conv.rs b/crate/src/conv.rs index 402ffd6..79e66f0 100644 --- a/crate/src/conv.rs +++ b/crate/src/conv.rs @@ -30,7 +30,7 @@ fn conv(photon_image: &mut PhotonImage, kernel: Kernel) { } } - photon_image.raw_pixels = filtered_img.to_bytes(); + photon_image.raw_pixels = filtered_img.into_bytes(); } /// Noise reduction. @@ -170,7 +170,7 @@ pub fn box_blur(photon_image: &mut PhotonImage) { pub fn gaussian_blur(photon_image: &mut PhotonImage, radius: i32) { // construct pixel data let img = helpers::dyn_image_from_raw(photon_image); - let mut src = img.to_bytes(); + let mut src = img.into_bytes(); let width = photon_image.get_width(); let height = photon_image.get_height(); diff --git a/crate/src/effects.rs b/crate/src/effects.rs index 5db3703..cdfc8d1 100644 --- a/crate/src/effects.rs +++ b/crate/src/effects.rs @@ -82,7 +82,7 @@ pub fn offset(photon_image: &mut PhotonImage, channel_index: usize, offset: u32) } } } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -194,7 +194,7 @@ pub fn multiple_offsets( img.put_pixel(x, y, px); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -311,7 +311,7 @@ pub fn halftone(photon_image: &mut PhotonImage) { // img.put_pixel(x, y + 1, px2); } } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -411,7 +411,7 @@ pub fn colorize(photon_image: &mut PhotonImage) { px = image::Rgba([r as u8, g as u8, b as u8, 255]); img.put_pixel(x, y, px); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -520,10 +520,12 @@ pub fn solarize_retimg(photon_image: &PhotonImage) -> PhotonImage { img.put_pixel(x, y, px); } + let (width, height) = img.dimensions(); + PhotonImage { - raw_pixels: img.to_bytes(), - width: img.width(), - height: img.height(), + raw_pixels: img.into_bytes(), + width, + height, } } @@ -615,7 +617,7 @@ pub fn adjust_contrast(photon_image: &mut PhotonImage, contrast: f32) { img.put_pixel(x, y, px); } - photon_image.raw_pixels = img.to_bytes(); + photon_image.raw_pixels = img.into_bytes(); } /// Tint an image by adding an offset to averaged RGB channel values. @@ -672,7 +674,7 @@ pub fn tint( img.put_pixel(x, y, px); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -692,7 +694,7 @@ fn draw_horizontal_strips(photon_image: &mut PhotonImage, num_strips: u8, color: y_pos = i as u32 * (height_strip * 2); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -766,7 +768,7 @@ fn draw_vertical_strips(photon_image: &mut PhotonImage, num_strips: u8, color: R x_pos = i as u32 * (width_strip * 2); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -925,7 +927,7 @@ pub fn oil(photon_image: &mut PhotonImage, radius: i32, intensity: f64) { ) } } - let raw_pixels = target.to_bytes(); + let raw_pixels = target.into_bytes(); photon_image.raw_pixels = raw_pixels; } /// Turn an image into an frosted glass see through diff --git a/crate/src/helpers.rs b/crate/src/helpers.rs index deb683a..bd54129 100644 --- a/crate/src/helpers.rs +++ b/crate/src/helpers.rs @@ -34,7 +34,7 @@ pub fn save_dyn_image(img: DynamicImage, filtered_img_path: &str) { /// Get raw pixels (as a vec of u8s) from a DynamicImage pub fn get_pixels(img: DynamicImage) -> Vec { // get an image's raw pixels, and return as a vec of u8s - img.to_bytes() + img.into_bytes() } /// Convert a PhotonImage to a DynamicImage type (struct used by the `image` crate) diff --git a/crate/src/lib.rs b/crate/src/lib.rs index afd00fb..ada0a16 100644 --- a/crate/src/lib.rs +++ b/crate/src/lib.rs @@ -41,7 +41,7 @@ use base64::{decode, encode}; use image::DynamicImage::ImageRgba8; -use image::{GenericImage, GenericImageView}; +use image::GenericImage; use serde::{Deserialize, Serialize}; use std::io::Cursor; @@ -485,12 +485,16 @@ pub fn base64_to_image(base64: &str) -> PhotonImage { let mut img = image::load_from_memory(slice).unwrap(); img = ImageRgba8(img.to_rgba8()); - let raw_pixels = img.to_bytes(); + + let width = img.width(); + let height = img.height(); + + let raw_pixels = img.into_bytes(); PhotonImage { raw_pixels, - width: img.width(), - height: img.height(), + width, + height, } } diff --git a/crate/src/monochrome.rs b/crate/src/monochrome.rs index 3b09ea9..227541d 100644 --- a/crate/src/monochrome.rs +++ b/crate/src/monochrome.rs @@ -317,7 +317,7 @@ pub fn grayscale_shades(photon_image: &mut PhotonImage, num_shades: u8) { img.put_pixel(x, y, image::Rgba([gray, gray, gray, 255])); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -409,7 +409,7 @@ pub fn single_channel_grayscale(photon_image: &mut PhotonImage, channel: usize) image::Rgba([channel_data, channel_data, channel_data, 255]), ); } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } diff --git a/crate/src/multiple.rs b/crate/src/multiple.rs index b7623dd..12a69f1 100644 --- a/crate/src/multiple.rs +++ b/crate/src/multiple.rs @@ -36,7 +36,7 @@ pub fn watermark(img: &mut PhotonImage, watermark: &PhotonImage, x: i64, y: i64) let dyn_watermark: DynamicImage = crate::helpers::dyn_image_from_raw(watermark); let mut dyn_img: DynamicImage = crate::helpers::dyn_image_from_raw(img); image::imageops::overlay(&mut dyn_img, &dyn_watermark, x, y); - img.raw_pixels = dyn_img.to_bytes(); + img.raw_pixels = dyn_img.into_bytes(); } /// Blend two images together. @@ -139,7 +139,7 @@ pub fn blend( ); } let dynimage = ImageRgba8(img); - photon_image.raw_pixels = dynimage.to_bytes(); + photon_image.raw_pixels = dynimage.into_bytes(); } // #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] @@ -214,7 +214,7 @@ pub fn replace_background( img.put_pixel(x, y, px); } } - let raw_pixels = img.to_bytes(); + let raw_pixels = img.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -255,7 +255,7 @@ pub fn create_gradient(width: u32, height: u32) -> PhotonImage { } } let rgba_img = ImageRgba8(image); - let raw_pixels = rgba_img.to_bytes(); + let raw_pixels = rgba_img.into_bytes(); PhotonImage { raw_pixels, width, diff --git a/crate/src/native.rs b/crate/src/native.rs index 036d056..1b1671f 100644 --- a/crate/src/native.rs +++ b/crate/src/native.rs @@ -118,5 +118,5 @@ pub fn image_to_bytes(img: PhotonImage) -> Vec { let img_buffer = ImageBuffer::from_vec(width, height, raw_pixels).unwrap(); let dynimage = ImageRgba8(img_buffer); - dynimage.to_bytes() + dynimage.into_bytes() } diff --git a/crate/src/noise.rs b/crate/src/noise.rs index dafd009..bfc3067 100644 --- a/crate/src/noise.rs +++ b/crate/src/noise.rs @@ -61,7 +61,7 @@ pub fn add_noise_rand(photon_image: &mut PhotonImage) { ); img.put_pixel(x, y, px); } - photon_image.raw_pixels = img.to_bytes(); + photon_image.raw_pixels = img.into_bytes(); } /// Add pink-tinted noise to an image. @@ -111,5 +111,5 @@ pub fn pink_noise(photon_image: &mut PhotonImage) { px = image::Rgba([new_r_val, new_g_val, new_b_val, 255]); img.put_pixel(x, y, px); } - photon_image.raw_pixels = img.to_bytes(); + photon_image.raw_pixels = img.into_bytes(); } diff --git a/crate/src/transform.rs b/crate/src/transform.rs index e0e7355..20706c4 100644 --- a/crate/src/transform.rs +++ b/crate/src/transform.rs @@ -51,11 +51,15 @@ pub fn crop( cropped_img.put_pixel(x, y, px); } let dynimage = ImageRgba8(cropped_img); - let raw_pixels = dynimage.to_bytes(); + + let width = dynimage.width(); + let height = dynimage.height(); + + let raw_pixels = dynimage.into_bytes(); PhotonImage { raw_pixels, - width: dynimage.width(), - height: dynimage.height(), + width, + height, } } @@ -130,7 +134,7 @@ pub fn fliph(photon_image: &mut PhotonImage) { } let dynimage = ImageRgba8(flipped_img); - let raw_pixels = dynimage.to_bytes(); + let raw_pixels = dynimage.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -164,7 +168,7 @@ pub fn flipv(photon_image: &mut PhotonImage) { } let dynimage = ImageRgba8(flipped_img); - let raw_pixels = dynimage.to_bytes(); + let raw_pixels = dynimage.into_bytes(); photon_image.raw_pixels = raw_pixels; } @@ -219,13 +223,16 @@ pub fn resize_img_browser( .dyn_into::() .unwrap(); - canvas.set_width(resized_img.width()); - canvas.set_height(resized_img.height()); + let width = resized_img.width(); + let height = resized_img.height(); + + canvas.set_width(width); + canvas.set_height(width); let new_img_data = ImageData::new_with_u8_clamped_array_and_sh( - Clamped(&mut resized_img.to_bytes()), - canvas.width(), - canvas.height(), + Clamped(&mut resized_img.into_bytes()), + width, + height, ); let ctx = canvas @@ -266,10 +273,13 @@ pub fn resize( sampling_filter, )); + let width = resized_img.width(); + let height = resized_img.height(); + PhotonImage { - raw_pixels: resized_img.to_bytes(), - width: resized_img.width(), - height: resized_img.height(), + raw_pixels: resized_img.into_bytes(), + width, + height, } } @@ -319,10 +329,13 @@ pub fn seam_carve(img: &PhotonImage, width: u32, height: u32) -> PhotonImage { let img = ImageRgba8(img); + let width = img.width(); + let height = img.height(); + PhotonImage { - raw_pixels: img.to_bytes(), - width: img.width(), - height: img.height(), + raw_pixels: img.into_bytes(), + width, + height, } } @@ -627,9 +640,9 @@ pub fn rotate(img: &PhotonImage, angle: i32) -> PhotonImage { } let dynimage = ImageRgba8(rgba_img); - let raw_pixels = dynimage.to_bytes(); let src_width = dynimage.width(); let src_height = dynimage.height(); + let raw_pixels = dynimage.into_bytes(); let angle_deg = positive_angle - right_angle_count * 90; if angle_deg == 0 { From 18a958986c9c6d918ed1859700471aef29e48e9f Mon Sep 17 00:00:00 2001 From: rianhalid Date: Sat, 27 Jan 2024 17:34:36 +0800 Subject: [PATCH 4/5] add .vscode to ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6ebe563..f30a6ef 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ react_app_demo/package-lock.json photon-docs/site output*.jpg output*.png +.vscode \ No newline at end of file From 3273bbbc258a73c7a93f37c1bff972ce1a3a209a Mon Sep 17 00:00:00 2001 From: rianhalid Date: Wed, 31 Jan 2024 22:38:27 +0800 Subject: [PATCH 5/5] reflect types changes in examples to make generated test pass --- crate/src/multiple.rs | 2 +- crate/src/text.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crate/src/multiple.rs b/crate/src/multiple.rs index 12a69f1..2590c04 100644 --- a/crate/src/multiple.rs +++ b/crate/src/multiple.rs @@ -29,7 +29,7 @@ use wasm_bindgen::prelude::*; /// /// let mut img = open_image("img.jpg").expect("File should open"); /// let water_mark = open_image("watermark.jpg").expect("File should open"); -/// watermark(&mut img, &water_mark, 30_u32, 40_u32); +/// watermark(&mut img, &water_mark, 30_i64, 40_i64); /// ``` #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] pub fn watermark(img: &mut PhotonImage, watermark: &PhotonImage, x: i64, y: i64) { diff --git a/crate/src/text.rs b/crate/src/text.rs index 38b81ad..1c9233f 100644 --- a/crate/src/text.rs +++ b/crate/src/text.rs @@ -32,7 +32,7 @@ use wasm_bindgen::prelude::*; /// /// // Open the image. A PhotonImage is returned. /// let mut img = open_image("img.jpg").expect("File should open"); -/// draw_text_with_border(&mut img, "Welcome to Photon!", 10_u32, 10_u32); +/// draw_text_with_border(&mut img, "Welcome to Photon!", 10_i32, 10_i32); /// ``` #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] pub fn draw_text_with_border(photon_img: &mut PhotonImage, text: &str, x: i32, y: i32) { @@ -102,7 +102,7 @@ pub fn draw_text_with_border(photon_img: &mut PhotonImage, text: &str, x: i32, y /// /// // Open the image. A PhotonImage is returned. /// let mut img = open_image("img.jpg").expect("File should open"); -/// draw_text(&mut img, "Welcome to Photon!", 10_u32, 10_u32); +/// draw_text(&mut img, "Welcome to Photon!", 10_i32, 10_i32); /// ``` #[cfg_attr(feature = "enable_wasm", wasm_bindgen)] pub fn draw_text(photon_img: &mut PhotonImage, text: &str, x: i32, y: i32) {