@@ -841,7 +841,7 @@ fn compute_image_parallel(components: &[Component],
841841 . enumerate ( )
842842 . for_each ( |( row, line) | {
843843 upsampler. upsample_and_interleave_row ( & data, row, output_size. width as usize , line) ;
844- color_convert_func ( line, output_size . width as usize ) ;
844+ color_convert_func ( line) ;
845845 } ) ;
846846
847847 Ok ( image)
@@ -861,7 +861,7 @@ fn compute_image_parallel(components: &[Component],
861861 for ( row, line) in image. chunks_mut ( line_size)
862862 . enumerate ( ) {
863863 upsampler. upsample_and_interleave_row ( & data, row, output_size. width as usize , line) ;
864- color_convert_func ( line, output_size . width as usize ) ;
864+ color_convert_func ( line) ;
865865 }
866866
867867 Ok ( image)
@@ -870,7 +870,7 @@ fn compute_image_parallel(components: &[Component],
870870fn choose_color_convert_func ( component_count : usize ,
871871 _is_jfif : bool ,
872872 color_transform : Option < AdobeColorTransform > )
873- -> Result < fn ( & mut [ u8 ] , usize ) > {
873+ -> Result < fn ( & mut [ u8 ] ) > {
874874 match component_count {
875875 3 => {
876876 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
@@ -894,37 +894,36 @@ fn choose_color_convert_func(component_count: usize,
894894 }
895895}
896896
897- fn color_convert_line_null ( _data : & mut [ u8 ] , _width : usize ) {
897+ fn color_convert_line_null ( _data : & mut [ u8 ] ) {
898898}
899899
900- fn color_convert_line_ycbcr ( data : & mut [ u8 ] , width : usize ) {
901- for i in 0 .. width {
902- let ( r, g, b) = ycbcr_to_rgb ( data[ i * 3 ] , data[ i * 3 + 1 ] , data[ i * 3 + 2 ] ) ;
903-
904- data[ i * 3 ] = r;
905- data[ i * 3 + 1 ] = g;
906- data[ i * 3 + 2 ] = b;
900+ fn color_convert_line_ycbcr ( data : & mut [ u8 ] ) {
901+ for chunk in data. chunks_exact_mut ( 3 ) {
902+ let ( r, g, b) = ycbcr_to_rgb ( chunk[ 0 ] , chunk[ 1 ] , chunk[ 2 ] ) ;
903+ chunk[ 0 ] = r;
904+ chunk[ 1 ] = g;
905+ chunk[ 2 ] = b;
907906 }
908907}
909908
910- fn color_convert_line_ycck ( data : & mut [ u8 ] , width : usize ) {
911- for i in 0 .. width {
912- let ( r, g, b) = ycbcr_to_rgb ( data[ i * 4 ] , data[ i * 4 + 1 ] , data[ i * 4 + 2 ] ) ;
913- let k = data[ i * 4 + 3 ] ;
909+ fn color_convert_line_ycck ( data : & mut [ u8 ] ) {
910+ for chunk in data. chunks_exact_mut ( 4 ) {
911+ let ( r, g, b) = ycbcr_to_rgb ( chunk[ 0 ] , chunk[ 1 ] , chunk[ 2 ] ) ;
912+ let k = chunk[ 3 ] ;
913+ chunk[ 0 ] = r;
914+ chunk[ 1 ] = g;
915+ chunk[ 2 ] = b;
916+ chunk[ 3 ] = 255 - k;
914917
915- data[ i * 4 ] = r;
916- data[ i * 4 + 1 ] = g;
917- data[ i * 4 + 2 ] = b;
918- data[ i * 4 + 3 ] = 255 - k;
919918 }
920919}
921920
922- fn color_convert_line_cmyk ( data : & mut [ u8 ] , width : usize ) {
923- for i in 0 .. width {
924- data [ i * 4 ] = 255 - data [ i * 4 ] ;
925- data [ i * 4 + 1 ] = 255 - data [ i * 4 + 1 ] ;
926- data [ i * 4 + 2 ] = 255 - data [ i * 4 + 2 ] ;
927- data [ i * 4 + 3 ] = 255 - data [ i * 4 + 3 ] ;
921+ fn color_convert_line_cmyk ( data : & mut [ u8 ] ) {
922+ for chunk in data . chunks_exact_mut ( 4 ) {
923+ chunk [ 0 ] = 255 - chunk [ 0 ] ;
924+ chunk [ 1 ] = 255 - chunk [ 1 ] ;
925+ chunk [ 2 ] = 255 - chunk [ 2 ] ;
926+ chunk [ 3 ] = 255 - chunk [ 3 ] ;
928927 }
929928}
930929
@@ -938,13 +937,19 @@ fn ycbcr_to_rgb(y: u8, cb: u8, cr: u8) -> (u8, u8, u8) {
938937 let g = y - 0.34414 * cb - 0.71414 * cr;
939938 let b = y + 1.77200 * cb;
940939
941- ( clamp ( ( r + 0.5 ) as i32 , 0 , 255 ) as u8 ,
942- clamp ( ( g + 0.5 ) as i32 , 0 , 255 ) as u8 ,
943- clamp ( ( b + 0.5 ) as i32 , 0 , 255 ) as u8 )
940+ // TODO: Rust has defined float-to-int conversion as saturating,
941+ // which is exactly what we need here. However, as of this writing
942+ // it still hasn't reached the stable channel.
943+ // This can be simplified to `(r + 0.5) as u8` without any clamping
944+ // as soon as our MSRV reaches the version that has saturating casts.
945+ // The version without explicit clamping is also noticeably faster.
946+ ( clamp_to_u8 ( ( r + 0.5 ) as i32 ) as u8 ,
947+ clamp_to_u8 ( ( g + 0.5 ) as i32 ) as u8 ,
948+ clamp_to_u8 ( ( b + 0.5 ) as i32 ) as u8 )
944949}
945950
946- fn clamp < T : PartialOrd > ( value : T , min : T , max : T ) -> T {
947- if value < min { return min ; }
948- if value > max { return max ; }
951+ fn clamp_to_u8 ( value : i32 ) -> i32 {
952+ let value = std :: cmp :: max ( value , 0 ) ;
953+ let value = std :: cmp :: min ( value , 255 ) ;
949954 value
950955}
0 commit comments