1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
#![warn(clippy::pedantic)]
/*!
# image-blend
### Library to perform blending and alpha channel operations using the image crate
Implementation of support for type-agnostic blending algorithms such as screen, multiply, lighter, etc, for the [image](https://crates.io/crates/image) crate
Also provide support for getting alpha channnels as grayscale images, setting alpha channels from grayscale images, and transplanting alpha channels directly from one image to another
#### Type-agnostic: this library will automatically convert between input type when blending two images together.
The only limitation to this is that you cannot blend an Rgb/Rgba image into a Luma image.
## Usage:
Syntax is the same when working with Dynamic and Imagebuffer.
### Working with dynamic images
#### Blend two images together
```rust
use image::open;
use image_blend::DynamicChops;
use image_blend::pixelops::pixel_mult;
// Load an image
let mut img1_dynamic = open("test_data/1.png").unwrap();
// Load another image
let img2_dynamic = open("test_data/2.png").unwrap();
// Blend the images using the pixel_mult function
img1_dynamic.blend(&img2_dynamic, pixel_mult, true, false).unwrap();
img1_dynamic.save("tests_out/doctest_dynamic_blend_result.png").unwrap();
```
#### Get and set the alpha channels
```rust
use image::open;
use image_blend::DynamicChops;
// Load an image and get its alpha channel
let img1_dynamic = open("test_data/1.png").unwrap();
let img1_alpha = img1_dynamic.get_alpha().unwrap();
img1_alpha.clone().save("tests_out/doctest_dynamic_getalpha_alpha.png").unwrap();
// Load another image and set its alpha channel to the first image's alpha channel, using the copied alpha channel
let mut img2_dynamic = open("test_data/2.png").unwrap();
img2_dynamic.set_alpha(&img1_alpha).unwrap();
img2_dynamic.save("tests_out/doctest_dynamic_getalpha_result.png").unwrap();
```
#### Transplant an alpha channel directly from one image to another
```rust
use image::open;
use image_blend::DynamicChops;
// Load an image and get its alpha channel
let img1_dynamic = open("test_data/1.png").unwrap();
// Load another image and set its alpha channel to a copy of the first image's alpha channel.
let mut img2_dynamic = open("test_data/2.png").unwrap();
img2_dynamic.transplant_alpha(&img1_dynamic).unwrap();
img2_dynamic.save("tests_out/doctest_dynamic_transplantalpha_result.png").unwrap();
```
### Working with imagebuffers
Note how in these examples, the image buffers have different types but it doesn't matter as the library handles this.
#### Blend two images together
```rust
use image::open;
use image_blend::BufferBlend;
use image_blend::pixelops::pixel_mult;
// Load an image
let mut img1_dynamic = open("test_data/1.png").unwrap();
let mut img1_buffer = img1_dynamic.as_mut_rgba8().unwrap();
// Load another image
let img2_dynamic = open("test_data/2.png").unwrap();
let img2_buffer = img2_dynamic.to_rgba16();
// Blend the images using the pixel_mult function
img1_buffer.blend(&img2_buffer, pixel_mult, true, false).unwrap();
img1_buffer.save("tests_out/doctest_buffer_blend_result.png").unwrap();
```
#### Get and set alpha channels
```rust
use image::open;
use image_blend::{BufferGetAlpha, BufferSetAlpha};
// Load an image and get its alpha channel
let img1_dynamic = open("test_data/1.png").unwrap();
let img1_buffer = img1_dynamic.as_rgba8().unwrap();
let img1_alpha = img1_buffer.get_alpha().unwrap();
img1_alpha.clone().save("tests_out/doctest_buffer_getalpha_alpha.png").unwrap();
// Load another image and set its alpha channel to the first image's alpha channel, using the copied alpha channel
let mut img2_dynamic = open("test_data/2.png").unwrap();
let mut img2_buffer = img2_dynamic.to_rgba16();
img2_buffer.set_alpha(&img1_alpha).unwrap();
img2_buffer.save("tests_out/doctest_buffer_getalpha_result.png").unwrap();
```
#### Transplant an alpha channel directly from one image to another
```rust
use image::open;
use image_blend::{BufferGetAlpha, BufferSetAlpha};
// Load an image and get its alpha channel
let img1_dynamic = open("test_data/1.png").unwrap();
let img1_buffer = img1_dynamic.as_rgba8().unwrap();
// Load another image and set its alpha channel to a copy of the first image's alpha channel.
let mut img2_dynamic = open("test_data/2.png").unwrap();
let mut img2_buffer = img2_dynamic.to_rgba16();
img2_buffer.transplant_alpha(&img1_buffer).unwrap();
img2_buffer.save("tests_out/doctest_buffer_transplantalpha_result.png").unwrap();
```
## Custom blend operations
Using custom blend operations is easy. You just need a function that takes 2 f64s and returns an f64.
The values passed to this function are `0..1` where `0.` is the darkest a pixel can be and `1.` the brightest. Type conversion and clamping of the return to `0..1` is handled for you.
`a` is self, `b` is other.
```rust
use image::open;
use image_blend::DynamicChops;
let closest_to_gray = |a: f64, b: f64| {
let a_diff = (a - 0.5).abs();
let b_diff = (b - 0.5).abs();
if a_diff < b_diff {
a
} else {
b
}
};
// Load an image
let mut img1_dynamic = open("test_data/1.png").unwrap();
// Load another image
let img2_dynamic = open("test_data/2.png").unwrap();
// Blend the images using our custom function
img1_dynamic.blend(&img2_dynamic, closest_to_gray, true, false).unwrap();
img1_dynamic.save("tests_out/doctest_dynamic_custom_result.png").unwrap();
```
*/
pub(crate) mod blend_ops;
pub(crate) mod dynamic_blend;
pub(crate) mod alpha_ops;
mod enums;
mod error;
mod tests;
pub use error::Error;
pub mod pixelops;
pub use alpha_ops::BufferGetAlpha;
pub use alpha_ops::BufferSetAlpha;
pub use alpha_ops::BufferStripAlpha;
pub use blend_ops::BufferBlend;
pub use dynamic_blend::DynamicChops;