1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use std::env;
16 use std::process::Command;
17 
18 use crabby_avif::decoder::*;
19 
main()20 fn main() {
21     // let data: [u8; 32] = [
22     //     0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66, 0x00, 0x00, 0x00,
23     //     0x00, 0x61, 0x76, 0x69, 0x66, 0x6d, 0x69, 0x66, 0x31, 0x6d, 0x69, 0x61, 0x66, 0x4d, 0x41,
24     //     0x31, 0x41,
25     // ];
26     // let data: [u8; 32] = [
27     //     0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x67, 0x00, 0x00, 0x00,
28     //     0x00, 0x61, 0x76, 0x69, 0x68, 0x6d, 0x69, 0x66, 0x31, 0x6d, 0x69, 0x61, 0x66, 0x4d, 0x41,
29     //     0x31, 0x41,
30     // ];
31     // let val = Decoder::peek_compatible_file_type(&data);
32     // println!("val: {val}");
33     // return;
34 
35     let args: Vec<String> = env::args().collect();
36 
37     if args.len() < 3 {
38         println!("Usage: {} <input_avif> <output> [--no-png]", args[0]);
39         std::process::exit(1);
40     }
41     let image_count;
42     {
43         let settings = Settings {
44             strictness: Strictness::None,
45             image_content_to_decode: ImageContentType::All,
46             allow_progressive: true,
47             ..Settings::default()
48         };
49         let mut decoder: Decoder = Default::default();
50         decoder.settings = settings;
51         match decoder.set_io_file(&args[1]) {
52             Ok(_) => {}
53             Err(err) => {
54                 println!("failed to set file io: {:#?}", err);
55                 std::process::exit(1);
56             }
57         };
58         let res = decoder.parse();
59         if res.is_err() {
60             println!("parse failed! {:#?}", res);
61             std::process::exit(1);
62         }
63         let _image = decoder.image();
64 
65         println!("\n^^^ decoder public properties ^^^");
66         println!("image_count: {}", decoder.image_count());
67         println!("timescale: {}", decoder.timescale());
68         println!(
69             "duration_in_timescales: {}",
70             decoder.duration_in_timescales()
71         );
72         println!("duration: {}", decoder.duration());
73         println!("repetition_count: {:#?}", decoder.repetition_count());
74         println!("$$$ end decoder public properties $$$\n");
75 
76         image_count = decoder.image_count();
77         //image_count = 1;
78         let mut writer: crabby_avif::utils::y4m::Y4MWriter = Default::default();
79         //let mut writer: crabby_avif::utils::raw::RawWriter = Default::default();
80         writer.filename = Some(args[2].clone());
81         //writer.rgb = true;
82 
83         for _i in 0..image_count {
84             let res = decoder.nth_image(0);
85             if res.is_err() {
86                 println!("next_image failed! {:#?}", res);
87                 std::process::exit(1);
88             }
89             let image = decoder.image().expect("image was none");
90             let ret = writer.write_frame(image);
91             if !ret {
92                 println!("error writing y4m file");
93                 std::process::exit(1);
94             }
95             println!("timing: {:#?}", decoder.image_timing());
96         }
97         println!("wrote {} frames into {}", image_count, args[2]);
98     }
99     if args.len() == 3 {
100         if image_count <= 1 {
101             let ffmpeg_infile = args[2].to_string();
102             let ffmpeg_outfile = format!("{}.png", args[2]);
103             let ffmpeg = Command::new("ffmpeg")
104                 .arg("-i")
105                 .arg(ffmpeg_infile)
106                 .arg("-frames:v")
107                 .arg("1")
108                 .arg("-y")
109                 .arg(ffmpeg_outfile)
110                 .output()
111                 .unwrap();
112             if !ffmpeg.status.success() {
113                 println!("ffmpeg to convert to png failed");
114                 std::process::exit(1);
115             }
116             println!("wrote {}.png", args[2]);
117         } else {
118             let ffmpeg_infile = args[2].to_string();
119             let ffmpeg_outfile = format!("{}.gif", args[2]);
120             let ffmpeg = Command::new("ffmpeg")
121                 .arg("-i")
122                 .arg(ffmpeg_infile)
123                 .arg("-y")
124                 .arg(ffmpeg_outfile)
125                 .output()
126                 .unwrap();
127             if !ffmpeg.status.success() {
128                 println!("ffmpeg to convert to gif failed");
129                 std::process::exit(1);
130             }
131             println!("wrote {}.gif", args[2]);
132         }
133     }
134     std::process::exit(0);
135 }
136