blob: e143d54706268e04a34a4d46e3a98d2970405f47 [file] [log] [blame]
extern crate glium;
extern crate glob;
extern crate png;
use std::env;
use std::io;
use std::fs::File;
use std::borrow::Cow;
use std::path;
use std::error::Error;
use glium::{Surface, Rect, BlitTarget};
use glium::texture::{RawImage2d, ClientFormat};
use glium::glutin::{self, Event, VirtualKeyCode, dpi};
use glium::backend::glutin::Display;
/// Load the image using `png`
fn load_image(path: &path::PathBuf) -> io::Result<RawImage2d<'static, u8>> {
use png::ColorType::*;
let decoder = png::Decoder::new(try!(File::open(path)));
let (info, mut reader) = try!(decoder.read_info());
let mut img_data = vec![0; info.buffer_size()];
try!(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: format
})
}
fn main_loop(files: Vec<path::PathBuf>) -> io::Result<()> {
use glium::glutin::{KeyboardInput, WindowEvent};
let mut files = files.iter();
let image = try!(load_image(files.next().unwrap()));
let mut events_loop = glutin::EventsLoop::new();
let window = glutin::WindowBuilder::new();
let context = glutin::ContextBuilder::new()
.with_vsync(true);
let display = Display::new(window, context, &events_loop)
.map_err(|err| io::Error::new(
io::ErrorKind::Other,
err.description()
))?;
// building the display, ie. the main object
resize_window(&display, &image);
let mut opengl_texture = glium::Texture2d::new(&display, image).unwrap();
let mut stop = false;
let mut res = Ok(());
'main: loop {
let frame = display.draw();
fill_v_flipped(&opengl_texture.as_surface(), &frame, glium::uniforms::MagnifySamplerFilter::Linear);
frame.finish().unwrap();
// polling and handling the events received by the window
events_loop.poll_events(|event| {
if stop {return;}
match event {
Event::WindowEvent {event: WindowEvent::CloseRequested, ..} => {
stop = true;
return;
}
Event::WindowEvent {
event: WindowEvent::KeyboardInput {
input: KeyboardInput {
state: glutin::ElementState::Pressed,
virtual_keycode: code,
..
},
..
},
..
} => match code {
Some(VirtualKeyCode::Escape) => {
stop = true;
return;
}
Some(VirtualKeyCode::Right) => {
match files.next() {
Some(path) => {
let image = match load_image(path) {
Ok(image) => image,
Err(err) => {
stop = true;
res = Err(err);
return;
}
};
resize_window(&display, &image);
opengl_texture = glium::Texture2d::new(&display, image).unwrap();
},
None => {
stop = true;
return;
}
}
},
_ => ()
},
_ => ()
}
});
if stop {break 'main;}
}
res
}
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;
} else if width < 5 && height < 5 {
width *= 10;
height *= 10;
}
display.gl_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 try!(glob::glob(&file).map_err(|err| {
io::Error::new(io::ErrorKind::Other, err.msg)
})) {
files.push(try!(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)
}
}
}