eye 0.5.0

Cross platform camera capture and control
Documentation
use jpeg_decoder::{Decoder, PixelFormat as JpegFormat};

use eye_hal::format::PixelFormat;

use super::{Blueprint, Codec, Error, ErrorKind, Parameters, Result};

pub fn blueprint() -> impl Blueprint {
    Builder::default()
}

#[derive(Debug, Clone)]
pub struct Builder {}

impl Default for Builder {
    fn default() -> Self {
        Builder {}
    }
}

impl Blueprint for Builder {
    fn instantiate(
        &self,
        inparams: Parameters,
        outparams: Parameters,
    ) -> Result<Box<dyn Codec + Send>> {
        if self
            .src_fmts()
            .iter()
            .find(|pixfmt| **pixfmt == inparams.pixfmt)
            .is_none()
            || self
                .dst_fmts()
                .iter()
                .find(|pixfmt| **pixfmt == outparams.pixfmt)
                .is_none()
        {
            return Err(Error::from(ErrorKind::UnsupportedFormat));
        }

        if inparams.width != outparams.width || inparams.height != outparams.height {
            return Err(Error::from(ErrorKind::InvalidParam));
        }

        Ok(Box::new(Instance {
            inparams,
            outparams,
        }))
    }

    fn src_fmts(&self) -> Vec<PixelFormat> {
        vec![PixelFormat::Jpeg]
    }

    fn dst_fmts(&self) -> Vec<PixelFormat> {
        vec![PixelFormat::Rgb(24)]
    }
}

pub struct Instance {
    inparams: Parameters,
    outparams: Parameters,
}

impl Codec for Instance {
    fn decode(&self, inbuf: &[u8], outbuf: &mut Vec<u8>) -> Result<()> {
        match (&self.inparams.pixfmt, &self.outparams.pixfmt) {
            (PixelFormat::Jpeg, PixelFormat::Rgb(24)) => convert_to_rgb(inbuf, outbuf),
            _ => Err(Error::from(ErrorKind::UnsupportedFormat)),
        }
    }
}

pub fn convert_to_rgb(src: &[u8], dst: &mut Vec<u8>) -> Result<()> {
    let mut decoder = Decoder::new(src);
    let data = match decoder.decode() {
        Ok(data) => data,
        Err(_) => return Err(Error::new(ErrorKind::Other, "failed to decode JPEG")),
    };

    let info = match decoder.info() {
        Some(info) => info,
        None => return Err(Error::new(ErrorKind::Other, "failed to read JPEG metadata")),
    };

    match info.pixel_format {
        JpegFormat::RGB24 => {
            *dst = data;
            Ok(())
        }
        _ => Err(Error::new(ErrorKind::Other, "cannot handle JPEG format")),
    }
}