mirror of https://github.com/bobwen-dev/hunter
add resize handling of media and take ysize into account
This commit is contained in:
parent
6e81584eca
commit
b7317949e5
|
@ -1,4 +1,5 @@
|
||||||
use crate::widget::{Widget, WidgetCore};
|
use crate::widget::{Widget, WidgetCore};
|
||||||
|
use crate::coordinates::Coordinates;
|
||||||
use crate::fail::HResult;
|
use crate::fail::HResult;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -18,7 +19,19 @@ pub struct ImgView {
|
||||||
|
|
||||||
impl ImgView {
|
impl ImgView {
|
||||||
pub fn new_from_file(core: WidgetCore, file: &Path) -> HResult<ImgView> {
|
pub fn new_from_file(core: WidgetCore, file: &Path) -> HResult<ImgView> {
|
||||||
let (xsize, ysize) = core.coordinates.size_u();
|
let mut view = ImgView {
|
||||||
|
core: core,
|
||||||
|
buffer: vec![],
|
||||||
|
file: file.to_path_buf()
|
||||||
|
};
|
||||||
|
|
||||||
|
view.encode_file()?;
|
||||||
|
Ok(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode_file(&mut self) -> HResult<()> {
|
||||||
|
let (xsize, ysize) = self.core.coordinates.size_u();
|
||||||
|
let file = &self.file;
|
||||||
|
|
||||||
let output = std::process::Command::new("preview-gen")
|
let output = std::process::Command::new("preview-gen")
|
||||||
.arg(format!("{}", (xsize)))
|
.arg(format!("{}", (xsize)))
|
||||||
|
@ -35,11 +48,9 @@ impl ImgView {
|
||||||
.map(|l| l.to_string())
|
.map(|l| l.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(ImgView {
|
self.buffer = output;
|
||||||
core: core,
|
|
||||||
buffer: output,
|
Ok(())
|
||||||
file: file.to_path_buf()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_image_data(&mut self, img_data: Vec<String>) {
|
pub fn set_image_data(&mut self, img_data: Vec<String>) {
|
||||||
|
@ -61,6 +72,15 @@ impl Widget for ImgView {
|
||||||
Ok(&mut self.core)
|
Ok(&mut self.core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
|
||||||
|
if &self.core.coordinates == coordinates { return Ok(()) }
|
||||||
|
|
||||||
|
self.core.coordinates = coordinates.clone();
|
||||||
|
self.encode_file()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn refresh(&mut self) -> HResult<()> {
|
fn refresh(&mut self) -> HResult<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -2,6 +2,7 @@ use lazy_static;
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
|
|
||||||
use crate::widget::{Widget, WidgetCore};
|
use crate::widget::{Widget, WidgetCore};
|
||||||
|
use crate::coordinates::Coordinates;
|
||||||
use crate::async_value::Stale;
|
use crate::async_value::Stale;
|
||||||
use crate::fail::{HResult, HError, ErrorLog};
|
use crate::fail::{HResult, HError, ErrorLog};
|
||||||
use crate::imgview::ImgView;
|
use crate::imgview::ImgView;
|
||||||
|
@ -95,7 +96,7 @@ impl MediaView {
|
||||||
let mut previewer = std::process::Command::new("preview-gen")
|
let mut previewer = std::process::Command::new("preview-gen")
|
||||||
.arg(format!("{}", (xsize)))
|
.arg(format!("{}", (xsize)))
|
||||||
// Leave space for position/seek bar
|
// Leave space for position/seek bar
|
||||||
.arg(format!("{}", (ysize-3)))
|
.arg(format!("{}", (ysize-1)))
|
||||||
.arg(format!("{}", ctype.to_str()))
|
.arg(format!("{}", ctype.to_str()))
|
||||||
.arg(format!("{}", auto))
|
.arg(format!("{}", auto))
|
||||||
.arg(format!("{}", mute))
|
.arg(format!("{}", mute))
|
||||||
|
@ -190,19 +191,23 @@ impl MediaView {
|
||||||
|
|
||||||
pub fn start_video(&mut self) -> HResult<()> {
|
pub fn start_video(&mut self) -> HResult<()> {
|
||||||
let runner = self.preview_runner.take();
|
let runner = self.preview_runner.take();
|
||||||
let stale = self.stale.clone();
|
|
||||||
let autoplay = self.autoplay();
|
|
||||||
let mute = self.mute();
|
|
||||||
let position = self.position.clone();
|
|
||||||
let duration = self.duration.clone();
|
|
||||||
|
|
||||||
if runner.is_some() {
|
if runner.is_some() {
|
||||||
self.clear().log();
|
let stale = self.stale.clone();
|
||||||
|
let autoplay = self.autoplay();
|
||||||
|
let mute = self.mute();
|
||||||
|
let position = self.position.clone();
|
||||||
|
let duration = self.duration.clone();
|
||||||
|
let clear = self.get_clearlist()?;
|
||||||
|
|
||||||
std::thread::spawn(move || -> HResult<()> {
|
std::thread::spawn(move || -> HResult<()> {
|
||||||
|
// Sleep a bit to avoid overloading the system when scrolling
|
||||||
let sleeptime = std::time::Duration::from_millis(50);
|
let sleeptime = std::time::Duration::from_millis(50);
|
||||||
std::thread::sleep(sleeptime);
|
std::thread::sleep(sleeptime);
|
||||||
|
|
||||||
if !stale.is_stale()? {
|
if !stale.is_stale()? {
|
||||||
|
print!("{}", clear);
|
||||||
|
|
||||||
runner.map(|runner| runner(autoplay,
|
runner.map(|runner| runner(autoplay,
|
||||||
mute,
|
mute,
|
||||||
position,
|
position,
|
||||||
|
@ -295,7 +300,7 @@ impl MediaView {
|
||||||
let auto = AUTOPLAY.read()?.clone();
|
let auto = AUTOPLAY.read()?.clone();
|
||||||
let pos = self.position.lock()?.clone();
|
let pos = self.position.lock()?.clone();
|
||||||
|
|
||||||
// This combination means only first frame show, since
|
// This combination means only first frame is shown, since
|
||||||
// self.paused will be false, even with autoplay off
|
// self.paused will be false, even with autoplay off
|
||||||
if pos == 0 && auto == false && self.paused == false {
|
if pos == 0 && auto == false && self.paused == false {
|
||||||
self.toggle_autoplay();
|
self.toggle_autoplay();
|
||||||
|
@ -396,6 +401,24 @@ impl Widget for MediaView {
|
||||||
Ok(&mut self.core)
|
Ok(&mut self.core)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
|
||||||
|
if &self.core.coordinates == coordinates { return Ok(()); }
|
||||||
|
|
||||||
|
self.core.coordinates = coordinates.clone();
|
||||||
|
|
||||||
|
let mut imgview = self.imgview.lock()?;
|
||||||
|
imgview.set_coordinates(&coordinates)?;
|
||||||
|
|
||||||
|
let xsize = self.core.coordinates.xsize_u();
|
||||||
|
let ysize = self.core.coordinates.ysize_u() - 1;
|
||||||
|
|
||||||
|
let xystring = format!("xy\n{}\n{}\n", xsize, ysize);
|
||||||
|
|
||||||
|
self.controller.send(xystring)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn refresh(&mut self) -> HResult<()> {
|
fn refresh(&mut self) -> HResult<()> {
|
||||||
self.start_video().log();
|
self.start_video().log();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,8 +5,8 @@ use image::{Pixel, FilterType, DynamicImage, GenericImageView};
|
||||||
|
|
||||||
use termion::color::{Bg, Fg, Rgb};
|
use termion::color::{Bg, Fg, Rgb};
|
||||||
#[cfg(feature = "video")]
|
#[cfg(feature = "video")]
|
||||||
use termion::{input::TermRead,
|
use termion::input::TermRead;
|
||||||
event::Key};
|
|
||||||
|
|
||||||
#[cfg(feature = "video")]
|
#[cfg(feature = "video")]
|
||||||
use gstreamer::{self, prelude::*};
|
use gstreamer::{self, prelude::*};
|
||||||
|
@ -20,6 +20,8 @@ use failure::format_err;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
pub type MResult<T> = Result<T, Error>;
|
pub type MResult<T> = Result<T, Error>;
|
||||||
|
|
||||||
|
@ -77,12 +79,9 @@ fn image_preview(path: &str,
|
||||||
ysize: usize) -> MResult<()> {
|
ysize: usize) -> MResult<()> {
|
||||||
let img = image::open(&path)?;
|
let img = image::open(&path)?;
|
||||||
|
|
||||||
let renderer = Renderer {
|
let renderer = Renderer::new(xsize, ysize);
|
||||||
xsize,
|
|
||||||
ysize
|
|
||||||
};
|
|
||||||
|
|
||||||
renderer.send_image(img)?;
|
renderer.send_image(&img)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +92,7 @@ fn video_preview(path: &String,
|
||||||
autoplay: bool,
|
autoplay: bool,
|
||||||
mute: bool)
|
mute: bool)
|
||||||
-> MResult<()> {
|
-> MResult<()> {
|
||||||
|
|
||||||
let (player, appsink) = make_gstreamer()?;
|
let (player, appsink) = make_gstreamer()?;
|
||||||
|
|
||||||
let uri = format!("file://{}", &path);
|
let uri = format!("file://{}", &path);
|
||||||
|
@ -100,10 +100,12 @@ fn video_preview(path: &String,
|
||||||
player.set_property("uri", &uri)?;
|
player.set_property("uri", &uri)?;
|
||||||
|
|
||||||
|
|
||||||
let renderer = Renderer {
|
let renderer = Renderer::new(xsize, ysize);
|
||||||
xsize,
|
let renderer = Arc::new(RwLock::new(renderer));
|
||||||
ysize
|
let crenderer = renderer.clone();
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let p = player.clone();
|
let p = player.clone();
|
||||||
|
|
||||||
|
@ -124,26 +126,28 @@ fn video_preview(path: &String,
|
||||||
.map(|d| d.seconds().unwrap_or(0))
|
.map(|d| d.seconds().unwrap_or(0))
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
match renderer.send_frame(&*sample,
|
if let Ok(mut renderer) = crenderer.write() {
|
||||||
position,
|
match renderer.send_frame(&*sample,
|
||||||
duration) {
|
position,
|
||||||
Ok(()) => {
|
duration) {
|
||||||
if autoplay == false {
|
Ok(()) => {
|
||||||
// Just render first frame to get a static image
|
if autoplay == false {
|
||||||
match p.set_state(gstreamer::State::Paused)
|
// Just render first frame to get a static image
|
||||||
.into_result() {
|
match p.set_state(gstreamer::State::Paused)
|
||||||
Ok(_) => gstreamer::FlowReturn::Eos,
|
.into_result() {
|
||||||
Err(_) => gstreamer::FlowReturn::Error
|
Ok(_) => gstreamer::FlowReturn::Eos,
|
||||||
}
|
Err(_) => gstreamer::FlowReturn::Error
|
||||||
} else {
|
}
|
||||||
gstreamer::FlowReturn::Ok
|
} else {
|
||||||
|
gstreamer::FlowReturn::Ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("{:?}", err);
|
||||||
|
gstreamer::FlowReturn::Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
} else { gstreamer::FlowReturn::Error }
|
||||||
println!("{:?}", err);
|
|
||||||
gstreamer::FlowReturn::Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -161,67 +165,95 @@ fn video_preview(path: &String,
|
||||||
player.set_state(gstreamer::State::Playing).into_result()?;
|
player.set_state(gstreamer::State::Playing).into_result()?;
|
||||||
|
|
||||||
|
|
||||||
read_keys(player)?;
|
|
||||||
|
|
||||||
|
|
||||||
|
read_keys(player, Some(renderer))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "video")]
|
#[cfg(feature = "video")]
|
||||||
pub fn read_keys(player: gstreamer::Element) -> MResult<()> {
|
fn read_keys(player: gstreamer::Element,
|
||||||
|
renderer: Option<Arc<RwLock<Renderer>>>) -> MResult<()> {
|
||||||
let seek_time = gstreamer::ClockTime::from_seconds(5);
|
let seek_time = gstreamer::ClockTime::from_seconds(5);
|
||||||
for key in std::io::stdin().keys() {
|
|
||||||
match key {
|
|
||||||
Ok(Key::Char('q')) => std::process::exit(0),
|
|
||||||
Ok(Key::Char('>')) => {
|
|
||||||
if let Some(mut time) = player.query_position::<gstreamer::ClockTime>() {
|
|
||||||
time += seek_time;
|
|
||||||
|
|
||||||
player.seek_simple(
|
let stdin = std::io::stdin();
|
||||||
gstreamer::SeekFlags::FLUSH,
|
let mut stdin = stdin.lock();
|
||||||
gstreamer::format::GenericFormattedValue::from_time(time)
|
|
||||||
)?;
|
loop {
|
||||||
}
|
let input = stdin
|
||||||
},
|
.read_line()?
|
||||||
Ok(Key::Char('<')) => {
|
.unwrap_or_else(|| String::from("q"));
|
||||||
if let Some(mut time) = player.query_position::<gstreamer::ClockTime>() {
|
|
||||||
if time >= seek_time {
|
|
||||||
time -= seek_time;
|
match input.as_str() {
|
||||||
} else {
|
"q" => std::process::exit(0),
|
||||||
time = gstreamer::ClockTime(Some(0));
|
">" => {
|
||||||
|
if let Some(mut time) = player
|
||||||
|
.query_position::<gstreamer::ClockTime>() {
|
||||||
|
time += seek_time;
|
||||||
|
|
||||||
|
player.seek_simple(
|
||||||
|
gstreamer::SeekFlags::FLUSH,
|
||||||
|
gstreamer::format::GenericFormattedValue::from_time(time)
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"<" => {
|
||||||
|
if let Some(mut time) = player
|
||||||
|
.query_position::<gstreamer::ClockTime>() {
|
||||||
|
if time >= seek_time {
|
||||||
|
time -= seek_time;
|
||||||
|
} else {
|
||||||
|
time = gstreamer::ClockTime(Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
player.seek_simple(
|
player.seek_simple(
|
||||||
gstreamer::SeekFlags::FLUSH,
|
gstreamer::SeekFlags::FLUSH,
|
||||||
gstreamer::format::GenericFormattedValue::from_time(time)
|
gstreamer::format::GenericFormattedValue::from_time(time)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Key::Char('p')) => {
|
"p" => {
|
||||||
player.set_state(gstreamer::State::Playing).into_result()?;
|
player.set_state(gstreamer::State::Playing).into_result()?;
|
||||||
|
|
||||||
// To actually start playing again
|
// To actually start playing again
|
||||||
if let Some(time) = player.query_position::<gstreamer::ClockTime>() {
|
if let Some(time) = player
|
||||||
player.seek_simple(
|
.query_position::<gstreamer::ClockTime>() {
|
||||||
gstreamer::SeekFlags::FLUSH,
|
player.seek_simple(
|
||||||
gstreamer::format::GenericFormattedValue::from_time(time)
|
gstreamer::SeekFlags::FLUSH,
|
||||||
)?;
|
gstreamer::format::GenericFormattedValue::from_time(time)
|
||||||
}
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(Key::Char('a')) => {
|
"a" => {
|
||||||
player.set_state(gstreamer::State::Paused).into_result()?;
|
player.set_state(gstreamer::State::Paused).into_result()?;
|
||||||
}
|
}
|
||||||
Ok(Key::Char('m')) => {
|
"m" => {
|
||||||
player.set_property("volume", &0.0)?;
|
player.set_property("volume", &0.0)?;
|
||||||
}
|
}
|
||||||
Ok(Key::Char('u')) => {
|
"u" => {
|
||||||
player.set_property("volume", &1.0)?;
|
player.set_property("volume", &1.0)?;
|
||||||
}
|
}
|
||||||
|
"xy" => {
|
||||||
|
if let Some(ref renderer) = renderer {
|
||||||
|
let xsize = stdin.read_line()?;
|
||||||
|
let ysize = stdin.read_line()?;
|
||||||
|
|
||||||
|
let xsize = xsize.unwrap_or(String::from("0")).parse::<usize>()?;
|
||||||
|
let ysize = ysize.unwrap_or(String::from("0")).parse::<usize>()?;
|
||||||
|
|
||||||
|
let mut renderer = renderer
|
||||||
|
.write()
|
||||||
|
.map_err(|_| format_err!("Renderer RwLock failed!"))?;
|
||||||
|
|
||||||
|
renderer.set_size(xsize, ysize)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "video")]
|
#[cfg(feature = "video")]
|
||||||
|
@ -275,7 +307,7 @@ pub fn audio_preview(path: &String,
|
||||||
player.set_state(gstreamer::State::Playing).into_result()?;
|
player.set_state(gstreamer::State::Playing).into_result()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_keys(player)?;
|
read_keys(player, None)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -326,22 +358,66 @@ pub fn make_gstreamer() -> MResult<(gstreamer::Element,
|
||||||
|
|
||||||
struct Renderer {
|
struct Renderer {
|
||||||
xsize: usize,
|
xsize: usize,
|
||||||
ysize: usize
|
ysize: usize,
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
last_frame: Option<DynamicImage>,
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
position: Option<usize>,
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
duration: Option<usize>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
fn send_image(&self, image: DynamicImage) -> MResult<()> {
|
fn new(xsize: usize, ysize: usize) -> Renderer {
|
||||||
|
Renderer {
|
||||||
|
xsize,
|
||||||
|
ysize,
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
last_frame: None,
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
position: None,
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
duration: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature = "video")]
|
||||||
|
fn set_size(&mut self, xsize: usize, ysize: usize) -> MResult<()> {
|
||||||
|
self.xsize = xsize;
|
||||||
|
self.ysize = ysize;
|
||||||
|
|
||||||
|
if let Some(ref frame) = self.last_frame {
|
||||||
|
let pos = self.position.unwrap_or(0);
|
||||||
|
let dur = self.duration.unwrap_or(0);
|
||||||
|
|
||||||
|
// Use send_image, because send_frame takes SampleRef
|
||||||
|
self.send_image(frame)?;
|
||||||
|
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
writeln!(stdout, "")?;
|
||||||
|
writeln!(stdout, "{}", pos)?;
|
||||||
|
writeln!(stdout, "{}", dur)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_image(&self, image: &DynamicImage) -> MResult<()> {
|
||||||
let rendered_img = self.render_image(image);
|
let rendered_img = self.render_image(image);
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
for line in rendered_img {
|
for line in rendered_img {
|
||||||
write!(std::io::stdout(), "{}\n", line)?;
|
writeln!(stdout, "{}", line)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "video")]
|
#[cfg(feature = "video")]
|
||||||
fn send_frame(&self,
|
fn send_frame(&mut self,
|
||||||
frame: &gstreamer::sample::SampleRef,
|
frame: &gstreamer::sample::SampleRef,
|
||||||
position: u64,
|
position: u64,
|
||||||
duration: u64)
|
duration: u64)
|
||||||
|
@ -354,23 +430,30 @@ impl Renderer {
|
||||||
let img = image::load_from_memory_with_format(&map,
|
let img = image::load_from_memory_with_format(&map,
|
||||||
image::ImageFormat::PNM)?;
|
image::ImageFormat::PNM)?;
|
||||||
|
|
||||||
let rendered_img = self.render_image(img);
|
let rendered_img = self.render_image(&img);
|
||||||
|
|
||||||
|
self.last_frame = Some(img);
|
||||||
|
self.position = Some(position as usize);
|
||||||
|
self.duration = Some(duration as usize);
|
||||||
|
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
for line in rendered_img {
|
for line in rendered_img {
|
||||||
writeln!(std::io::stdout(), "{}", line)?;
|
writeln!(stdout, "{}", line)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty line means end of frame
|
// Empty line means end of frame
|
||||||
writeln!(std::io::stdout(), "")?;
|
writeln!(stdout, "")?;
|
||||||
|
|
||||||
// Send position and duration
|
// Send position and duration
|
||||||
writeln!(std::io::stdout(), "{}", position)?;
|
writeln!(stdout, "{}", position)?;
|
||||||
writeln!(std::io::stdout(), "{}", duration)?;
|
writeln!(stdout, "{}", duration)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_image(&self, image: DynamicImage) -> Vec<String> {
|
pub fn render_image(&self, image: &DynamicImage) -> Vec<String> {
|
||||||
let (xsize, ysize) = self.max_size(&image);
|
let (xsize, ysize) = self.max_size(&image);
|
||||||
|
|
||||||
let img = image.resize_exact(xsize as u32,
|
let img = image.resize_exact(xsize as u32,
|
||||||
|
@ -405,18 +488,37 @@ impl Renderer {
|
||||||
pub fn max_size(&self, image: &DynamicImage) -> (usize, usize)
|
pub fn max_size(&self, image: &DynamicImage) -> (usize, usize)
|
||||||
{
|
{
|
||||||
let xsize = self.xsize;
|
let xsize = self.xsize;
|
||||||
|
let ysize = self.ysize;
|
||||||
let img_xsize = image.width();
|
let img_xsize = image.width();
|
||||||
let img_ysize = image.height();
|
let img_ysize = image.height();
|
||||||
let img_ratio = img_xsize as f32 / img_ysize as f32;
|
let img_ratio = img_xsize as f32 / img_ysize as f32;
|
||||||
|
|
||||||
let mut new_y = if img_ratio < 1 as f32 {
|
let mut new_x = xsize;
|
||||||
xsize as f32 * img_ratio
|
let mut new_y;
|
||||||
|
|
||||||
|
new_y = if img_ratio < 1 as f32 {
|
||||||
|
(xsize as f32 * img_ratio) as usize
|
||||||
} else {
|
} else {
|
||||||
xsize as f32 / img_ratio
|
(xsize as f32 / img_ratio) as usize
|
||||||
};
|
};
|
||||||
if new_y as u32 % 2 == 1 {
|
|
||||||
new_y += 1 as f32;
|
// Multiply by two because of half-block
|
||||||
|
if new_y > ysize*2 {
|
||||||
|
new_y = self.ysize * 2;
|
||||||
|
|
||||||
|
new_x = if img_ratio < 1 as f32 {
|
||||||
|
(ysize as f32 / img_ratio) as usize * 2
|
||||||
|
} else {
|
||||||
|
(ysize as f32 * img_ratio) as usize * 2
|
||||||
|
};
|
||||||
}
|
}
|
||||||
(xsize, new_y as usize)
|
|
||||||
|
// To make half-block encoding easier, y should be divisible by 2
|
||||||
|
if new_y as u32 % 2 == 1 {
|
||||||
|
new_y += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
(new_x as usize, new_y as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue