Thank you for these caveats. I noticed the need of using the user_black, user_cblack.
I notice the use of COLOR() is somehow same as using FC(), right? The latter is used in raw2image() apparently.
I haven't go through those functions yet. COLOR() is not documented so can you say a bit more about how to use this? I had a look in libraw.h
You wrote:
int COLOR(int row, int col) { return libraw_internal_data.internal_output_params.fuji_width? FCF(row,col):FC(row,col);}
If COLOR(row, col) gives a color value at pixel(2,2), that value must be in some color table, right? Where/how do I know which color table this COLOR() output value corresponds to?
Or did you mean, more simply, that COLOR(row,col) is meant to be used like this:
colorValue at pixel (2,2) = imgdata.image(COLOR(row,col)) ?
which would just consist in converting 2D coordinates in the 1D buffer index.
If you will use dcraw_process() for image postprocessing, you need to fix values in raw_image[] array, because dcraw_process() will call raw2image_ex(), so override any changes made in image[] array.
Also, you need to set imdata.params.user_black and user_cblack[4] to zero to prevent additional black level subtraction in dcraw_process()
Regarding a correction pipeline, would it make sense to make my own corrections on the non-demosaiced raw_image, such as subtracting my own dark image (an average "master" of dark images in fact) taken with the same camera (same parameters), and calling raw2image() on the dark-subtracted raw_image? Or should I better perform this on the imgdata.image after the raw2image() call ?
I'm soon publishing my software for which i'm trying to implement Libraw, so, again, thank you for your time.
Pixels (in raw_image) are recorded 'as in raw file'.
Colors are depending on camera CFA pattern.
The LibRaw::COLOR(row,col) call will return color for given pixel (row,col) are in image[] coordinate space i.e. visible area (so counted from top_margin,left_margin point of raw_image)
Let me take one step back on raw_image(). I see the initialization and dimensioning of raw_image, set as a one dimension array (row, or column, that's just an abstraction here):
does that go to the next row where I'd see the BGBG associated to the same pixel ? you said 4 values per pixel, as expected for Bayer image, so just checking I understand how they are set in the raw files.
raw2images arranges pixel values (from raw_image array, 1 value per pixel) to image[][4] array (4 values per pixel).
So, only one of image[N][0..3] is non-zero after raw2image, all other 3 components are still zero.
This is 'prepare for interpolation' step.
Actual interpolation (and white balance, output color profile conversion, brightness adjustment) is made by dcraw_process()
Could not understand the question
pixels 16799706 .... 16799710
are all in the same row
So, only two colors.
Again
ROWn: RGRGRGRGRGRGR
ROWn+1: GBGBGBGBGBGB
So, do you mean that, above, pixInd 16799706 is telling me that R = 2175, and that
pixInd 16799707 is giving my G2 = 2207 ?
pixInd 16799708 is B = 2134
pixInd 16799709 is G = 2161
and then these 4 values are my RGBG for one non-demosaiced single colored pixel?
Looks normal for me (after raw2image, not dcraw_process):
Each row (or column )in bayer pattern contains only two colors:
RGRGRGRG
GBGBGBGB
(really G2 in second row)
int iwidth = rawProcess.imgdata.sizes.iwidth;
// somewhere in the middle of the picture, far from edges.
int row = 2898;
int col = 2898;
// Display just 5 pixels
int nPixels = 5;
int first_visible_pixel = rawProcess.imgdata.sizes.raw_width*rawProcess.imgdata.sizes.top_margin + rawProcess.imgdata.sizes.left_margin;
then looping over a pixel index with i from 0 to 4 in :
after raw2image(), imgdata.image[pixInd][0 to 3] gives, with the following printout arguments:
image[pixInd][0] | image[pixInd][1] | image[pixInd][2] | image[pixInd][3],
row and column are both in 1-st dimension.
The (row,col) pixel values are in
image[row*imgdata.sizes.iwidth + col] [0..3]
iwidth is equal to imgdata.sizes.width for normal processing and width/2 for 'half' interpolation (where imgdata.params.half_size is non-zero).
Border values (1st/last row or 1st/last column) in image may be not fully interpolated because there is no data for it.
Better use image[iwidth*2 + 2] for inspection (this is pixel at (2,2))
Which dimension is going across the R G B G values. At first I thought it was [0 to 3] (2nd dimensions, "columns") which was giving the R G B G (which I abusively call the "channels"). Is that the other way round? Are they, in fact, in the 1st dimension (rows)? I'm often confused on the dimension when I see tables of pointers such as: imgdata.image = (ushort (*)[4]) calloc(S.iwidth*S.iheight,sizeof(*imgdata.image));
I've been doing some testing. I've selected the 4 first pixels of the data (I ignored the hidden ones for calibration), for a .CR2 file (canon 5D), at 3 stages of processing: after unpack(), after raw2image(), after dcraw_processed(). See below (the 4 "channels" of the 2nd dimension are separated by the separator " | "):
Why aren't the raw2image() values in the same column and instead, dispatched alternatively in the 0th and 1st column? Is that just to prepare the data for later demosaicing in a way that's compatible with all possible sensors? The values are indeed identical to the raw values. So it is unclear what happens between unpack() raw_image[] values and raw2image() image[][] values
Are the dcraw_processed() values dispatched in the 1st three columns to be considered as the R | G | B (and 4th is unused) components, after demosaicing?
Initialization of rawdata buffer in unpack(), can't miss it, it's clear. Populated this raw data buffer, still can't see it within unpack(). I make here a distinction between initializing something, and assigning value (which you call "populate" i guess). That's that part I still don't grasp.
Consider my test (it's done in Qt framework, hence the qDebug() instead of printf() for printing out in debug mode):
LibRaw rawProcess;
rawProcess.open_file("/......./F36A7292.CR2");
rawProcess.unpack()
// printout raw values
int first_visible_pixel = rawProcess.imgdata.sizes.raw_width*rawProcess.imgdata.sizes.top_margin + rawProcess.imgdata.sizes.left_margin;
for( int i=0; i< 100; i++)
{
qDebug() << "raw_image["<< i << "] =" << rawProcess.imgdata.rawdata.raw_image[i+first_visible_pixel];
}
This is giving me my raw values.
And I still don't see how the raw_image values get assigned (populated) within unpack(). In what I pasted in the early post, i don't see the lines of codes where this happen, for the Canon case (Nikon case seems a bit different). All I see is initialized buffer, and freed buffer (for Bayer image, and non-Nikon)
Sorry for repeating the question, I must be missing something obvious. Maybe a slap in my face will make me see. (by Copy pasting that invisible line that I don't see?)
If you don't want to repeat yourself, I'll understand and will go back again to what you say and try to find what i missed.
For bayer images, COLOR is just FC()
For fuji (SuperCCD, X-Trans) it is not
Thank you for these caveats. I noticed the need of using the user_black, user_cblack.
I notice the use of COLOR() is somehow same as using FC(), right? The latter is used in raw2image() apparently.
I haven't go through those functions yet. COLOR() is not documented so can you say a bit more about how to use this? I had a look in libraw.h
You wrote:
If COLOR(row, col) gives a color value at pixel(2,2), that value must be in some color table, right? Where/how do I know which color table this COLOR() output value corresponds to?
Or did you mean, more simply, that COLOR(row,col) is meant to be used like this:
colorValue at pixel (2,2) = imgdata.image(COLOR(row,col)) ?
which would just consist in converting 2D coordinates in the 1D buffer index.
If you will use dcraw_process() for image postprocessing, you need to fix values in raw_image[] array, because dcraw_process() will call raw2image_ex(), so override any changes made in image[] array.
Also, you need to set imdata.params.user_black and user_cblack[4] to zero to prevent additional black level subtraction in dcraw_process()
Regarding a correction pipeline, would it make sense to make my own corrections on the non-demosaiced raw_image, such as subtracting my own dark image (an average "master" of dark images in fact) taken with the same camera (same parameters), and calling raw2image() on the dark-subtracted raw_image? Or should I better perform this on the imgdata.image after the raw2image() call ?
I'm soon publishing my software for which i'm trying to implement Libraw, so, again, thank you for your time.
Pixels (in raw_image) are recorded 'as in raw file'.
Colors are depending on camera CFA pattern.
The LibRaw::COLOR(row,col) call will return color for given pixel (row,col) are in image[] coordinate space i.e. visible area (so counted from top_margin,left_margin point of raw_image)
Ok. I'm still processing your explanations:
Let me take one step back on raw_image(). I see the initialization and dimensioning of raw_image, set as a one dimension array (row, or column, that's just an abstraction here):
When i display the raw values, if I printout the raw_image[] at 4 consecutive indices,
say:
unpack(): raw_image[ i ] = 2135
unpack(): raw_image[ i+1 ] = 2091
unpack(): raw_image[ i+2 ] = 2126
unpack(): raw_image[ i+3 ] = 2174
assuming i'm in row_N, say, at the beginning of the row, are these values corresponding to RGRG?
Then if I print at
unpack(): raw_image[ i + width]
unpack(): raw_image[ i+1 + width]
unpack(): raw_image[ i+2 + width]
unpack(): raw_image[ i+3 +width]
does that go to the next row where I'd see the BGBG associated to the same pixel ? you said 4 values per pixel, as expected for Bayer image, so just checking I understand how they are set in the raw files.
Thanks
raw2images arranges pixel values (from raw_image array, 1 value per pixel) to image[][4] array (4 values per pixel).
So, only one of image[N][0..3] is non-zero after raw2image, all other 3 components are still zero.
This is 'prepare for interpolation' step.
Actual interpolation (and white balance, output color profile conversion, brightness adjustment) is made by dcraw_process()
Yes, I'm aware of how a detector is structured. I'm confused on the software side.
The RGBG is just confusing me with how they get represented in the ushort (*)[4] array.
I saw your other reply. i'm gonna do some more tests and try to understand it better, displaying Row_N and Row_N+1
Thanks.
Have you noted, that in bayer-pattern cameras (all modern, except foveon sensors) each pixel is monochrome (R _or_ G _or_ B) ?
Could not understand the question
pixels 16799706 .... 16799710
are all in the same row
So, only two colors.
Again
ROWn: RGRGRGRGRGRGR
ROWn+1: GBGBGBGBGBGB
yes, that's what I did 2 replies above with
pixInd = iwidth*row + col + i
(I iterated over i 5 times).
Please see my "in-between" reply above. It's really important that I get that cleared out.
Hmm... getting there...
raw2image(): imgdata.image[ 16799706 ][0 to 3] = | 2175 | 0 | 0 | 0
raw2image(): imgdata.image[ 16799707 ][0 to 3] = | 0 | 2207 | 0 | 0
raw2image(): imgdata.image[ 16799708 ][0 to 3] = | 2134 | 0 | 0 | 0
raw2image(): imgdata.image[ 16799709 ][0 to 3] = | 0 | 2161 | 0 | 0
raw2image(): imgdata.image[ 16799710 ][0 to 3] = | 2139 | 0 | 0 | 0
So, do you mean that, above, pixInd 16799706 is telling me that R = 2175, and that
pixInd 16799707 is giving my G2 = 2207 ?
pixInd 16799708 is B = 2134
pixInd 16799709 is G = 2161
and then these 4 values are my RGBG for one non-demosaiced single colored pixel?
Also, please note, that image[] do not contain invisible pixels.
So, raw_image[(row+top_margin)*raw_width + left_margin+col] becomes just image[row*iwidth+col]
Looks normal for me (after raw2image, not dcraw_process):
Each row (or column )in bayer pattern contains only two colors:
RGRGRGRG
GBGBGBGB
(really G2 in second row)
Away from edges, I did this:
then looping over a pixel index with i from 0 to 4 in :
pixInd = first_visible_pixel + iwidth*row + col+ i;
rawProcess.imgdata.rawdata.raw_image[pixInd] gives:
unpack(): raw_image[ 17273428 ] = 2135
unpack(): raw_image[ 17273429 ] = 2091
unpack(): raw_image[ 17273430 ] = 2126
unpack(): raw_image[ 17273431 ] = 2174
unpack(): raw_image[ 17273432 ] = 2191
after raw2image(), imgdata.image[pixInd][0 to 3] gives, with the following printout arguments:
image[pixInd][0] | image[pixInd][1] | image[pixInd][2] | image[pixInd][3],
with now,
pixInd = iwidth*row + col + i
;raw2image(): imgdata.image[ 16799706 ][0 to 3] = | 2175 | 0 | 0 | 0
raw2image(): imgdata.image[ 16799707 ][0 to 3] = | 0 | 2207 | 0 | 0
raw2image(): imgdata.image[ 16799708 ][0 to 3] = | 2134 | 0 | 0 | 0
raw2image(): imgdata.image[ 16799709 ][0 to 3] = | 0 | 2161 | 0 | 0
raw2image(): imgdata.image[ 16799710 ][0 to 3] = | 2139 | 0 | 0 | 0
I'd like to understand why the values in imgdata.image, after raw2image() are put alternatively in channel 0 and channel 1.
Currently, to me these values mean (for imgdata.image[][]):
pixel 16799706 has R = 2175 , G = 0, B = 0, G2 = 0
pixel 16799707 has R = 0 , G = 2207, B = 0, G2 = 0
etc...
Which i probably misunderstand as my image is clearly filled with all colors.
What am i missing this time?
Oh ok, indeed I was wondering about 0 values may be due to edges.
Ok, i'll try inspecting away from edges.
You cleared out my question on the dimensions, thanks a lot!
Raphael
row and column are both in 1-st dimension.
The (row,col) pixel values are in
image[row*imgdata.sizes.iwidth + col] [0..3]
iwidth is equal to imgdata.sizes.width for normal processing and width/2 for 'half' interpolation (where imgdata.params.half_size is non-zero).
Border values (1st/last row or 1st/last column) in image may be not fully interpolated because there is no data for it.
Better use image[iwidth*2 + 2] for inspection (this is pixel at (2,2))
Ok, I understand the Bayer pattern of RGBG. My question is just to be clear on how to read the dimensions.
By printing out:
raw2image(): imgdata.image[ 0 ][0 to 3] = | 2141 | 0 | 0 | 0
raw2image(): imgdata.image[ 1 ][0 to 3] = | 0 | 2098 | 0 | 0
raw2image(): imgdata.image[ 2 ][0 to 3] = | 2034 | 0 | 0 | 0
raw2image(): imgdata.image[ 3 ][0 to 3] = | 0 | 2084 | 0 | 0
Which dimension is going across the R G B G values. At first I thought it was [0 to 3] (2nd dimensions, "columns") which was giving the R G B G (which I abusively call the "channels"). Is that the other way round? Are they, in fact, in the 1st dimension (rows)? I'm often confused on the dimension when I see tables of pointers such as:
imgdata.image = (ushort (*)[4]) calloc(S.iwidth*S.iheight,sizeof(*imgdata.image));
You didn't say anything about the other question:
dcraw_processed(): imgdata.image[ 0 ][0 to 3] = | 1576 | 0 | 688 | 0
Is the row here the demosaiced RGB values of a given pixel (from left to right column) ?
Thanks
raw2image() put pixel values according to color of this particular pixel (0 for Red, 1 and 3 for G/G2, 2 for Blue)
I've been doing some testing. I've selected the 4 first pixels of the data (I ignored the hidden ones for calibration), for a .CR2 file (canon 5D), at 3 stages of processing: after unpack(), after raw2image(), after dcraw_processed(). See below (the 4 "channels" of the 2nd dimension are separated by the separator " | "):
user_qual = -1
imgdata.idata.cdesc = RGBG
unpack(): raw_image[ 0 ] = 2141
unpack(): raw_image[ 1 ] = 2098
unpack(): raw_image[ 2 ] = 2034
unpack(): raw_image[ 3 ] = 2084
raw2image(): imgdata.image[ 0 ][0 to 3] = | 2141 | 0 | 0 | 0
raw2image(): imgdata.image[ 1 ][0 to 3] = | 0 | 2098 | 0 | 0
raw2image(): imgdata.image[ 2 ][0 to 3] = | 2034 | 0 | 0 | 0
raw2image(): imgdata.image[ 3 ][0 to 3] = | 0 | 2084 | 0 | 0
dcraw_processed(): imgdata.image[ 0 ][0 to 3] = | 1576 | 0 | 688 | 0
dcraw_processed(): imgdata.image[ 1 ][0 to 3] = | 616 | 136 | 626 | 0
dcraw_processed(): imgdata.image[ 2 ][0 to 3] = | 0 | 132 | 371 | 0
dcraw_processed(): imgdata.image[ 3 ][0 to 3] = | 0 | 287 | 36 | 0
Why aren't the raw2image() values in the same column and instead, dispatched alternatively in the 0th and 1st column? Is that just to prepare the data for later demosaicing in a way that's compatible with all possible sensors? The values are indeed identical to the raw values. So it is unclear what happens between unpack() raw_image[] values and raw2image() image[][] values
Are the dcraw_processed() values dispatched in the 1st three columns to be considered as the R | G | B (and 4th is unused) components, after demosaicing?
Thanks
Oh dear... that explains all! Thanks a lot!!!!!
Raphael
raw_image values are read in *_load_raw() call (specific to image format) called by
(this->*load_raw)();
Initialization of rawdata buffer in unpack(), can't miss it, it's clear. Populated this raw data buffer, still can't see it within unpack(). I make here a distinction between initializing something, and assigning value (which you call "populate" i guess). That's that part I still don't grasp.
Consider my test (it's done in Qt framework, hence the qDebug() instead of printf() for printing out in debug mode):
This is giving me my raw values.
And I still don't see how the raw_image values get assigned (populated) within unpack(). In what I pasted in the early post, i don't see the lines of codes where this happen, for the Canon case (Nikon case seems a bit different). All I see is initialized buffer, and freed buffer (for Bayer image, and non-Nikon)
Sorry for repeating the question, I must be missing something obvious. Maybe a slap in my face will make me see. (by Copy pasting that invisible line that I don't see?)
If you don't want to repeat yourself, I'll understand and will go back again to what you say and try to find what i missed.
Thanks.
No-no-no
load_raw() uses preallocated buffer (unles OWNALLOC specified in decoder flags).
Again:
imgdata.image[] is allocated and populated in raw2image() or raw2image_ex() calls.
imgdata.rawdata.* pointers are initialized in unpack() call.
Is that in fact in
(this->*load_raw)()
(within unpack())that the raw_data buffer gets populated?
Pages