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
Encoder
trait has been overhauled- New associated type
<_ as Encoder>::Config
for 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_static
andEncoder::encode_sequence
have been added - Encoders now take metadata, which can be an
&Image
,&Frame
, orEncoderMetadata
- You can derive an
EncoderMetadata
from anImage
orFrame
with theFrom
/Into
trait
(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
SingleFrameIterator
struct allows for iterating over a single static image
- Replaced with
ImageFormat
struct is now moved into a private standaloneformat
module.- This is breaking if you were importing
ril::image::ImageFormat
(useril::ImageFormat
instead)
- 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
P
does 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:
LinearGradientInterpolation
renamed toGradientInterpolation
LinearGradientBlendMode
renamed toGradientBlendMode
- Removes
Pixel::inverted
in favor ofstd::ops::Not
- Instead of
pixel.inverted()
, you can now do!pixel
image.inverted()
is removed and replaced with!image
- This is not the same as the old
Pixel::inverted
as it will also invert alpha - Adds various implementations for
Image<Rgba>
:Image::<Rgba>::split_rgb_and_alpha
splits the image into(Image<Rgb>, Image<L>)
Image::<Rgba>::from_rgb_and_alpha
creates an RGBA image from(Image<Rgb>, Image<L>)
Image::<Rgba>::map_rgb_pixels
maps 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_pixels
maps only the alpha pixels of the image
- Instead of
Fill
/IntoFill
structs are now moved into a standalonefill
module.- 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
TextAlign
enum for text alignment (left, center, right) - Adds
TextLayout::with_align
to 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::IOError
renamed toError::IoError
Other changes
- Implement
std::error::Error
forError
- Add radial gradients via
RadialGradient
- This adds
GradientPosition
andRadialGradientCover
enums
- This adds
- Add conic gradients via
ConicGradient
- Add
Rectangle::at
method, which creates a rectangle at specified coordinates. - Add
Rectangle::square
to create a rectangle with equal side lengths - Document
Fill
/IntoFill
structs - Add
ImageFill
fill struct for image-clipped fills.IntoFill
is implemented for&Image
.
- Add
ResizeAlgorithm::Tile
which repeats copies of the image to fill the target dimensions
Performance improvements
Not
(invert/negation) forRgb
is much more efficient in release mode
Bug fixes
- Fix
Line
panicking with reversed vertices- This error was most commonly encountered with rendering
Polygon
with borders or antialiasing
- This error was most commonly encountered with rendering
- Fix compile-time errors when enabling
jpeg
feature without enabling thegif
feature - Fix memory leaks when encoding/decoding WebP images
Deprecated methods
Rectangle::new
deprecated in favor ofRectangle::at
. Additionally, identical behavior can be found with
<Rectangle as Default>::default
.