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}