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