glycin-utils 3.0.0-alpha

Sandboxed image decoding
Documentation
use std::io::{Cursor, Read, Seek};

use gufo_common::math::{checked, Checked};

use super::{EditingFrame, Error};
use crate::memory_format::MemoryFormatInfo;

pub fn clip(
    buf: Vec<u8>,
    frame: &mut EditingFrame,
    (x, y, width, height): (u32, u32, u32, u32),
) -> Result<Vec<u8>, Error> {
    let pixel_size = frame.memory_format.n_bytes().u32();

    checked![y, pixel_size];

    let new_stride = (width * pixel_size).check()?;
    let size = (Checked::new(height) * new_stride).usize().check()?;
    let mut new = Vec::with_capacity(size);

    let stride = frame.stride as i64;
    let x_ = (x as i64 * pixel_size.i64()).check()?;
    let width_ = width as i64 * pixel_size.i64();

    checked![stride];

    let mut cur = Cursor::new(buf);
    let mut row = vec![0; (width as usize * pixel_size.usize()).check()?];

    cur.seek_relative((y.i64() * stride).check()?)?;

    for _ in 0..height {
        cur.seek_relative(x_)?;
        cur.read_exact(&mut row)?;
        new.extend_from_slice(&row);
        cur.seek_relative((stride - x_ - width_).check()?)?;
    }

    frame.width = width;
    frame.height = height;
    frame.stride = new_stride;

    Ok(new)
}