Thumbnails WIP
This commit is contained in:
parent
8415f9cb9d
commit
aed4212043
194
src/image.rs
194
src/image.rs
@ -1,5 +1,6 @@
|
|||||||
use iced::widget::image::Handle;
|
use iced::widget::image::Handle;
|
||||||
use iced::widget::image::Image as IcedImage;
|
use iced::widget::image::Image as IcedImage;
|
||||||
|
use image::imageops::FilterType;
|
||||||
// use image::codecs::jpeg::JpegDecoder;
|
// use image::codecs::jpeg::JpegDecoder;
|
||||||
// use image::codecs::jpeg::JpegDecoder;
|
// use image::codecs::jpeg::JpegDecoder;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
@ -7,6 +8,7 @@ use image::ImageReader;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use memmap2::Mmap;
|
use memmap2::Mmap;
|
||||||
use zune_image::codecs::jpeg::JpegDecoder;
|
use zune_image::codecs::jpeg::JpegDecoder;
|
||||||
|
use zune_image::codecs::qoi::zune_core::colorspace::ColorSpace;
|
||||||
use zune_image::codecs::qoi::zune_core::options::DecoderOptions;
|
use zune_image::codecs::qoi::zune_core::options::DecoderOptions;
|
||||||
use zune_image::image::Image as ZuneImage;
|
use zune_image::image::Image as ZuneImage;
|
||||||
|
|
||||||
@ -14,6 +16,7 @@ use std::fs;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::fs::read;
|
use std::fs::read;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::Cursor;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -79,93 +82,82 @@ pub fn create_iced_handle(width: u32, height: u32, rgba: Vec<u8>) -> Handle {
|
|||||||
Handle::from_rgba(width, height, rgba)
|
Handle::from_rgba(width, height, rgba)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_thumbnail(
|
// pub fn load_thumbnail(
|
||||||
path: &str,
|
// path: &str,
|
||||||
approach: Approach,
|
// approach: Approach,
|
||||||
) -> Result<iced::widget::image::Handle, String> {
|
// ) -> Result<iced::widget::image::Handle, String> {
|
||||||
match approach {
|
// match approach {
|
||||||
Approach::Mmap => {
|
// Approach::Mmap => {
|
||||||
let mmap = map_file(path).unwrap();
|
// let mmap = map_file(path).unwrap();
|
||||||
println!("mapped file");
|
// println!("mapped file");
|
||||||
let img = read_zune_image(mmap.deref())?;
|
// let img = read_zune_image(mmap.deref())?;
|
||||||
let width = img.dimensions().0 as u32;
|
// let width = img.dimensions().0 as u32;
|
||||||
let height = img.dimensions().1 as u32;
|
// let height = img.dimensions().1 as u32;
|
||||||
println!("loaded");
|
// println!("loaded");
|
||||||
let flat = flatten_zune_image(&img);
|
// let flat = flatten_zune_image(&img);
|
||||||
println!("flattened");
|
// println!("flattened");
|
||||||
let rgba = convert_zune_rgb_to_rgba(flat);
|
// let rgba = convert_zune_rgb_to_rgba(flat);
|
||||||
println!("rgbad");
|
// println!("rgbad");
|
||||||
let conv = create_iced_handle(width, height, rgba);
|
// let conv = create_iced_handle(width, height, rgba);
|
||||||
println!("iced");
|
// println!("iced");
|
||||||
|
|
||||||
Ok(conv)
|
// Ok(conv)
|
||||||
}
|
// }
|
||||||
Approach::Path => {
|
// Approach::Path => {
|
||||||
let img = read_zune_image_path(path);
|
// let img = read_zune_image_path(path);
|
||||||
let width = img.dimensions().0 as u32;
|
// let width = img.dimensions().0 as u32;
|
||||||
let height = img.dimensions().1 as u32;
|
// let height = img.dimensions().1 as u32;
|
||||||
println!("loaded");
|
// println!("loaded");
|
||||||
let flat = flatten_zune_image(&img);
|
// let flat = flatten_zune_image(&img);
|
||||||
println!("flattened");
|
// println!("flattened");
|
||||||
let rgba = convert_zune_rgb_to_rgba(flat);
|
// let rgba = convert_zune_rgb_to_rgba(flat);
|
||||||
println!("rgbad");
|
// println!("rgbad");
|
||||||
let conv = create_iced_handle(width, height, rgba);
|
// let conv = create_iced_handle(width, height, rgba);
|
||||||
println!("iced");
|
// println!("iced");
|
||||||
|
|
||||||
Ok(conv)
|
// Ok(conv)
|
||||||
}
|
// }
|
||||||
Approach::ImageRs => {
|
// Approach::ImageRs => {
|
||||||
let mmap = map_file(path).unwrap();
|
// let mmap = map_file(path).unwrap();
|
||||||
let img = image::load_from_memory(mmap.deref()).map_err(|e| e.to_string())?;
|
// let img = image::load_from_memory(mmap.deref()).map_err(|e| e.to_string())?;
|
||||||
let width = img.width();
|
// let width = img.width();
|
||||||
let height = img.height();
|
// let height = img.height();
|
||||||
println!("loaded");
|
// println!("loaded");
|
||||||
let rgba = flatten_image_image(img);
|
// let rgba = flatten_image_image(img);
|
||||||
println!("rgbad");
|
// println!("rgbad");
|
||||||
let conv = create_iced_handle(width, height, rgba);
|
// let conv = create_iced_handle(width, height, rgba);
|
||||||
println!("iced");
|
// println!("iced");
|
||||||
|
|
||||||
Ok(conv)
|
// Ok(conv)
|
||||||
}
|
// }
|
||||||
Approach::ImageRsPath => {
|
// Approach::ImageRsPath => {
|
||||||
let img = ImageReader::open(path).unwrap().decode().unwrap();
|
// let img = ImageReader::open(path).unwrap().decode().unwrap();
|
||||||
let width = img.width();
|
// let width = img.width();
|
||||||
let height = img.height();
|
// let height = img.height();
|
||||||
println!("loaded");
|
// println!("loaded");
|
||||||
let rgba = flatten_image_image(img);
|
// let rgba = flatten_image_image(img);
|
||||||
println!("rgbad");
|
// println!("rgbad");
|
||||||
let conv = create_iced_handle(width, height, rgba);
|
// let conv = create_iced_handle(width, height, rgba);
|
||||||
println!("iced");
|
// println!("iced");
|
||||||
|
|
||||||
Ok(conv)
|
// Ok(conv)
|
||||||
}
|
// }
|
||||||
Approach::Iced => Ok(Handle::from_path(path)),
|
// Approach::Iced => Ok(Handle::from_path(path)),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn load_image_argb(path: PathBuf) -> ImflowImageBuffer {
|
pub fn load_image_argb(path: PathBuf) -> ImflowImageBuffer {
|
||||||
let total_start = Instant::now();
|
let total_start = Instant::now();
|
||||||
|
|
||||||
// Stage 1: Memory map the file
|
|
||||||
let stage1_start = Instant::now();
|
|
||||||
let mmap = map_file_path(path.clone()).unwrap();
|
|
||||||
let stage1_time = stage1_start.elapsed();
|
|
||||||
// println!("File mapping took: {:?}", stage1_time);
|
|
||||||
|
|
||||||
// let file = File::open(path).unwrap();
|
|
||||||
let file_contents = read(path).unwrap();
|
let file_contents = read(path).unwrap();
|
||||||
// let mmap = map_file_path(path.into()).unwrap();
|
|
||||||
|
|
||||||
let mut decoder = JpegDecoder::new(&file_contents);
|
let mut decoder = JpegDecoder::new(&file_contents);
|
||||||
let options = DecoderOptions::new_fast()
|
let options = DecoderOptions::new_fast().jpeg_set_out_colorspace(ColorSpace::BGRA);
|
||||||
.jpeg_set_max_scans(5)
|
|
||||||
.jpeg_set_out_colorspace(zune_image::codecs::qoi::zune_core::colorspace::ColorSpace::BGRA);
|
|
||||||
decoder.set_options(options);
|
decoder.set_options(options);
|
||||||
decoder.decode_headers().unwrap();
|
decoder.decode_headers().unwrap();
|
||||||
let info = decoder.info().unwrap();
|
let info = decoder.info().unwrap();
|
||||||
let width = info.width as usize;
|
let width = info.width as usize;
|
||||||
let height = info.height as usize;
|
let height = info.height as usize;
|
||||||
println!("{} x {}", width, height);
|
|
||||||
let mut buffer2: Vec<u8> = vec![0; width * height * 4];
|
let mut buffer2: Vec<u8> = vec![0; width * height * 4];
|
||||||
decoder.decode_into(buffer2.as_mut_slice());
|
decoder.decode_into(buffer2.as_mut_slice());
|
||||||
|
|
||||||
@ -215,6 +207,19 @@ pub struct ImflowImageBuffer {
|
|||||||
pub argb_buffer: Vec<u32>,
|
pub argb_buffer: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn image_to_argb_buffer(img: DynamicImage) -> Vec<u32> {
|
||||||
|
let mut buffer: Vec<u32> = vec![0; (img.width() * img.height()) as usize];
|
||||||
|
let mut flat = img.into_rgba8().into_raw();
|
||||||
|
|
||||||
|
for (rgba, argb) in flat.chunks_mut(4).zip(buffer.iter_mut()) {
|
||||||
|
let r = rgba[0] as u32;
|
||||||
|
let g = rgba[1] as u32;
|
||||||
|
let b = rgba[2] as u32;
|
||||||
|
*argb = r << 16 | g << 8 | b;
|
||||||
|
}
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_image_argb_imagers(path: PathBuf) -> ImflowImageBuffer {
|
pub fn load_image_argb_imagers(path: PathBuf) -> ImflowImageBuffer {
|
||||||
let total_start = Instant::now();
|
let total_start = Instant::now();
|
||||||
|
|
||||||
@ -277,11 +282,48 @@ pub fn get_embedded_thumbnail(path: PathBuf) -> Option<Vec<u8>> {
|
|||||||
let meta = rexiv2::Metadata::new_from_path(path);
|
let meta = rexiv2::Metadata::new_from_path(path);
|
||||||
match meta {
|
match meta {
|
||||||
Ok(meta) => {
|
Ok(meta) => {
|
||||||
|
// println!("{:?}", meta.get_preview_images());
|
||||||
meta.get_thumbnail().map(|v| v.to_vec())
|
meta.get_thumbnail().map(|v| v.to_vec())
|
||||||
|
},
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_thumbnail(path: PathBuf) -> ImflowImageBuffer {
|
||||||
|
if let Some(thumbnail) = get_embedded_thumbnail(path.clone()) {
|
||||||
|
let decoder = image::ImageReader::new(Cursor::new(thumbnail))
|
||||||
|
.with_guessed_format()
|
||||||
|
.unwrap();
|
||||||
|
let image = decoder.decode().unwrap();
|
||||||
|
|
||||||
|
let width: usize = image.width() as usize;
|
||||||
|
let height: usize = image.height() as usize;
|
||||||
|
let mut flat = image.into_rgba8().into_raw();
|
||||||
|
let mut buffer: Vec<u32> = vec![0; width * height];
|
||||||
|
|
||||||
|
for (rgba, argb) in flat.chunks_mut(4).zip(buffer.iter_mut()) {
|
||||||
|
let r = rgba[0] as u32;
|
||||||
|
let g = rgba[1] as u32;
|
||||||
|
let b = rgba[2] as u32;
|
||||||
|
*argb = r << 16 | g << 8 | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImflowImageBuffer {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
argb_buffer: buffer,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let reader = image::ImageReader::new(Cursor::new(read(path).unwrap()));
|
||||||
|
let image = reader.decode().unwrap().resize(640, 480, FilterType::Nearest);
|
||||||
|
let width = image.width() as usize;
|
||||||
|
let height = image.height() as usize;
|
||||||
|
let buffer = image_to_argb_buffer(image);
|
||||||
|
|
||||||
|
ImflowImageBuffer {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
argb_buffer: buffer,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => None,
|
|
||||||
}
|
|
||||||
// let file = std::fs::File::open(path).ok()?;
|
|
||||||
// let exif = Reader::new().read_from_container(&mut std::io::BufReader::new(file)).ok()?;
|
|
||||||
// exif.get_thumbnail()
|
|
||||||
}
|
}
|
||||||
|
@ -694,10 +694,10 @@ impl MainApp {
|
|||||||
.clone();
|
.clone();
|
||||||
self.current_image = Some(path.clone());
|
self.current_image = Some(path.clone());
|
||||||
if !self.loaded_images.contains_key(&path.to_path_buf()) {
|
if !self.loaded_images.contains_key(&path.to_path_buf()) {
|
||||||
self.loaded_images.insert(
|
// self.loaded_images.insert(
|
||||||
path.to_path_buf(),
|
// path.to_path_buf(),
|
||||||
load_thumbnail(path.to_str().unwrap(), Approach::ImageRs).unwrap(),
|
// load_thumbnail(path.to_str().unwrap(), Approach::ImageRs).unwrap(),
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user