I am reading RAW files (usually NEF format) using Libraw and everything seems ok. After some processing, I need to save the RAW image as a DNG file. However, when I open the DNG file with Photoshop, the colors seem wrong.
For finding the CFA pattern, I look into the first two rows and columns of the pattern using RawProcessor.COLOR. I get the following pattern: \00\01\01\02. So then I write the raw image into file as:
const int width = RawProcessor.imgdata.sizes.raw_width;
const int height = RawProcessor.imgdata.sizes.raw_height;
const std::array<float, 9> color_matrix = {
raw_color.cam_xyz[0][0], raw_color.cam_xyz[0][1], raw_color.cam_xyz[0][2],
raw_color.cam_xyz[1][0], raw_color.cam_xyz[1][1], raw_color.cam_xyz[1][2],
raw_color.cam_xyz[2][0], raw_color.cam_xyz[2][1], raw_color.cam_xyz[2][2],
};
const std::array<float, 3> as_shot_neutral = {
1.0f / (raw_color.cam_mul[0] / raw_color.cam_mul[1]),
1.f,
1.0f / (raw_color.cam_mul[2] / raw_color.cam_mul[1])
};
const auto base_black_level = static_cast<float>(raw_color.black);
std::array<float, 4> black_level = {
base_black_level + static_cast<float>(raw_color.cblack[0]),
base_black_level + static_cast<float>(raw_color.cblack[1]),
base_black_level + static_cast<float>(raw_color.cblack[2]),
base_black_level + static_cast<float>(raw_color.cblack[3])
};
if (raw_color.cblack[4] == 2 && raw_color.cblack[5] == 2) {
for (int x = 0; x < raw_color.cblack[4]; ++x) {
for (int y = 0; y < raw_color.cblack[5]; ++y) {
const auto index = y * 2 + x;
black_level[index] = raw_color.cblack[6 + index];
}
}
}
static const uint32_t white_level = raw_color.maximum;
static const short bayerPatternDimensions[] = { 2, 2 };
TIFF* tif = TIFFOpen(strAddr.c_str(), "w");
TIFFSetField(tif, TIFFTAG_DNGVERSION, "\01\01\00\00");
TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, bayerPatternDimensions);
TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, "\00\01\01\02");
TIFFSetField(tif, TIFFTAG_MAKE, "DNG");
TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, "DNG");
TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, &color_matrix );
TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, &as_shot_neutral );
TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 4, &black_level);
TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &white_level);
for (int i = 0; i < height; i++)
TIFFWriteScanline(tif, &RawProcessor.imgdata.rawdata.raw_image[(i)*width], i, 0);
TIFFWriteDirectory(tif);
TIFFClose(tif);
I find cam_xyz using: RawProcessor.imgdata.color.cam_xyz, which is a 4x3 matrix and I remove the last row to get cam_xyz. cam_mul comes from RawProcessor.imgdata.color.cam_mul which has 4 elements and I remove the last element to get cam_mul. The values for cam_mul are inversed before passing to the Tiff tag.
EDIT: Here is the code for reading the RAW image using LibRaw from file:
LibRaw RawProcessor;
int ret;
if ((ret = RawProcessor.open_file(strAddr.c_str())) != LIBRAW_SUCCESS)
return false;
// Unpack the image
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
return false;
// Data unpacking
ret = RawProcessor.dcraw_process();
if (LIBRAW_SUCCESS != ret) // error at the previous step
return false;
else // Successful document processing
{
std::cout << "Successful document processing..." << std::endl;
// Process the RAW data
}
I get the following values for the cam_xyz:
[1.0405 -0.3755 -0.127
-0.5461 1.3787 0.1793
-0.104 0.2015 0.6785
0 0 0 ]
and cam_mul : [1.78906, 1, 1.67969, 1].
As I said I have a big problem which is when I load the DNG image in Photoshop the colors are not correct which can be because of color matrix or white balance.
Another problem is that when I load the original NEF file in Photoshop, the size is 5504x8256, while the size of the DNG file is 5520x8288. I have checked these values also:
RawProcessor.imgdata.sizes.top_margin: 0
RawProcessor.imgdata.sizes.left_margin: 2
which does not correspond to the sizes I get opening the NEF file in another software. Any idea where the problem is?
Trying any image from this gallery (https://www.photographyblog.com/previews/nikon_d850_photos) will give a result similar to this, where the original RAW image is the bottom image and the top image is the converted DNG image: