diff options
Diffstat (limited to 'vendor/png/examples/show.rs')
-rw-r--r-- | vendor/png/examples/show.rs | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/vendor/png/examples/show.rs b/vendor/png/examples/show.rs new file mode 100644 index 0000000..d8ddf75 --- /dev/null +++ b/vendor/png/examples/show.rs @@ -0,0 +1,198 @@ +use glium::{ + backend::glutin::Display, + glutin::{ + self, dpi, + event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event_loop::ControlFlow, + }, + texture::{ClientFormat, RawImage2d}, + BlitTarget, Rect, Surface, +}; +use std::{borrow::Cow, env, fs::File, io, path}; + +/// Load the image using `png` +fn load_image(path: &path::PathBuf) -> io::Result<RawImage2d<'static, u8>> { + use png::ColorType::*; + let mut decoder = png::Decoder::new(File::open(path)?); + decoder.set_transformations(png::Transformations::normalize_to_color8()); + let mut reader = decoder.read_info()?; + let mut img_data = vec![0; reader.output_buffer_size()]; + let info = reader.next_frame(&mut img_data)?; + + let (data, format) = match info.color_type { + Rgb => (img_data, ClientFormat::U8U8U8), + Rgba => (img_data, ClientFormat::U8U8U8U8), + Grayscale => ( + { + let mut vec = Vec::with_capacity(img_data.len() * 3); + for g in img_data { + vec.extend([g, g, g].iter().cloned()) + } + vec + }, + ClientFormat::U8U8U8, + ), + GrayscaleAlpha => ( + { + let mut vec = Vec::with_capacity(img_data.len() * 3); + for ga in img_data.chunks(2) { + let g = ga[0]; + let a = ga[1]; + vec.extend([g, g, g, a].iter().cloned()) + } + vec + }, + ClientFormat::U8U8U8U8, + ), + _ => unreachable!("uncovered color type"), + }; + + Ok(RawImage2d { + data: Cow::Owned(data), + width: info.width, + height: info.height, + format, + }) +} + +fn main_loop(files: Vec<path::PathBuf>) -> io::Result<()> { + let mut files = files.into_iter(); + let image = load_image(&files.next().unwrap())?; + + let event_loop = glutin::event_loop::EventLoop::new(); + let window_builder = glutin::window::WindowBuilder::new().with_title("Show Example"); + let context_builder = glutin::ContextBuilder::new().with_vsync(true); + let display = glium::Display::new(window_builder, context_builder, &event_loop) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; + resize_window(&display, &image); + let mut texture = glium::Texture2d::new(&display, image).unwrap(); + draw(&display, &texture); + + event_loop.run(move |event, _, control_flow| match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => exit(control_flow), + Event::WindowEvent { + event: + WindowEvent::KeyboardInput { + input: + KeyboardInput { + state: ElementState::Pressed, + virtual_keycode: code, + .. + }, + .. + }, + .. + } => match code { + Some(VirtualKeyCode::Escape) => exit(control_flow), + Some(VirtualKeyCode::Right) => match &files.next() { + Some(path) => { + match load_image(path) { + Ok(image) => { + resize_window(&display, &image); + texture = glium::Texture2d::new(&display, image).unwrap(); + draw(&display, &texture); + } + Err(err) => { + println!("Error: {}", err); + exit(control_flow); + } + }; + } + None => exit(control_flow), + }, + _ => {} + }, + Event::RedrawRequested(_) => draw(&display, &texture), + _ => {} + }); +} + +fn draw(display: &glium::Display, texture: &glium::Texture2d) { + let frame = display.draw(); + fill_v_flipped( + &texture.as_surface(), + &frame, + glium::uniforms::MagnifySamplerFilter::Linear, + ); + frame.finish().unwrap(); +} + +fn exit(control_flow: &mut ControlFlow) { + *control_flow = ControlFlow::Exit; +} + +fn fill_v_flipped<S1, S2>(src: &S1, target: &S2, filter: glium::uniforms::MagnifySamplerFilter) +where + S1: Surface, + S2: Surface, +{ + let src_dim = src.get_dimensions(); + let src_rect = Rect { + left: 0, + bottom: 0, + width: src_dim.0 as u32, + height: src_dim.1 as u32, + }; + let target_dim = target.get_dimensions(); + let target_rect = BlitTarget { + left: 0, + bottom: target_dim.1, + width: target_dim.0 as i32, + height: -(target_dim.1 as i32), + }; + src.blit_color(&src_rect, target, &target_rect, filter); +} + +fn resize_window(display: &Display, image: &RawImage2d<'static, u8>) { + let mut width = image.width; + let mut height = image.height; + if width < 50 && height < 50 { + width *= 10; + height *= 10; + } + display + .gl_window() + .window() + .set_inner_size(dpi::LogicalSize::new(f64::from(width), f64::from(height))); +} + +fn main() { + let args: Vec<String> = env::args().collect(); + if args.len() < 2 { + println!("Usage: show files [...]"); + } else { + let mut files = vec![]; + for file in args.iter().skip(1) { + match if file.contains('*') { + (|| -> io::Result<_> { + for entry in glob::glob(file) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err.msg))? + { + files.push( + entry + .map_err(|_| io::Error::new(io::ErrorKind::Other, "glob error"))?, + ) + } + Ok(()) + })() + } else { + files.push(path::PathBuf::from(file)); + Ok(()) + } { + Ok(_) => (), + Err(err) => { + println!("{}: {}", file, err); + break; + } + } + } + // "tests/pngsuite/pngsuite.png" + match main_loop(files) { + Ok(_) => (), + Err(err) => println!("Error: {}", err), + } + } +} |