- Reduce memory allocation necessary to decode images
- Implement RGB swap for BGR8 DDS images
- Fix targa and dds decoding from publicly visible memory streams
Breaking Changes
The Pfim
class has been renamed to Pfimage
to avoid namespace collision. Migration should be simple:
- using (var image = Pfim.FromFile(file))
+ using (var image = Pfimage.FromFile(file))
Other Changes
- Fix rounding errors in DXT1, DXT3, and DXT5 where the decoded channels may be inaccurate within a few degrees. See PR #98 and issue #88 for more info
- Fix image decoding on smaller buffers and chunked streams
- Pfim is now a strong named assembly
- Code samples updated to use NET 6.0
- Add support for B5G5R5A1_UNORM encoded DDS images
- Add initial support for b8g8r8x8 encoded DDS images
- Add more support for TGA images with dimensions that require stride padding
- Add support for decoding DXT1 with alpha channel. This required changing the image format of DXT1 images to 32 bit rgba instead of 24 bit rgb, so this is technically is a breaking change as code that assumed 24 bit data for DXT1 images will need to change.
- Add a floor of 1 to dimensions of mipmap calculations
Much thanks to @ptasev for this release:
- Add BC4 DDS support
- Add BC5S DDS support
- Add BC6H DDS support
Much thanks to @ptasev for identifying the bugs / implementing features
- Support for BC7 DDS decoding
- Support for BC2 DDS decoding
- Support for BC5U DDS decoding
- Fixed decoding of BC3 and BC5 DDS
- Fixed blue channel for BC5 DDS images when allocator reused buffer
Two big changes: netstandard 2.0 targeting and DDS mipmap support.
With a bump to netstandard 2.0, Pfim is able to slim down dependencies and the amount of code that is conditionally compiled. The only platforms that lose out here are platforms that are EOL or nearing EOL.
Each image file may contain several images in addition to the main image decoded. There are pre-calculated / optimized for smaller dimensions -- often called mipmaps. Previously there was no way to access these images until now.
New property under IImage
MipMapOffset[] MipMaps { get; }
With MipMapOffset
defined with properties:
public int Stride { get; }
public int Width { get; }
public int Height { get; }
public int DataOffset { get; }
public int DataLen { get; }
These should look familiar to known IImage
properties, the one exception being DataOffset
. This is the offset that the mipmap data starts in IImage.Data
. To see usage, here is a snippet for WPF to split an IImage
into separate images by mipmaps
private IEnumerable<BitmapSource> WpfImage(IImage image)
{
var pinnedArray = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
var addr = pinnedArray.AddrOfPinnedObject();
var bsource = BitmapSource.Create(image.Width, image.Height, 96.0, 96.0,
PixelFormat(image), null, addr, image.DataLen, image.Stride);
handles.Add(pinnedArray);
yield return bsource;
foreach (var mip in image.MipMaps)
{
var mipAddr = addr + mip.DataOffset;
var mipSource = BitmapSource.Create(mip.Width, mip.Height, 96.0, 96.0,
PixelFormat(image), null, mipAddr, mip.DataLen, mip.Stride);
yield return mipSource;
}
}
Example image:
Only additional images are stored in MipMaps
(the base image is excluded).
This continues the work in 0.7.0
were users should start relying on the DataLen
property and not Data.Length
as now multiple images share this buffer
- Added:
Pfim.FromStream
to decode tga or dds image from a stream. Pfim will heuristically determine what image based on the header. - Added:
IImageAllocator
that will allow one to pool intermediate byte buffers as well as the resulting data buffer. This is to reduce memory usage and GC pressure. Benchmarks have naive pooling implementations showing up to a 3x performance improvement. Set a custom allocator throughPfimConfig
- Changed: Targa color maps are applied by default (so no need to write
IImage::ApplyColorMap
every time). If this behavior is not desired, one can setapplyColorMap
to false inPfimConfig
. - Changed:
IImage
implementsIDisposable
(so that the allocator can reclaim the data buffer). While disposing an image is only necessary when a custom allocator is supplied, the best practice is to still dispose an image:
using (var image = Pfim.FromFile(file)) { }
- Changed:
Pfim.FromFile
no longer determines the image type by file extension. Instead it will heuristically determine the image type based on the file header. - Changed: Exception thrown on invalid targa image types (3rd byte in the header)
- Added:
IImage::ApplyColorMap
, which will apply a colormap to the image, overwriting previous data and metadata like format, stride, pixel depth, etc. An example of a colormap is when an image only uses 256 colors. Instead of consuming 32 bits per pixel on disk, the image data instead will consist of 8 bit indices into the colormap located in the header of an image. - Support Targa images orientated in the top left corner.
- Targa images encoded in the top right or bottom right corners (two extremely rare formats) fallback to bottom left corner decoding.
- Fix errors or incorrect decoding of dds images with widths and heights that aren't divisible by their block size.
- Fix
MipMapCount
misspelling inDdsHeader
- Include Mipmap data as part of
IImage::Data
for DDS images that skipped decoding - Recognize and decode ATI2 dds images
- Expose
BitsPerPixel
inIImage
- Add configuration to the decoding process via
PfimConfig
:- Configurable buffer size for chunk decoding
- Allow opt-out of DDS BC decompression to allow for GPU offload.
- Optimize fast path for decoding
byte[]
data - Latency of decoding BC DDS images decreased by 10%
- Highly experimental decoding of DX10 images.
- Support for 24bit rgb dds images
- Support for additional 16bit dds images
- Rgba16 (each channel is 4 bits)
- R5g5b5a1
- R5g6b5
- R5g5b5
- Bug fixes for currently supported dds images
- Initial implementation for interpreting tga color maps
- Support for 16bit R5g5b5 tga images
- Support for 8bit tga images
- Fix bad calculation of tga strides
- Fix red and blue color swap for TopLeft encoded targa images
- 20x performance improvement for TopLeft encoded targa images
- Fix infinite loop on certain large targa and dds images
- Release .NET Standard 1.0 version that doesn't contain File IO
- Fix decoding of non-square uncompressed targa images
- Fix edge case decoding for compressed targa images
- Released for netstandard 1.3
- 25% performance improvement on compressed dds images
- Bugfix in compressed targa decoder
- Fix pixel depth calculations for compressed dds
- Internalized a lot of API to simplify usage
- Publish benchmarking
- All decoded images now derive from
IImage
- Initial release