@@ -6,6 +6,20 @@ use std::u8;
66use wasm_bindgen:: prelude:: * ;
77use image:: { self , ImageEncoder } ;
88
9+ // https://rustwasm.github.io/wasm-bindgen/examples/console-log.html
10+ #[ wasm_bindgen]
11+ extern "C" {
12+ #[ wasm_bindgen( js_namespace = console) ]
13+ fn log ( s : & str ) ;
14+ #[ wasm_bindgen( js_namespace = console, js_name = log) ]
15+ fn log_u32 ( a : u32 ) ;
16+ #[ wasm_bindgen( js_namespace = console, js_name = log) ]
17+ fn log_many ( a : & str , b : & str ) ;
18+ }
19+ macro_rules! console_log {
20+ ( $( $t: tt) * ) => ( log( & format_args!( $( $t) * ) . to_string( ) ) )
21+ }
22+
923pub struct ImageOptions {
1024 pub width : u32 ,
1125 pub height : u32 ,
@@ -19,9 +33,23 @@ fn str2f(s: &str) -> f32 {
1933 x
2034}
2135
22- fn img2vec ( im : & [ u8 ] ) -> ( Vec < [ u8 ; 3 ] > , ImageOptions ) {
36+ fn img2vec ( im : & [ u8 ] , limit_max_side : Option < u32 > ) -> ( Vec < [ u8 ; 3 ] > , ImageOptions ) {
2337 let img = image:: load_from_memory ( im) . expect ( "Failed to load image" ) ;
24- let rgb = img. to_rgb8 ( ) ;
38+ let mut rgb = img. to_rgb8 ( ) ;
39+
40+ if let Some ( max_side) = limit_max_side {
41+ let ( mut width, mut height) = rgb. dimensions ( ) ;
42+ if width > max_side || height > max_side {
43+ let scale = max_side as f32 / width. max ( height) as f32 ;
44+ width = ( width as f32 * scale) . round ( ) as u32 ;
45+ height = ( height as f32 * scale) . round ( ) as u32 ;
46+ rgb = image:: imageops:: resize (
47+ & rgb, width, height,
48+ image:: imageops:: FilterType :: Lanczos3
49+ ) ;
50+ }
51+ }
52+
2553 let mut pixels = Vec :: with_capacity ( rgb. width ( ) as usize * rgb. height ( ) as usize ) ;
2654 for pixel in rgb. pixels ( ) {
2755 pixels. push ( [ pixel[ 0 ] , pixel[ 1 ] , pixel[ 2 ] ] ) ;
@@ -33,8 +61,8 @@ fn img2vec(im: &[u8]) -> (Vec<[u8; 3]>, ImageOptions) {
3361 } )
3462}
3563
36- fn vec2pngblob ( pixels : & Vec < [ u8 ; 3 ] > , im_opt : ImageOptions ) -> Box < [ u8 ] > {
37- let ImageOptions { width, height } = im_opt;
64+ fn vec2pngblob ( pixels : & Vec < [ u8 ; 3 ] > , im_opt : ImageOptions , limit_max_side : Option < u32 > ) -> Box < [ u8 ] > {
65+ let ImageOptions { mut width, mut height } = im_opt;
3866
3967 let mut img = image:: RgbImage :: new ( width, height) ;
4068 for ( i, pixel) in pixels. iter ( ) . enumerate ( ) {
@@ -43,6 +71,18 @@ fn vec2pngblob(pixels: &Vec<[u8; 3]>, im_opt: ImageOptions) -> Box<[u8]> {
4371 img. put_pixel ( x, y, image:: Rgb ( * pixel) ) ;
4472 } ;
4573
74+ if let Some ( max_side) = limit_max_side {
75+ if width > max_side || height > max_side {
76+ let scale = max_side as f32 / width. max ( height) as f32 ;
77+ width = ( width as f32 * scale) . round ( ) as u32 ;
78+ height = ( height as f32 * scale) . round ( ) as u32 ;
79+ img = image:: imageops:: resize (
80+ & img, width, height,
81+ image:: imageops:: FilterType :: Lanczos3
82+ ) ;
83+ }
84+ }
85+
4686 // Encode the image to PNG format
4787 let mut buf = Vec :: new ( ) ;
4888 let encoder = image:: codecs:: png:: PngEncoder :: new ( & mut buf) ;
@@ -53,29 +93,36 @@ fn vec2pngblob(pixels: &Vec<[u8; 3]>, im_opt: ImageOptions) -> Box<[u8]> {
5393 image:: ExtendedColorType :: Rgb8 ,
5494 ) . expect ( "Failed to encode image" ) ;
5595
96+ console_log ! ( "Export image, dimensions: {}x{}" , width, height) ;
5697 buf. into_boxed_slice ( )
5798}
5899
59100#[ wasm_bindgen]
60- pub fn encode ( im : & [ u8 ] , secret : & str ) -> Box < [ u8 ] > {
61- let ( mut im_v, im_opt) = img2vec ( im) ;
101+ pub fn encode ( im : & [ u8 ] , secret : & str , max_side : i32 ) -> Box < [ u8 ] > {
102+ console_log ! ( "Encoding image with secret: {}, max_side: {}" , secret, max_side) ;
103+ let max_side = if max_side < 1 { None } else { Some ( max_side as u32 ) } ;
104+
105+ let ( mut im_v, im_opt) = img2vec ( im, max_side) ;
62106
63107 let pixels = logistic_map:: encode (
64108 & mut im_v,
65109 str2f ( & secret)
66110 ) ;
67111
68- vec2pngblob ( & pixels, im_opt)
112+ vec2pngblob ( & pixels, im_opt, None )
69113}
70114
71115#[ wasm_bindgen]
72- pub fn decode ( im : & [ u8 ] , secret : & str ) -> Box < [ u8 ] > {
73- let ( im_v, im_opt) = img2vec ( im) ;
116+ pub fn decode ( im : & [ u8 ] , secret : & str , max_side : i32 ) -> Box < [ u8 ] > {
117+ console_log ! ( "Decoding image with secret: {}, max_side: {}" , secret, max_side) ;
118+ let max_side = if max_side < 1 { None } else { Some ( max_side as u32 ) } ;
119+
120+ let ( im_v, im_opt) = img2vec ( im, None ) ;
74121
75122 let pixels = logistic_map:: decode (
76123 & im_v,
77124 str2f ( & secret)
78125 ) ;
79126
80- vec2pngblob ( & pixels, im_opt)
127+ vec2pngblob ( & pixels, im_opt, max_side )
81128}
0 commit comments