1 extern crate jpeg_decoder as jpeg; 2 extern crate png; 3 4 use std::env; 5 use std::fs::File; 6 use std::io::{self, BufReader, Write}; 7 use std::process; 8 usage() -> !9fn usage() -> ! { 10 write!(io::stderr(), "usage: decode image.jpg image.png").unwrap(); 11 process::exit(1) 12 } 13 main()14fn main() { 15 let mut args = env::args().skip(1); 16 let input_path = args.next().unwrap_or_else(|| usage()); 17 let output_path = args.next().unwrap_or_else(|| usage()); 18 19 let input_file = File::open(input_path).expect("The specified input file could not be opened"); 20 let mut decoder = jpeg::Decoder::new(BufReader::new(input_file)); 21 let mut data = decoder.decode().expect("Decoding failed. If other software can successfully decode the specified JPEG image, then it's likely that there is a bug in jpeg-decoder"); 22 let info = decoder.info().unwrap(); 23 24 let output_file = File::create(output_path).unwrap(); 25 let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32); 26 encoder.set_depth(png::BitDepth::Eight); 27 28 match info.pixel_format { 29 jpeg::PixelFormat::L8 => encoder.set_color(png::ColorType::Grayscale), 30 jpeg::PixelFormat::RGB24 => encoder.set_color(png::ColorType::RGB), 31 jpeg::PixelFormat::CMYK32 => { 32 data = cmyk_to_rgb(&mut data); 33 encoder.set_color(png::ColorType::RGB) 34 }, 35 }; 36 37 encoder.write_header() 38 .expect("writing png header failed") 39 .write_image_data(&data) 40 .expect("png encoding failed"); 41 } 42 cmyk_to_rgb(input: &[u8]) -> Vec<u8>43fn cmyk_to_rgb(input: &[u8]) -> Vec<u8> { 44 let size = input.len() - input.len() / 4; 45 let mut output = Vec::with_capacity(size); 46 47 for pixel in input.chunks(4) { 48 let c = pixel[0] as f32 / 255.0; 49 let m = pixel[1] as f32 / 255.0; 50 let y = pixel[2] as f32 / 255.0; 51 let k = pixel[3] as f32 / 255.0; 52 53 // CMYK -> CMY 54 let c = c * (1.0 - k) + k; 55 let m = m * (1.0 - k) + k; 56 let y = y * (1.0 - k) + k; 57 58 // CMY -> RGB 59 let r = (1.0 - c) * 255.0; 60 let g = (1.0 - m) * 255.0; 61 let b = (1.0 - y) * 255.0; 62 63 output.push(r as u8); 64 output.push(g as u8); 65 output.push(b as u8); 66 } 67 68 output 69 } 70