Skip to content

Commit

Permalink
feat: gif
Browse files Browse the repository at this point in the history
  • Loading branch information
rsuu committed Dec 10, 2022
1 parent ab9bbf5 commit 54e9cf3
Show file tree
Hide file tree
Showing 16 changed files with 635 additions and 176 deletions.
356 changes: 342 additions & 14 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[package]
name = "rmg"
version = "0.2.1"
version = "0.2.3"
edition = "2021"
authors = ["RSUU <[email protected]>"]
description = "Rust: Tiny Manga Reader"
description = "Rust: Tiny Manga/Image Viewer"
readme = "README.md"
homepage = "https://crates.io/crates/rmg"
repository = "https://github.com/rsuu/rmg"
Expand Down Expand Up @@ -47,6 +47,13 @@ image = { version = "0.24.4" }
fir = {package="fast_image_resize" ,version="1.0.0"}
libheif-rs = { version = "0.15.0", optional = true }
asefile ={ version = "0.3.5", optional = true }
# gif
gif = "0.12.0"
gif-dispose = "4"
# svg
usvg = "0.27.0"
tiny-skia = "0.8.2"
resvg = "0.27.0"

# args
lexopt = "0.2.1"
Expand All @@ -65,7 +72,6 @@ log = "0.4.17"
simple_logger = { version = "2.3.0", features = ["colors", "threads"] }



[dev-dependencies]
# benchmark
criterion = "0.4.0"
Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# rmg

> Rust: Tiny Manga Reader
> Rust: Tiny Manga/Image Viewer
## Demo

Expand Down Expand Up @@ -67,13 +67,19 @@ WARN: You have to create the file by yourself.

## Supported formats

| Format | Supported | Default
| Format | Supported | Default |Dependency
|:-|:-|:-|
.jpg |✅ | ✅
.png|✅| ✅
.heic / .avif|🔬|❌
.gif|🚧|✅
.aseprite|🔬|❌
.jpg |✅ | ✅|
.png|✅| ✅|
.heic / .avif|🔬|❌|libheif
.gif|🔬|✅|
.aseprite|🔬|❌|

---
| Format | Supported | Default |Dependency
|:-|:-|:-|
.tar |✅ | ✅| tar
.zip / .cbz |✅ | ✅| zip

## Features

Expand Down
18 changes: 0 additions & 18 deletions examples/rgba.rs

This file was deleted.

45 changes: 24 additions & 21 deletions src/color/rgba.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
pub struct TransRgba {}

impl TransRgba {
pub fn argb_to_u32(rgba: &[u8; 4]) -> u32 {
let a = (rgba[3] as u32) << 8 * 3;
let r = (rgba[0] as u32) << 8 * 2;
let g = (rgba[1] as u32) << 8 * 1;
let b = (rgba[2] as u32) << 8 * 0;

r + g + b + a
#[inline(always)]
pub fn rgba_as_srgb_u32(r: &u8, g: &u8, b: &u8, a: &u8) -> u32 {
// (r, g, b, a) -> (a, r, g, b) -> u32
// 3 2 1 0 3 2 1 0
((*r as u32) << 8 * 2)
+ ((*g as u32) << 8 * 1)
+ ((*b as u32) << 8 * 0)
+ ((*a as u32) << 8 * 3)
}

#[inline(always)]
pub fn rgba_to_u32(rgba: &[u8; 4]) -> u32 {
let r = (rgba[0] as u32) << 8 * 3;
let g = (rgba[1] as u32) << 8 * 2;
let b = (rgba[2] as u32) << 8 * 1;
let a = (rgba[3] as u32) << 8 * 0;

r + g + b + a
pub fn rgba_as_u32(r: &u8, g: &u8, b: &u8, a: &u8) -> u32 {
// (r, g, b, a) -> u32
// 3 2 1 0
((*r as u32) << 8 * 3)
+ ((*g as u32) << 8 * 2)
+ ((*b as u32) << 8 * 1)
+ ((*a as u32) << 8 * 0)
}

#[inline(always)]
pub fn rgba_from_u32(rgba: u32) -> [u8; 4] {
let r = (rgba >> 24) & 0x0ff;
let g = (rgba >> 16) & 0x0ff;
let b = (rgba >> 8) & 0x0ff;
let a = rgba & 0x0ff;

[r as u8, g as u8, b as u8, a as u8]
pub fn rgba_from_u32(rgba: u32) -> (u8, u8, u8, u8) {
// u32 -> (r, g, b, a)
// 3 2 1 0
(
((rgba >> 8 * 3) & 0x0ff) as u8,
((rgba >> 8 * 2) & 0x0ff) as u8,
((rgba >> 8 * 1) & 0x0ff) as u8,
(rgba & 0x0ff) as u8,
)
}
}

Expand Down
57 changes: 52 additions & 5 deletions src/img/gif.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,56 @@
use image::codecs::gif::{GifDecoder, GifEncoder};
use image::{AnimationDecoder, ImageDecoder};
use gif;
use log;
use std::fs::File;
use std::io::Read;
use std::mem;

fn load_anim(bytes: &[u8]) {
if let Ok(ref anim) = image::load_from_memory(bytes) {
// let frames = gif::Frame::from_rgb(anim.width(), anim.height(), &mut anim.to_rgb8().to_vec());
use crate::utils::err::Res;
use crate::utils::traits::AutoLog;
use gif_dispose;

use super::size::Size;

pub fn load_gif(bytes: impl Read) -> Res<(Size<u32>, Vec<Vec<u8>>)> {
let mut res = vec![];
let mut buffer_frame = Vec::new();

let mut gif_opts = gif::DecodeOptions::new();
gif_opts.set_color_output(gif::ColorOutput::Indexed);
let mut decoder = gif_opts.read_info(bytes).unwrap();
let mut screen = gif_dispose::Screen::new_decoder(&decoder);

let size = Size {
width: decoder.width() as u32,
height: decoder.height() as u32,
};

loop {
"decoded frame"._dbg();

if let Some(frame) = decoder.read_next_frame().unwrap() {
screen.blit_frame(frame).unwrap();

for rgba in screen.pixels.buf().iter() {
buffer_frame.push(rgba.r);
buffer_frame.push(rgba.g);
buffer_frame.push(rgba.b);
buffer_frame.push(rgba.a);
}

res.push(mem::take(&mut buffer_frame));
} else {
break;
}
}

Ok((size, res))
}

// image
// let gif_decoder = GifDecoder::new(file)?;
// let frames = gif_decoder.into_frames().collect_frames()?;
// for f in frames {
// let delay = f.delay().numer_denom_ms().0 as u16;
// col.add_anim_frame(f.into_buffer(), delay);
// col.repeat = true;
// }
6 changes: 3 additions & 3 deletions src/img/heic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::utils::err::{MyErr, Res};
use log;

pub fn load_heic(bytes: &[u8]) -> Res<(u32, u32, Vec<u8>)> {
pub fn load_heic(bytes: &[u8]) -> Res<(u32, u32, Vec<Vec<u8>>)> {
cfg_if::cfg_if! {
if #[cfg(feature = "de_heic")] {
feat::load_heic(bytes)
Expand All @@ -17,7 +17,7 @@ mod feat {
use libheif_rs;

#[inline]
pub fn load_heic(bytes: &[u8]) -> Res<(u32, u32, Vec<u8>)> {
pub fn load_heic(bytes: &[u8]) -> Res<(u32, u32, Vec<Vec<u8>>)> {
if let Ok(ctx) = libheif_rs::HeifContext::read_from_bytes(&bytes) {
log::debug!("{}", bytes.len());

Expand Down Expand Up @@ -61,7 +61,7 @@ mod feat {
}
}

return Ok((width, height, res));
return Ok((width, height, vec![res]));
} else {
return Err(MyErr::Null(()));
}
Expand Down
17 changes: 12 additions & 5 deletions src/img/resize.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::color::rgba::TransRgba;
use crate::{
color::rgba::TransRgba,
img::heic,
img::size::{MetaSize, Size, TMetaSize},
utils::err::Res,
Expand All @@ -10,11 +10,15 @@ use image::DynamicImage;
use std::num::NonZeroU32;

#[inline(always)]
pub fn resize_rgba8(bytes: &[u8], meta: &MetaSize<u32>, filter: &fir::FilterType) -> Res<Vec<u8>> {
pub fn resize_rgba8(
bytes: Vec<u8>,
meta: &MetaSize<u32>,
filter: &fir::FilterType,
) -> Res<Vec<u8>> {
let mut src_image = fir::Image::from_vec_u8(
NonZeroU32::new(meta.image.width).ok_or(())?,
NonZeroU32::new(meta.image.height).ok_or(())?,
bytes.to_vec(),
bytes,
fir::PixelType::U8x4,
)?;
let dst_width = NonZeroU32::new(meta.fix.width).ok_or(())?;
Expand Down Expand Up @@ -45,7 +49,10 @@ pub fn resize_rgba8(bytes: &[u8], meta: &MetaSize<u32>, filter: &fir::FilterType

#[inline(always)]
pub fn srgb_u32(buffer: &mut Vec<u32>, bytes: &[u8]) {
for f in (0..bytes.len()).step_by(4) {
buffer.push(TransRgba::argb_to_u32(&bytes[f..f + 4].try_into().unwrap()));
*buffer = vec![0; bytes.len() / 4];

for (idx, f) in (0..bytes.len()).step_by(4).enumerate() {
buffer[idx] =
TransRgba::rgba_as_srgb_u32(&bytes[f], &bytes[f + 1], &bytes[f + 2], &bytes[f + 3]);
}
}
38 changes: 38 additions & 0 deletions src/img/svg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use resvg;
use tiny_skia;
use usvg;

/*
pub fn load_svg(bytes: &[u8]) -> Res<(Size<u32>, Vec<Vec<u8>>)> {
// let (width, height) = (3000, 3000);
let opt = usvg::Options::default();
let svg_data = std::fs::read(&img_location)?;
if let Ok(rtree) = usvg::Tree::from_data(&svg_data, &opt.to_ref()) {
// let pixmap_size = rtree.svg_node().size.to_screen_size()
let pixmap_size = rtree.size.to_screen_size();
// .scale_to(ScreenSize::new(width, height)?);
if let Some(mut pixmap) = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height())
{
resvg::render(
&rtree,
usvg::FitTo::Original,
tiny_skia::Transform::identity(),
pixmap.as_mut(),
)
.ok_or(anyhow!("Can't render SVG"))?;
// resvg::render(&rtree, usvg::FitTo::Height(height), pixmap.as_mut())?;
let buf: Option<RgbaImage> = image::ImageBuffer::from_raw(
pixmap_size.width(),
pixmap_size.height(),
pixmap.data().to_vec(),
);
if let Some(valid_buf) = buf {
col.add_still(valid_buf);
}
}
}
}
*/
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const EXT_LIST: &[&str] = &[
"jpg", "jpeg", "png", "heic", "heif", "avif", "ase", "aseprite",
"jpg", "jpeg", "png", "heic", "heif", "avif", "ase", "aseprite", "gif",
];
pub static mut TIMER: usize = 0;

Expand Down Expand Up @@ -93,6 +93,7 @@ pub mod img {
pub mod ase;
pub mod gif;
pub mod heic;
pub mod svg;
}

pub mod color {
Expand Down
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ where
}

_ => {
return Err(());
// Only one file.

todo!()
}
};
};
Expand Down
3 changes: 3 additions & 0 deletions src/reader/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub fn cat_img(
view_mode: config.base.view_mode,

page_number: 0,
page_loading: vec![0; buffer_max * 20],
};
let mut canvas = Canvas::new(window_size.width as usize, window_size.height as usize);

Expand Down Expand Up @@ -112,6 +113,7 @@ pub fn for_minifb_image(

canvas.flush(&buf.buffer.data[buf.rng..buf.rng + buf.buffer_max]);

// TODO: gif
std::thread::sleep(std::time::Duration::from_millis(40));
}
}
Expand Down Expand Up @@ -186,6 +188,7 @@ pub fn for_minifb_scroll(

buf.flush(canvas, &arc_state);

// TODO: dyn FPS
std::thread::sleep(std::time::Duration::from_millis(40));
}
}
Loading

0 comments on commit 54e9cf3

Please sign in to comment.