Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
c12i committed Nov 5, 2023
1 parent 1d9a646 commit 20babad
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 48 deletions.
57 changes: 31 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ See [this whitepaper](https://core.ac.uk/download/pdf/235050007.pdf) for referen

## Usage

1. Add `img_stegano`, `git` dependency in your `Cargo.toml`.
1. Add `img_stegano` as a `git` dependency in your `Cargo.toml`.

```toml
[dependencies]
Expand All @@ -24,18 +24,25 @@ img_stegano = {git = "https://github.com/collinsmuriuki/img_stegano.git"}

2. Import the `ImgStegano` to use as demonstrated in the following example:

`encode_from_image`: Encode and decode from [`DynamicImage`](https://creative-coding-the-hard-way.github.io/Agents/image/enum.DynamicImage.html)
`encode_from_image`: Encode and decode from an `Image` struct

```rust,no_run
use img_stegano::ImgStegano;
use img_stegano::{ImgStegano, Image, image::ImageFormat};
fn main() {
let image = img_stegano::image::open("dice.png").expect("failed to open image");
let encoded = ImgStegano::encode_from_image(&image, "foo bar");
encoded
.save_with_format("out.png", img_stegano::image::ImageFormat::Png)
.expect("Failed to save out.png");
let encoded = img_stegano::image::open("out.png").expect("Failed to open encoded out.png file");
// open image
let image = Image::open("dice.png").expect("Failed to open image");
// encode message to image
let encoded = ImgStegano::encode_from_image(image, "foo bar");
// save text encoded image
encoded.save("out.png", ImageFormat::Png).expect("Failed to save out.png");
// open text encoded image
let encoded = Image::open("out.png").expect("Failed to open encoded out.png file");
// decode text from image
let decoded_text = ImgStegano::decode_from_image(&encoded);
println!("{decoded_text}");
assert_eq!(decoded_text, "foo bar".to_string());
Expand All @@ -46,7 +53,7 @@ fn main() {

```rust,no_run
use std::{fs::File, io::Read};
use img_stegano::ImgStegano;
use img_stegano::{ImgStegano, Image, image::ImageFormat};
fn main() {
// Load the input image
Expand All @@ -55,22 +62,20 @@ fn main() {
file.read_to_end(&mut buffer).unwrap();
// encode from buffer
let encoded = ImgStegano::encode_from_u8_array(&buffer, "png", "foo bar")
.expect("Failed to encode message to image");
let encoded = img_stegano::image::load_from_memory_with_format(&encoded, img_stegano::image::ImageFormat::Png)
.expect("Failed to load image");
let encoded = ImgStegano::encode_from_u8_array(&buffer, "png", "foo bar").expect("Failed to encode message to image");
// save encoded file
// save text encoded image
let encoded = Image::open_from_u8_array(&encoded, ImageFormat::Png).expect("Failed to load image");
encoded
.save_with_format("out2.png", img_stegano::image::ImageFormat::Png)
.save("out2.png", ImageFormat::Png)
.expect("Failed to save out2.png");
// decode saved encoded file
// open saved text encoded image
let mut decoded = File::open("out2.png").expect("Failed to open input file");
let mut decoded_buffer = Vec::new();
decoded.read_to_end(&mut decoded_buffer).unwrap();
// decode from buffer
// decode encoded text from image buffer
let decoded_text = ImgStegano::decode_from_u8_array(&decoded_buffer).expect("Failed to decode image");
println!("{decoded_text}");
assert_eq!(decoded_text, "foo bar".to_string());
Expand All @@ -80,19 +85,19 @@ fn main() {
`encode_from_path`: Encode and decode from path

```rust,no_run
use img_stegano::ImgStegano;
use img_stegano::{ImgStegano, Image, image::ImageFormat};
fn main() {
// encode from file path
let encoded = ImgStegano::encode_from_path("dice.png", "foo bar")
.expect("Failed to encode text to image");
// save encoded file
let encoded = ImgStegano::encode_from_path("dice.png", "foo bar").expect("Failed to encode text to image");
// save text encoded image
encoded
.save_with_format("out3.png", img_stegano::image::ImageFormat::Png)
.save("out3.png", ImageFormat::Png)
.expect("Failed to save image");
// decode from saved encoded file path
let decoded_text =
ImgStegano::decode_from_path("out3.png").expect("Failed to decode text from image");
// decode saved text encoded image from its path
let decoded_text = ImgStegano::decode_from_path("out3.png").expect("Failed to decode text from image");
println!("{decoded_text}");
assert_eq!(decoded_text, "foo bar".to_string());
}
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#![doc = include_str!("../README.md")]

pub use img_stegano_core::{image, ImgStegano, ImgSteganoError};
pub use img_stegano_core::{Image, ImgStegano, ImgSteganoError};

pub mod image {
pub use img_stegano_core::ImageFormat;
}
47 changes: 37 additions & 10 deletions stegano-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ mod error;
use std::{io::Cursor, path::PathBuf};

pub use error::ImgSteganoError;
pub use image;
use image::{DynamicImage, GenericImage, GenericImageView, ImageFormat, Pixel, Rgba};
pub use image::ImageFormat;
use image::{DynamicImage, GenericImage, GenericImageView, Pixel, Rgba};

pub struct ImgStegano;

impl ImgStegano {
pub fn encode_from_image(input_image: &DynamicImage, message: &str) -> DynamicImage {
pub fn encode_from_image(Image(input_image): Image, message: &str) -> Image {
let mut output_image = input_image.clone();
let message = message
.as_bytes()
Expand All @@ -34,7 +34,7 @@ impl ImgStegano {
}
}
}
output_image
output_image.into()
}

pub fn encode_from_u8_array(
Expand All @@ -45,7 +45,8 @@ impl ImgStegano {
let image_format = ImageFormat::from_extension(image_extension)
.ok_or(ImgSteganoError::InvalidImageFormat)?;
let image = image::load_from_memory_with_format(input_image, image_format)?;
let encoded_image = Self::encode_from_image(&image, message);
let encoded_image = Self::encode_from_image(image.into(), message);
let Image(encoded_image) = encoded_image;
let mut encoded: Vec<u8> = Vec::new();
let mut cursor = Cursor::new(&mut encoded);
encoded_image.write_to(&mut cursor, image_format)?;
Expand All @@ -55,13 +56,13 @@ impl ImgStegano {
pub fn encode_from_path<T: Into<PathBuf>>(
image_path: T,
message: &str,
) -> Result<DynamicImage, ImgSteganoError> {
) -> Result<Image, ImgSteganoError> {
let image = image::open(image_path.into())?;
let encoded_image = Self::encode_from_image(&image, message);
let encoded_image = Self::encode_from_image(image.into(), message);
Ok(encoded_image)
}

pub fn decode_from_image(encoded_image: &DynamicImage) -> String {
pub fn decode_from_image(Image(encoded_image): &Image) -> String {
let (width, height) = encoded_image.dimensions();
let mut binary_message = String::new();
let mut current_byte = 0u8;
Expand Down Expand Up @@ -92,13 +93,39 @@ impl ImgStegano {

pub fn decode_from_u8_array(input_image: &[u8]) -> Result<String, ImgSteganoError> {
let image = image::load_from_memory_with_format(input_image, image::ImageFormat::Png)?;
let decoded = Self::decode_from_image(&image);
let decoded = Self::decode_from_image(&image.into());
Ok(decoded)
}

pub fn decode_from_path<T: Into<PathBuf>>(image_path: T) -> Result<String, ImgSteganoError> {
let image = image::open(image_path.into())?;
let decoded = Self::decode_from_image(&image);
let decoded = Self::decode_from_image(&image.into());
Ok(decoded)
}
}

#[derive(Debug, Clone)]
pub struct Image(DynamicImage);

impl Image {
pub fn open(path: &str) -> Result<Self, ImgSteganoError> {
let image = image::open(path)?;
Ok(Image(image))
}

pub fn open_from_u8_array(buf: &[u8], format: ImageFormat) -> Result<Self, ImgSteganoError> {
let image = image::load_from_memory_with_format(buf, format)?;
Ok(Image(image))
}

pub fn save(&self, path: &str, format: ImageFormat) -> Result<(), ImgSteganoError> {
self.0.save_with_format(path, format)?;
Ok(())
}
}

impl From<DynamicImage> for Image {
fn from(value: DynamicImage) -> Self {
Image(value)
}
}
21 changes: 10 additions & 11 deletions stegano-core/tests/test_steganography.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
use std::{fs::File, io::Read};

use img_stegano_core::image::{load_from_memory_with_format, open, ImageFormat};
use img_stegano_core::ImgStegano;
use img_stegano_core::{Image, ImageFormat, ImgStegano};

#[test]
fn test_encode_and_decode_from_image() {
let image = open("dice.png").expect("failed to open image");
let encoded = ImgStegano::encode_from_image(&image, "foo bar");
let image = Image::open("dice.png").expect("failed to open image");
let encoded = ImgStegano::encode_from_image(image, "foo bar");
encoded
.save_with_format("out.png", ImageFormat::Png)
.save("out.png", ImageFormat::Png)
.expect("Failed to save out.png");
let encoded = open("out.png").expect("Failed to open encoded out.png file");
let encoded = Image::open("out.png").expect("Failed to open image");
let decoded_text = ImgStegano::decode_from_image(&encoded);
assert_eq!(decoded_text, "foo bar".to_string());
}
Expand All @@ -22,10 +21,10 @@ fn test_encode_and_decode_from_u8_array() {
file.read_to_end(&mut buffer).unwrap();
let encoded = ImgStegano::encode_from_u8_array(&buffer, "png", "foo bar")
.expect("Failed to encode message to image");
let encoded =
load_from_memory_with_format(&encoded, ImageFormat::Png).expect("Failed to load image");
let encoded = Image::open_from_u8_array(&encoded, ImageFormat::Png)
.expect("Failed to open image from buffer");
encoded
.save_with_format("out2.png", ImageFormat::Png)
.save("out2.png", ImageFormat::Png)
.expect("Failed to save out2.png");
let mut decoded = File::open("out2.png").expect("Failed to open input file");
let mut decoded_buffer = Vec::new();
Expand All @@ -40,8 +39,8 @@ fn test_encode_and_decode_from_path() {
let encoded = ImgStegano::encode_from_path("dice.png", "foo bar")
.expect("Failed to encode text to image");
encoded
.save_with_format("out3.png", ImageFormat::Png)
.expect("Failed to save image");
.save("out3.png", ImageFormat::Png)
.expect("Failed to save out3.png");
let decoded_text =
ImgStegano::decode_from_path("out3.png").expect("Failed to decode text from image");
assert_eq!(decoded_text, "foo bar".to_string());
Expand Down

0 comments on commit 20babad

Please sign in to comment.