Overview
libraw wraps LibRaw — the industry-standard C library for decoding RAW image files from digital cameras. LibRaw evolved from Dave Coffin's dcraw, adding thread safety, a clean API, and robust error handling while supporting over 1,000 camera models.
RAW files preserve the unprocessed sensor data exactly as the camera captured it. Processing a RAW file involves demosaicing the Bayer colour array, applying white balance, colour correction, tone curves, and gamma encoding to produce a viewable image. libraw exposes the full pipeline with sensible defaults and fine-grained control when you need it.
Requires libraw-dev. Ubuntu/Debian: sudo apt install libraw-dev
Supported RAW Formats
| Brand | Format codes | Notes |
|---|---|---|
| Canon | CR2, CR3, CRW | All EOS, PowerShot, Cinema EOS models |
| Nikon | NEF, NRW | All DSLR and mirrorless Z-series |
| Sony | ARW, SR2, SRF | Alpha, RX, ZV series |
| Fujifilm | RAF | X-Trans and Bayer sensor bodies |
| Olympus / OM System | ORF | Micro Four Thirds |
| Panasonic / Leica | RW2, RWL | Lumix, Leica M/SL/Q series |
| Adobe DNG | DNG | Universal RAW container; many smartphones |
| Others | PEF, ERF, MRW, DCR, SRF… | Pentax, Epson, Minolta, Kodak, 50+ more |
Processing Pipeline
A RAW file goes through several stages before it becomes a viewable image. Understanding the pipeline helps you choose where to intervene with custom parameters.
| Stage | Function | Description |
|---|---|---|
| 1. Unpack | Unpack(P) | Read compressed sensor data from the file into memory |
| 2. Demosaic | Process / ProcessEx | Reconstruct full-colour RGB from the Bayer mosaic pattern |
| 3. Colour correction | TRawOutputParams.OutputColor | Apply camera colour matrix; target sRGB, Adobe RGB, ProPhoto, etc. |
| 4. White balance | UseCameraWB / UseAutoWB | Neutralise the colour temperature of the light source |
| 5. Gamma / tone | Gamma, Brightness, Highlight | Apply gamma curve and handle highlight clipping or blending |
| 6. Output | GetImage / SaveTiff / SavePPM | Write 8-bit or 16-bit pixel data to memory or disk |
Demosaic Algorithms
Demosaicing is the most computationally expensive step. Choose the algorithm that balances quality against speed for your workload. AHD is the default and best choice for most use cases.
| Algorithm | Constant | Quality | Speed | Notes |
|---|---|---|---|---|
| Linear | daLinear | Low | Very fast | Simple bilinear interpolation; good for batch preview |
| VNG | daVNG | Medium | Moderate | Variable Number of Gradients; reduces maze artefacts |
| PPG | daPPG | Medium-high | Fast | Patterned Pixel Grouping; good compromise |
| AHD | daAHD | High | Moderate | Adaptive Homogeneity-Directed; default, best general quality |
| DCB | daDCB | High | Slow | DCB interpolation; sharper edges than AHD |
| Modified AHD | daModAHD | High | Moderate | AHD variant with improved false-colour suppression |
Quick Start
Load a RAW file and get pixels
uses libraw;
{ One-shot: open, unpack, process with defaults, return image data }
var img := LoadRAW('/photos/DSC_0001.NEF');
WriteLn('Size: ' + IntToStr(img.Width) + 'x' + IntToStr(img.Height));
WriteLn('Channels: ' + IntToStr(img.Colors));
WriteLn('Bit depth: ' + IntToStr(img.BitsPerSample));
WriteLn('Pixel data: ' + IntToStr(Length(img.Data)) + ' bytes');
Extract the embedded JPEG thumbnail
uses libraw;
{ Fast path: extract camera-generated JPEG without full RAW decode }
var thumb := ExtractThumb('/photos/IMG_1234.CR3');
WriteLn('Thumbnail: ' + IntToStr(thumb.Width) + 'x' + IntToStr(thumb.Height));
{ thumb.Format = 1 means JPEG bytes ready to write }
if thumb.Format = 1 then
WriteLn('JPEG size: ' + IntToStr(Length(thumb.Data)) + ' bytes');
Read EXIF/GPS metadata without decoding
uses libraw;
var P := NewProcessor();
OpenFile(P, '/photos/DSCF5200.RAF');
{ GetMetadata does NOT require Unpack — very fast }
var meta := GetMetadata(P);
WriteLn(meta.Make + ' ' + meta.Model);
WriteLn('ISO ' + FloatToStr(meta.ISO));
WriteLn('f/' + FloatToStr(meta.Aperture));
WriteLn('1/' + IntToStr(Round(1.0 / meta.ShutterSpeed)) + ' s');
WriteLn(FloatToStr(meta.FocalLength) + ' mm');
if meta.GPSValid then
WriteLn('GPS: ' + FloatToStr(meta.GPSLat) + ', ' + FloatToStr(meta.GPSLon));
FreeProcessor(P);
Full pipeline with custom parameters
uses libraw;
var P := NewProcessor();
OpenFile(P, '/photos/shot.ARW');
Unpack(P);
{ Customise output: 16-bit, AHD demosaic, camera white balance, sRGB }
var opts: TRawOutputParams;
opts.Demosaic := daAHD;
opts.OutputBPS := 16;
opts.OutputColor := 1; { sRGB }
opts.UseCameraWB := True;
opts.AutoBrightness:= True;
opts.HalfSize := False;
ProcessEx(P, opts);
SaveTiff(P, '/output/result.tiff');
FreeProcessor(P);
Types
TRawProcessor
type
TRawProcessor = Integer; { opaque handle returned by NewProcessor }
TRawImage
type
TRawImage = record
Width : Integer; { output image width in pixels }
Height : Integer; { output image height in pixels }
Colors : Integer; { 1=monochrome, 3=RGB, 4=RGBA }
BitsPerSample: Integer; { 8 or 16 }
Data : string; { raw pixel bytes (Width*Height*Colors*(BPS/8)) }
end;
TRawThumbnail
type
TRawThumbnail = record
Width : Integer; { thumbnail width }
Height : Integer; { thumbnail height }
Format : Integer; { 1=JPEG bytes, 2=RGB bitmap }
Data : string; { JPEG bytes (Format=1) or RGB bitmap (Format=2) }
end;
TRawMetadata
type
TRawMetadata = record
Make : string; { camera manufacturer, e.g. 'Canon' }
Model : string; { camera model, e.g. 'EOS R5' }
Software : string; { firmware version string }
Artist : string; { photographer name from EXIF }
Description : string; { image description tag }
Timestamp : Int64; { Unix timestamp of capture }
ISO : Double; { ISO sensitivity }
Aperture : Double; { f-number (e.g. 2.8) }
ShutterSpeed : Double; { exposure time in seconds }
FocalLength : Double; { focal length in mm }
Flash : Boolean; { True if flash fired }
WhiteBalance : array[0..3] of Double; { RGBG WB multipliers }
CameraMatrix : array[0..8] of Double; { 3x3 colour correction matrix }
GPSLat : Double; { GPS latitude (degrees) }
GPSLon : Double; { GPS longitude (degrees) }
GPSAlt : Double; { GPS altitude (metres) }
GPSValid : Boolean; { True if GPS data present }
Width : Integer; { output (processed) width }
Height : Integer; { output (processed) height }
RawWidth : Integer; { full sensor width including margins }
RawHeight : Integer; { full sensor height including margins }
Orientation : Integer; { EXIF: 1=normal, 3=180, 6=90CW, 8=90CCW }
end;
TDemosaicAlgorithm
type
TDemosaicAlgorithm = (
daLinear = 0, { bilinear — fast, low quality }
daVNG = 1, { Variable Number of Gradients }
daPPG = 2, { Patterned Pixel Grouping }
daAHD = 3, { Adaptive Homogeneity-Directed — default }
daDCB = 4, { DCB interpolation }
daModAHD = 11 { Modified AHD — improved false-colour suppression }
);
TRawOutputParams
type
TRawOutputParams = record
HalfSize : Boolean; { half-size output for fast preview }
Demosaic : TDemosaicAlgorithm; { interpolation algorithm }
AutoBrightness : Boolean; { auto-expose output }
Brightness : Double; { brightness multiplier (1.0 = normal) }
Highlight : Integer; { 0=clip, 1=unclip, 2=blend highlights }
Gamma : array[0..1] of Double; { [0]=power, [1]=slope }
NoAutoBright : Boolean; { disable auto-brightness }
UseCameraWB : Boolean; { use camera-recorded white balance }
UseAutoWB : Boolean; { compute automatic white balance }
OutputBPS : Integer; { output bit depth: 8 or 16 }
OutputColor : Integer; { 0=raw, 1=sRGB, 2=Adobe, 3=Wide, 4=ProPhoto }
end;
Processor Lifecycle
Every decoding session uses a processor handle. Create one with NewProcessor, open a file, decode, and free when done. Processors are not thread-safe; use one per goroutine/agent.
| Function | Description |
|---|---|
| NewProcessor() | Allocate a new RAW processor. Returns a handle used by all other calls. |
| FreeProcessor(P) | Release all memory held by the processor. Always call when done. |
Open / Decode API
Open a RAW source, then unpack and process in sequence. GetMetadata is the only call that does not require Unpack.
| Function | Description |
|---|---|
| OpenFile(P, Path) | Open a RAW file by path. Must be called before any decode operation. |
| OpenBuffer(P, Data) | Open a RAW file already loaded into a string buffer (e.g. from a network response). |
| Unpack(P) | Decompress the RAW sensor data into memory. Required before Process. |
| UnpackThumb(P) | Unpack only the embedded thumbnail. Much faster than a full Unpack; use when only the preview is needed. |
| Process(P) | Run the full processing pipeline with default parameters. Produces the output image. |
| ProcessEx(P, Params) | Run the pipeline with a TRawOutputParams record for fine-grained control. |
Output API
Retrieve processed pixel data or save directly to disk. Call these after Process (or UnpackThumb for thumbnail extraction).
| Function | Description |
|---|---|
| GetImage(P) | Return the processed image as a TRawImage record with pixel bytes in .Data. |
| GetThumbnail(P) | Return the embedded thumbnail as a TRawThumbnail. Call after UnpackThumb. |
| SaveTiff(P, Path) | Write the processed image to a TIFF file (lossless; supports 16-bit). |
| SavePPM(P, Path) | Write as a Portable Pixmap (.ppm). Simple uncompressed format, useful for piping to other tools. |
Metadata API
EXIF and camera metadata can be read immediately after OpenFile without unpacking. This makes metadata extraction extremely fast — suitable for indexing large photo libraries.
| Function | Description |
|---|---|
| GetMetadata(P) | Return a TRawMetadata record with all EXIF/IPTC/GPS fields. Does not require Unpack. |
| GetMake(P) | Return the camera manufacturer string (quick alternative to GetMetadata). |
| GetModel(P) | Return the camera model string. |
| GetDimensions(P, Width, Height) | Return the full RAW sensor dimensions via out parameters. |
| SupportedCameraCount() | Return the total number of camera models supported by this LibRaw build. |
| GetSupportedCamera(Index) | Return the name of the camera at the given index (0-based). |
Convenience API
One-shot helpers that handle the full lifecycle internally. Use these for simple scripts where you do not need to customise the pipeline.
| Function | Description |
|---|---|
| LoadRAW(Path) | Open, unpack, process with defaults, return TRawImage, and free. Single call for the common case. |
| ExtractThumb(Path) | Open, unpack thumbnail, return TRawThumbnail, and free. No full RAW decode. |
| LibRawVersion() | Return the LibRaw version string, e.g. '0.21.2'. |
Comparison
| Tool | Type | vs libraw |
|---|---|---|
| dcraw | CLI / C source | LibRaw is based on dcraw but adds a proper API, thread safety, and active maintenance |
| RawTherapee | GUI application | Uses LibRaw internally for decoding; adds a full non-destructive editing UI |
| Darktable | GUI application | Same — LibRaw for RAW decode, Darktable adds advanced colour science and workflow |
| libjpeg / libtiff | C library | Handle compressed/lossless formats; do not decode RAW sensor data |
| OpenCV | C++ library | imread() can open some RAW via system libs but lacks the metadata depth and format coverage of LibRaw |
Create one processor per file, call OpenFile then GetMetadata, then FreeProcessor. Skip Unpack entirely. This is the fastest possible path for reading EXIF from thousands of RAW files without decoding pixels.
Package Info
System Requirements
libraw-devUbuntu/Debian:
sudo apt install libraw-dev
Supported Brands
Nikon — NEF, NRW
Sony — ARW, SR2, SRF
Fujifilm — RAF
Olympus — ORF
Panasonic — RW2
Leica — DNG, RWL
Adobe DNG
1000+ camera models total
Functions
- NewProcessor
- FreeProcessor
- OpenFile / OpenBuffer
- Unpack / UnpackThumb
- Process / ProcessEx
- GetImage
- GetThumbnail
- SaveTiff / SavePPM
- GetMetadata
- GetMake / GetModel
- GetDimensions
- SupportedCameraCount
- GetSupportedCamera
- LoadRAW
- ExtractThumb
- LibRawVersion