Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
bb7eb75
switch to pixeli crate
ripytide Jun 2, 2024
4799471
mass rename subpixel to component
ripytide Jun 2, 2024
e791ef6
checkpoint
ripytide Jun 2, 2024
e8f8b4b
fixe
ripytide Jun 2, 2024
0f2ca5d
more fixes
ripytide Jun 2, 2024
54417c8
fix more imports
ripytide Jun 2, 2024
8ab056c
mass rename CHANNEL_COUNT to COMPONENT_COUNT
ripytide Jun 2, 2024
ea41eca
remove uneeded traits
ripytide Jun 2, 2024
f4c6d14
mass rename primitive to pixelcomponent
ripytide Jun 2, 2024
c496c56
checkpoint
ripytide Jun 2, 2024
8777c18
mass replace rgba to struct version
ripytide Jun 2, 2024
0485f35
checkpoint
ripytide Jun 2, 2024
f8d7538
fixed all non imageops functions
ripytide Jun 2, 2024
d2d35d2
checkpoint
ripytide Jun 2, 2024
4ab3bad
mass replace rgb struct
ripytide Jun 2, 2024
02dc022
passed round 1 of the compiler
ripytide Jun 2, 2024
b9c7860
more fixes
ripytide Jun 2, 2024
060d15b
start on more fixes
ripytide Jun 2, 2024
60c544e
checkpoint
ripytide Jun 3, 2024
d43f64d
mass replace rgba and rgb again
ripytide Jun 3, 2024
3f95591
mass replace grayalpha
ripytide Jun 3, 2024
6d8d7e7
checkpoint
ripytide Jun 3, 2024
114fa7a
checkpoint
ripytide Jun 3, 2024
2d97cbf
checkpoint
ripytide Jun 3, 2024
6d82ff0
checkpoint
ripytide Jun 3, 2024
17238d8
checkpoint
ripytide Jun 3, 2024
a7e102b
more fixes
ripytide Jun 4, 2024
e7fa791
more fixes
ripytide Jun 4, 2024
0ab15b8
no more errors/warnings
ripytide Jun 4, 2024
144ae7e
added gray f32 image variants
ripytide Jun 4, 2024
e1ced1e
add test variants for new image types
ripytide Jun 4, 2024
d455c5e
fix remaining tests
ripytide Jun 4, 2024
0eb667b
cargo fmt
ripytide Jun 4, 2024
3aa0d56
switch to the crates.io version of pixeli
ripytide Jun 4, 2024
ab5a2da
re-export the pixeli crate
ripytide Jun 4, 2024
e84b66b
fix more errors after ci checks
ripytide Jun 4, 2024
c5af5cd
fix fuzz ci test
ripytide Jun 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 38 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "image"
version = "0.25.1"
version = "0.26.0"
edition = "2021"
resolver = "2"

Expand All @@ -22,22 +22,25 @@ categories = ["multimedia::images", "multimedia::encoding", "encoding"]
exclude = ["src/png/testdata/*", "examples/*", "tests/*"]

include = [
"/LICENSE-APACHE",
"/LICENSE-MIT",
"/README.md",
"/CHANGES.md",
"/src/",
"/benches/",
"/LICENSE-APACHE",
"/LICENSE-MIT",
"/README.md",
"/CHANGES.md",
"/src/",
"/benches/",
]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
bytemuck = { version = "1.8.0", features = ["extern_crate_alloc"] } # includes cast_vec
bytemuck = { version = "1.8.0", features = [
"extern_crate_alloc",
] } # includes cast_vec
byteorder-lite = "0.1.0"
num-traits = { version = "0.2.0" }
pixeli = "0.2.1"

# Optional dependencies
color_quant = { version = "1.1", optional = true }
Expand Down Expand Up @@ -67,7 +70,23 @@ criterion = "0.5.0"
default = ["rayon", "default-formats"]

# Format features
default-formats = ["avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp"]
default-formats = [
"avif",
"bmp",
"dds",
"exr",
"ff",
"gif",
"hdr",
"ico",
"jpeg",
"png",
"pnm",
"qoi",
"tga",
"tiff",
"webp",
]
avif = ["dep:ravif", "dep:rgb"]
bmp = []
dds = []
Expand All @@ -86,10 +105,17 @@ webp = ["dep:image-webp"]

# Other features
rayon = ["dep:rayon"] # Enables multi-threading
nasm = ["ravif?/asm"] # Enables use of nasm by rav1e (requires nasm to be installed)
nasm = [
"ravif?/asm",
] # Enables use of nasm by rav1e (requires nasm to be installed)
color_quant = ["dep:color_quant"] # Enables color quantization
avif-native = ["dep:mp4parse", "dep:dcv-color-primitives", "dep:dav1d"] # Enable native dependency libdav1d
benchmarks = [] # Build some inline benchmarks. Useful only during development (requires nightly Rust)
avif-native = [
"dep:mp4parse",
"dep:dcv-color-primitives",
"dep:dav1d",
] # Enable native dependency libdav1d
benchmarks = [
] # Build some inline benchmarks. Useful only during development (requires nightly Rust)

[[bench]]
path = "benches/decode.rs"
Expand Down
95 changes: 51 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Image

[![crates.io](https://img.shields.io/crates/v/image.svg)](https://crates.io/crates/image)
[![Documentation](https://docs.rs/image/badge.svg)](https://docs.rs/image)
[![Build Status](https://github.com/image-rs/image/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image/actions)
Expand Down Expand Up @@ -42,23 +43,23 @@ image format encoders and decoders.

<!--- NOTE: Make sure to keep this table in sync with the one in src/lib.rs -->

| Format | Decoding | Encoding |
| -------- | ----------------------------------------- | --------------------------------------- |
| AVIF | Yes (8-bit only) \* | Yes (lossy only) |
| BMP | Yes | Yes |
| DDS | Yes | --- |
| Farbfeld | Yes | Yes |
| GIF | Yes | Yes |
| HDR | Yes | Yes |
| ICO | Yes | Yes |
| JPEG | Yes | Yes |
| EXR | Yes | Yes |
| PNG | Yes | Yes |
| PNM | Yes | Yes |
| QOI | Yes | Yes |
| TGA | Yes | Yes |
| TIFF | Yes | Yes |
| WebP | Yes | Yes (lossless only) |
| Format | Decoding | Encoding |
| -------- | ------------------- | ------------------- |
| AVIF | Yes (8-bit only) \* | Yes (lossy only) |
| BMP | Yes | Yes |
| DDS | Yes | --- |
| Farbfeld | Yes | Yes |
| GIF | Yes | Yes |
| HDR | Yes | Yes |
| ICO | Yes | Yes |
| JPEG | Yes | Yes |
| EXR | Yes | Yes |
| PNG | Yes | Yes |
| PNM | Yes | Yes |
| QOI | Yes | Yes |
| TGA | Yes | Yes |
| TIFF | Yes | Yes |
| WebP | Yes | Yes (lossless only) |

- \* Requires the `avif-native` feature, uses the libdav1d C library.

Expand All @@ -68,11 +69,13 @@ This crate provides a number of different types for representing images.
Individual pixels within images are indexed with (0,0) at the top left corner.

### [`ImageBuffer`](https://docs.rs/image/*/image/struct.ImageBuffer.html)

An image parameterised by its Pixel type, represented by a width and height and
a vector of pixels. It provides direct access to its pixels and implements the
`GenericImageView` and `GenericImage` traits.

### [`DynamicImage`](https://docs.rs/image/*/image/enum.DynamicImage.html)

A `DynamicImage` is an enumeration over all supported `ImageBuffer<P>` types.
Its exact image type is determined at runtime. It is the type returned when
opening an image. For convenience `DynamicImage` reimplements all image
Expand All @@ -83,11 +86,11 @@ processing functions.
Traits that provide methods for inspecting (`GenericImageView`) and manipulating (`GenericImage`) images, parameterised over the image's pixel type.

### [`SubImage`](https://docs.rs/image/*/image/struct.SubImage.html)

A view into another image, delimited by the coordinates of a rectangle.
The coordinates given set the position of the top left corner of the rectangle.
This is used to perform image processing functions on a subregion of an image.


## The [`ImageDecoder`](https://docs.rs/image/*/image/trait.ImageDecoder.html) and [`ImageDecoderRect`](https://docs.rs/image/*/image/trait.ImageDecoderRect.html) Traits

All image format decoders implement the `ImageDecoder` trait which provide
Expand All @@ -96,46 +99,50 @@ additionally provide `ImageDecoderRect` implementations which allow for
decoding only part of an image at once.

The most important methods for decoders are...
+ **dimensions**: Return a tuple containing the width and height of the image.
+ **color_type**: Return the color type of the image data produced by this decoder.
+ **read_image**: Decode the entire image into a slice of bytes.

- **dimensions**: Return a tuple containing the width and height of the image.
- **color_type**: Return the color type of the image data produced by this decoder.
- **read_image**: Decode the entire image into a slice of bytes.

## Pixels

`image` provides the following pixel types:
+ **Rgb**: RGB pixel
+ **Rgba**: RGB with alpha (RGBA pixel)
+ **Luma**: Grayscale pixel
+ **LumaA**: Grayscale with alpha

- **Rgb**: RGB pixel
- **Rgba**: RGB with alpha (RGBA pixel)
- **Luma**: Grayscale pixel
- **LumaA**: Grayscale with alpha

All pixels are parameterised by their component type.

## Image Processing Functions

These are the functions defined in the `imageops` module. All functions operate on types that implement the `GenericImage` trait.
Note that some of the functions are very slow in debug mode. Make sure to use release mode if you experience any performance issues.

+ **blur**: Performs a Gaussian blur on the supplied image.
+ **brighten**: Brighten the supplied image.
+ **huerotate**: Hue rotate the supplied image by degrees.
+ **contrast**: Adjust the contrast of the supplied image.
+ **crop**: Return a mutable view into an image.
+ **filter3x3**: Perform a 3x3 box filter on the supplied image.
+ **flip_horizontal**: Flip an image horizontally.
+ **flip_vertical**: Flip an image vertically.
+ **grayscale**: Convert the supplied image to grayscale.
+ **invert**: Invert each pixel within the supplied image This function operates in place.
+ **resize**: Resize the supplied image to the specified dimensions.
+ **rotate180**: Rotate an image 180 degrees clockwise.
+ **rotate270**: Rotate an image 270 degrees clockwise.
+ **rotate90**: Rotate an image 90 degrees clockwise.
+ **unsharpen**: Performs an unsharpen mask on the supplied image.
- **blur**: Performs a Gaussian blur on the supplied image.
- **brighten**: Brighten the supplied image.
- **huerotate**: Hue rotate the supplied image by degrees.
- **contrast**: Adjust the contrast of the supplied image.
- **crop**: Return a mutable view into an image.
- **filter3x3**: Perform a 3x3 box filter on the supplied image.
- **flip_horizontal**: Flip an image horizontally.
- **flip_vertical**: Flip an image vertically.
- **grayscale**: Convert the supplied image to grayscale.
- **invert**: Invert each pixel within the supplied image This function operates in place.
- **resize**: Resize the supplied image to the specified dimensions.
- **rotate180**: Rotate an image 180 degrees clockwise.
- **rotate270**: Rotate an image 270 degrees clockwise.
- **rotate90**: Rotate an image 90 degrees clockwise.
- **unsharpen**: Performs an unsharpen mask on the supplied image.

For more options, see the [`imageproc`](https://crates.io/crates/imageproc) crate.

## Examples

### Opening and Saving Images

`image` provides the `open` function for opening images from a path. The image
`image` provides the `open` function for opening images from a path. The image
format is determined from the path's file extension. An `io` module provides a
reader which offer some more control.

Expand Down Expand Up @@ -173,7 +180,7 @@ let mut imgbuf = image::ImageBuffer::new(imgx, imgy);
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let r = (0.3 * x as f32) as u8;
let b = (0.3 * y as f32) as u8;
*pixel = image::Rgb([r, 0, b]);
*pixel = pixeli::Rgb{r, g: 0, b};
}

// A redundant loop to demonstrate reading image data
Expand All @@ -192,8 +199,7 @@ for x in 0..imgx {
}

let pixel = imgbuf.get_pixel_mut(x, y);
let image::Rgb(data) = *pixel;
*pixel = image::Rgb([data[0], i as u8, data[2]]);
*pixel = pixeli::Rgb{r: pixel.r, g: i as u8, b: pixel.b};
}
}

Expand All @@ -206,6 +212,7 @@ Example output:
<img src="examples/fractal.png" alt="A Julia Fractal, c: -0.4 + 0.6i" width="500" />

### Writing raw buffers

If the high level interface is not needed because the image was obtained by other means, `image` provides the function `save_buffer` to save a buffer to a file.

```rust,no_run
Expand Down
25 changes: 22 additions & 3 deletions benches/copy_from.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use image::{GenericImage, ImageBuffer, Rgba};
use image::{GenericImage, ImageBuffer};
use pixeli::Rgba;

pub fn bench_copy_from(c: &mut Criterion) {
let src = ImageBuffer::from_pixel(2048, 2048, Rgba([255u8, 0, 0, 255]));
let mut dst = ImageBuffer::from_pixel(2048, 2048, Rgba([0u8, 0, 0, 255]));
let src = ImageBuffer::from_pixel(
2048,
2048,
Rgba {
r: 255u8,
g: 0,
b: 0,
a: 255,
},
);
let mut dst = ImageBuffer::from_pixel(
2048,
2048,
Rgba {
r: 0u8,
g: 0,
b: 0,
a: 255,
},
);

c.bench_function("copy_from", |b| {
b.iter(|| dst.copy_from(black_box(&src), 0, 0))
Expand Down
7 changes: 4 additions & 3 deletions examples/concat/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use image::{GenericImage, GenericImageView, ImageBuffer, Pixel, Primitive};
use image::{Blend, GenericImage, GenericImageView, ImageBuffer};
use pixeli::{ContiguousPixel, Pixel, PixelComponent};

/// Example showcasing a generic implementation of image concatenation.
///
Expand All @@ -20,8 +21,8 @@ fn main() {
fn h_concat<I, P, S>(images: &[I]) -> ImageBuffer<P, Vec<S>>
where
I: GenericImageView<Pixel = P>,
P: Pixel<Subpixel = S> + 'static,
S: Primitive + 'static,
P: Pixel<Component = S> + ContiguousPixel + Blend + 'static,
S: PixelComponent + 'static,
{
// The final width is the sum of all images width.
let img_width_out: u32 = images.iter().map(|im| im.width()).sum();
Expand Down
11 changes: 8 additions & 3 deletions examples/fractal.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! An example of generating julia fractals.

use pixeli::Rgb;
extern crate image;
extern crate num_complex;

Expand All @@ -16,7 +18,7 @@ fn main() {
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let r = (0.3 * x as f32) as u8;
let b = (0.3 * y as f32) as u8;
*pixel = image::Rgb([r, 0, b]);
*pixel = Rgb { r, g: 0, b };
}

// A redundant loop to demonstrate reading image data
Expand All @@ -35,8 +37,11 @@ fn main() {
}

let pixel = imgbuf.get_pixel_mut(x, y);
let data = (*pixel as image::Rgb<u8>).0;
*pixel = image::Rgb([data[0], i as u8, data[2]]);
*pixel = Rgb {
r: pixel.r,
g: i as u8,
b: pixel.b,
};
}
}

Expand Down
23 changes: 17 additions & 6 deletions examples/gradient/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
use image::{Pixel, Rgba, RgbaImage};
use image::RgbaImage;
use pixeli::Rgba;

fn main() {
let mut img = RgbaImage::new(100, 100);

let start = Rgba::from_slice(&[0, 128, 0, 0]);
let end = Rgba::from_slice(&[255, 255, 255, 255]);
let start = Rgba {
r: 0,
g: 128,
b: 0,
a: 0,
};
let end = Rgba {
r: 255,
g: 255,
b: 255,
a: 255,
};

image::imageops::vertical_gradient(&mut img, start, end);
image::imageops::vertical_gradient(&mut img, &start, &end);
img.save("vertical_gradient.png").unwrap();
image::imageops::vertical_gradient(&mut img, end, start);
image::imageops::vertical_gradient(&mut img, &end, &start);
img.save("vertical_gradient_reverse.png").unwrap();

image::imageops::horizontal_gradient(&mut img, start, end);
image::imageops::horizontal_gradient(&mut img, &start, &end);
img.save("horizontal_gradient.png").unwrap();
}
Loading