mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 07:33:18 +02:00
Add some logic for more binary formats
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
use crossterm::{cursor, terminal, Attribute, RawScreen};
|
||||
use indexmap::IndexMap;
|
||||
use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Value};
|
||||
use pretty_hex::*;
|
||||
|
||||
struct BinaryView;
|
||||
|
||||
@ -38,17 +39,16 @@ impl Plugin for BinaryView {
|
||||
}
|
||||
|
||||
fn view_binary(b: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use pretty_hex::*;
|
||||
if b.len() > 3 {
|
||||
match (b[0], b[1], b[2]) {
|
||||
(0x4e, 0x45, 0x53) => {
|
||||
view_contents(b)?;
|
||||
view_contents_interactive(b)?;
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
println!("{:?}", b.hex_dump());
|
||||
view_contents(b)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ impl Context {
|
||||
let cursor = cursor();
|
||||
cursor.goto(0, 0)?;
|
||||
|
||||
let mut prev_color: Option<(u8,u8,u8)> = None;
|
||||
let mut prev_color: Option<(u8, u8, u8)> = None;
|
||||
let mut prev_count = 1;
|
||||
|
||||
for pixel in &self.frame_buffer {
|
||||
@ -93,7 +93,7 @@ impl Context {
|
||||
prev_count = 1;
|
||||
}
|
||||
_ => {
|
||||
prev_color = Some(pixel.1);
|
||||
prev_color = Some(pixel.1);
|
||||
prev_count = 1;
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,139 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RawImageBuffer {
|
||||
dimensions: (u64, u64),
|
||||
colortype: image::ColorType,
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
fn load_from_png_buffer(buffer: &[u8]) -> Option<(RawImageBuffer)> {
|
||||
use image::ImageDecoder;
|
||||
|
||||
let decoder = image::png::PNGDecoder::new(buffer);
|
||||
if decoder.is_err() {
|
||||
return None;
|
||||
}
|
||||
let decoder = decoder.unwrap();
|
||||
|
||||
let dimensions = decoder.dimensions();
|
||||
let colortype = decoder.colortype();
|
||||
let buffer = decoder.read_image().unwrap();
|
||||
|
||||
Some(RawImageBuffer {
|
||||
dimensions,
|
||||
colortype,
|
||||
buffer,
|
||||
})
|
||||
}
|
||||
|
||||
fn load_from_jpg_buffer(buffer: &[u8]) -> Option<(RawImageBuffer)> {
|
||||
use image::ImageDecoder;
|
||||
|
||||
let decoder = image::jpeg::JPEGDecoder::new(buffer);
|
||||
if decoder.is_err() {
|
||||
return None;
|
||||
}
|
||||
let decoder = decoder.unwrap();
|
||||
|
||||
let dimensions = decoder.dimensions();
|
||||
let colortype = decoder.colortype();
|
||||
let buffer = decoder.read_image().unwrap();
|
||||
|
||||
Some(RawImageBuffer {
|
||||
dimensions,
|
||||
colortype,
|
||||
buffer,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn view_contents(buffer: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut raw_image_buffer = load_from_png_buffer(buffer);
|
||||
|
||||
if raw_image_buffer.is_none() {
|
||||
raw_image_buffer = load_from_jpg_buffer(buffer);
|
||||
}
|
||||
|
||||
if raw_image_buffer.is_none() {
|
||||
//Not yet supported
|
||||
println!("{:?}", buffer.hex_dump());
|
||||
return Ok(());
|
||||
}
|
||||
let raw_image_buffer = raw_image_buffer.unwrap();
|
||||
|
||||
let mut context: Context = Context::blank();
|
||||
let _ = context.update();
|
||||
context.clear();
|
||||
|
||||
match raw_image_buffer.colortype {
|
||||
image::ColorType::RGBA(8) => {
|
||||
let img = image::ImageBuffer::<image::Rgba<u8>, Vec<u8>>::from_vec(
|
||||
raw_image_buffer.dimensions.0 as u32,
|
||||
raw_image_buffer.dimensions.1 as u32,
|
||||
raw_image_buffer.buffer,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let resized_img = image::imageops::resize(
|
||||
&img,
|
||||
context.width as u32,
|
||||
context.height as u32,
|
||||
image::FilterType::Lanczos3,
|
||||
);
|
||||
|
||||
let mut count = 0;
|
||||
for pixel in resized_img.pixels() {
|
||||
use image::Pixel;
|
||||
let rgb = pixel.to_rgb();
|
||||
//print!("{}", rgb[0]);
|
||||
context.frame_buffer[count] = ('@', (rgb[0], rgb[1], rgb[2]));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
image::ColorType::RGB(8) => {
|
||||
let img = image::ImageBuffer::<image::Rgb<u8>, Vec<u8>>::from_vec(
|
||||
raw_image_buffer.dimensions.0 as u32,
|
||||
raw_image_buffer.dimensions.1 as u32,
|
||||
raw_image_buffer.buffer,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let resized_img = image::imageops::resize(
|
||||
&img,
|
||||
context.width as u32,
|
||||
context.height as u32,
|
||||
image::FilterType::Lanczos3,
|
||||
);
|
||||
|
||||
let mut count = 0;
|
||||
for pixel in resized_img.pixels() {
|
||||
use image::Pixel;
|
||||
let rgb = pixel.to_rgb();
|
||||
//print!("{}", rgb[0]);
|
||||
context.frame_buffer[count] = ('@', (rgb[0], rgb[1], rgb[2]));
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
//Not yet supported
|
||||
println!("{:?}", buffer.hex_dump());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
context.flush()?;
|
||||
|
||||
let cursor = cursor();
|
||||
let _ = cursor.show();
|
||||
|
||||
#[allow(unused)]
|
||||
let screen = RawScreen::disable_raw_mode();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn view_contents_interactive(buffer: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use rawkey::{KeyCode, RawKey};
|
||||
|
||||
let mut nes = neso::Nes::new(48000.0);
|
||||
@ -163,28 +295,25 @@ pub fn view_contents(buffer: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let image_buffer = nes.image_buffer();
|
||||
|
||||
let mut new_offscreen = vec![0; context.height * context.width * 4];
|
||||
let mut resizer = resize::new(
|
||||
256,
|
||||
240,
|
||||
context.width,
|
||||
context.height,
|
||||
resize::Pixel::RGBA,
|
||||
resize::Type::Triangle,
|
||||
);
|
||||
let slice = unsafe { std::slice::from_raw_parts(image_buffer, 256 * 240 * 4) };
|
||||
resizer.resize(&slice, &mut new_offscreen);
|
||||
let img =
|
||||
image::ImageBuffer::<image::Rgba<u8>, &[u8]>::from_raw(256, 240, slice).unwrap();
|
||||
let resized_img = image::imageops::resize(
|
||||
&img,
|
||||
context.width as u32,
|
||||
context.height as u32,
|
||||
image::FilterType::Lanczos3,
|
||||
);
|
||||
|
||||
context.clear();
|
||||
|
||||
for row in 0..context.height {
|
||||
for col in 0..(context.width) {
|
||||
let red = new_offscreen[col * 4 + row * context.width * 4];
|
||||
let green = new_offscreen[col * 4 + 1 + row * context.width * 4];
|
||||
let blue = new_offscreen[col * 4 + 2 + row * context.width * 4];
|
||||
let mut count = 0;
|
||||
for pixel in resized_img.pixels() {
|
||||
use image::Pixel;
|
||||
let rgb = pixel.to_rgb();
|
||||
|
||||
context.frame_buffer[col + row * context.width] = ('@', (red, green, blue));
|
||||
}
|
||||
context.frame_buffer[count] = ('@', (rgb[0], rgb[1], rgb[2]));
|
||||
count += 1;
|
||||
}
|
||||
context.flush()?;
|
||||
|
||||
|
Reference in New Issue
Block a user