raster/lib.rs
1//! # Raster
2//!
3//! Raster is an image processing lib for Rust.
4//!
5//! It provides a simplified API for processing raster images (JPEG, PNG and GIF).
6//!
7//! ## Installation
8//! Add this to your Cargo.toml file:
9//!
10//! ```rust,ignore
11//! [dependencies]
12//!
13//! raster = "x.x.x"
14//! ```
15//! Where x are version numbers of the [latest version](https://crates.io/crates/raster) of raster. Eg.: 0.1.0
16//!
17//! Then add the raster crate in your main.rs:
18//!
19//! ```rust,ignore
20//! extern crate raster; // In your main rust file
21//! ```
22//!
23//! ## Creating Images
24//! ### From an image file
25//!
26//! ```rust,ignore
27//! // Create an image from file
28//! let image = raster::open("tests/in/sample.png").unwrap();
29//!
30//! ```
31//! Raster will detect the image format based on the file name.
32//!
33//! ### Create a blank image
34//! ```rust,ignore
35//! use raster::Image; // Include the Image struct
36//!
37//! // Create a blank 150x100 image. Defaults to a black background.
38//! let image = Image::blank(150, 100);
39//!
40//! ```
41//!
42//! ## Saving Images
43//! Save the opened image file:
44//!
45//! ```
46//! // Create an image from file
47//! let image = raster::open("tests/in/sample.png").unwrap();
48//!
49//! // Save opened image
50//! raster::save(&image, "tests/out/test_open_save.png").unwrap();
51//!
52//! ```
53//!
54//!
55//!
56//!
57//! ## Blending 2 Images
58//!
59//! Here are two images blended using the normal mode.
60//!
61//! 
62//!
63//! More blending modes and options are available, see the blend API.
64//!
65//! ## Resizing Images
66//!
67//! An example of images resized to "fit" in a 200x200 box.
68//!
69//!  
70//!
71//! More modes available, see the resize API.
72//!
73//! ## Rotating Images
74//!
75//! Images can be rotated both clockwise and counter-clockwise at any arbitrary angle with a custom background color.
76//!
77//! 
78//! 
79//!
80//! ## And Many More...
81//!
82//! More options are available, checkout the modules below.
83//!
84
85// modules
86pub mod compare;
87pub mod editor;
88pub mod error;
89pub mod filter;
90pub mod interpolate;
91pub mod transform;
92mod blend;
93mod color;
94mod endec;
95mod image;
96mod position;
97
98// crates
99extern crate gif;
100extern crate image as piston_image;
101extern crate png;
102
103// from rust
104use std::ascii::AsciiExt;
105use std::fs::File;
106use std::path::Path;
107
108// from external crate
109use piston_image::GenericImage;
110
111// from local crate
112use error::{RasterError, RasterResult};
113
114// re-exports
115pub use blend::BlendMode;
116pub use color::Color;
117pub use editor::ResizeMode;
118pub use filter::BlurMode;
119pub use image::Histogram;
120pub use image::Image;
121pub use image::ImageFormat;
122pub use interpolate::InterpolationMode;
123pub use position::PositionMode;
124pub use transform::TransformMode;
125
126
127/// Create an image from an image file.
128///
129/// # Errors
130///
131/// This function can return `RasterError::Io`, `RasterError::Decode`, or `RasterError::UnsupportedFormat` upon failure.
132/// See error module for more info.
133///
134/// # Examples
135///
136/// ```
137/// // Create an image from file
138/// let image = raster::open("tests/in/sample.png").unwrap();
139/// println!("{:?}", image.bytes);
140/// ```
141pub fn open(image_file: &str) -> RasterResult<Image> {
142
143 let path = Path::new(image_file);
144 let ext = path.extension().and_then(|s| s.to_str())
145 .map_or("".to_string(), |s| s.to_ascii_lowercase());
146
147 // Open the file with basic error check
148 let file = try!(File::open(image_file));
149
150 match &ext[..] {
151 "gif" => {
152 Ok(try!(endec::decode_gif(&file)))
153 },
154 "jpg" | "jpeg" => {
155 let src = try!(piston_image::open(image_file));
156 let (w, h) = src.dimensions();
157 let mut bytes = Vec::with_capacity((w * h) as usize * 4);
158 for y in 0..h {
159 for x in 0..w {
160 let p = src.get_pixel(x, y);
161 bytes.extend_from_slice(&p.data[0..4]);
162 }
163 }
164 Ok(Image{
165 width: w as i32,
166 height: h as i32,
167 bytes: bytes
168 })
169 },
170 "png" => {
171 Ok(try!(endec::decode_png(&file)))
172 },
173 _ => {
174 Err(RasterError::UnsupportedFormat(ext))
175 }
176 }
177}
178
179/// Save an image to an image file. The image type is detected from the file extension of the file name.
180///
181/// # Errors
182///
183/// This function can return `RasterError::Io`, `RasterError::Encode`, or `RasterError::UnsupportedFormat` upon failure.
184/// See error module for more info.
185///
186/// # Examples
187///
188/// ```
189/// // Create an image from file
190/// let image = raster::open("tests/in/sample.png").unwrap();
191/// raster::save(&image, "tests/out/test.png").unwrap();
192/// ```
193pub fn save(image: &Image, out: &str) -> RasterResult<()> {
194
195 let path = Path::new(out);
196 let ext = path.extension().and_then(|s| s.to_str())
197 .map_or("".to_string(), |s| s.to_ascii_lowercase());
198
199 match &ext[..] {
200 "gif" => {
201 Ok(try!(endec::encode_gif(&image, &path)))
202 },
203 "jpg" | "jpeg" => {
204 piston_image::save_buffer(
205 &path,
206 &image.bytes,
207 image.width as u32,
208 image.height as u32,
209 piston_image::RGBA(8)
210 ).map_err(|_| RasterError::Encode(ImageFormat::Jpeg, "Format".to_string()))
211 },
212 "png" => {
213 Ok(try!(endec::encode_png(&image, &path)))
214 },
215 _ => {
216 Err(RasterError::UnsupportedFormat(ext))
217 }
218 }
219}