25 KiB
Rust Image Release Notes
Rust image aims to be a pure-Rust implementation of various popular image formats. Accompanying reading/write support, rust image provides basic imaging processing function. See README.md for further details.
Known issues
- Not all Interlaced (progressive) or animated images are well supported.
- The color space information of pixels is not clearly communicated.
- Initialization via byte-based buffers and ffi is a work-in-progress.
Changes
Unreleased
- More convenient to use buffers will be added in the future. In particular,
improving initialization, passing of output buffers, and adding a more
complete representation for layouts. The plan is for these to interact with
the rest of the library through a byte-based interface similar to
ImageDecoder. See ongoing work onimage-canvasif you want to participate.
Version 0.24.5
Structural changes:
- Increased the minimum supported Rust version (MSRV) to 1.61.
- Increased the version requirement for the
tiffcrate to 0.8.0. - Increased the version requirement for the
jpegcrate to 0.3.0.
Bug fixes:
- The
as_rgb32ffunction ofDynamicImageis now correctly documented. - Fixed a crash when decoding ICO images. Added a regression test.
- Fixed a panic when transforming webp images. Added a regression test.
- Added a check to prevent integer overflow when calculating file size for BMP images. The missing check could panic in debug mode or else set an incorrect file size in release mode.
- Upgraded the PNG image encoder to use the newer
PngEncoder::write_imageinstead of the deprecatedPngEncoder::encodewhich did not account for byte order and could result in images with incorrect colors. - Fixed
InsufficientMemoryerror when trying to decode a PNG image. - Fix warnings and CI issues.
- Typos and links in the documentation have been corrected.
Performance:
- Added check for dynamic image dimensions before resizing. This improves performance in cases where the image does not need to be resized or has already been resized.
Version 0.24.4
New Features:
- Encoding for
webpis now available with the native library. This needs to be activate explicitly with theweb-encoderfeature. exrdecoding has gained basic limit support.
Bug fixes:
- The
Iterator::size_hintimplementation of pixel iterators has been fixed to return the current length indicated by itsExactSizeIteratorhint. - Typos and bad references in the documentation have been removed.
Performance:
ImageBuffer::get_pixel{,_mut}is now marked inline.resizenow short-circuits when image dimensions are unchanged.
Version 0.24.3
New Features:
TiffDecodernow supports setting resource limits.
Bug fixes:
- Fix compile issues on little endian systems.
- Various panics discovered by fuzzing.
Version 0.24.2
Structural changes:
- CI now runs
cargo-deny, checking dependent crates to an OSS license list and against RUSTSEC advisories.
New Features:
- The WebP decoder recognizes and decodes images with
VP8Xheader. - The DDS decoder recognizes and decodes images with
DX10headers.
Bug fixes:
- Calling
DynamicImage/ImageBuffer's methodswrite_toandsavewill now work properly even if the backing container is larger than the image layout requires. Only the relevant slice of pixel data is passed to the encoder. - Fixed a OOM-panic caused by malformed images in the
gifdecoder.
Version 0.24.1
Bug Fixes:
- ImageBuffer::get_pixel_checked would sometimes return the incorrect pixel.
- PNG encoding would sometimes not recognize unsupported color.
Version 0.24.0
Breaking changes
Structural changes:
- Minimum Rust version is now
1.56and may change in minor versions until further notice. It is now tracked in the library'sCargo.toml, instead, by the standard[package.rust-version]field. Note: this applies to the library itself. You may need different version resolutions for dependencies when using a non-stable version of Rust. - The
math::utils::{nq, utils}modules have been removed. These are better served through thecolor_quantcrate and the standard library respectively. - All codecs are now available through
image::codecs, no longer top-level. ExtendedColorTypeandDynamicImagehave been made#[non_exhaustive], providing more methods instead of exhaustive matching.- Reading images through the generic
io::Reader, as well as generic convenience interfaces, now requires the underlying reader to beBufRead + Seek. This allows more efficient support more formats. Similarly, writing now requires writers to beWrite + Seek. - The
Bgra*variants of buffers, which were only half-supported, have been removed. The owning buffer typesImageBufferandDynamicImagefundamentally already make a choice in supported pixel representations. This allows for more consistent internal behavior. Callers are expected to convert formats when using those buffers, which they are required to do in any case already, and which is routinely performed by decoders.
Trait reworks:
- The
Pixeltrait is no longer implemented quite as liberally for structs defined in the crate. Instead, it is now restricted to a set of known channel which ensures accuracy in computations involving those channels. - The
ImageDecoderExttrait has been renamed toImageDecoderRect, according to its actual functionality. - The
Pixeltrait and itsSubpixelfield no longer require (or provide) a'staticlifetime bound. - The
Pixeltrait no longer requires specifying an associated, constantColorType. This was of little relevance to computation but made it much harder to implement and extend correctly. Instead, the privatePixelWithColorTypeextension is added for interfaces that require a properly known variant. - Reworked how
SubImageinteracts with theGenericImagetrait. It is now a default implementation. Note thatSubImagenow has inherent methods that avoid double-indirection, the trait's method will no longer avoid this. - The
Primitivetrait now requires implementations to provide a minimum and maximum logical bound for the purpose of converting to other primitive representations.
Additions
Image formats:
- Reading lossless WebP is now supported.
- The OpenEXR format is now supported.
- The
jpegdecoder has been upgraded to Lossless JPEG. - The
AvifEncodernow correctly handles alpha-less images. Some additional color formats are converted to RGBA as well. - The
Bmpcodec now decodes more valid images. It can decode a raw image without performing the palette mapping. It provides a method to access the palette. The encoder provides the inverse capabilities. Tiffis now an output format.
Buffers and Operations:
- The channel / primitive type
f32is now supported. Currently only the OpenEXR codec makes full use of it but this is expected to change. ImageBuffer::{get_pixel_checked, get_pixel_mut_checked}provide panic-free access to pixels and channels by returningOption<&P>andOption<&mut P>.ImageBuffer::write_tohas been added, encoding the buffer to a writer. This method already existed onDynamicImage.DynamicImagenow implementsFrom<_>for all supported buffer types.DynamicImagenow implementsDefault, an emptyRgba8image.imageops::overlaynow takes coordinates asi64.
Limits:
- Added
LimitsandLimitSupport, utilized inio::Reader. These can be configured for rudimentary protection against resource exhaustion (images pretending to require a very large buffer). These types are not yet exhaustive by design, and more and stricter limits may be added in the future. - Encoders that do provide inherent support for limits, or reserve a
significant amount of internal memory, are urged to implement the
set_limitsextension toImageDecoder. Some strict limit are opt-in, which may cause decoding to fail if not supported.
Miscellaneous:
PNMSubtypehas been renamed toPnmSubtype, by Rust's naming scheme.- Several incorrectly capitalized
PNM*aliases have been removed. - Several
enumtypes that had previously used a hidden variant now use the official#[non_exhaustive]attribute instead.
Version 0.23.14
-
Unified gif blending in different decode methods, fixing out-of-bounds checks in a number of weirdly positioned frames.
-
Hardened TGA decoder against a number of malicious inputs.
-
Fix forward incompatible usage of the panic macro.
-
Fix load_rect for gif reaching
unreachable!()code. -
Added
ExtendedColorType::A8. -
Allow TGA to load alpha-only images.
-
Optimized load_rect to avoid unnecessary seeks.
Version 0.23.13
-
Fix an inconsistency in supported formats of different methods for encoding an image.
-
Fix
thumbnailchoosing an empty image. It now always prefer non-empty image dimensions. -
Fix integer overflow in calculating requires bytes for decoded image buffers for farbfeld, hdr, and pnm decoders. These will now error early.
-
Fix a panic decoding certain
jpegimage without frames or meta data. -
Optimized the
jpegencoder. -
Optimized
GenericImage::copy_fromdefault impl in various cases. -
Add
avifdecoders. You must enable it explicitly and it is not covered by our usual MSRV policy of Rust 1.34. Instead, only latest stable is supported. -
Add
ImageFormat::{can_read, can_write} -
Add
Frame::buffer_mut -
Add speed and quality options on
avifencoder. -
Add speed parameter to
gifencoder. -
Expose control over sequence repeat to the
gifencoder. -
Add
{contrast,brighten,huerotate}_in_placefunctions in imageproc. -
Relax
Defaultimpl ofImageBuffer, removing the bound on the color type. -
Derive Debug, Hash, PartialEq, Eq for DynamicImage
Version 0.23.12
-
Fix a soundness issue affecting the impls of
Pixel::from_slice_mut. This would previously reborrow the mutable input reference as a shared one but then proceed to construct the mutable result reference from it. While UB according to Rust's memory model, we're fairly certain that no miscompilation can happen with the LLVM codegen in practice. See 5cbe1e6767d11aff3f14c7ad69a06b04e8d583c7 for more details. -
Fix
imageops::blurpanicking whensigma = 0.0. It now defaults to1.0as all negative values. -
Fix re-exporting
png::{CompressionType, FilterType}to maintain SemVer compatibility with the0.23releases. -
Add
ImageFormat::from_extension -
Add copyless DynamicImage to byte slice/vec conversion.
-
Add bit-depth specific
into_andto_DynamicImage conversion methods.
Version 0.23.11
- The
NeuQuantimplementation is now supplied bycolor_quant. Use of the type defined by this library is discouraged. - The
jpegdecoder can now downscale images that are decoded by 1,2,4,8. - Optimized the jpeg encoding ~5-15%.
- Deprecated the
clampfunction. Usenum-traitsinstead. - The ICO decoder now accepts an empty mask.
- Fixed an overflow in ICO mask decoding potentially leading to panic.
- Added
ImageOutputFormatforAVIF - Updated
tiffto0.6with lzw performance improvements.
Version 0.23.10
- Added AVIF encoding capabilities using the
ravifcrate. Please note that the feature targets the latest stable compiler and is not enabled by default. - Added
ImageBuffer::as_rawto inspect the underlying container. - Updated
gifto0.11with large performance improvements.
Version 0.23.9
- Introduced correctly capitalized aliases for some scream case types
- Introduced
imageops::{vertical_gradient, horizontal_gradient}for writing simple color gradients into an image. - Sped up methods iterating over
Pixels,PixelsMut, etc. by using exact chunks internally. This should auto-vectorizeImageBuffer::from_pixel. - Adjusted
Cloneimpls of iterators to not require a bound on the pixel. - Add
Debugimpls for iterators where the pixel's channel implements it. - Add comparison impls for
FilterType
Version 0.23.8
flat::Errornow implements the standardErrortrait- The type parameter of
Maphas been relaxed to?Sized - Added the
imageops::tilefunction that repeats one image across another
Version 0.23.7
- Iterators over immutable pixels of
ImageBuffercan now be cloned - Added a
tgaencoder - Added
ColorMap::lookup, an optional reversal of the map - The
EncodableLayouttrait is now exported
Version 0.23.6
- Added
png::ApngDecoder, an adapter decoding the animation in an APNG. - Fixed a bug in
jpegencoding that would darken output colors. - Added a utility constructor
FlatSamples::with_monocolor. - Added
ImageBuffer::as_flat_samples_mutwhich is a mutable variant of the existing ffi-helperImageBuffer::as_flat_samples.
Version 0.23.5
- The
pngencoder now allows configuring compression and filter type. The output is not part of stability guarantees, see its documentation. - The
jpegencoder now accepts any implementor ofGenericImageView. This allows images that are only partially present in memory to be encoded. ImageBuffernow derivesHash,PartialEq,Eq.- The
Pixels/PixelsMutiterator no longer yields out-of-bounds pixels when the underlying buffer is larger than required. - The
pbmdecoder correctly decodes ascii data again, fixing a regression where it would use the sample value1as white instead of255. - Fix encoding of RGBA data in
gifframes. - Constructing a
Rows/RowsMutiterator no longer panics when the image has a width or height of0.
Version 0.23.4
- Improved the performance of decoding animated gifs
- Added
crop_immwhich functions likecropbut on a shared reference - The gif
DisposalMethod::Anyis treated asKeep, consistent with browsers - Most errors no longer allocate a string, instead implement Display.
- Add some implementations of
Error::source
Version 0.23.3
- Added
ColorType::has_alphato facilitate lossless conversion - Recognize extended WebP formats for decoding
- Added decoding and encoding for the
farbfeldformat - Export named iterator types created from various
ImageBuffermethods - Error in jpeg encoder for images larger than 65536 pixels, fixes panic
Version 0.23.2
- The dependency on
jpeg-decodernow reflects minimum requirements.
Version 0.23.1
- Fix cmyk_to_rgb (jpeg) causing off by one rounding errors.
- A number of performance improvements for jpeg (encode and decode), bmp, vp8
- Added more details to errors for many formats
Version 0.23.0
This major release intends to improve the interface with regards to handling of color format data and errors for both decoding and encoding. This necessitated many breaking changes anyways so it was used to improve the compliance to the interface guidelines such as outstanding renaming.
It is not yet perfect with regards to color spaces but it was designed mainly as an improvement over the current interface with regards to in-memory color formats, first. We'll get to color spaces in a later major version.
- Heavily reworked
ColorType:- This type is now used for denoting formats for which we support operations
on buffers in these memory representations. Particularly, all channels in
pixel types are assumed to be an integer number of bytes (In terms of the
Rust type system, these are
Sizedand one can crate slices of channel values). - An
ExtendedColorTypeis used to express more generic color formats for which the library has limited support but can be converted/scaled/mapped into aColorTypebuffer. This operation might be fallible but, for example, includes sources with 1/2/4-bit components. - Both types are non-exhaustive to add more formats in a minor release.
- A work-in-progress (#1085) will further separate the color model from the
specific channel instantiation, e.g. both
8-bit RGBand16-bit BGRare instantiations ofRGBcolor model.
- This type is now used for denoting formats for which we support operations
on buffers in these memory representations. Particularly, all channels in
pixel types are assumed to be an integer number of bytes (In terms of the
Rust type system, these are
- Heavily rework
ImageError:- The top-level enum type now serves to differentiate cause with multiple
opaque representations for the actual error. These are no longer simple
Strings but contains useful types. Third-party decoders that have no
variant in
ImageFormathave also been considered. - Support for
Error::sourcethat can be downcast to an error from a matching version of the underlying decoders. Note that the version is not part of the stable interface guarantees, this should not be relied upon for correctness and only be used as an optimization. - Added image format indications to errors.
- The error values produced by decoder will be upgraded incrementally. See something that still produces plain old String messages? Feel free to send a PR.
- The top-level enum type now serves to differentiate cause with multiple
opaque representations for the actual error. These are no longer simple
Strings but contains useful types. Third-party decoders that have no
variant in
- Reworked the
ImageDecodertrait:read_imagetakes an output buffer argument instead of allocating all memory on its own.- The return type of
dimensionsnow aligns withGenericImagesizes. - The
colortypemethod was renamed tocolor_typefor conformity.
- The enums
ColorType,DynamicImage,imageops::FilterType,ImageFormatno longer re-export all of their variants in the top-level of the crate. This removes the growing pollution in the documentation and usage. You can still insert the equivalent statement on your own:use image::ImageFormat::{self, *}; - The result of
encodeoperations is now uniformly anImageResult<()>. - Removed public converters from some
tiff,png,gif,jpegtypes, mainly such as error conversion. This allows upgrading the dependency across major versions without a major release inimageitself. - On that note, the public interface of
gifencoder no longer takes agif::Framebut rather deals withimage::Frameonly. If you require to specify the disposal method, transparency, etc. then you may want to wait with upgrading but (see next change). - The
gifencoder now errors on invalid dimensions or unsupported color formats. It would previously silently reinterpret bytes as RGB/RGBA. - The capitalization of
ImageFormatand other enum variants has been adjusted to adhere to the API guidelines. These variants are now spelledGif,Png, etc. The same change has been made to the name of types such asHDRDecoder. - The
Progresstype has finally received public accessor method. Strange that no one reported them missing. - Introduced
PixelDensityandPixelDensityUnitto store DPI information in formats that support encoding this form of meta data (e.g. injpeg).
Version 0.22.5
- Added
GenericImage::copy_within, specialized forImageBuffer - Fixed decoding of interlaced
giffiles - Prepare for future compatibility of array
IntoIteratorin example code
Version 0.22.4
- Added in-place variants for flip and rotate operations.
- The bmp encoder now checks if dimensions are valid for the format. It would previously write a subset or panic.
- Removed deprecated implementations of
Error::description - Added
DynamicImage::into_*which convert without an additional allocation. - The PNG encoder errors on unsupported color types where it had previously silently swapped color channels.
- Enabled saving images as
gifwithsave_buffer.
Version 0.22.3
- Added a new module
iocontaining a configurableReader. It can replace the bunch of free functions:image::{load_*, open, image_dimensions}while enabling new combinations such asopenbut with format deduced from content instead of file path. - Fixed
const_errlint in the macro expanded implementations ofPixel. This can only affect your crate ifimageis used as a path dependency.
Version 0.22.2
- Undeprecate
unsafetrait accessors. Further evaluation showed that their deprecation should be delayed until traitimplspecialization is available. - Fixed magic bytes used to detect
tiffimages. - Added
DynamicImage::from_decoder. - Fixed a bug in the
PNGReaderthat caused an infinite loop. - Added
ColorType::{bits_per_pixel, num_components}. - Added
ImageFormat::from_path, same format deduction as theopenmethod. - Fixed a panic in the gif decoder.
- Aligned background color handling of
gifto web browser implementations. - Fixed handling of partial frames in animated
gif. - Removed unused direct
lzwdependency, an indirect dependency intiff.
Version 0.22.1
- Fixed build without no features enabled
Version 0.22
- The required Rust version is now
1.34.2. - Note the website and blog: image-rs.org and blog.image-rs.org
PixelMutnow only onImageBufferand removed fromGenericImageinterface. Prefer iterating manually in the generic case.- Replaced an unsafe interface in the hdr decoder with a safe variant.
- Support loading 2-bit BMP images
- Add method to save an
ImageBuffer/DynamicImagewith specified format - Update tiff to
0.3with a writer - Update png to
0.15, fixes reading of interlaced sub-byte pixels - Always use custom struct for
ImageDecoder::Reader - Added
apply_without_alphaandmap_without_alphatoPixeltrait - Pixel information now with associated constants instead of static methods
- Changed color structs to tuple types with single component. Improves ergonomics of destructuring assignment and construction.
- Add lifetime parameter on
ImageDecodertrait. - Remove unnecessary
'staticbounds on affine operations - Add function to retrieve image dimensions without loading full image
- Allow different image types in overlay and replace
- Iterators over rows of
ImageBuffer, mutable variants
Version 0.21.2
- Fixed a variety of crashes and opaque errors in webp
- Updated the png limits to be less restrictive
- Reworked even more
unsafeoperations into safe alternatives - Derived Debug on FilterType and Deref on Pixel
- Removed a restriction on DXT to always require power of two dimensions
- Change the encoding of RGBA in bmp using bitfields
- Corrected various urls
Version 0.21.1
- A fairly important bugfix backport
- Fixed a potentially memory safety issue in the hdr and tiff decoders, see #885
- See the full advisory for an analysis
- Fixes
ImageBufferindex calculation for very, very large images - Fix some crashes while parsing specific incomplete pnm images
- Added comprehensive fuzzing for the pam image types
Version 0.21
- Updated README to use
GenericImageView - Removed outdated version number from CHANGES
- Compiles now with wasm-unknown-emscripten target
- Restructured
ImageDecodertrait - Updated README with a more colorful example for the Julia fractal
- Use Rust 1.24.1 as minimum supported version
- Support for loading GIF frames one at a time with
animation::Frames - The TGA decoder now recognizes 32 bpp as RGBA(8)
- Fixed
to_bgradocument comment - Added release test script
- Removed unsafe code blocks several places
- Fixed overlay overflow bug issues with documented proofs
Version 0.20
- Clippy lint pass
- Updated num-rational dependency
- Added BGRA and BGR color types
- Improved performance of image resizing
- Improved PBM decoding
- PNM P4 decoding now returns bits instead of bytes
- Fixed move of overlapping buffers in BMP decoder
- Fixed some document comments
GenericImageandGenericImageViewis now object-safe- Moved TIFF code to its own library
- Fixed README examples
- Fixed ordering of interpolated parameters in TIFF decode error string
- Thumbnail now handles upscaling
- GIF encoding for multiple frames
- Improved subimages API
- Cargo fmt fixes
Version 0.19
- Fixed panic when blending with alpha zero.
- Made
saveconsistent. - Consistent size calculation.
- Fixed bug in
apply_with_alpha. - Implemented
TGADecoder::read_scanline. - Use deprecated attribute for
pixels_mut. - Fixed bug in JPEG grayscale encoding.
- Fixed multi image TIFF.
- PNM encoder.
- Added
#[derive(Hash)]forColorType. - Use
num-derivefor#[derive(FromPrimitive)]. - Added
into_framesimplementation for GIF. - Made rayon an optional dependency.
- Fixed issue where resizing image did not give exact width/height.
- Improved downscale.
- Added a way to expose options when saving files.
- Fixed some compiler warnings.
- Switched to lzw crate instead of using built-in version.
- Added
ExactSizeIteratorimplementations to buffer structs. - Added
resize_to_fillmethod. - DXT encoding support.
- Applied clippy suggestions.
Version 0.4
- Various improvements.
- Additional supported image formats (BMP and ICO).
- GIF and PNG codec moved into separate crates.
Version 0.3
- Replace
std::old_iowithstd::io.
Version 0.2
- Support for interlaced PNG images.
- Writing support for GIF images (full color and paletted).
- Color quantizer that converts 32bit images to paletted including the alpha channel.
- Initial support for reading TGA images.
- Reading support for TIFF images (packbits and FAX compression not supported).
- Various bug fixes and improvements.
Version 0.1
- Initial release
- Basic reading support for png, jpeg, gif, ppm and webp.
- Basic writing support for png and jpeg.
- A collection of basic imaging processing function like
blurorinvert