@@ -2,11 +2,9 @@ use structopt::StructOpt;
2
2
use image:: GenericImageView ;
3
3
use num_traits:: pow:: Pow ;
4
4
use bitvec:: prelude:: * ;
5
- use std:: convert:: From ;
6
5
use std:: string:: String ;
7
-
8
- mod hpsnr;
9
-
6
+ use img_quality;
7
+ use std:: fmt;
10
8
11
9
#[ derive( StructOpt , Debug ) ]
12
10
#[ structopt( name = "basic" ) ]
@@ -15,67 +13,122 @@ struct Opt {
15
13
file : String
16
14
}
17
15
16
+ #[ derive( Clone ) ]
17
+ struct VecBlock {
18
+ width : usize , height : usize ,
19
+ pixels : Vec < u8 >
20
+ }
18
21
22
+ #[ derive( Debug , Clone ) ]
19
23
struct BtcBlock {
20
- highCcolor : u8 ,
21
- lowColor : u8 ,
22
- pixels : BitVec
24
+ highColor : u8 , lowColor : u8 ,
25
+ width : usize , height : usize ,
26
+ pixels : Vec < u8 >
23
27
}
24
28
29
+ impl fmt:: Display for BtcBlock { fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
30
+ return write ! ( f, "VecBlock ({}, {}) with a = {}, b = {} has pixels {:?}" , self . width, self . height, self . highColor, self . lowColor, self . pixels) ;
31
+ } }
32
+
25
33
struct BtcImage {
26
- imgSize : ( u32 , u32 ) ,
27
- blockSize : ( u32 , u32 ) ,
34
+ blockCountX : usize , blockCountY : usize ,
35
+ width : usize , height : usize ,
28
36
blocks : Vec < BtcBlock >
29
37
}
30
38
39
+ fn no_overflow_cast ( x : f64 ) -> u8 {
40
+ if x < 0.0 { 0 } else if x > 255.0 { 255 } else { x as u8 }
41
+ }
42
+
43
+ fn get_block_nb ( i : usize , img_width : usize , img_height : usize , block_width : usize , block_height : usize , block_count_x : usize ) -> ( usize , usize , usize ) {
44
+ let pos_x = ( i % img_width) as usize ;
45
+ let pos_y = ( ( i - pos_x) / img_width) as usize ;
46
+
47
+ let block_x = pos_x / block_width;
48
+ let block_y = pos_y / block_height;
49
+ let block_count = block_x + ( block_y * block_count_x) ;
50
+ //println!("{:?}, {:?}, {:?}, {:?}, {:?}, {:?}, ", block_x, block_y, block_count_x, block_count_y, pos_x, pos_y);
51
+
52
+ let block_pos_x = pos_x % block_width;
53
+ let block_pos_y = pos_y % block_height;
54
+
55
+ return ( block_count, block_pos_x, block_pos_y) ;
56
+ }
31
57
32
58
fn btc_encode ( image : image:: DynamicImage , blockWidth : usize , blockHeight : usize ) -> BtcImage {
33
- let mut pixels : Vec < u8 > = image. raw_pixels ( ) ;
59
+ let pixels : Vec < u8 > = image. raw_pixels ( ) ;
34
60
let size = image. dimensions ( ) ;
35
61
let img_width = size. 0 as usize ;
36
62
let img_height = size. 1 as usize ;
37
63
38
-
39
-
40
-
41
64
// Build the blocks
42
65
let block_count_x = ( img_width as f64 / blockWidth as f64 ) . ceil ( ) as usize ;
43
66
let block_count_y = ( img_height as f64 / blockHeight as f64 ) . ceil ( ) as usize ;
44
- let block_count_total = block_count_x* block_count_y;
45
- let mut blocks: Vec < Vec < u8 > > = vec ! [ vec![ ] ; block_count_total] ;
67
+ let block_count_total = block_count_x * block_count_y;
68
+ let mut blocks: Vec < VecBlock > = vec ! [ VecBlock { height : 0 , width : 0 , pixels : vec![ ] } ; block_count_total] ;
69
+
46
70
for i in 0 ..pixels. len ( ) {
47
- let pos_x = ( i % img_width) as usize ;
48
- let pos_y = ( ( i - pos_x) / img_width) as usize ;
71
+
72
+ let ( block_pos, block_pos_x, block_pos_y) = get_block_nb ( i, img_width, img_height, blockWidth, blockHeight, block_count_x) ;
73
+ let block = & mut blocks[ block_pos] ;
49
74
50
- let block_x = pos_x / blockWidth;
51
- let block_y = pos_y / blockHeight;
52
- let block_count = block_x + ( block_y * block_count_y) ;
75
+ if block_pos_x + 1 > block. width { block. width = block_pos_x + 1 ; }
76
+ if block_pos_y + 1 > block. height { block. height = block_pos_y + 1 ; }
77
+ block. pixels . push ( pixels[ i] ) ;
78
+ }
53
79
54
- //println!("{:?}, {:?}, {:?}, {:?}, {:?}, {:?}, ", block_x, block_y, block_count_x, block_count_y, pos_x, pos_y);
80
+ // println!("{:?}, {:?}", blocks[0].len(), blocks[0]);
81
+ // println!("{:?}", pixels.len());
55
82
56
- blocks[ block_count] . push ( pixels[ i] ) ;
83
+ let mut result : BtcImage = BtcImage { blockCountX : block_count_x, blockCountY : block_count_y, blocks : vec ! [ ] , width : img_width, height : img_height} ;
84
+ for i in 0 ..blocks. len ( ) {
85
+ let block = & blocks[ i] ;
86
+
87
+ let h : f64 = block. pixels . iter ( ) . map ( |& x| x as f64 ) . sum :: < f64 > ( ) as f64 / block. pixels . len ( ) as f64 ;
88
+ let h2 : f64 = block. pixels . iter ( ) . map ( |& val| ( val as f64 ) . pow ( 2 ) ) . sum :: < f64 > ( ) / block. pixels . len ( ) as f64 ;
89
+ let theta : f64 = ( h2 - h. pow ( 2 ) as f64 ) . sqrt ( ) ;
90
+ let q = block. pixels . iter ( ) . filter ( |& & x| x as f64 >= h) . count ( ) as f64 ;
91
+ let m = block. pixels . len ( ) as f64 ;
92
+
93
+ let a = if m-q == 0.0 { h } else { h - ( theta * ( q/( m-q) ) . sqrt ( ) ) } ;
94
+ let b = if q == 0.0 { h } else { h + ( theta * ( ( m-q) /q) . sqrt ( ) ) } ;
95
+ // println!("{:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, ", i, h, h2, theta, q, m, a, b);
96
+
97
+ //let pix : BitVec = block.pixels.iter().map(|&x| if x < h as u8 { 0 } else { 1 }).collect::<Vec<u8>>().into();
98
+ let pix : Vec < u8 > = block. pixels . iter ( ) . map ( |& x| if x < h as u8 { 0 } else { 1 } ) . collect :: < Vec < u8 > > ( ) . into ( ) ;
99
+ let newblock = BtcBlock { pixels : pix, lowColor : no_overflow_cast ( a) , highColor : no_overflow_cast ( b) , width : block. width , height : block. height } ;
100
+ //println!("newblock : {}", newblock);
101
+ result. blocks . push ( newblock) ;
102
+
57
103
}
58
104
59
- //println!("{:?}", blocks[0].len());
105
+ return result;
106
+ }
60
107
108
+ fn btc_decode ( image : BtcImage ) -> image:: DynamicImage {
109
+ let mut pixels : Vec < u8 > = vec ! [ ] ;
61
110
62
- for i in 0 ..blocks. len ( ) {
63
-
64
- let block = blocks[ i] ;
111
+ let basewidth = image. blocks [ 0 ] . width ;
112
+ let baseheight = image. blocks [ 0 ] . height ;
113
+ let fullsize = image. width * image. height ;
114
+ // println!("{:?}, {:?}", basewidth, baseheight);
65
115
66
- let avg = block. iter ( ) . sum ( ) as f64 / block. len ( ) as f64 ;
67
- let sd = ( block. iter ( ) . map ( |val| ( * val as f64 - avg) . pow ( 2 ) ) . sum ( ) as f64 / block. len ( ) as f64 ) . sqrt ( ) ;
68
-
116
+ for i in 0 ..fullsize {
117
+
118
+ let ( block_pos, block_pos_x, block_pos_y) = get_block_nb ( i, image. width , image. height , basewidth, baseheight, image. blockCountX ) ;
119
+ let block = & image. blocks [ block_pos] ;
120
+ let pixel_pos = ( block_pos_y * block. width ) + block_pos_x;
121
+
122
+ let pixel = block. pixels [ pixel_pos] ;
123
+ pixels. push ( if pixel == 1 { block. highColor } else { block. lowColor } ) ;
69
124
70
125
71
126
}
72
127
73
- return BtcImage { imgSize : ( 0 , 0 ) , blockSize : ( 0 , 0 ) , blocks : vec ! [ ] } ;
74
- }
128
+ // println!("{:?}", pixels.len());
75
129
76
- //fn btc_decode(image: BtcImage) -> image::DynamicImage {
77
-
78
- //}
130
+ return image:: DynamicImage :: ImageLuma8 ( image:: ImageBuffer :: from_vec ( image. width as u32 , image. height as u32 , pixels) . unwrap ( ) ) ;
131
+ }
79
132
80
133
81
134
fn main ( ) {
@@ -101,15 +154,23 @@ fn main() {
101
154
println ! ( "Saving input image" ) ;
102
155
img. save ( "./input.png" ) . unwrap ( ) ;
103
156
104
- /*let output = btc_decode(btc_encode(img.clone()));
157
+ let output_4 = btc_decode ( btc_encode ( img. clone ( ) , 4 , 4 ) ) ;
158
+ let output_8 = btc_decode ( btc_encode ( img. clone ( ) , 8 , 8 ) ) ;
159
+ let output_16 = btc_decode ( btc_encode ( img. clone ( ) , 16 , 16 ) ) ;
160
+ let output_32 = btc_decode ( btc_encode ( img. clone ( ) , 32 , 32 ) ) ;
105
161
106
- println!("MSE : {}", mse(&img, &output).unwrap());
162
+ println ! ( "HPSNR 4x4 : {}" , img_quality:: hpsnr( & img, & output_4) . unwrap( ) ) ;
163
+ println ! ( "HPSNR 8x8 : {}" , img_quality:: hpsnr( & img, & output_8) . unwrap( ) ) ;
164
+ println ! ( "HPSNR 16x16 : {}" , img_quality:: hpsnr( & img, & output_16) . unwrap( ) ) ;
165
+ println ! ( "HPSNR 32x32 : {}" , img_quality:: hpsnr( & img, & output_32) . unwrap( ) ) ;
107
166
108
167
109
168
110
- println!("Saving result");
111
- output.save("./output.png").unwrap();*/
112
- btc_encode ( img. clone ( ) , 32 , 32 ) ;
169
+ println ! ( "Saving results" ) ;
170
+ output_4. save ( "./output4.png" ) . unwrap ( ) ;
171
+ output_8. save ( "./output8.png" ) . unwrap ( ) ;
172
+ output_16. save ( "./output16.png" ) . unwrap ( ) ;
173
+ output_32. save ( "./output32.png" ) . unwrap ( ) ;
113
174
114
175
115
176
}
0 commit comments