Releases: jay3332/ril
Releases · jay3332/ril
v0.10.2
v0.10.1
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
.
v0.9
v0.9 (2022-12-13)
Breaking changes
Pixel::force_into_rgb[a]
method is now replaced withPixel::as_rgb[a]
, which also takes self by reference instead
of by value.- All provided
Draw
objects (but not theDraw
trait itself) are now generic overF: IntoFill
instead ofP: Pixel
- The trait
IntoFill
is explained below - There should be no change in usage because for any
P: Pixel
,P
is implemented forIntoFill
- If you are extracting the fill color from a
Draw
object, you will need to access the.color()
method on
theSolidColor
struct. It is aconst fn
. - The
Draw
trait is still generic overP: Pixel
, no changes there
- The trait
Other changes
ColorType::is_dynamic
is now aconst fn
- Add
ColorType::has_alpha
for whether the color type has an alpha channel - Add new
Fill
trait, used to represent a fill color (or gradient, see below) for aDraw
object. This replaces the
simplePixel
trait previously used for this purpose.- Add new
IntoFill
trait, which provides a way to convert anything to aFill
object- Associated type
<_ as IntoFill>::Pixel
is the pixel type of the fill. - Associated type
<_ as IntoFill>::Fill
is the actual fill type. IntoFill
is implemented for allP: Pixel
and turns intodraw::SolidColor<P>
IntoFill
is implemented forLinearGradient
(see below) and turns intogradient::LinearGradientFill<P>
- Associated type
- Add new
- Add support for gradients
- Enabled with the
gradient
feature, which is enabled by default - New
LinearGradient
struct, which represents a linear gradientLinearGradientBlendMode
andLinearGradientInterpolation
enums are re-exports from thecolorgrad
crate,
which is used to configure the gradient's blending mode and interpolation.
- Enabled with the
- Add
Polygon::regular
method, which creates a regular polygon with the given amount of sides, center, and radius- This uses the
Polygon::regular_rotated
method, which is the same method, but you are able to specify the rotation
of the polygon in radians.
- This uses the
Linear gradient example
use ril::prelude::*;
fn main() -> ril::Result<()> {
// Create a new 256x256 RGB image with a black background
let mut image = Image::new(256, 256, Rgb::black());
// Create the `LinearGradient` object
let gradient = LinearGradient::new()
// The gradient will be rotated 45 degrees
.with_angle_degrees(45.0)
// The first stop is at 0.0, and is red
.with_color(Rgb::new(255, 0, 0))
// The second stop is at 0.5, and is white
.with_color(Rgb::new(255, 255, 255))
// We can also specify color stop positions manually:
// .with_color_at(0.5, Rgb::new(255, 255, 255))
// ...
// The third stop is at 1.0, and is green
.with_color(Rgb::new(0, 255, 0));
// Fill a hexagon with the gradient and draw it to the image
image.draw(&Polygon::regular(6, image.center(), 64).with_fill(gradient));
// Save the image to a PNG file
image.save_inferred("gradient_output.png")
}
Output
Full Changelog: v0.8...v0.9
v0.8
v0.8 (2022-11-30)
Breaking changes
Paste
draw struct now stores images and masks by reference instead of by value. This is to prevent
unnecessary cloning of large images and/or masks.- Paste now has two generic lifetime arguments:
Paste<'img, 'mask, _>
. - This also means that
Image::paste
,Image::paste_with_mask
, andImage::with
methods now take images and masks
by reference instead of by value too.
- Paste now has two generic lifetime arguments:
Other changes
- Add support for drawing lines and polygons using
Line
andPolygon
draw entities- Drawing a line or polygon with rounded vertices and a non-centered border position results in undesired output as
of now.
- Drawing a line or polygon with rounded vertices and a non-centered border position results in undesired output as
- Add new
static
feature. When enabled, this will statically link any native dependencies - Add non-zero width/height assertions to image constructors
Bug fixes
- Fix GIF decoding bug for images with a global palette
- Fix conversion using
Pixel::from_arbitrary_palette
with dynamic pixels
Full Changelog: v0.7...v0.8
v0.7
v0.7 (2022-11-22)
Breaking changes
ImageSequence::first_frame
now returnsOption<&Frame>
instead of&Frame
.- Also introduces new
first_frame_mut
andfirst_frame[_mut]_unchecked
methods.
- Also introduces new
Other changes
- Add crate-level support for image quantization
- The new
quantize
feature enables thecolor_quant
dependency for more complex quantization algorithms
This is enabled by default, mainly becausecolor_quant
appears to not pull any additional dependencies Quantizer
struct can handle direct quantization of raw pixel dataImage::quantize
is a higher-level method that can quantize an image into a paletted image- Implement
From<Image<Rgb[a]>>
forImage<PalettedRgb[a]>
which utlizes quantization
- The new
- Fix decoding bug for JPEG images with L pixels