All notable changes to this project will be documented in this file. This changelog was created during the development of v0.5, therefore all changes logged prior to v0.5 may not be accurate and are only based on previous Git commits.
Versions prior to v0.7 are not tagged/released on GitHub.
- Add
PngEncoderOptions::new
- Fix GIF encoding issues as produced in #38
- Fix text alignment rendering duplicately (#28)
- Fix
TextLayout
s with varying fonts not registering properly (#29) - Fix paletted images panicking when attempting to encode as GIFs
- Fix encoding image sequences not respecting delay and disposal method
- Fix tests/doctests
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
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()
}
- 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
- 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
Not
(invert/negation) forRgb
is much more efficient in release mode
- 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
Rectangle::new
deprecated in favor ofRectangle::at
. Additionally, identical behavior can be found with<Rectangle as Default>::default
.
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
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
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")
}
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:
- 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.
- Add new
static
feature. When enabled, this will statically link any native dependencies - Add non-zero width/height assertions to image constructors
- Fix GIF decoding bug for images with a global palette
- Fix conversion using
Pixel::from_arbitrary_palette
with dynamic pixels
ImageSequence::first_frame
now returnsOption<&Frame>
instead of&Frame
.- Also introduces new
first_frame_mut
andfirst_frame[_mut]_unchecked
methods.
- Also introduces new
- 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
- Add WebP encoding and decoding support
- Add the
all-pure
crate feature that enables all feature except forwebp
- This is because WASM does not support WebP since the feature uses the native
libwebp
. (as of v0.6-dev)
- This is because WASM does not support WebP since the feature uses the native
- Rework of pixel interface
- Remove
PixelData
enum in place of more efficientPixel::BIT_DEPTH
andPixel::COLOR_TYPE
constants- Includes new
Pixel::color_type
method for dynamic pixels PixelData::from_raw
is nowPixel::from_raw_parts
- Includes new
- Implement
Hash
for pixel types Pixel::Subpixel
associated type now has boundsCopy + Into<u8>
- Most places that take
&mut Image
can now takeimpl DerefMut<Target = Image>
instead (e.g. draw/text methods) Pixel::from_dynamic
can now do dynamic conversions between any pixel types
- Remove
- Implement all
From<Image<_>>
forImage<T>
as an alternative toImage::convert::<T>
- Implement paletted images
Image::from_paletted_pixels
can create an image from raw paletted pixelsImage::palette[_mut][_unchecked]
methods for accessing the image's paletteImage::map_palette
for mapping the image's paletteImage::flatten_palette
for converting a paletted image to a non-paletted image- New pixel trait
Paletted<'p>
where'p
is the lifetime of the palette (usually owned by the parentImage
) - New pixel types:
PalettedRgb
andPalettedRgba
Pixel::Color
associated type is eitherSelf
for non-paletted pixels or the palette's pixel type for paletted pixelsPixel::from_arbitrary_palette
for converting any raw indexed pixel to the desired pixel typePixel::from_raw_parts_paletted
isPixel::from_raw_parts
that accepts a palette
- Other QoL API improvements
Image
construct method naming changes (this is also reflected forImageSequence
)Image::decode_from_bytes
is nowImage::from_reader
Image::decode_inferred_from_bytes
is nowImage::from_reader_inferred
- Add
Image::from_bytes[_inferred]
for decoding directly from anyimpl AsRef<[u8]>
- Useful for using with
include_bytes!
macro - For
ImageSequence
this will only accept slices only (&[u8]
instead ofimpl AsRef<[u8]>
)
- Useful for using with
- Add a variety of colorops
Image::brighten[ed]
will brighten the image by a given amountImage::darken[ed]
will darken the image by a given amountImage::hue_rotate[d]
will rotate the hue of the image by a given amount
- Add
Pixel::Subpixel
associated type, this is the type of the subpixel (e.g.u8
forRgba
)- Add
Pixel::map_subpixels
for mapping the subpixels of a pixel
- Add
- Add
TrueColor
pixel trait, implemented for allPixels
that are convertable intoRgb
orRgba
- Separate various encoding dependencies and other features into cargo features
- Add text rendering support
- Various performance improvements
- Add GIF en/decoding support
- Add JPEG en/decoding support
- Add support for
ImageSequence
and APNGs - Switch encoders to use external crates
Initial release