Add some logic for more binary formats

This commit is contained in:
Jonathan Turner
2019-07-05 19:53:09 +12:00
parent fc7ef89fe6
commit ea997289d9
3 changed files with 279 additions and 22 deletions

View File

@ -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()?;