photon_rs/
native.rs

1//! Native-only functions.
2//! Includes functions that open images from the file-system, etc.,
3
4use image::DynamicImage::ImageRgba8;
5use image::{GenericImageView, ImageBuffer};
6use std::io;
7use std::path::Path;
8// use wasm_bindgen::prelude::*;
9use crate::PhotonImage;
10use thiserror::Error;
11
12#[derive(Debug, Error)]
13pub enum Error {
14    #[error(transparent)]
15    ImageError(#[from] image::ImageError),
16
17    #[error(transparent)]
18    IoError(#[from] io::Error),
19}
20
21/// Open an image at a given path from the filesystem.
22/// A PhotonImage is returned.
23/// # Arguments
24/// * `img_path` - Path to the image you wish to edit.
25///
26/// # Example
27/// ```no_run
28/// use photon_rs::native::open_image;
29///
30/// // Open the image. A PhotonImage is returned.
31/// let img = open_image("img.jpg").expect("File should open");
32///
33/// // ... image editing functionality here ...
34/// ```
35pub fn open_image<P>(img_path: P) -> Result<PhotonImage, Error>
36where
37    P: AsRef<Path>,
38{
39    let img = image::open(img_path)?;
40
41    let (width, height) = img.dimensions();
42
43    // Convert the DynamicImage type to raw vec representing RGBA pixels (not RGB)
44    let raw_pixels = img.to_rgba8().to_vec();
45
46    Ok(PhotonImage {
47        raw_pixels,
48        width,
49        height,
50    })
51}
52
53/// Saves a image from a byte slice
54/// A PhotonImage is returned.
55/// # Arguments
56/// * `buffer` - A byte slice containing the image you want to edit.
57///
58/// # Example
59/// ```no_run
60/// use photon_rs::native::open_image_from_bytes;
61///
62/// // Code to read a file to buffer. If you are reading from a file its better to use `open_image`
63/// let buffer = std::fs::read("img.jpg").expect("File Should Open");
64///
65/// // Open the image. A PhotonImage is returned.
66/// let img = open_image_from_bytes(buffer.as_slice()).expect("Buffer should be valid");
67///
68/// // ... image editing functionality here ...
69/// ```
70pub fn open_image_from_bytes(buffer: &[u8]) -> Result<PhotonImage, Error> {
71    let img = image::load_from_memory(buffer)?;
72    let (width, height) = img.dimensions();
73    let raw_pixels = img.to_rgba8().to_vec();
74
75    Ok(PhotonImage {
76        raw_pixels,
77        width,
78        height,
79    })
80}
81/// Save the image to the filesystem at a given path.
82/// # Arguments
83/// * img: The PhotonImage you wish to save.
84/// * `img_path` - Path for the outputted image.
85///
86/// # Example
87/// ```no_run
88/// use photon_rs::native::{open_image, save_image};
89///
90/// let img = open_image("img.jpg").expect("File should open");
91/// // Save the image at the given path.
92/// save_image(img,"manipulated_image.jpg").expect("Save failed");
93/// ```
94pub fn save_image<P>(img: PhotonImage, img_path: P) -> Result<(), Error>
95where
96    P: AsRef<Path>,
97{
98    let raw_pixels = img.raw_pixels;
99    let width = img.width;
100    let height = img.height;
101
102    let img_buffer = ImageBuffer::from_vec(width, height, raw_pixels).unwrap();
103    let dynimage = ImageRgba8(img_buffer);
104
105    dynimage.save(img_path)?;
106    Ok(())
107}
108
109/// Save the image to a vector of bytes
110/// # Arguments
111/// * img: The PhotonImage you wish to save.
112///
113/// # Example
114/// ```no_run
115/// use photon_rs::native::{open_image,image_to_bytes};
116///
117/// let img = open_image("img.jpg").expect("File should open");
118/// // Save the image at a vec<u8>
119/// let byt = image_to_bytes(img);
120/// ```
121pub fn image_to_bytes(img: PhotonImage) -> Vec<u8> {
122    let raw_pixels = img.raw_pixels;
123    let width = img.width;
124    let height = img.height;
125
126    let img_buffer = ImageBuffer::from_vec(width, height, raw_pixels).unwrap();
127    let dynimage = ImageRgba8(img_buffer);
128    dynimage.into_bytes()
129}