Rawspeed
Raw Image Decoder Library
Install / Use
/learn @klauspost/RawspeedREADME
WARNING: rawspeed is now maintained under darktable-org/rawspeed repo! Do NOT open new issues in this old repo! Do NOT send new pull requests to this old repo!
#RawSpeed Developer Information
##What is RawSpeed?
RawSpeed…
- is capable of decoding various images in RAW file format.
- is intended to provide the fastest decoding speed possible.
- supports the most common DSLR and similar class brands.
- supplies unmodified RAW data, optionally scaled to 16 bit, or normalized to 0->1 float point data.
- supplies CFA layout for all known cameras.
- provides automatic black level calculation for cameras having such information.
- optionally crops off “junk” areas of images, containing no valid image information.
- can add support for new cameras by adding definitions to an xml file.
- is extensively crash-tested on broken files.
- decodes images from memory, not a file stream. You can use a memory mapped file, but it is rarely faster.
- is currently tested on more than 500 unique cameras.
- can add support for new cameras by updating an xml file.
- open source under the LGPL v2 license.
RawSpeed does NOT…
- read metadata information, beside whitebalance information.
- do any color correction or whitebalance correction.
- de-mosaic the image.
- supply a viewable image or thumbnail.
- crop the image to the same sizes as manufactures, but supplies biggest possible images.
So RawSpeed is not intended to be a complete RAW file display library, but only act as the first stage decoding, delivering the RAW data to your application.
##Version 2, new cameras and features
- Support for Sigma foveon cameras.
- Support for Fuji cameras.
- Support old Minolta, Panasonic, Sony cameras (contributed by Pedro Côrte-Real)
- Arbitrary CFA definition sizes.
- Use pugixml for xml parsing to avoid depending on libxml.
##Getting Source Code
You can get access to the lastest version using from here. You will need to include the “RawSpeed” and “data” folder in your own project.
This includes a Microsoft Visual Studio project to build a test application. The test application uses libgfl to output 16 bit images. This library is not required for your own implementation though.
To see a GCC-based implementation, you can check out this directory, which is the implementation Rawstudio uses to load the images. This also includes an automake file to set up. You can also have a look at the darktable implementation, for which there is a Cmake based build file.
##Background of RawSpeed
So my main objectives were to make a very fast loader that worked for 75% of the cameras out there, and was able to decode a RAW file at close to the optimal speed. The last 25% of the cameras out there could be serviced by a more generic loader, or convert their images to DNG – which as a sidenote usually compresses better than your camera.
RawSpeed is not at the moment a separate library, so you have to include it in your project directly.
##Include files
All needed headers are available by including “RawSpeed-API.h”. You must have the pthread library and headers installed and available.
RawSpeed uses pthreads ~~and libxml2~~, which is the only external requirements beside standard C/C++ libraries. As of v2, libxml is no longer required.
You must implement a single function: “int rawspeed_get_number_of_processor_cores();”, which should return the maximum number of threads that should be used for decoding, if multithreaded decoding is possible.
Everything is encapsulated on a “RawSpeed” namespace. To avoid clutter the examples below assume you have a “using namespace RawSpeed;” before using the code.
##The Camera Definition file
This file describes basic information about different cameras, so new cameras can be supported without code changes. See the separate documentation on the Camera Definition File.
The camera definitions are read into the CameraMetaData object, which you can retain for re-use later. You initialize this data by doing
static CameraMetaData *metadata = NULL;
if (NULL == metadata)
{
try {
metadata = new CameraMetaData("path_to_cameras.xml");
} catch (CameraMetadataException &e) {
// Reading metadata failed. e.what() will contain error message.
}
}
The memory impact of this object is quite small, so you don’t have to free it every time. You can however delete and re-create it, if you know the metadata file has been updated.
You can disable specific cameras in the xml file, or if you would want to do it in code, you can use:
// Disable specific camera
metadata.disableCamera("Canon", "Canon EOS 100D")
// Disable all cameras from maker:
metadata.disableCamera("Fuji")
##Using RawSpeed
You need to have the file data in a FileMap object. This can either be created by supplying the file content in memory using FileMap(buffer_pointer, size_of_buffer), or use a “FileReader” object to read the content of a file, like this:
FileReader reader(filename);
FileMap* map = NULL;
try {
map = reader.readFile();
} catch (FileIOException &e) {
// Handle errors
}
The next step is to start decoding. The first step is to get a decoder:
RawParser parser(map);
RawDecoder *decoder = parser.getDecoder();
This will do basic parsing of the file, and return a decoder that is capable of decoding the image. If no decoder can be found or another error occurs a “RawDecoderException” object will be thrown. The next step is to determine whether the specific camera is supported:
decoder->failOnUnknown = FALSE;
decoder->checkSupport(metadata);
The “failOnUnknown” property will indicate whether the decoder should refuse to decode unknown cameras. Otherwise RawSpeed will only refuse to decode the image, if it is confirmed that the camera type cannot be decoded correctly. If the image isn’t supported a “RawDecoderException” will be thrown.
Reaching this point should be very fast in terms of CPU time, so the support check is very quick, if file data is quickly available. Next we decode the image:
decoder->decodeRaw();
decoder->decodeMetaData(metadata);
RawImage raw = decoder->mRaw;
This will decode the image, and apply metadata information. The RawImage is at this point completely untouched Raw data, however the image has been cropped to the active image area in decodeMetaData. Error reporting is: If a fatal error occurs a RawDecoderException is thrown.
Non-fatal errors are pushed into a "vector" array in the decoder object called "errors". With these types of errors, there WILL be a raw image available, but it will likely contain junk sections in undecodable parts. However, as much as it was possible to decode will be available. So treat these messages as warnings.
Another thing to note here is that the RawImage object is automatically refcounted, so you can pass the object around without worrying about the image being freed before all instances are out of scope. Do however keep this in mind if you pass the pointer to image data to another part of your application.
raw->scaleBlackWhite();
This will apply the black/white scaling to the image, so the data is normalized into the 0->65535 range no matter what the sensor adjustment is (for 16 bit images). This function does no throw any errors. Now you can retrieve information about the image:
int components_per_pixel = raw->getCpp();
RawImageType type = raw->getDataType();
bool is_cfa = r->isCFA;
Components per pixel indicates how many components are present per pixel. Common values are 1 on CFA images, and 3, found in some DNG images for instance. Do note, you cannot assume that an images is CFA just because it is 1 cpp - greyscale dng images from things like scanners can be saved like that.
The RawImageType can be TYPE_USHORT16 (most common) which indicates unsigned 16 bit data or TYPE_FLOAT32 (found in some DNGs)
The isCFA indicates whether the image has all components per pixel, or if it was taken with a colorfilter array. This usually corresponds to the number of components per pixel (1 on CFA, 3 on non-CFA).
The ColorfilterArray contains information about the placement of colors in the CFA:
if (TRUE == is_cfa) {
ColorFilterArray cfa = raw->cfa;
int dcraw_filter = cfa.getDcrawFilter();
int cfa_width = cfa.size.x;
int cfa_height = cfa.size.y;
CFAColor c = cfa.getColorAt(0,0);
}
To get this information as a dcraw compatible filter information, you can use getDcrawFilter() function.
You can also use getColorAt(x, y) to get a single color information. ~~Note that unlike dcraw, RawSpeed only supports 2×2 patterns, so you can reuse this information.~~ CFAColor can be CFA_RED, CFA_GREEN, CFA_BLUE for instance.
Finally information about the image itself:
unsigned char* data = raw->getData(0,0);
int width = raw->dim.x;
int height = raw->dim.y;
int pitch_in_bytes = raw->pitch;
The getData(x, y) function will give you a pointer to the Raw data at pixel x, y. This is the coordinate after crop, so you can start copying data right away. Don’t use this function on every pixel, but instead increment the pointer yourself. The width and height gives you the size of the image in pixels – again after crop.
Pitch is the number of bytes between lines, since this is usually NOT width * components_per_pixel * bytes_per_component. So in this instance, to calculate a pointer at line y, use &data[y * raw->pitch] for instance.
Finally to clean up, use:
delete map;
delete decoder;
Actually the map and decoder can be deallocated once the m
