1 use image::{GenericImage, Pixel}; 2 use std::{ 3 io::{self, Write}, 4 os::raw::{c_uchar, c_int, c_void}, 5 ptr, 6 slice 7 }; 8 9 type Alloc = *mut c_void; 10 type Dither = *mut c_void; 11 type Output = *mut c_void; 12 type Status = c_int; 13 type WriteFn = extern "C" fn(data: *mut c_uchar, len: c_int, userdata: *mut c_void) -> Status; 14 15 const SIXEL_BUILTIN_XTERM256: c_int = 3; 16 17 #[link(name = "sixel")] 18 extern "C" { sixel_output_new(output: *mut Output, write_fn: WriteFn, userdata: *mut c_void, alloc: Alloc) -> Status19 fn sixel_output_new(output: *mut Output, write_fn: WriteFn, userdata: *mut c_void, alloc: Alloc) -> Status; sixel_dither_get(kind: c_int) -> Dither20 fn sixel_dither_get(kind: c_int) -> Dither; sixel_encode(data: *mut c_uchar, width: c_int, height: c_int, _: c_int, dither: Dither, output: Output) -> Status21 fn sixel_encode(data: *mut c_uchar, width: c_int, height: c_int, _: c_int, dither: Dither, output: Output) -> Status; 22 } 23 24 #[derive(Clone, Copy, Debug)] 25 pub struct Sixel; 26 27 impl super::Converter for Sixel { display<W, I, P>(&self, fmt: &mut W, image: &I) -> io::Result<()> where W: Write, I: GenericImage<Pixel = P>, P: Pixel<Subpixel = u8>28 fn display<W, I, P>(&self, fmt: &mut W, image: &I) -> io::Result<()> 29 where W: Write, 30 I: GenericImage<Pixel = P>, 31 P: Pixel<Subpixel = u8> 32 { 33 extern "C" fn write_fn(data: *mut c_uchar, len: c_int, userdata: *mut c_void) -> c_int { 34 unsafe { 35 let output: &mut Vec<u8> = &mut *(userdata as *mut Vec<u8>); 36 output.write_all(slice::from_raw_parts(data, len as usize)).unwrap(); 37 0 38 } 39 } 40 41 let mut data = Vec::with_capacity(image.width() as usize * image.height() as usize * 3); 42 for y in 0..image.height() { 43 for x in 0..image.width() { 44 let pixel = image.get_pixel(x, y).to_rgb(); 45 data.push(pixel[0]); 46 data.push(pixel[1]); 47 data.push(pixel[2]); 48 } 49 } 50 51 let data: *mut c_uchar = data.as_mut_ptr() as *mut c_uchar; 52 53 let mut output: Vec<u8> = Vec::new(); 54 let mut sixel_output = ptr::null_mut(); 55 56 if unsafe { 57 sixel_output_new( 58 &mut sixel_output, 59 write_fn, 60 &mut output as *mut _ as *mut c_void, 61 ptr::null_mut() 62 ) 63 } != 0 { 64 return Err(io::Error::new(io::ErrorKind::Other, "sixel_output_new error")); 65 } 66 67 let sixel_dither = unsafe { sixel_dither_get(SIXEL_BUILTIN_XTERM256) }; 68 69 let result = unsafe { 70 sixel_encode(data, image.width() as i32, image.height() as i32, 0, sixel_dither, sixel_output) 71 }; 72 73 if result == 0 { 74 write!(fmt, "{}", ::std::str::from_utf8(&output).unwrap()) 75 } else { 76 Err(io::Error::new(io::ErrorKind::Other, "sixel_encode error")) 77 } 78 } actual_pos(&self, x: u32, y: u32) -> (u32, u32)79 fn actual_pos(&self, x: u32, y: u32) -> (u32, u32) { 80 (x * 10, y * 10) 81 } 82 } 83