Recent comments

Reply to: User defined custom white balance   4 years 7 months ago

Does that mean that I could ask Libraw to use (for example) the "Fine weather" white balance coefficients from the X-T1 raw file metadata Maker-notes?

How would I do that?

Thanks again

Reply to: User defined custom white balance   4 years 7 months ago

Aha! So, are those pre-built values buried in the entries like:

{ "Fujifilm X-T1", 0, 0,
{ 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } },

or if not where to find them in the code and how do they get propogated into pre_mul?

Many thanks
David

Reply to: User defined custom white balance   4 years 7 months ago

Of course, one may use pre-set WBs if extracted from camera metadata.

Reply to: User defined custom white balance   4 years 7 months ago

D65 multipliers are pre-built, so there is no daylight WB for unsupported cameras.

Reply to: User defined custom white balance   4 years 7 months ago

I'm sorry but it appears frm the output of raw-identify that the Libraw code has derived the pre_mul values from the D65 illuminant WB coefficents and other information returned in the raw file for the X-T1. I cannot see where else these

Derived D65 multipliers: 2.147247 0.934710 1.221633

values which are the contents of the pre_mul array could have come from (unless they are hard coded into LibRaw). A pre_mul array with all values set to 1.0 by LibRaw just doesn't make any sense for processing a raw fille for Daylight WB.

So again I ask you how is pre_mul set from the WB coefficients and other data read from the raw file, so I can better understand your code and maybe make contributions in the future.

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

I've already answered to that (1st/2nd replies in this thread):
LibRaw::COLOR(row,col) returns color index for (row,col)
So, for bayer, 4 calls for (0,0), (0,1), (1,0), (1,1) will give you bayer pattern used.

COLOR() == 3 is 'second green'

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

Thanks Alex,

I now have my application working. However, I have one last question.

Is it possible to find the Bayer filter pattern (CFA) from LibRaw? Basically, I need to establish if a specific camera is either:

  • RGGB
  • BGGR
  • GBRG
  • GRBG

I have looked at imgdata.idata.cdesc but this returns RGBG regardless of the camera in use. It seems that my Nikon DSLRs are using BGGR but Canon cameras are using RGGB.

Is it possible to receive this information from LibRaw?

Many thanks for your kind help.

Amanda

Reply to: User defined custom white balance   4 years 7 months ago

Dear Sir:

"in none of those places does there appear to be any derivation of the pre_mul
value from the WB Coefficients, even though it is clear that such a
derivation must take place."

No, it mustn't, unless WB coeffs are user-supplied.

Reply to: User defined custom white balance   4 years 7 months ago

Yes, I totally understand its not supported in the current release, but it would nonetheless be very helpful to me if you could provide some understanding of how your code works in this area.

You are correct CM2 means nothing to me at all.

   \libraw\libraw.h(104):  DllDef float libraw_get_pre_mul(libraw_data_t *lr, int index);
  \libraw\libraw_types.h(481):    float pre_mul[4];
  \internal\var_defines.h(61):#define pre_mul         (imgdata.color.pre_mul)
  \internal\dcraw_common.cpp(413):    pre_mul[i - 1] = 1 / (frac * mul[hi][i] + (1 - frac) * mul[lo][i]);
  \internal\dcraw_common.cpp(510):      pre_mul[i] = 1.0 / (total[st][i] + total[st][i + 4]);
  \internal\dcraw_common.cpp(525):  mc = pre_mul[1] / pre_mul[2];
  \internal\dcraw_common.cpp(526):  yc = pre_mul[3] / pre_mul[2];
  \internal\dcraw_common.cpp(4847):      pre_mul[i] = 1 / num;
  \internal\dcraw_common.cpp(4853):      pre_mul[i] = 1.0;
  \internal\dcraw_common.cpp(4925):    FORCC balance[geshifilter-c] = pre_mul[c] * gmb_cam[20][c];
  \internal\dcraw_common.cpp(5016):      mul[row] = 0.125 * pre_mul[FC(row + 1, 0) | 1] / pre_mul[FC(row, 0) | 1];
  \internal\dcraw_common.cpp(5131):      mul[row] = 0.125 * pre_mul[FC(row + 1, 0) | 1] / pre_mul[FC(row, 0) | 1];
  \internal\dcraw_common.cpp(5236):    memcpy(pre_mul, user_mul, sizeof pre_mul);
  \internal\dcraw_common.cpp(5269):    FORC4 if (dsum[c]) pre_mul[c] = dsum[c + 4] / dsum[c];
  \internal\dcraw_common.cpp(5286):      pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1.0;
  \internal\dcraw_common.cpp(5291):      FORC4 pre_mul[c] = (float)sum[c + 4] / sum[c];
  \internal\dcraw_common.cpp(5293):      memcpy(pre_mul, cam_mul, sizeof pre_mul);
  \internal\dcraw_common.cpp(5310):      pre_mul[c] /= cam_mul[c];
  \internal\dcraw_common.cpp(5313):  if (pre_mul[1] == 0)
  \internal\dcraw_common.cpp(5314):    pre_mul[1] = 1;
  \internal\dcraw_common.cpp(5315):  if (pre_mul[3] == 0)
  \internal\dcraw_common.cpp(5316):    pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
  \internal\dcraw_common.cpp(5324):    if (dmin > pre_mul[c])
  \internal\dcraw_common.cpp(5325):      dmin = pre_mul[c];
  \internal\dcraw_common.cpp(5326):    if (dmax < pre_mul[c])
  \internal\dcraw_common.cpp(5327):      dmax = pre_mul[c];
  \internal\dcraw_common.cpp(5331):  FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
  \internal\dcraw_common.cpp(5336):    FORC4 fprintf(stderr, " %f", pre_mul[c]);
  \internal\dcraw_common.cpp(6601):  FORCC if (clip > (i = 65535 * pre_mul[c])) clip = i;
  \internal\dcraw_common.cpp(6645):  FORCC hsat[c] = 32000 * pre_mul[c];
  \internal\dcraw_common.cpp(6647):    if (pre_mul[kc] < pre_mul[c])
  \internal\dcraw_common.cpp(14075):    FORCC if(fabs(cc[c][c])>0.0001) pre_mul[c] /= cc[c][c];
  \internal\dcraw_common.cpp(17758):    pre_mul[i] = i < 3;
  \internal\dcraw_common.cpp(18601):    pre_mul[0] = 1.2085;
  \internal\dcraw_common.cpp(18602):    pre_mul[1] = 1.0943;
  \internal\dcraw_common.cpp(18603):    pre_mul[3] = 1.1103;
  \internal\dcraw_common.cpp(18618):      pre_mul[0] = 1.196;
  \internal\dcraw_common.cpp(18619):      pre_mul[1] = 1.246;
  \internal\dcraw_common.cpp(18620):      pre_mul[2] = 1.018;
  \internal\dcraw_common.cpp(19341):      pre_mul[1] = 1.179;
  \internal\dcraw_common.cpp(19342):      pre_mul[2] = 1.209;
  \internal\dcraw_common.cpp(19343):      pre_mul[3] = 1.036;
  \src\libraw_c_api.cpp(387):  DllDef float libraw_get_pre_mul(libraw_data_t *lr, int index)
  \src\libraw_c_api.cpp(391):    return lr->color.pre_mul[LIM(index, 0, 3)];
  \src\libraw_cxx.cpp(1222):    imgdata.color.pre_mul[i] = 1.0;
  \src\libraw_cxx.cpp(2110):          imgdata.color.pre_mul[c] /= (delta[c] / maxdelta);
  \src\libraw_cxx.cpp(2148):      imgdata.color.pre_mul[0] = 1.f / 0.3984f;
  \src\libraw_cxx.cpp(2149):      imgdata.color.pre_mul[2] = 1.f / 0.7666f;
  \src\libraw_cxx.cpp(2150):      imgdata.color.pre_mul[1] = imgdata.color.pre_mul[3] = 1.0;
  \src\libraw_cxx.cpp(4048):      if (dmax > C.pre_mul[c])
  \src\libraw_cxx.cpp(4049):        dmax = C.pre_mul[c];
  \src\libraw_cxx.cpp(4052):      scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
  Matching lines: 52    Matching files: 6    Total files searched: 16


in none of those places does there appear to be any derivation of the pre_mul value from the WB Coefficients, even though it is clear that such a derivation must take place.[/geshifilter-c]

Reply to: User defined custom white balance   4 years 7 months ago

Dear Sir:

> Why are you not providing me with a helpful explanation of what is happening here
> a helpful explanation

The camera is not supported in the version you are using, right? So, what do you expect to be helpful? I'm at loss, since "CM2" obviously means very little to you.

> where in the LibRaw code the pre_mul value is set from the White Balance Coefficients

What does search for pre_mul return?

Reply to: User defined custom white balance   4 years 7 months ago

I have to say that I don't understand your approach to my enquiry. Why are you not providing me with a helpful explanation of what is happening here, rather than just pointing me to the source code and say "go figure it out yourself". I have to question the point of having a LibRaw support forum here if the people who know the code won't explain why something isn't working in the way that someone trying to use it expected.

I was already aware of the annotated DCRaw web-site and have been there a number of times. On this occasion however I am still completely in the dark as to quite where in the LibRaw code the pre_mul value is set from the White Balance Coefficients, and very specifically I don't understand quite why pre_mul was set to values of 1.0 for the unsupported X-T3, but was set to useful values for the X-T1.

I don't want to add support for the camera in question to libraw in the current release. I realise that it will very likely be supported in the 0.20.? release as I believe it is already supported in the snapshots.

Reply to: User defined custom white balance   4 years 7 months ago

Dear Sir:

The camera is not supported in the LibRaw version you are using, that's why the derived pre-muls for daylight are not available. If you want to support it instead of waiting for the next release, you need to spend some time familiarizing yourself with the code. The link I've provided above should be very helpful.

Reply to: User defined custom white balance   4 years 7 months ago

Iliah, please will you bear with me. I've just spent a whole day chasing this problem.

I *still* don't understand why pre_mul was set to 1.0, 1.0, 1.0 for the Fuji X-T3, but was set to relevant values based on the D65 Illimunant White Balance values for the X-T1.

I had already searched the code looking for everywhere that pre_mul[] values are set and for the life of me I couldn't find the code that converts the WB_Coeffs to the pre_mul values. OK you may think I am stupid, but please I'm looking for assistance here, not a pointer the annotated DCRaw code.

Reply to: User defined custom white balance   4 years 7 months ago

I tried to find the code that sets pre_mull from the d65 coefficients and totally failed. Where is it please?

Reply to: User defined custom white balance   4 years 7 months ago

Dear Sir:
Criticism is welcome, that's how we improve.
"Uncalled for" also means "unnecessary" and "unfair". Everything was right in front of you, please pay attention.
I'm not going to continue this discussion, let's stick to questions and answers that are relevant.

Reply to: User defined custom white balance   4 years 7 months ago

Why is that uncalled for? Given that those multipliers are clearly used to set the default pre_mul, that seemed like a sensible suggestion to me. There was no criticism.

David

Reply to: User defined custom white balance   4 years 7 months ago

Dear Sir:

"Notice the last line above"

You can either use the numbers from "Makernotes 'D65' WB multipliers: 665 302 406 302" line which is also above; or you may want to familiarize yourself with the procedure that results in calculation of "Derived D65 multipliers" and insert a CM2 into your copy of LibRaw.

"the code could attempt to default to calculating the D65 co-efficients instead of setting them to 1.0." is uncalled for.

Reply to: User defined custom white balance   4 years 7 months ago

OK I now understand what's happening:

>raw-identify -v "DSCF3954(X-Trans).RAF"

Filename: DSCF3954(X-Trans).RAF
Timestamp: Sat Oct 6 15:56:45 2018
Camera: Fujifilm X-T3 ID: 0x0
Body serial: 8CQ04794
Owner:
:
: stuff deleted
:
Filter pattern: GGGGBRGGGGRBGGGG
Makernotes 'As shot' WB multipliers: 563.000000 302.000000 531.000000 0.000000
Makernotes 'Tungsten' WB multipliers: 367 302 818 302
Makernotes 'Fine Weather' WB multipliers: 546 302 539 302
Makernotes 'Shade' WB multipliers: 595 302 462 302
Makernotes 'Daylight Fluorescent D' WB multipliers: 701 302 471 302
Makernotes 'Cool White Fluorescent W' WB multipliers: 571 302 736 302
Makernotes 'Warm White Fluorescent L' WB multipliers: 596 302 585 302
Makernotes 'Illuminant A' WB multipliers: 367 302 818 302
Makernotes 'D65' WB multipliers: 623 302 476 302
Makernotes 'Camera Auto' WB multipliers: 563 302 531 302
Camera2RGB matrix:
1.0000 0.0000 0.0000
0.0000 1.0000 0.0000
0.0000 0.0000 1.0000

XYZ->CamRGB matrix:
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000
0.0000 0.0000 0.0000

Derived D65 multipliers: 1.000000 1.000000 1.000000

Notice the last line above ...

I know that 0.19.3 doesn't officially support the X-T3, but I think the code could attempt to default to calculating the D65 co-efficients instead of setting them to 1.0.

I am happy that it is working as I expected with a raw file from an X-T1!

>raw-identify -v _DSF3925.RAF

Filename: _DSF3925.RAF
Timestamp: Wed Mar 15 20:56:39 2017
Camera: Fujifilm X-T1 ID: 0x0

: Stuff deleted.

Makernotes 'As shot' WB multipliers: 581.000000 302.000000 468.000000 0.000000
Makernotes 'Tungsten' WB multipliers: 389 302 686 302
Makernotes 'Fine Weather' WB multipliers: 581 302 468 302
Makernotes 'Shade' WB multipliers: 642 302 401 302
Makernotes 'Daylight Fluorescent D' WB multipliers: 735 302 410 302
Makernotes 'Cool White Fluorescent W' WB multipliers: 598 302 619 302
Makernotes 'Warm White Fluorescent L' WB multipliers: 622 302 485 302
Makernotes 'Illuminant A' WB multipliers: 389 302 686 302
Makernotes 'D65' WB multipliers: 665 302 406 302
Makernotes 'Camera Auto' WB multipliers: 590 302 468 302
Camera2RGB matrix:
1.6442 -0.5539 -0.0904
-0.1896 1.6455 -0.4559
0.0505 -0.5409 1.4904

XYZ->CamRGB matrix:
0.8458 -0.2451 -0.0855
-0.4597 1.2447 0.2407
-0.1475 0.2482 0.6526

Derived D65 multipliers: 2.147247 0.934710 1.221633

Sorry if this has been a bother.
David

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

Short answer:
- you need to subtract black level values from (unaltered) RAW values
- than multiply to normalized per-channel WB coefficients.

Long(er) answer: use subtract_black(), scale_colors() and pre_inteprolate() functions code as a reference, these functions are called before interpolation (demosaic) call to perform data ajustments before debayering.

Reply to: User defined custom white balance   4 years 7 months ago

They not only look identical, they are identical:

D:\Users\amonra\Documents\Astrophotography\DSS Test Images>dcraw_emu -v -v -r 1.0 1.0 1.0 1.0 "DSCF3954(X-Trans).RAF"
Processing file DSCF3954(X-Trans).RAF
Reading metadata finished
Starting Reading RAW data (expecting 2 iterations)
Reading RAW data finished
Starting Scaling colors (expecting 2 iterations)
Scaling colors finished
Starting Pre-interpolating (expecting 2 iterations)
Pre-interpolating finished
Starting Converting to RGB (expecting 2 iterations)
Converting to RGB finished
Writing file DSCF3954(X-Trans).RAF.ppm

D:\Users\amonra\Documents\Astrophotography\DSS Test Images>rename "DSCF3954(X-Trans).RAF.ppm" "DSCF3954(X-Trans).RAF.NoWB.ppm"

D:\Users\amonra\Documents\Astrophotography\DSS Test Images>dcraw_emu -v -v "DSCF3954(X-Trans).RAF"
Processing file DSCF3954(X-Trans).RAF
Reading metadata finished
Starting Reading RAW data (expecting 2 iterations)
Reading RAW data finished
Starting Scaling colors (expecting 2 iterations)
Scaling colors finished
Starting Pre-interpolating (expecting 2 iterations)
Pre-interpolating finished
Starting Converting to RGB (expecting 2 iterations)
Converting to RGB finished
Writing file DSCF3954(X-Trans).RAF.ppm

D:\Users\amonra\Documents\Astrophotography\DSS Test Images>fc "DSCF3954(X-Trans).RAF.NoWB.ppm" "DSCF3954(X-Trans).RAF.ppm"
Comparing files DSCF3954(X-Trans).RAF.NoWB.ppm and DSCF3954(X-TRANS).RAF.PPM
FC: no differences encountered

D:\Users\amonra\Documents\Astrophotography\DSS Test Images>

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

Thanks Alex,

I can now decode images from Canon DSLRs that only show the active area. My test code now looks like this:

m_raw_proc->open_buffer(data, size);
m_raw_proc->unpack();
 
int pos = 0;
int top_margin = m_raw_proc->imgdata.sizes.top_margin;
int left_margin = m_raw_proc->imgdata.sizes.left_margin;
int raw_pitch = m_raw_proc->imgdata.sizes.raw_pitch / 2;
 
for (int r = 0; r < m_raw_proc->imgdata.sizes.height; r++)
{
	for (int c = 0; c < m_raw_proc->imgdata.sizes.width; c++)
	{
		buffer[pos] = m_raw_proc->imgdata.rawdata.raw_image[(r + top_margin) * raw_pitch + left_margin + c];
		pos++;
	}
}

After this code has run, I have undebayered data in buffer[]. This works very well but I have no idea how to apply the in-camera white balance. I would be grateful if you would be able to explain how I apply a white balance or direct me to a resource that explains this. Indeed, is this even possible without using the dcraw functions?

Once again, I thank you for your continued help.

Amanda

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

Theoretical part:
1) Many (not all) digital cameras have 'masked' (opaque) pixel areas (or black frame), so image area is less than full sensor area. These black pixels may be used for black level calibration, banding suppression, etc (the area that may be used is specific for camera model, so we do not discuss it now).

2) imgdata.rawdata.raw_image[] array contains full sensor area decoded from RAW files. It need to be cropped on processing to exclude black frame.
There are several variables in imgdata.sizes that describes sensor area:
- raw_width, raw_height - full sensor size.
- raw_pitch - row pitch (in bytes! so divide it by 2 for raw_image, by 6 for color3_image) in rawdata.* pointers. Usually raw_pitch is just raw_width *2, but this not always so (eg. if file decoded via DNG SDK).
- top_margin, left_maring - pixel coordinates for top-left image visible area
- width, height - size of visible area (there is some special case for Fuji Super-CCD sensors used on very old cameras; let's drop it).

So, there are two ways to use:

A. Continue to use imgdata.rawdata.raw_image array w/o copying it into imgdata.image.
You'll need to change your all-pixel loops to something like (i'll skip some imgdata.sizes prefixes to shorten statements...)
// srow - source row, drow - dest row, same for col

for(srow = imgdata.sizes.top_margin, drow=0; srow <= top_margin + height; srow++, drow++)
for(scol = imgdata.sizes.left_margin, dcol=0; scol <= left_margin+width....
buffer[srow * width + scol] = imgdata.rawdata.raw_image[drow*raw_pitch/2 + dcol];

B. Use LibRaw::raw2image() call:
This call will allocate imdata.image[..][4] array with 4-components per pixel.
After this call, 3 out of 4 components are zero, and only image[row*width+col][COLOR(row,col)] is not.

If you perform debayering in your own code, raw2image may be not optimal choice because of extra memory use. You may consider de-bayering in place (directly in imgdata.image[][4] array) to save memory.

Feel free to ask if you need additional explanations

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

Further to my original post.

My code works for Nikon DSLR cameras via imgdata.rawdata (albeit the images seem to be under-exposed) but images from Canon DSLRs are showing bad data near the top of each image. I've been reading various forum posts and it seems that I need to call raw2image() in order to get data that only contains visible (active pixels) pixels but I am struggling to get unbayered data.

It is my understanding that after calling raw2image() and without calling dcraw_process() I should have an undebayered dataset in imgdata.image[][] which only contains visible pixels, is that correct?

What I need to do is to copy data from imgdata.image[][] to a one dimensional 16-bit integer array (size is width * height) that gets saved as a FITS or a TIFF file which can then be debayered later by my post-processing application.

Here is a code example of what I am currently doing:

if ((ret = m_raw_proc->open_buffer(data, size)) != 0)
{
     // Handle error
}
 
if ((ret = m_raw_proc->unpack() != 0))
{
    // Handle error
}
 
if ((ret = m_raw_proc->raw2image()) != 0)
{
    // Handle error
}
 
m_width = m_raw_proc->imgdata.sizes.iwidth;
m_height = m_raw_proc->imgdata.sizes.iheight;
 
for (int n = 0; n < m_width * m_height; n++)
{
	buffer[n] = m_raw_proc->imgdata.image[n][0];
}

However, when I try to debayer the image in an external application, the code above is heavily bias to a specific primary colour. How do I correctly access the undebayered data from imgdata.image[][]?

Thanks
Amanda

Reply to: LibRaw / C++ Undebayered Buffer   4 years 7 months ago

Thanks Alex,

I now have my application working perfectly.

Amanda

Pages