image-blp 1.2.0

Library to encode/decode Blizzard BLP texture format
Documentation
use super::error::Error;
use super::mipmap::generate_mipmaps;
use crate::types::*;
use ::image::{imageops::FilterType, DynamicImage, RgbaImage};

pub fn dxtn_to_image(
    header: &BlpHeader,
    image: &BlpDxtn,
    mipmap_level: usize,
) -> Result<DynamicImage, Error> {
    if mipmap_level >= image.images.len() {
        return Err(Error::MissingImage(mipmap_level));
    }
    let raw_image = &image.images[mipmap_level];
    let (width, height) = header.mipmap_size(mipmap_level);
    let size = (width as usize) * (height as usize) * 4;

    let mut output = vec![0; size];
    let decoder: texpresso::Format = image.format.into();
    decoder.decompress(
        &raw_image.content,
        width as usize,
        height as usize,
        &mut output,
    );
    let result = RgbaImage::from_raw(width, height, output).ok_or(Error::Dxt1RawConvertFail)?;
    Ok(DynamicImage::ImageRgba8(result))
}

pub fn image_to_dxtn(
    image: DynamicImage,
    format: DxtnFormat,
    make_mipmaps: bool,
    mipmap_filter: FilterType,
    compress_algorithm: texpresso::Algorithm,
) -> Result<BlpDxtn, Error> {
    let raw_images = if make_mipmaps {
        generate_mipmaps(image, mipmap_filter)?.into_iter()
    } else {
        vec![image].into_iter()
    };
    let encoder: texpresso::Format = format.into();
    let mut images = vec![];
    for image in raw_images {
        let rgba = image.into_rgba8();
        let width = rgba.width() as usize;
        let height = rgba.height() as usize;
        let output_size = encoder.compressed_size(width, height);
        let mut output = vec![0; output_size];
        let params = texpresso::Params {
            algorithm: compress_algorithm,
            ..Default::default()
        };
        encoder.compress(rgba.as_raw(), width, height, params, &mut output);
        images.push(DxtnImage { content: output })
    }

    Ok(BlpDxtn {
        format,
        cmap: vec![0; 256],
        images,
    })
}