1- use image:: { io:: Reader as ImageReader , ImageError } ;
1+ use image:: { io:: Reader as ImageReader , GenericImageView , RgbImage } ;
22use std:: { env, io:: { self , ErrorKind } , path:: Path , ffi:: OsStr , error:: Error } ;
33use cgmath:: { Vector3 , InnerSpace } ;
44
55//From source 2013: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/materialsystem/stdshaders/common_fxc.h#L41
66const OO_SQRT_3 : f32 = 0.57735025882720947f32 ;
7- static bumpBasisTranspose : [ Vector3 < f32 > ; 3 ] = [
7+ static BUMP_BASIS_TRANSPOSE : [ Vector3 < f32 > ; 3 ] = [
88 Vector3 :: new ( 0.81649661064147949f32 , -0.40824833512306213f32 , -0.40824833512306213f32 ) ,
99 Vector3 :: new ( 0.0f32 , 0.70710676908493042f32 , -0.7071068286895752f32 ) ,
1010 Vector3 :: new ( OO_SQRT_3 , OO_SQRT_3 , OO_SQRT_3 )
1111] ;
1212
1313fn main ( ) {
1414 let mut args: Vec < String > = env:: args ( ) . collect ( ) ;
15-
15+
1616 if args. len ( ) == 1 {
1717 println ! ( "[ssbump To Normal Converter by rob5300]\n https://github.com/rob5300" ) ;
1818 println ! ( "Enter path of file to convert (or pass as launch arg):" ) ;
1919 let mut buffer = String :: new ( ) ;
2020 let stdin = io:: stdin ( ) ;
21- stdin. read_line ( & mut buffer) ;
21+ match stdin. read_line ( & mut buffer) {
22+ Err ( e) => println ! ( "Input not valid" ) ,
23+ Ok ( _) => ( ) ,
24+ }
2225 //Remove trailing new line chars
2326 if buffer. ends_with ( '\n' ) {
2427 buffer. pop ( ) ;
@@ -41,7 +44,8 @@ fn main() {
4144
4245 for x in 1 ..args. len ( ) {
4346 let arg = & args[ x] ;
44- match ConvertImage ( & arg) {
47+ println ! ( "Starting conversion of '{}'..." , arg) ;
48+ match convert_image ( & arg) {
4549 Ok ( ( ) ) => println ! ( "File '{}' converted successfully." , arg) ,
4650 Err ( e) => println ! ( "Image conversion error for '{}': {}" , arg, e)
4751 }
@@ -55,37 +59,41 @@ fn path_error() -> io::Error
5559 io:: Error :: new ( ErrorKind :: Other , "Path of image was malformed or contained invalid characters" )
5660}
5761
58- fn ConvertImage ( path : & String ) -> Result < ( ) , Box < dyn Error > > {
59- let mut img = ImageReader :: open ( path) ?. decode ( ) ?;
62+ fn convert_image ( path : & String ) -> Result < ( ) , Box < dyn Error > > {
63+ let img = ImageReader :: open ( path) ?. decode ( ) ?;
6064 let width = img. width ( ) ;
6165 let height = img. height ( ) ;
62- let rgb_img = img. as_mut_rgb8 ( ) . expect ( "Failed to get rgb image" ) ;
66+ let pixels = img. pixels ( ) ;
67+ let mut new_image = RgbImage :: new ( width, height) ;
6368
6469 //Adjust pixels on image
65- for y in 0 ..height {
66- for x in 0 ..width {
67- let pixel = rgb_img. get_pixel_mut ( x, y) ;
68- //Convert pixel colour to a vector
69- let pixel_vector = Vector3 :: new ( pixel[ 0 ] as f32 / 255f32 , pixel[ 1 ] as f32 / 255f32 , pixel[ 2 ] as f32 / 255f32 ) ;
70- //Convert normal vector back to traditional tangent normal
71- pixel[ 0 ] = ConvertVector ( & pixel_vector, 0 ) ;
72- pixel[ 1 ] = ConvertVector ( & pixel_vector, 1 ) ;
73- pixel[ 2 ] = ConvertVector ( & pixel_vector, 2 ) ;
74- }
70+ for pixel in pixels {
71+ //Convert pixel colour to a vector
72+ let rgb = pixel. 2 ;
73+ let pixel_vector = Vector3 :: new ( rgb[ 0 ] as f32 / 255f32 , rgb[ 1 ] as f32 / 255f32 , rgb[ 2 ] as f32 / 255f32 ) ;
74+ //Convert normal vector back to traditional tangent normal
75+ let new_rgb = new_image. get_pixel_mut ( pixel. 0 , pixel. 1 ) ;
76+ new_rgb[ 0 ] = convert_vector ( & pixel_vector, 0 ) ;
77+ new_rgb[ 1 ] = convert_vector ( & pixel_vector, 1 ) ;
78+ new_rgb[ 2 ] = convert_vector ( & pixel_vector, 2 ) ;
7579 }
7680
77- let originalPath = Path :: new ( path) ;
81+ let original_path = Path :: new ( path) ;
7882 //Add _normal into filename
79- let mut newFilePath = originalPath. to_owned ( ) ;
80- let oldName = originalPath. file_stem ( ) . ok_or_else ( path_error) ?. to_str ( ) . ok_or_else ( path_error) ?;
81- let oldExt = originalPath. extension ( ) . ok_or_else ( path_error) ?. to_str ( ) . ok_or_else ( path_error) ?;
82- let newFileName = [ oldName, "_normal." , oldExt] . concat ( ) ;
83- newFilePath. set_file_name ( OsStr :: new ( & newFileName) ) ;
84- img. save ( & newFilePath) ?;
85- println ! ( "Wrote new file to '{}'." , newFilePath. to_str( ) . ok_or_else( path_error) ?) ;
83+ let mut new_file_path = original_path. to_owned ( ) ;
84+ let old_name = original_path. file_stem ( ) . ok_or_else ( path_error) ?. to_str ( ) . ok_or_else ( path_error) ?;
85+ let new_file_name = [ old_name, "_normal." , "png" ] . concat ( ) ;
86+ new_file_path. set_file_name ( OsStr :: new ( & new_file_name) ) ;
87+
88+ //Save new image to disk
89+ if new_file_path. exists ( ) {
90+ println ! ( "Overriding existing image..." ) ;
91+ }
92+ new_image. save_with_format ( & new_file_path, image:: ImageFormat :: Png ) ?;
93+ println ! ( "Wrote converted normal map to '{}'." , new_file_path. to_str( ) . ok_or_else( path_error) ?) ;
8694 Ok ( ( ) )
8795}
8896
89- fn ConvertVector ( pixel : & Vector3 < f32 > , index : usize ) -> u8 {
90- return ( ( ( pixel. dot ( bumpBasisTranspose [ index] ) * 0.5f32 ) + 0.5f32 ) * 255f32 ) as u8 ;
97+ fn convert_vector ( pixel : & Vector3 < f32 > , index : usize ) -> u8 {
98+ return ( ( ( pixel. dot ( BUMP_BASIS_TRANSPOSE [ index] ) * 0.5f32 ) + 0.5f32 ) * 255f32 ) as u8 ;
9199}
0 commit comments