v0.10
v0.10 (2023-10-12)
Major encoder/decoder interface changes
v0.10 introduces a major overhaul to the Encoder/Decoder interfaces.
- Added support for lazy encoding of image sequences.
- The
Encodertrait has been overhauled- New associated type
<_ as Encoder>::Configfor configuring specific encoders - Encoding logic between static images and image sequences are now unified: main encoding logic will occur in
Encoder::add_frame - Shortcut associated methods
Encoder::encode_staticandEncoder::encode_sequencehave been added - Encoders now take metadata, which can be an
&Image,&Frame, orEncoderMetadata- You can derive an
EncoderMetadatafrom anImageorFramewith theFrom/Intotrait
(i.e.EncoderMetadata::from(&image))
- You can derive an
- See below to see how you can lazily encode a stream of frames into a GIF
- New associated type
- The
- Removed
DynamicFrameIterator- Replaced with
Box<dyn FrameIterator<_>> - The new
SingleFrameIteratorstruct allows for iterating over a single static image
- Replaced with
ImageFormatstruct is now moved into a private standaloneformatmodule.- This is breaking if you were importing
ril::image::ImageFormat(useril::ImageFormatinstead)
- This is breaking if you were importing
Example: Lazily encoding a GIF
use std::fs::File;
use std::time::Duration;
use ril::encodings::gif::GifEncoder; // import the encoder for your desired format
use ril::prelude::*;
fn main() -> ril::Result<()> {
let mut dest = File::create("output.gif")?;
// Create a new 256x256 RGB image with a black background
let black_image = Image::new(256, 256, Rgb::black());
// Create a new 256x256 RGB image with a white background
let white_image = Image::new(256, 256, Rgb::white());
// Prepare the encoder, using one of our images as metadata
// note: the image ONLY serves as metadata (e.g. dimensions, bit depth, etc.),
// it is not encoded into the GIF itself when calling `Encoder::new`
// note: you will see what `into_handle` does later
let mut encoder = GifEncoder::new(&mut dest, &image)?;
// Lazily encode 10 frames into the GIF
for i in 0..10 {
// Create a new frame with a delay of 1 second
let frame = if i % 2 == 0 { black_image.clone() } else { white_image.clone() };
let frame = Frame::from_image(frame).with_delay(Duration::from_secs(1));
// Add the frame to the encoder
encoder.add_frame(&frame)?;
}
// Finish the encoding process
encoder.finish()
}Other breaking changes
- Image generic type
Pdoes not have a default anymore- In other words:
struct Image<P: Pixel = Dynamic>is nowstruct Image<P: Pixel> - This means when you create a new image, you will need to specify the pixel type:
Image::<Rgb>::new(256, 256, Rgb::black())Image::<Dynamic>::open("image.png")?
- You can add a type alias
type DynamicImage = Image<Dynamic>;if you want to keep the old behavior
- In other words:
LinearGradientInterpolationrenamed toGradientInterpolationLinearGradientBlendModerenamed toGradientBlendMode- Removes
Pixel::invertedin favor ofstd::ops::Not- Instead of
pixel.inverted(), you can now do!pixelimage.inverted()is removed and replaced with!image
- This is not the same as the old
Pixel::invertedas it will also invert alpha - Adds various implementations for
Image<Rgba>:Image::<Rgba>::split_rgb_and_alphasplits the image into(Image<Rgb>, Image<L>)Image::<Rgba>::from_rgb_and_alphacreates an RGBA image from(Image<Rgb>, Image<L>)Image::<Rgba>::map_rgb_pixelsmaps only the R@claGB pixels of the image- Allows for
image.map_rgb_pixels(|p| !p)for the previous behavior
- Allows for
Image::<Rgba>::map_alpha_pixelsmaps only the alpha pixels of the image
- Instead of
Fill/IntoFillstructs are now moved into a standalonefillmodule.- Differentiate text anchor and text alignment
TextLayout::{centered, with_horizontal_anchor, with_vertical_anchor}will now change the text anchor but
not the alignment the text- Adds
TextAlignenum for text alignment (left, center, right) - Adds
TextLayout::with_alignto specify text alignment - This is a breaking change behavior-wise
- For example, if you have
.centered()in your code, you will need to change it to
.with_align(TextAlign::Center).centered()to produce the same results.
- For example, if you have
Error::IOErrorrenamed toError::IoError
Other changes
- Implement
std::error::ErrorforError - Add radial gradients via
RadialGradient- This adds
GradientPositionandRadialGradientCoverenums
- This adds
- Add conic gradients via
ConicGradient - Add
Rectangle::atmethod, which creates a rectangle at specified coordinates. - Add
Rectangle::squareto create a rectangle with equal side lengths - Document
Fill/IntoFillstructs - Add
ImageFillfill struct for image-clipped fills.IntoFillis implemented for&Image.
- Add
ResizeAlgorithm::Tilewhich repeats copies of the image to fill the target dimensions
Performance improvements
Not(invert/negation) forRgbis much more efficient in release mode
Bug fixes
- Fix
Linepanicking with reversed vertices- This error was most commonly encountered with rendering
Polygonwith borders or antialiasing
- This error was most commonly encountered with rendering
- Fix compile-time errors when enabling
jpegfeature without enabling thegiffeature - Fix memory leaks when encoding/decoding WebP images
Deprecated methods
Rectangle::newdeprecated in favor ofRectangle::at. Additionally, identical behavior can be found with
<Rectangle as Default>::default.