Pfim
| Language | C# (.NET Standard 2.0) |
|---|---|
| License | MIT |
| Repository | github.com/nickbabcock/Pfim |
| Documentation | README and the samples in the repository |
| Depends on | nothing |
| Read / write | yes / no; palette, grayscale and true-color TGA, raw and RLE |
Pfim decodes TGA and DDS files into a raw pixel buffer and does nothing else: no drawing, no encoding. It’s fast, has no dependencies and works on any .NET runtime, which makes it a good fit for game tools, modding utilities and texture viewers. You pass the buffer to whatever displays or saves images: WPF, GDI+, a GPU texture, or ImageSharp.
Pixels come out in the byte order of the file: BGR for 24-bit and BGRA for 32-bit images, which matches the Bgra32 / Format32bppArgb layouts of WPF and GDI+.
Installation#
Shell
dotnet add package Pfim
Basic usage: decode a TGA#
C#
using Pfim;
using IImage image = Pfimage.FromFile("in.tga");
Console.WriteLine($"{image.Width} x {image.Height}, {image.BitsPerPixel} bpp, format {image.Format}");
Console.WriteLine($"stride {image.Stride}, {image.DataLen} bytes of pixels");
// image.Data holds the pixels; image.Format is Rgb24, Rgba32, Rgb8, R5g5b5 ...
Pfimage.FromFile checks for the DDS magic and otherwise decodes the file as TGA.
How to convert a TGA to PNG with ImageSharp#
C#
using Pfim;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using IImage tga = Pfimage.FromFile("in.tga");
using Image png = tga.Format switch
{
Pfim.ImageFormat.Rgba32 => Image.LoadPixelData<Bgra32>(tga.Data.AsSpan(0, tga.DataLen), tga.Width, tga.Height, tga.Stride),
Pfim.ImageFormat.Rgb24 => Image.LoadPixelData<Bgr24>(tga.Data.AsSpan(0, tga.DataLen), tga.Width, tga.Height, tga.Stride),
_ => throw new NotSupportedException(tga.Format.ToString()),
};
png.SaveAsPng("out.png");
How to show a TGA in WPF#
C#
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Pfim;
using IImage tga = Pfimage.FromFile("in.tga");
PixelFormat format = tga.Format switch
{
Pfim.ImageFormat.Rgba32 => PixelFormats.Bgra32,
Pfim.ImageFormat.Rgb24 => PixelFormats.Bgr24,
Pfim.ImageFormat.Rgb8 => PixelFormats.Gray8,
_ => throw new NotSupportedException(tga.Format.ToString()),
};
BitmapSource bitmap = BitmapSource.Create(tga.Width, tga.Height, 96, 96, format, null, tga.Data, tga.Stride);
// imageControl.Source = bitmap;
How to read the TGA header#
Cast to Targa to get the parsed header:
C#
using Pfim;
using IImage image = Pfimage.FromFile("in.tga");
if (image is Targa targa)
{
TargaHeader h = targa.Header;
Console.WriteLine($"type {h.ImageType}, compressed {h.IsCompressed}, orientation {h.Orientation}, id \"{h.ImageId}\"");
}
How to decode a TGA from a stream#
C#
using var stream = File.OpenRead("texture.tga");
using IImage image = Targa.Create(stream, new PfimConfig());
Tips#
- With palette images, Pfim applies the color map by default (
PfimConfig(applyColorMap: true)); passfalseto get the raw indices and the palette inTargaHeader.ColorMap. Datacan be larger thanDataLenwhen you use a pooled allocator (PfimConfig(allocator: ...)): always useDataLenandStride.