1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use gaiku_common::{Chunk, FileFormat}; use png::{ColorType, Decoder}; use std::fs::File; pub struct PNGReader; impl FileFormat for PNGReader { fn load(stream: &mut File) -> Vec<Chunk> { let mut result = vec![]; let decoder = Decoder::new(stream); match decoder.read_info() { Ok((info, mut reader)) => { println!( "PNG w: {} h: {} bit_depth: {:?} buffer_size: {} color_type: {:?}", info.width, info.height, info.bit_depth, info.buffer_size(), info.color_type ); let mut buf = vec![0; info.buffer_size()]; reader.next_frame(&mut buf).unwrap(); let data = match info.color_type { ColorType::RGB => buf, ColorType::RGBA => buf, ColorType::Grayscale => { let mut vec = Vec::with_capacity(buf.len() * 3); for g in buf { vec.extend([g, g, g].iter().cloned()) } vec } ColorType::GrayscaleAlpha => { let mut vec = Vec::with_capacity(buf.len() * 3); for ga in buf.chunks(2) { let g = ga[0]; let a = ga[1]; vec.extend([g, g, g, a].iter().cloned()) } vec } _ => unreachable!("uncovered color type"), }; let mut i = 0; let mut colors = vec![[0; 4]; (info.width * info.height) as usize]; for color in data.chunks(4) { if color.len() == 3 { colors[i] = [color[0] << 0, color[1] << 0, color[2] << 0, 255]; } else { colors[i] = [color[0] << 0, color[1] << 0, color[2] << 0, color[3] << 0]; } i += 1; } let mut chunk = Chunk::new( [0.0, 0.0, 0.0], info.width as usize, info.height as usize, 1, ); for x in 0..info.width as usize { for y in 0..info.height as usize { let color = colors[x + y * info.width as usize]; let value = (color[0] | color[1]) as f32 / 255.0; chunk.set(x, y, 0, value); } } result.push(chunk); } Err(error) => println!("PNG error: {}", error), } result } }