From ed31c4201834719b2b75dca7cad1637abf1a80bb Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Sun, 2 Jun 2024 18:38:25 -0400 Subject: Made codecs object-safe and deal with bytes only --- src/lossless/lsb.rs | 65 ++++++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 41 deletions(-) (limited to 'src/lossless/lsb.rs') diff --git a/src/lossless/lsb.rs b/src/lossless/lsb.rs index 59dcc0b..f8f1113 100644 --- a/src/lossless/lsb.rs +++ b/src/lossless/lsb.rs @@ -1,33 +1,25 @@ -use std::cmp::Ordering; +use std::{cmp::Ordering, io::{BufWriter, Cursor}}; -use image::{ColorType, DynamicImage, GenericImageView, Pixel}; -use thiserror::Error; +use image::{DynamicImage, GenericImageView, Pixel}; -use crate::codec::Codec; +use crate::{codec::Codec, CodecError}; /// Least-significant bit (LSB) steganography encodes data in the least-significant bits of colors /// in an image. This implementation reduces the colors in the carrier (irreversibly) in order to /// allow a byte of data to fit in each pixel of the image. 3 bits of data are encoded per pixel, /// and the 9th bit is used to signal the end of data. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct LsbCodec; impl Codec for LsbCodec { - type Carrier = DynamicImage; - type Payload = Vec; - type Output = Self::Carrier; - type Error = LsbError; - - fn encode(&self, carrier: C, payload: P) -> Result - where - C: Into, - P: Into, + fn encode(&self, carrier: &[u8], payload: &[u8]) -> Result, CodecError> { - let mut image: DynamicImage = carrier.into(); - let payload: Vec = payload.into(); + let image_format = image::guess_format(carrier.into()).unwrap(); + let mut image: DynamicImage = image::load_from_memory(carrier.into()).unwrap(); + let payload: &[u8] = payload.into(); if image.pixels().count() < payload.len() { - return Err(LsbError::PayloadTooBig); + return Err(CodecError::DataInvalid("Payload Too Big for Carrier".into())); } let mut payload_iter = payload.iter(); @@ -51,17 +43,20 @@ impl Codec for LsbCodec { } } }, - _ => return Err(LsbError::UnsupportedFormat { format: image.color() }) + _ => return Err(CodecError::DataInvalid("Unsupported Image Color Format".into())) } - Ok(image) + let mut buf = BufWriter::new(Cursor::new(Vec::::new())); + if let Err(e) = image.write_to(&mut buf, image_format) { + return Err(CodecError::DependencyError(e.to_string())) + } + Ok(buf.into_inner().unwrap().into_inner()) } - fn decode(&self, carrier: E) -> Result<(Self::Carrier, Self::Payload), LsbError> - where - E: Into, + fn decode(&self, carrier: &[u8]) -> Result<(Vec, Vec), CodecError> { - let mut image: DynamicImage = carrier.into(); + let image_format = image::guess_format(carrier.into()).unwrap(); + let mut image: DynamicImage = image::load_from_memory(carrier.into()).unwrap(); let mut payload: Vec = Vec::new(); match image { @@ -83,10 +78,14 @@ impl Codec for LsbCodec { } } }, - _ => return Err(LsbError::UnsupportedFormat { format: image.color() }) + _ => return Err(CodecError::DataInvalid("Unsupported Image Color Format".into())) } - Ok((image, payload)) + let mut buf = BufWriter::new(Cursor::new(Vec::::new())); + if let Err(e) = image.write_to(&mut buf, image_format) { + return Err(CodecError::DependencyError(e.to_string())) + } + Ok((buf.into_inner().unwrap().into_inner(), payload)) } } @@ -138,19 +137,3 @@ fn decode_pixel>(pixel: &mut P) -> Option { } Some(payload_byte) } - -/// Errors thrown by the LSB Codec. -#[derive(Error, Debug)] -pub enum LsbError { - - /// Error thrown when payload is too big for the carrier. - #[error("Payload is too big for the carrier. Choose a smaller payload or an image with greater pixel dimensions.")] - PayloadTooBig, - - /// Error thrown when pixel format is unsupported. - #[error("Specified image format ({format:?}) is unsupported.")] - UnsupportedFormat { - /// Provided (invalid) format. - format: ColorType - }, -} -- cgit v1.2.3