j2k-jpeg 0.6.1

JPEG inspect/decode and fallback encode support for j2k
Documentation
use j2k_core::Downscale;
use j2k_jpeg::{ComponentRowWriter, Decoder, Rect, ScratchPool};

use j2k_test_support as fixtures;

#[derive(Default)]
struct CollectRows {
    gray: Vec<Vec<u8>>,
    ycbcr: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)>,
    rgb: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)>,
}

impl ComponentRowWriter for CollectRows {
    fn write_gray_row(&mut self, _y: u32, gray_row: &[u8]) -> Result<(), j2k_jpeg::JpegError> {
        self.gray.push(gray_row.to_vec());
        Ok(())
    }

    fn write_ycbcr_row(
        &mut self,
        _y: u32,
        y_row: &[u8],
        cb_row: &[u8],
        cr_row: &[u8],
    ) -> Result<(), j2k_jpeg::JpegError> {
        self.ycbcr
            .push((y_row.to_vec(), cb_row.to_vec(), cr_row.to_vec()));
        Ok(())
    }

    fn write_rgb_row(
        &mut self,
        _y: u32,
        r_row: &[u8],
        g_row: &[u8],
        b_row: &[u8],
    ) -> Result<(), j2k_jpeg::JpegError> {
        self.rgb
            .push((r_row.to_vec(), g_row.to_vec(), b_row.to_vec()));
        Ok(())
    }
}

#[test]
fn component_rows_expose_ycbcr_rows_for_full_decode() {
    let mut pool = ScratchPool::new();
    let mut rows = CollectRows::default();
    let jpeg = fixtures::minimal_baseline_420_jpeg();
    let decoder = Decoder::new(&jpeg).expect("decoder");

    decoder
        .decode_component_rows_with_scratch(&mut pool, &mut rows)
        .expect("decode component rows");

    assert!(rows.gray.is_empty());
    assert!(rows.rgb.is_empty());
    assert_eq!(rows.ycbcr.len(), 16);
    assert!(rows
        .ycbcr
        .iter()
        .all(|(y, cb, cr)| y.len() == 16 && cb.len() == 16 && cr.len() == 16));
}

#[test]
fn component_rows_region_scaled_rebases_output_rows() {
    let mut pool = ScratchPool::new();
    let mut rows = CollectRows::default();
    let jpeg = fixtures::minimal_baseline_420_jpeg();
    let decoder = Decoder::new(&jpeg).expect("decoder");
    let roi = Rect {
        x: 4,
        y: 4,
        w: 8,
        h: 8,
    };

    decoder
        .decode_region_component_rows_with_scratch(&mut pool, &mut rows, roi, Downscale::Half)
        .expect("decode region component rows");

    assert_eq!(rows.ycbcr.len(), 4);
    assert!(rows
        .ycbcr
        .iter()
        .all(|(y, cb, cr)| y.len() == 4 && cb.len() == 4 && cr.len() == 4));
}