refactor: split kra (krita) logic into image hook
may further split this into its own crate; seems quite useful! (albeit somewhat short and easy) since there aren't any runtime dependancies, it could even go into image-extras maybe
This commit is contained in:
parent
c96a1cbdd1
commit
101adc7a89
3 changed files with 75 additions and 105 deletions
41
src/kra.rs
Normal file
41
src/kra.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
use std::{
|
||||
ffi::OsString,
|
||||
io::{self, Read},
|
||||
};
|
||||
|
||||
use image::{
|
||||
ImageDecoder, ImageError, ImageReader, ImageResult,
|
||||
error::DecodingError,
|
||||
hooks::{self, GenericReader},
|
||||
};
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub fn register() -> bool {
|
||||
hooks::register_decoding_hook(OsString::from("kra"), Box::new(hook))
|
||||
}
|
||||
|
||||
fn hook<'a>(reader: GenericReader<'a>) -> ImageResult<Box<dyn ImageDecoder + 'a>> {
|
||||
let mut zip = ZipArchive::new(reader).map_err(|e| {
|
||||
ImageError::Decoding(DecodingError::new(
|
||||
image::error::ImageFormatHint::PathExtension("kra".into()),
|
||||
e,
|
||||
))
|
||||
})?;
|
||||
|
||||
let mut reader = zip.by_name("mergedimage.png").map_err(|e| {
|
||||
ImageError::Decoding(DecodingError::new(
|
||||
image::error::ImageFormatHint::PathExtension("kra".into()),
|
||||
e,
|
||||
))
|
||||
})?;
|
||||
|
||||
// reading it all and wrapping it with a Cursor
|
||||
// is the only way I know to give it Seek
|
||||
// (which is required by ImageReader)
|
||||
let mut buf = Vec::new();
|
||||
reader.read_to_end(&mut buf)?;
|
||||
|
||||
let image_reader = ImageReader::with_format(io::Cursor::new(buf), image::ImageFormat::Png);
|
||||
|
||||
Ok(Box::new(image_reader.into_decoder()?))
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ use iced::{
|
|||
};
|
||||
use image::{EncodableLayout, RgbaImage, imageops};
|
||||
|
||||
mod kra;
|
||||
mod utils;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -209,6 +210,7 @@ impl State {
|
|||
|
||||
fn main() -> Result<(), iced::Error> {
|
||||
jxl_oxide::integration::register_image_decoding_hook();
|
||||
kra::register();
|
||||
|
||||
iced::application(State::new, State::update, State::view)
|
||||
.subscription(State::subscription)
|
||||
|
|
|
|||
75
src/utils.rs
75
src/utils.rs
|
|
@ -1,80 +1,12 @@
|
|||
use std::{
|
||||
fs,
|
||||
io::{self, Read},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use iced::widget;
|
||||
use image::{DynamicImage, ImageDecoder, ImageReader, RgbaImage};
|
||||
use rfd::FileDialog;
|
||||
use zip::ZipArchive;
|
||||
|
||||
pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
|
||||
let path = path.as_ref();
|
||||
|
||||
let decoded_image = if path.extension().is_some_and(|ext| ext == "kra") {
|
||||
let reader = match fs::File::open(path).map(io::BufReader::new) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
"failed to create reader for '{}': {e}",
|
||||
path.display()
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let mut zip = match ZipArchive::new(reader) {
|
||||
Ok(z) => z,
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
"failed to open zip archive '{}': {e}",
|
||||
path.display()
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let mut reader = match zip.by_name("mergedimage.png") {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
"failed to open file in zip archive '{}': {e}",
|
||||
path.display()
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// reading it all and wrapping it with a Cursor
|
||||
// is the only way I know to give it Seek
|
||||
// (which is required by ImageReader)
|
||||
let mut buf = Vec::new();
|
||||
if let Err(e) = reader.read_to_end(&mut buf) {
|
||||
return Err(format!(
|
||||
"error when reading file in zip archive '{}': {e}",
|
||||
path.display()
|
||||
));
|
||||
};
|
||||
|
||||
let image_reader = ImageReader::with_format(io::Cursor::new(buf), image::ImageFormat::Png);
|
||||
|
||||
let decoder = match image_reader.into_decoder() {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
"failed to create decoder for '{}': {e}",
|
||||
path.display()
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let decoded_image = match DynamicImage::from_decoder(decoder) {
|
||||
Ok(i) => i,
|
||||
Err(e) => {
|
||||
return Err(format!("failed to decode image '{}': {e}", path.display()));
|
||||
}
|
||||
};
|
||||
|
||||
decoded_image
|
||||
} else {
|
||||
let image_reader = match ImageReader::open(path) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
|
|
@ -95,8 +27,6 @@ pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
|
|||
}
|
||||
};
|
||||
|
||||
// we don't need to check this for the kra branch
|
||||
// since PNGs don't have metadata oreintation
|
||||
let oreintation = match decoder.orientation() {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
|
|
@ -116,9 +46,6 @@ pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
|
|||
|
||||
decoded_image.apply_orientation(oreintation);
|
||||
|
||||
decoded_image
|
||||
};
|
||||
|
||||
Ok(decoded_image.into_rgba8())
|
||||
}
|
||||
pub fn pick_image() -> Result<PathBuf, String> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue