Reputation: 61
I'm reading a DNG file on Android with libraw in C++ which works pretty fine. I want to pass the pixel data to Cimg for manipulation purposes (rotating etc.).
The problem is that the image in Cimg looks weird. I think that problem is that the original pixel data from libraw are stored in a different order than in Cimg. In libraw (due to the DNG file) its RGBGRGBGRGBG while Cimg stores the pixel data in the way RRRRRR....GGGGGGG....BBBBBB. Does anyone know how to convert from RGBGRGBGRGBG to RRRRRR....GGGGGGG....BBBBBB?
Here are both images, on the left is dng file and on the right is tiff file exported from cimg (both imported into Photoshop).
Here is my code:
LibRaw rawProcessor;
rawProcessor.open_file("file.dng");
rawProcessor.unpack();
int ret2=rawProcessor.dcraw_process();
libraw_processed_image_t* image = rawProcessor.dcraw_make_mem_image(&ret2);
float xres=72.0;
CImg<unsigned char> cimgOriginal(image->data,image->width,image->height, true);
cimgOriginal.shift(10*(-1), 10*(-1),0,0,0);
cimgOriginal.rotate(360.0-5, (float) 1200, (float) 800,0,0);
cimgOriginal.save_tiff("file.tiff", 0, &xres,0,false);
Thanks!
Mike
Upvotes: 1
Views: 321
Reputation: 61
Thank you for your help, Mark! In the meantime I've figured out that Cimg can do it from packed RGB to planar RGB - with a method called permute_axes(). The documentation about permute_axes() is very short but here is a good explanation:
https://www.codefull.org/2014/11/cimg-does-not-store-pixels-in-the-interleaved-format/
With the following code I was able to get the image in Cimg. The attached screenshots shows DNG on the left and the image exported to tiff from Cimg.The image with leaves (taken from here: https://www.kenrockwell.com/leica/m9/sample-photos-3.htm) is a 8 bit DNG. The second example (with mouse and pen) shows my 16 bit DNG from Pixel 5. The code works also with 16 bit DNG files:
LibRaw rawProcessor;
rawProcessor.imgdata.params.use_auto_wb = 0; // Auto white-Balance
rawProcessor.imgdata.params.use_camera_wb = 1; // Use camera WB instead
rawProcessor.imgdata.params.output_color = 1; // [0-6] Output colorspace (0=raw, 1=sRGB, 2=Adobe, 3=Wide, 4=ProPhoto, 5=XYZ, 6=ACES)
rawProcessor.imgdata.params.no_auto_bright = 0; // No automatic brightnes
// Open the file and read the metadata
rawProcessor.open_file("L1004220.DNG");
// The metadata are accessible through data fields of the class
int w = rawProcessor.imgdata.sizes.width;
int h = rawProcessor.imgdata.sizes.height;
printf("Image size: %d x %d\n",w,h);
// Let us unpack the image
rawProcessor.unpack();
int ret2=rawProcessor.dcraw_process();
libraw_processed_image_t* image = rawProcessor.dcraw_make_mem_image(&ret2);
float xres=72.0;
CImg<unsigned char> cimgOriginal(image->data, 3, w, h, 1, true);
cimgOriginal.permute_axes("yzcx");
cimgOriginal.save_tiff("L1004220.DNG.tiff", 0,
&xres,0,true);
Upvotes: 1
Reputation: 207345
libraw
stores pixels in "packed" (a.k.a. "interleaved") format. So a 3x2 image will be stored like this:
R G B R G B R G B R G B R G B R G B
CImg
, on the other hand, stores pixels in "planar" format, which bunches all the red pixels together in a plane, followed by all the green, then all the blue ones. So that same 3x2 image will be stored like this:
R R R R R R G G G G G G B B B B B B
I haven't done any C++ for years, so my code will be shockingly awful quality, but it does work at least:
#include "libraw/libraw.h"
#define cimg_display 0
#include "CImg.h"
using namespace cimg_library;
int main(int ac, char *av[])
{
// Let us create an image processor
LibRaw rawProcessor;
// Open the file and read the metadata
rawProcessor.open_file("image.dng");
// The metadata are accessible through data fields of the class
int w = rawProcessor.imgdata.sizes.width;
int h = rawProcessor.imgdata.sizes.height;
printf("Image size: %d x %d\n",w,h);
// Let us unpack the image
rawProcessor.unpack();
int ret2=rawProcessor.dcraw_process();
libraw_processed_image_t* image = rawProcessor.dcraw_make_mem_image(&ret2);
// Create buffer that CImg can use
unsigned char * buffer;
buffer = new unsigned char [w * h *3];
// Pointer to the buffer from libraw where our data currently is
unsigned char *p = image->data;
// Pointers into the planar buffer for CImg
unsigned char* Rp = buffer;
unsigned char* Gp = buffer + h * w;
unsigned char* Bp = buffer + 2 * h * w;
// Unpack the packed pixel ino R, G and B planes
for(int pixel=0; pixel<=w*h; pixel++){
*Rp++ = *p++;
*Gp++ = *p++;
*Bp++ = *p++;
}
// Convert RGB packed raw image to planar format CImg in buffer
CImg<unsigned char> cimgOriginal(buffer, w, h, 1, 3,true);
float xres = 72;
cimgOriginal.save_tiff("result.tif", 0, &xres, 0,false);
rawProcessor.recycle();
return 0;
}
Compiled on Raspberry Pi OS with:
g++ -O3 main.cpp -L /usr/local/lib -I /usr/local/include -lraw -I CImg
I tested it by downloading the first DNG sample picture from Ken Rockwell, here.
Upvotes: 0