tiff
TIFF decoding and encoding library in pure Rust
0.11.3
108M downloads/mo
#769 most downloaded on crates.io
image-rs/image-tiff
What this package is like to depend on
Last release 6 months ago
10 Feb 2026
Ships unpredictably
gaps range from 2 weeks to 1.4 years
Most releases are documented
notes for 20 of 26 stable releases
1 version withdrawn
withdrawn after publishing
8 years old
28 releases · first in 2018
5 releases in the last 12 months
see the full history below
Release timeline
28 releases · Jun 2018 to Feb 2026Releases
latest 28-
0.11.310 Feb 2026Release notes
Open source →Additions:
- Added support for
webpcompression (as per GDAL) under thewebpfeature flag (default: off). - Added
Decoder::image_ifd, creating anIfdDecoderof the current IFD. - Added
IfdDecoder::directory, returning theDirectoryunderlying it. - Added
LowerHexandUpwerHeximplementations forIfdPointer.
Notes:
- A new example
tiff-lsdemonstrates use of the new features.
Release notes
Open source →Additions:
- Added support for
webpcompression (as per GDAL) under thewebpfeature flag (default: off). - Added
Decoder::image_ifd, creating anIfdDecoderof the current IFD. - Added
IfdDecoder::directory, returning theDirectoryunderlying it. - Added
LowerHexandUpwerHeximplementations forIfdPointer.
Notes:
- A new example
tiff-lsdemonstrates use of the new features.
- Added support for
-
0.11.225 Jan 2026Release notes
Open source →Changes:
- Planar files can now be read with
Decoder::read_image_to_bufferif the
limits allow for such a large buffer size. Previously only the first plane
was read and the decoder will attempt a fallback to this behavior if the
limits do not allow all planes to be allocated.
Fixes:
- An off-by-one error in a
debug_assertofValueBuffercaused its use in
IfdDecoder::find_tag_bufto panic outside release mode when the buffer
exactly matched the required size.
Additions:
- The methods
ColorType::{num_samples, bit_depth}are now public. This
promises that we only have homogeneous color depths in this major version.
Release notes
Open source →Changes:
- Planar files can now be read with
Decoder::read_image_to_bufferif the limits allow for such a large buffer size. Previously only the first plane was read and the decoder will attempt a fallback to this behavior if the limits do not allow all planes to be allocated.
Fixes:
- An off-by-one error in a
debug_assertofValueBuffercaused its use inIfdDecoder::find_tag_bufto panic outside release mode when the buffer exactly matched the required size.
Additions:
- The methods
ColorType::{num_samples, bit_depth}are now public. This promises that we only have homogeneous color depths in this major version.
- Planar files can now be read with
-
0.11.113 Jan 2026Release notes
Open source →Late note: We no longer distribute benchmark images (tests/benches) as part
of the crate itself. Please fetch them from upstream.Fixes:
- The enumeration types in
tagsare now all marked with a representation of
their underlying TIFF type (e.g.repr(u16)) and variants are explicitly
assigned their corresponding values. That is you may read the raw
discriminant and interpret that as the value—except forUnknownvariants. - The variants
RationalBigandSRationalBigofdecoder::ifd::Valueare
deprecated as they have no corresponding TIFF type and were not constructed
during decoding.
Additions:
- Types in
tagsnow generally implementTiffValueand can be handed to the
DirectoryEncoder::write_tagmethod. Unlike primitive types they do not
always implement the trait for slices of themselves. - Added
tags::ValueBuffer, a byte-based buffer for tags with a runtime value
type and count. - Added
IfdDecoder::find_tag_{buf,bytes}to read tag values into a
ValueBufferor byte slice respectively without interpreting them
immediately within the Rust type system. - Added
DirectoryEncoder::write_{data,tag}_bufthat takes aValueBuffer
instead of a statically typed argument. - Added
DirectoryEncoder::write_entry{,_buf,_bytes}that encode their
argument into the file and return anEntryfor later use, without
immediately adding a tag-entry pair to the directory. - The
TiffValuetrait is now implemented for several builtintags::*types
or slices of them as appropriate for their use as values of their intended
TIFF tag. - The
TiffValuetrait is now implemented for[T; N]for all types that
implement it for slices.
Release notes
Open source →Fixes:
- The enumeration types in
tagsare now all marked with a representation of their underlying TIFF type (e.g.repr(u16)) and variants are explicitly assigned their corresponding values. That is you may read the raw discriminant and interpret that as the value—except forUnknownvariants. - The variants
RationalBigandSRationalBigofdecoder::ifd::Valueare deprecated as they have no corresponding TIFF type and were not constructed during decoding.
Additions:
- Types in
tagsnow generally implementTiffValueand can be handed to theDirectoryEncoder::write_tagmethod. Unlike primitive types they do not always implement the trait for slices of themselves. - Added
tags::ValueBuffer, a byte-based buffer for tags with a runtime value type and count. - Added
IfdDecoder::find_tag_{buf,bytes}to read tag values into aValueBufferor byte slice respectively without interpreting them immediately within the Rust type system. - Added
DirectoryEncoder::write_{data,tag}_bufthat takes aValueBufferinstead of a statically typed argument. - Added
DirectoryEncoder::write_entry{,_buf,_bytes}that encode their argument into the file and return anEntryfor later use, without immediately adding a tag-entry pair to the directory. - The
TiffValuetrait is now implemented for several builtintags::*types or slices of them as appropriate for their use as values of their intended TIFF tag. - The
TiffValuetrait is now implemented for[T; N]for all types that implement it for slices.
- The enumeration types in
-
0.11.005 Jan 2026Release notes
Open source →Directorynow implementsFromIterator<(Tag, Value)>.
Changes:
- The decoder now interprets the
ExtraSamplestag. The sample count must now
more strict match the expected value with alpha channels only allowing for
explicitly denoted unassociated or associated alpha. This effects the
indicated color type when decoding images with additional samples indicated
as unspecified relation. Previously, these may have been interpreted as
alpha by the total sample count (e.g. RgbA if 4 samples under a photometric
interpretation of RGB). - The decoder handles planar data, current limited to non-subsampled channels.
TheDecoder::read_imagemethod return planes one-after-another depending on
the size of the buffer that was passed. Decoder::read_image_to_buffernow takes&mut DecodingResultand resizes
it according to the required layout. Previously, a borrowedDecodingBuffer
was passed which can be replaced by callingas_bytes_mutand
read_image_bytes.- Several methods of tags are now
const. Note that does not guarantee any
particular value when calling these methods.
Fixes:
- Fix a bug in the uncompressed encoder that could lead to short writes, i.e.
data silently dropped when the underlying writer did not accept all data in a
single write call. - Encoding YCbCr data now writes the
ChromaSubsamplingtag as(1, 1)to
indicate no subsampling, instead of leaving it at its default of(2, 2). - The decoder will reject subsampled YCbCr data as there is no upsampling
routine, except for JPEG compressed images where the JPEG decoders handles
this. Since the buffer in that case indicates a full-sized plane for all
color samples any future support for the tag will upsample all planes (at
least within this major version).
Additions:
- Added support for the
CieLabcolor type. - Added
DecodingResult::resize_toto create a buffer with a matching sample
type and dimensions. - Added
ByteOrder::nativeto access the platform's native endianness. - Added
ByteOrder::convertto change the byte-order of values in a byte
buffer, depending on theirTypeas described at runtime. - Added
DirectoryOffset::newto encode a directory whose offset is known to
the caller but that has not been written through the encoder itself. - Added
Encoder::extra_samplesto encode images with more samples than their
color's trait implementation would otherwise suggest. - Added
DirectoryEncoder::extend_fromto encode multiple tag entries from a
directory whose values were written to the file by means outside the
encoder's control. - Added
Decoder::read_coding_unit_bytesto retrieve data of corresponding
coordinates from potentially planar data, which is encoded in multiple chunks
of the file.
Release notes
Open source →Directorynow implementsFromIterator<(Tag, Value)>.
Changes:
- The decoder now interprets the
ExtraSamplestag. The sample count must now more strict match the expected value with alpha channels only allowing for explicitly denoted unassociated or associated alpha. This effects the indicated color type when decoding images with additional samples indicated as unspecified relation. Previously, these may have been interpreted as alpha by the total sample count (e.g. RgbA if 4 samples under a photometric interpretation of RGB). - The decoder handles planar data, current limited to non-subsampled channels.
The
Decoder::read_imagemethod return planes one-after-another depending on the size of the buffer that was passed. Decoder::read_image_to_buffernow takes&mut DecodingResultand resizes it according to the required layout. Previously, a borrowedDecodingBufferwas passed which can be replaced by callingas_bytes_mutandread_image_bytes.- Several methods of tags are now
const. Note that does not guarantee any particular value when calling these methods.
Fixes:
- Fix a bug in the uncompressed encoder that could lead to short writes, i.e. data silently dropped when the underlying writer did not accept all data in a single write call.
- Encoding YCbCr data now writes the
ChromaSubsamplingtag as(1, 1)to indicate no subsampling, instead of leaving it at its default of(2, 2). - The decoder will reject subsampled YCbCr data as there is no upsampling routine, except for JPEG compressed images where the JPEG decoders handles this. Since the buffer in that case indicates a full-sized plane for all color samples any future support for the tag will upsample all planes (at least within this major version).
Additions:
- Added support for the
CieLabcolor type. - Added
DecodingResult::resize_toto create a buffer with a matching sample type and dimensions. - Added
ByteOrder::nativeto access the platform's native endianness. - Added
ByteOrder::convertto change the byte-order of values in a byte buffer, depending on theirTypeas described at runtime. - Added
DirectoryOffset::newto encode a directory whose offset is known to the caller but that has not been written through the encoder itself. - Added
Encoder::extra_samplesto encode images with more samples than their color's trait implementation would otherwise suggest. - Added
DirectoryEncoder::extend_fromto encode multiple tag entries from a directory whose values were written to the file by means outside the encoder's control. - Added
Decoder::read_coding_unit_bytesto retrieve data of corresponding coordinates from potentially planar data, which is encoded in multiple chunks of the file.
-
0.10.301 Sep 2025Release notes
Open source →New features:
- Group 4
faxis now recognized as a compression type and decoded. - A crate feature
faxcontrols related dependencies, on by default.
Changes:
- The presence of PhotometricInterpretation::WhiteIsZero now returns an error
if the color type can not be inverted by the library where they were
previously silently ignored. Please report any missing color types.
Fixes:
- The PhotometricInterpretation::WhiteIsZero is now also applied to 1-bit
images, as well as 2-bit and 4-bit sample types where previously the presence
of this tag was ignored.
Release notes
Open source →New features:
- Group 4
faxis now recognized as a compression type and decoded. - A crate feature
faxcontrols related dependencies, on by default.
Changes:
- The presence of PhotometricInterpretation::WhiteIsZero now returns an error if the color type can not be inverted by the library where they were previously silently ignored. Please report any missing color types.
Fixes:
- The PhotometricInterpretation::WhiteIsZero is now also applied to 1-bit images, as well as 2-bit and 4-bit sample types where previously the presence of this tag was ignored.
- Group 4
-
0.10.226 Aug 2025Release notes
Open source →New features:
- Added a dedicated
Directorytype (#277) - Expose methods related to
Directorypublicly (#278) - Implement writing directories (#281, #283)
- Add ICC (color profile) to the set of known tags (#287)
- Added
Decoder.inner()to access the underlying reader (#289) - Added methods for reading into a pre-allocated byte buffer (#285)
Changes:
- No longer perform color conversion when decoding embedded JPEG. This fixes decoding for JPEG images with alpha channel. (#274)
- More lenient LZW decoding to match libtiff (#231)
Fixes:
- Fixed seeking multiple times in a row (#279)
This republishes 0.10.1, fixing an accidentally removed method (
Decoder::find_tag_unsigned_vec).Release notes
Open source →Republished 0.10.1, fixing an accidentally removed method (
Decoder::find_tag_unsigned_vec). - Added a dedicated
-
0.10.125 Aug 2025 withdrawnRelease notes
Open source →New features:
- Added a dedicated
Directorytype (#277) - Expose methods related to
Directorypublicly (#278) - Implement writing directories (#281, #283)
- Add ICC (color profile) to the set of known tags (#287)
- Added
Decoder.inner()to access the underlying reader (#289) - Added methods for reading into a pre-allocated byte buffer (#285)
Changes:
- No longer perform color conversion when decoding embedded JPEG. This fixes decoding for JPEG images with alpha channel. (#274)
- More lenient LZW decoding to match libtiff (#231)
Fixes:
- Fixed seeking multiple times in a row (#279)
Release notes
Open source →New features:
- Added a dedicated
Directorytype (#277) - Expose methods related to
Directorypublicly (#278) - Implement writing directories (#281, #283)
- Add ICC (color profile) to the set of known tags (#287)
- Added
Decoder.inner()to access the underlying reader (#289) - Added methods for reading into a pre-allocated byte buffer (#285)
Changes:
- No longer perform color conversion when decoding embedded JPEG. This fixes decoding for JPEG images with alpha channel. (#274)
- More lenient LZW decoding to match libtiff (#231)
Fixes:
- Fixed seeking multiple times in a row (#279)
- Added a dedicated
-
0.10.021 Jun 2025Release notes
Open source →New features:
- Added
ColorType::MultibandandColorType::CMYKA. - Added
Value::ByteandValue::SignedByteto representu8andi8tags. - Encoding can now use horizontal predictor.
- The
Decoder::tag_itermethod allows iterating over all tags in the image. - Half precision floating point values are now supported during decoding.
- ZStandard compression has been added as an additional compression method
during decoding, but requires the
zstdfeature flag.
Changes:
- Switched
u16andi16values to be intepreted asValue::ShortandValue::SignedShortrespectively. - Changed JPEG compression to use the
zune-jpegcrate instead ofjpeg-decoder. - The
deflate,jpeg, andlzwcompression methods are now controlled by (enabled by default) feature flags.
Fixes:
- Fixed a bug in 1 bit-per-pixel decoding.
- Added
-
0.9.113 Jan 2024Release notes
Open source →New features:
- Basic support for planar configuration.
- Allow arbitrary number of samples as long as all have the same bit depth.
Fixes:
- Don't panic when parsing metadata when custom compression is used.
-
0.9.006 Feb 2023Release notes
Open source →New features:
- Added support for photometric interpretation
YCbCrand added related
ColorType.
Fixes:
- Decoding tiled images calculates padding correctly when image width or height
is a multiple of tile size. It could previously corrupt the last tile per row
by skipping over data.
Release notes
Open source →New features:
- Added support for photometric interpretation
YCbCrand added relatedColorType.
Fixes:
- Decoding tiled images calculates padding correctly when image width or height is a multiple of tile size. It could previously corrupt the last tile per row by skipping over data.
- Added support for photometric interpretation
-
0.8.110 Dec 2022Release notes
Open source →Changes:
- The jpeg decoder gained to ability to utilize the Photometric Interpretation directly instead of relying on a custom APP segment.
Fixes:
- A spurious error within the PackBits decoder lead to the incorrect results (wrong bits or errors), based on the maximum size of reads from the underlying reader.
- Removed a panic path in jpeg decoding, when a feature such as photometric interpretation is not supported. An error is returned instead.
-
0.8.010 Nov 2022Release notes
Open source →Changes:
- The minimum supported rust version is now indicated in
Cargo.toml. - The enums
TiffFormatErrorandTiffUnsupportedErrorare now marked with the#[non_exhaustive]attribute. - Additionally, tag related enums
Value,Tags,Type,CompressionMethod,PhotometricInterpretation,PlanarConfiguration,Predictor,ResolutionUnit,SampleFormatare also changed.
Removals:
- Removed deprecated methods of
Decoder:init,read_jpeg,read_strip_to_buffer,read_strip,read_tile. The implicit chunk (row or tile) index order could not be easily tracked by the caller. New separate utility interfaces may be introduced at a later point, for now callers are obligated to choose their own.
Fixes:
- Update to
jpeg_decoder = 0.3.
- The minimum supported rust version is now indicated in
-
0.7.429 Oct 2022Release notes
Open source →New features:
- Creating an encoder for invalid, zero-sized images is now rejected.
Fixes:
- Fix panic, in a case where decoding jpeg encoded images did not expect the jpeg decoder to return an error.
- Fix panic by validating
rows_per_stripbetter, fixing a division-by-zero.
-
0.7.324 Jul 2022Release notes
Open source →New features:
- Allow decoder to access specific tiles by index.
- Add support for floating point predictor.
- Tiled jpeg file support.
Changes:
- Various refactoring and performance improvements.
-
0.7.211 Apr 2022Release notes
Open source →New features:
- Encoding with
ImageEncodernow takes an optional compressor argument, allowing compressed encoding. See the methodsTiffEncoder::{new_image,write_image}_with_compression. jpeg_decoderhas been upgraded, now supports lossless JPEG.
Changes:
- Decoding now more consistently reads and interprets the initial IFD, instead of performing some interpretation lazily. (This change prepares fully lazy and backwards seeking.)
- Encoding with
-
0.7.122 Sep 2021Release notes
Open source →New features:
- Encoding signed integer formats is now supported.
- Extensive fuzzing with
cargo fuzz.
Changes:
- Tile decoding should be a little faster, requires one less intermediate buffer.
- Images whose IFDs form a cycle due to their offsets will now raise an error when the cycle would be entered (jumping back should still be supported).
Fixes:
- Fixed a regression that caused conflict between strips and tile images, causing errors in decoding some images.
- Use checked integer arithmetic in limit calculations, fixes overflows.
- IFD Tags are now always cleared between images.
- Found by fuzzing: Several memory limit overflows; JPEG now correctly validates offsets and a minimum size of its table; Check upper limit of strip byte size correctly;
Notes: Our CI has warned that this version no longer builds on
1.34.2out of the box. We're still committed to the MSRV on this major version yet one dependency—flate2—has already bumped it in a SemVer compatible version of its own. This is out-of-our-control (cargo's dependency resolution does not allow us to address this in a reasonable manner).This can be address this by pinning the version of
flate2to1.0.21in your own files. However, you should understand that this puts you in considerable maintenance debt as you will no longer receive any updates for this dependency and any package that requires a new version of the1.0series would be incompatible with this requirement (cargo might yell at you very loudly). -
0.7.025 May 2021Release notes
Open source →New features:
- Support for encoding BigTiff (#122)
- Breaking: Encoder types now have a generic parameter to differentiate BigTiff and standard Tiff encoding. Defaults to standard Tiff.
- Basic tile decoding (#125)
- Breaking: There is a new
TiffError::UsageErrorvariant.
- Breaking: There is a new
- Support for datatypes
Int8andInt16(#114)- Breaking:
DecodingResultandDecodingBufferhave the two new variantsI8andI16.
- Breaking:
- Support for
i32arrays (#118)- Breaking:
DecodingResultandDecodingBufferhave a newI32variant.
- Breaking:
- Support for
IfdandIfdBigtag types andI64data type (#119)- Breaking:
DecodingResultandDecodingBufferhave a newI64variant.
- Breaking:
- Add
SMinSampleValueandSMaxSampleValue(#123)
Changes:
- Improve deflate support (#132)
* Switch to streaming decompression via
flate2. Aside from performance improvements and lower RAM consumption, this fixes a bug wheremax_uncompressed_lengthwas precalculated for a single tile but then used as a hard limit on the whole data, failing to decompress any tiled images.- Add support for new
Deflatetag in addition toOldDeflate.
- Add support for new
- Breaking: Remove
InflateError, which is no longer needed withflate2(#134) - Breaking: Support for
MinIsWhiteis restricted to unsigned and floating point values. This is expected to be be re-added once some contradictory interpretation regarding semantics for signed values is resolved.
Fixes:
- Validate that ASCII tags are valid ASCII and end with a null byte (#121)
Internal:
- Support for encoding BigTiff (#122)
-
0.6.112 Dec 2020Release notes
Open source →New features:
- Support for reading
u16and ascii string tags. - Added
Limits::unlimitedfor disabling all limits. - Added
ImageEncoder::rows_per_stripto overwrite the default.
Changes:
- The default strip size for chunked encoding is now 1MB, up from 8KB. This should lead to more efficient decoding and compression.
Fixes:
- Fixed a bug where LZW compressed strips could not be decoded, instead
returning an error
Inconsistent sizes encountered. - Reading a tag with a complex type and a single value returns the proper Value variant, instead of a vector with one entry.
- Support for reading
-
0.6.012 Oct 2020Release notes
Open source →New features:
- Support for decoding BigTIFF with 64-bit offsets
- The value types byte,
f32,f64are now recognized - Support for Modern JPEG encoded images
Improvements:
- Better support for adding auxiliary tags before encoding image data
- Switched to lzw decoder library
weezlfor performance - The
ColorTypetrait now supportsSAMPLE_ENCODINGhints
Fixes:
- Fixed decoding of inline ASCII in tags
- Fixed handling after null terminator in ASCII data
- Recognize tile and sample format tags
-
0.6.0-alpha13 Aug 2020 pre-releaseNothing published for this version
-
0.5.001 Jun 2020Release notes
Open source →- Added support for 32-bit and 64-bit decoded values.
- Added CMYK(16|32|64) color type support.
- Check many internal integer conversions to increase stability. This should only lead to images being reported as faulty that would previously silently break platform limits. If there are any false positives, please report them.
- Remove an erroneous check of decoded length in lzw compressed images.
-
0.4.023 Nov 2019Release notes
Open source →- Several enumerations are now non_exhaustive for future extensions.
These are
Tag,Type,Value,PhotometricInterpretation,CompressionMethod,Predictor. - Enums gained a dedicated method to convert to their TIFF variant value with
the specified type. Performing these conversions by casting the discriminant
with
asis not guaranteed to be stable, except where documented explicitly. - Removed the num-derive and num dependencies.
- Added support for decoding
deflatecompressed images. - Make the decoder
Limitscustomizable by exposing members. - Fixed multi-page TIFF encoding writing incorrect offsets.
- Several enumerations are now non_exhaustive for future extensions.
These are
-
0.3.126 May 2019Nothing published for this version
-
0.3.025 Apr 2019Nothing published for this version
-
0.2.204 Feb 2019Nothing published for this version
-
0.2.126 Sep 2018Nothing published for this version
-
0.2.020 Sep 2018Nothing published for this version
-
0.1.018 Jun 2018Nothing published for this version