Skip to content

Commit

Permalink
v0.0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
ksk001100 committed Mar 28, 2022
1 parent 71feae8 commit 0ef69af
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 32 deletions.
26 changes: 23 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "picterm"
version = "0.0.6"
version = "0.0.7"
authors = ["Keisuke Toyota <[email protected]>"]
edition = "2018"
repository = "https://github.com/ksk001100/picterm"
Expand All @@ -16,4 +16,6 @@ image = "0.23"
tokio = { version = "1", features = ["full"] }
eyre = "0.6"
seahorse = "2.0.0"
byte-unit = "4.0"
byte-unit = "4.0"
ansi_rgb = "0.2"
rgb = "0.8"
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

TUI image viewer

![](screenshot.png)
![](assets/picterm.gif)

## Install
```bash
Expand All @@ -19,9 +19,12 @@ $ cargo install --path .

## Usage
```bash
$ picterm --help # => Show help
$ picterm -h
$ picterm # => Current directory
$ picterm ./
$ picterm $HOME/Downloads/
$ picterm ~/Pictures/sample.png
```

## Support file format
Expand Down
Binary file added assets/picterm.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed screenshot.png
Binary file not shown.
28 changes: 27 additions & 1 deletion src/image.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use image::{DynamicImage, GenericImageView};
use ansi_rgb::Background;
use image::{DynamicImage, GenericImageView, Rgba};
use rgb::RGB8;

pub fn image_fit_size(img: &DynamicImage, term_w: u32, term_h: u32) -> (u32, u32) {
let (img_width, img_height) = img.dimensions();
Expand Down Expand Up @@ -30,3 +32,27 @@ pub fn get_dimensions(width: u32, height: u32, bound_width: u32, bound_height: u
(intermediate, std::cmp::max(1, bound_height / 2))
}
}

pub fn print_term_image(img: DynamicImage) {
let size = crossterm::terminal::size().unwrap();
let (w, h) = image_fit_size(&img, size.0 as u32, size.1 as u32);
let imgbuf = img
.resize_exact(w, h, image::imageops::FilterType::Triangle)
.to_rgba8();
let (width, height) = imgbuf.dimensions();

for y in 0..height {
for x in 0..width {
let pixel = imgbuf.get_pixel(x, y);
let Rgba(data) = *pixel;

if data[3] == 0 {
print!(" ");
} else {
let bg = RGB8::new(data[0], data[1], data[2]);
print!("{}", " ".bg(bg));
}
}
println!("");
}
}
2 changes: 1 addition & 1 deletion src/inputs/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct Events {

impl Events {
pub fn new(tick_rate: Duration) -> Events {
let (tx, rx) = tokio::sync::mpsc::channel(100);
let (tx, rx) = tokio::sync::mpsc::channel(1000);
let stop_capture = Arc::new(AtomicBool::new(false));

let event_tx = tx.clone();
Expand Down
38 changes: 17 additions & 21 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
use eyre::Result;
use picterm::{
app::App,
image::print_term_image,
io::{handler::IoAsyncHandler, IoEvent},
start_ui,
utils::{select_mode, Mode},
};
use seahorse::{App as SeahorseApp, Context};
use std::{env, path::Path, sync::Arc};
use std::{env, sync::Arc};

fn main() -> Result<()> {
let args = env::args().collect();
let cli_app = SeahorseApp::new(env!("CARGO_PKG_NAME"))
.description(env!("CARGO_PKG_DESCRIPTION"))
.author(env!("CARGO_PKG_AUTHORS"))
.version(env!("CARGO_PKG_VERSION"))
.usage(format!("{} [directory]", env!("CARGO_PKG_NAME")))
.action(tui_main);
.usage(format!("{} [directory or image file]", env!("CARGO_PKG_NAME")))
.action(action);

cli_app.run(args);

Ok(())
}

fn tui_main(c: &Context) {
check_args(&c.args);
fn action(c: &Context) {
match select_mode(&c.args) {
Mode::CLI => cli_main(&c.args[0]),
Mode::TUI => tui_main(),
}
}

fn cli_main(path: &String) {
let img = image::open(path).unwrap();
print_term_image(img);
}

fn tui_main() {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
let (sync_io_tx, mut sync_io_rx) = tokio::sync::mpsc::channel::<IoEvent>(1000);
Expand All @@ -41,19 +53,3 @@ fn tui_main(c: &Context) {
start_ui(&app_ui).await.unwrap();
});
}

fn check_args(args: &[String]) {
match args.len() {
0 => (),
1 => {
if !Path::new(&args[0]).is_dir() {
eprintln!("Please specify only one directory as an argument");
std::process::exit(1);
}
}
_ => {
eprintln!("Please specify only one directory as an argument");
std::process::exit(1);
}
}
}
36 changes: 33 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
use std::{fs, path::PathBuf};
use std::{
fs,
path::{Path, PathBuf},
};

pub fn get_image_paths(path: &str) -> Vec<PathBuf> {
static FILE_TYPES: [&str; 6] = ["png", "jpg", "jpeg", "webp", "bmp", "gif"];
static FILE_TYPES: [&str; 6] = ["png", "jpg", "jpeg", "webp", "bmp", "gif"];

pub enum Mode {
CLI,
TUI,
}

pub fn get_image_paths(path: &str) -> Vec<PathBuf> {
let paths = fs::read_dir(path).unwrap();
let mut result = vec![];

Expand All @@ -17,3 +25,25 @@ pub fn get_image_paths(path: &str) -> Vec<PathBuf> {

result
}

pub fn select_mode(args: &[String]) -> Mode {
match args.len() {
0 => Mode::TUI,
1 => {
if Path::new(&args[0]).is_dir() {
Mode::TUI
} else if FILE_TYPES
.contains(&Path::new(&args[0]).extension().unwrap().to_str().unwrap())
{
Mode::CLI
} else {
eprintln!("The argument must be a directory or a single image file.");
std::process::exit(1);
}
}
_ => {
eprintln!("The argument must be a directory or a single image file.");
std::process::exit(1);
}
}
}

0 comments on commit 0ef69af

Please sign in to comment.