Skip to content

Commit de51ee6

Browse files
authored
fix(raw): fix channel layout (AcademySoftwareFoundation#4516)
The function libraw_filter_to_str() converts the `imgdata.idata.filters` field to human readable form, by mapping a few hardcoded values. I found the issue by converting images with disabled demosaicing, which writes the Bayer pattern into the ImageBuf metadata. The Panasonic GX9 didn't have any pattern recognised; The Canon R5 was incorrectly recognised as GMCY. The `imgdata.idata.filters` actually contains a sequence of 2-bit values, where each represents an index in a 4-character long string `imgdata.idata.cdesc`. I have modified the code to extract the channels from `imgdata.idata.cdesc` as expected. I have also disabled the normalisation code, which I believe was incorrect, and never executed due to the issue above. The current tests pass, however, I'll start a discussion on the piece of code I have concerns with. --------- Signed-off-by: Anton Dukhovnikov <[email protected]>
1 parent 2f0caf7 commit de51ee6

File tree

1 file changed

+16
-33
lines changed

1 file changed

+16
-33
lines changed

src/raw.imageio/rawinput.cpp

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -245,28 +245,16 @@ OIIO_EXPORT const char* raw_input_extensions[]
245245
OIIO_PLUGIN_EXPORTS_END
246246

247247
namespace {
248-
const char*
249-
libraw_filter_to_str(unsigned int filters)
248+
std::string
249+
libraw_filter_to_str(unsigned int filters, const char* cdesc)
250250
{
251-
// Convert the libraw filter pattern description
252-
// into a slightly more human readable string
253-
// LibRaw/internal/defines.h:166
254-
switch (filters) {
255-
// CYGM
256-
case 0xe1e4e1e4: return "GMYC";
257-
case 0x1b4e4b1e: return "CYGM";
258-
case 0x1e4b4e1b: return "YCGM";
259-
case 0xb4b4b4b4: return "GMCY";
260-
case 0x1e4e1e4e: return "CYMG";
261-
262-
// RGB
263-
case 0x16161616: return "BGRG";
264-
case 0x61616161: return "GRGB";
265-
case 0x49494949: return "GBGR";
266-
case 0x94949494: return "RGBG";
267-
default: break;
251+
char result[5] = { 0, 0, 0, 0, 0 };
252+
for (size_t i = 0; i < 4; i++) {
253+
size_t index = filters & 3; // Grab the last 2 bits
254+
result[i] = cdesc[index];
255+
filters >>= 2;
268256
}
269-
return "";
257+
return result;
270258
}
271259
} // namespace
272260

@@ -490,22 +478,16 @@ RawInput::open_raw(bool unpack, const std::string& name,
490478
if (config.get_int_attribute("raw:use_camera_wb", 1) == 1) {
491479
auto& color = m_processor->imgdata.color;
492480
auto& params = m_processor->imgdata.params;
493-
auto& idata = m_processor->imgdata.idata;
494481

495-
auto is_rgbg_or_bgrg = [&](unsigned int filters) {
496-
std::string filter(libraw_filter_to_str(filters));
497-
return filter == "RGBG" || filter == "BGRG";
498-
};
499482
float norm[4] = { color.cam_mul[0], color.cam_mul[1], color.cam_mul[2],
500483
color.cam_mul[3] };
501484

502-
if (is_rgbg_or_bgrg(idata.filters)) {
503-
// normalize white balance around green
504-
norm[0] /= norm[1];
505-
norm[1] /= norm[1];
506-
norm[2] /= norm[3] > 0 ? norm[3] : norm[1];
507-
norm[3] /= norm[3] > 0 ? norm[3] : norm[1];
508-
}
485+
// // normalize white balance around green
486+
// norm[0] /= norm[1];
487+
// norm[2] /= norm[3] > 0 ? norm[3] : norm[1];
488+
// norm[3] /= norm[3] > 0 ? norm[3] : norm[1];
489+
// norm[1] /= norm[1];
490+
509491
params.user_mul[0] = norm[0];
510492
params.user_mul[1] = norm[1];
511493
params.user_mul[2] = norm[2];
@@ -676,7 +658,8 @@ RawInput::open_raw(bool unpack, const std::string& name,
676658

677659
// Put the details about the filter pattern into the metadata
678660
std::string filter(
679-
libraw_filter_to_str(m_processor->imgdata.idata.filters));
661+
libraw_filter_to_str(m_processor->imgdata.idata.filters,
662+
m_processor->imgdata.idata.cdesc));
680663
if (filter.empty()) {
681664
filter = "unknown";
682665
}

0 commit comments

Comments
 (0)