view examples/common.rs @ 718:c187e0a6b751

ecl_vm: Implement 121 functions 0 and 1.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 24 Sep 2019 17:49:23 +0200
parents d5d5496e4e53
children 8d29dac12219
line wrap: on
line source

use image::{GenericImageView, DynamicImage, ImageError};
use luminance::pixel::{NormRGB8UI, NormRGBA8UI};
use luminance::texture::{Dim2, Flat, Sampler, Texture, GenMipmaps};
use luminance_glfw::GlfwSurface;
use touhou::th06::anm0::Anm0;
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::Path;

pub fn load_file_into_vec(filename: &Path) -> Vec<u8> {
    let file = File::open(filename).unwrap();
    let mut file = BufReader::new(file);
    let mut buf = vec![];
    file.read_to_end(&mut buf).unwrap();
    buf
}

pub enum LoadedTexture {
    Rgba(Texture<Flat, Dim2, NormRGBA8UI>),
    Rgb(Texture<Flat, Dim2, NormRGB8UI>),
}

#[derive(Debug)]
pub enum TextureLoadError {
    CannotOpenRgb(String, ImageError),
    CannotOpenAlpha(String, ImageError),
    AlphaToGrayscale(String),
}

fn load_rgb_png(surface: &mut GlfwSurface, path: &Path) -> Result<LoadedTexture, TextureLoadError> {
    // load the texture into memory as a whole bloc (i.e. no streaming)
    match image::open(&path) {
        Ok(img) => {
            let (width, height) = img.dimensions();
            let texels = img
                .pixels()
                .map(|(_x, _y, rgb)| (rgb[0], rgb[1], rgb[2]))
                .collect::<Vec<_>>();

            // create the luminance texture; the third argument is the number of mipmaps we want (leave it
            // to 0 for now) and the latest is a the sampler to use when sampling the texels in the
            // shader (we’ll just use the default one)
            let tex =
                Texture::new(surface, [width, height], 0, Sampler::default()).expect("luminance texture creation");

            // the first argument disables mipmap generation (we don’t care so far)
            tex.upload(GenMipmaps::No, &texels).unwrap();

            Ok(LoadedTexture::Rgb(tex))
        }

        Err(e) => {
            Err(TextureLoadError::CannotOpenRgb(path.to_str().unwrap().to_owned(), e))
        }
    }
}

fn load_rgb_a_pngs(surface: &mut GlfwSurface, rgb: &Path, alpha: &Path) -> Result<LoadedTexture, TextureLoadError> {
    // load the texture into memory as a whole bloc (i.e. no streaming)
    match image::open(&alpha) {
        Ok(img) => {
            let (width, height) = img.dimensions();
            let alpha = match img.grayscale() {
                DynamicImage::ImageLuma8(img) => img,
                _ => {
                    return Err(TextureLoadError::AlphaToGrayscale(alpha.to_str().unwrap().to_owned()))
                }
            };
            let img = match image::open(&rgb) {
                Ok(img) => img,
                Err(e) => {
                    return Err(TextureLoadError::CannotOpenRgb(rgb.to_str().unwrap().to_owned(), e))
                },
            };
            let texels = img
                .pixels()
                .zip(alpha.pixels())
                .map(|((_x, _y, rgb), luma)| (rgb[0], rgb[1], rgb[2], luma[0]))
                .collect::<Vec<_>>();

            // create the luminance texture; the third argument is the number of mipmaps we want (leave it
            // to 0 for now) and the latest is a the sampler to use when sampling the texels in the
            // shader (we’ll just use the default one)
            let tex =
                Texture::new(surface, [width, height], 0, Sampler::default()).expect("luminance texture creation");

            // the first argument disables mipmap generation (we don’t care so far)
            tex.upload(GenMipmaps::No, &texels).unwrap();

            Ok(LoadedTexture::Rgba(tex))
        }

        Err(e) => {
            Err(TextureLoadError::CannotOpenAlpha(alpha.to_str().unwrap().to_owned(), e))
        }
    }
}

pub fn load_anm_image(mut surface: &mut GlfwSurface, anm0: &Anm0, anm_filename: &Path) -> Result<LoadedTexture, TextureLoadError> {
    let png_filename = anm_filename.with_file_name(Path::new(&anm0.png_filename).file_name().unwrap());
    match anm0.alpha_filename {
        Some(ref filename) => {
            let alpha_filename = anm_filename.with_file_name(Path::new(filename).file_name().unwrap());
            load_rgb_a_pngs(&mut surface, &png_filename, &alpha_filename)
        },
        None => {
            load_rgb_png(&mut surface, &png_filename)
        }
    }
}