@@ -31,6 +31,10 @@ struct Args {
3131 /// Fail if any difference is found (non-zero exit code)
3232 #[ arg( long) ]
3333 fail_on_diff : bool ,
34+
35+ /// Output results in JSON format
36+ #[ arg( long) ]
37+ json : bool ,
3438}
3539
3640fn main ( ) -> Result < ( ) > {
@@ -51,21 +55,26 @@ fn run_file_diff(args: &Args) -> Result<()> {
5155 args. output . is_some ( ) || args. preview ,
5256 ) ?;
5357
54- println ! ( "{}" , "Comparison Result:" . bold( ) ) ;
55- println ! ( " Similarity: {:.2}%" , res. score * 100.0 ) ;
56- println ! ( " Diff Pixels: {}" , res. diff_pixels) ;
57- println ! ( " Total Pixels: {}" , res. total_pixels) ;
58-
59- if let Some ( diff_img) = & res. diff_image {
60- if let Some ( output_path) = & args. output {
61- diff_img. save ( output_path) ?;
62- println ! ( " Diff image saved to: {}" , output_path. display( ) . to_string( ) . cyan( ) ) ;
63- }
58+ if args. json {
59+ println ! ( "{}" , serde_json:: to_string_pretty( & res) ?) ;
60+ } else {
61+ println ! ( "{}" , "Comparison Result:" . bold( ) ) ;
62+ println ! ( " Pixel Similarity: {:.2}%" , res. score * 100.0 ) ;
63+ println ! ( " SSIM Score: {:.4}" , res. ssim_score) ;
64+ println ! ( " Diff Pixels: {}" , res. diff_pixels) ;
65+ println ! ( " Total Pixels: {}" , res. total_pixels) ;
66+
67+ if let Some ( diff_img) = & res. diff_image {
68+ if let Some ( output_path) = & args. output {
69+ diff_img. save ( output_path) ?;
70+ println ! ( " Diff image saved to: {}" , output_path. display( ) . to_string( ) . cyan( ) ) ;
71+ }
6472
65- if args. preview {
66- println ! ( "\n {}" , "Terminal Preview:" . bold( ) ) ;
67- let dynamic_img = image:: DynamicImage :: ImageRgba8 ( diff_img. clone ( ) ) ;
68- terminal:: print_preview ( & dynamic_img) ;
73+ if args. preview {
74+ println ! ( "\n {}" , "Terminal Preview:" . bold( ) ) ;
75+ let dynamic_img = image:: DynamicImage :: ImageRgba8 ( diff_img. clone ( ) ) ;
76+ terminal:: print_preview ( & dynamic_img) ;
77+ }
6978 }
7079 }
7180
@@ -79,49 +88,61 @@ fn run_file_diff(args: &Args) -> Result<()> {
7988fn run_dir_diff ( args : & Args ) -> Result < ( ) > {
8089 let items = dir:: compare_directories ( & args. path_a , & args. path_b , args. threshold ) ?;
8190
82- println ! ( "\n {:<40} {:<10} {:<10}" , "File" , "Score" , "Status" ) ;
83- println ! ( "{}" , "-" . repeat( 65 ) ) ;
84-
8591 let mut diff_count = 0 ;
8692
87- let total_files = items. len ( ) ;
88- for item in items {
89- match item. status {
90- dir:: DirDiffStatus :: Match ( res) => {
91- let status = if res. diff_pixels > 0 {
92- diff_count += 1 ;
93- "DIFF" . red ( )
94- } else {
95- "OK" . green ( )
96- } ;
97- println ! ( "{:<40} {:<10.2}% {:<10}" ,
98- item. relative_path. display( ) . to_string( ) ,
99- res. score * 100.0 ,
100- status
101- ) ;
102- }
103- dir:: DirDiffStatus :: MissingInB => {
104- diff_count += 1 ;
105- println ! ( "{:<40} {:<10} {:<10}" ,
106- item. relative_path. display( ) . to_string( ) ,
107- "-" . dimmed( ) ,
108- "MISSING" . yellow( )
109- ) ;
93+ if args. json {
94+ println ! ( "{}" , serde_json:: to_string_pretty( & items) ?) ;
95+ // Calculate diff_count for exit code even in JSON mode
96+ for item in & items {
97+ match item. status {
98+ dir:: DirDiffStatus :: Match ( ref res) if res. diff_pixels > 0 => diff_count += 1 ,
99+ dir:: DirDiffStatus :: MissingInB => diff_count += 1 ,
100+ _ => { }
110101 }
111- dir:: DirDiffStatus :: Error ( e) => {
112- println ! ( "{:<40} {:<10} {:<10}" ,
113- item. relative_path. display( ) . to_string( ) ,
114- "ERROR" . red( ) ,
115- e. yellow( )
116- ) ;
102+ }
103+ } else {
104+ println ! ( "\n {:<40} {:<10} {:<10} {:<10}" , "File" , "Pixel" , "SSIM" , "Status" ) ;
105+ println ! ( "{}" , "-" . repeat( 75 ) ) ;
106+
107+ for item in & items {
108+ match item. status {
109+ dir:: DirDiffStatus :: Match ( ref res) => {
110+ let status = if res. diff_pixels > 0 {
111+ diff_count += 1 ;
112+ "DIFF" . red ( )
113+ } else {
114+ "OK" . green ( )
115+ } ;
116+ println ! ( "{:<40} {:<10.2}% {:<10.4} {:<10}" ,
117+ item. relative_path. display( ) . to_string( ) ,
118+ res. score * 100.0 ,
119+ res. ssim_score,
120+ status
121+ ) ;
122+ }
123+ dir:: DirDiffStatus :: MissingInB => {
124+ diff_count += 1 ;
125+ println ! ( "{:<40} {:<10} {:<10}" ,
126+ item. relative_path. display( ) . to_string( ) ,
127+ "-" . dimmed( ) ,
128+ "MISSING" . yellow( )
129+ ) ;
130+ }
131+ dir:: DirDiffStatus :: Error ( ref e) => {
132+ println ! ( "{:<40} {:<10} {:<10}" ,
133+ item. relative_path. display( ) . to_string( ) ,
134+ "ERROR" . red( ) ,
135+ e. yellow( )
136+ ) ;
137+ }
117138 }
118139 }
119- }
120140
121- println ! ( "\n Summary: {} files compared, {} differences found." ,
122- total_files,
123- diff_count
124- ) ;
141+ println ! ( "\n Summary: {} files compared, {} differences found." ,
142+ items. len( ) ,
143+ diff_count
144+ ) ;
145+ }
125146
126147 if args. fail_on_diff && diff_count > 0 {
127148 std:: process:: exit ( 1 ) ;
0 commit comments