Support of monochromatic DNG in LibRAW

Hello,

First of all, thanks for your great work.

I have an issue with reading monochromatic DNG image. The result is pretty weird. I can't figure out if there are problems with the source DNG image itself, or with LibRaw. Maybe I'm using it wrong, but usually DNG images are loaded pretty well. But not this one.

In the attachement there is comparison image just to take a quick look at the problem.

I'm using LibRaw 0.17.3, but I've tried latest LibRaw 0.20 beta, with the same results.

My LibRaw-related code (slightly simplified):

  1. LibRaw rawProcessor;
  2. int errCode = 0;
  3. errCode = rawProcessor.open_file(fileName.toUtf8().data());
  4.  
  5. if (errCode != LIBRAW_SUCCESS) {
  6. setLastError(QString("Can not open raw image: %1").arg(QString(libraw_strerror(errCode))));
  7. return nullptr;
  8. }
  9.  
  10. rawProcessor.imgdata.params.use_camera_wb = applyWhiteBalance;
  11. rawProcessor.imgdata.params.use_auto_wb = 0;
  12. rawProcessor.imgdata.params.no_auto_bright = 1;
  13. rawProcessor.imgdata.params.no_interpolation = 0;
  14. rawProcessor.imgdata.params.use_camera_matrix = applyColorMatrix;
  15. rawProcessor.imgdata.params.output_color = 0; // Raw
  16. rawProcessor.imgdata.params.output_bps = 16; // 16 bits per sample
  17. rawProcessor.imgdata.params.user_qual = 12; // AHD interpolation
  18.  
  19. if ((errCode = rawProcessor.unpack()) != LIBRAW_SUCCESS) {
  20. setLastError(QString("Can not unpack raw image: %1").arg(QString(libraw_strerror(errCode))));
  21. return nullptr;
  22. }
  23.  
  24. errCode = rawProcessor.dcraw_process();
  25.  
  26. if (errCode != LIBRAW_SUCCESS) {
  27. qDebug() << "LibRaw dcraw error:" << libraw_strerror(errCode);
  28. if (LIBRAW_FATAL_ERROR(errCode)) {
  29. setLastError(QString("Can not process raw image: %1").arg(QString(libraw_strerror(errCode))));
  30. return nullptr;
  31. }
  32. }
  33.  
  34. libraw_processed_image_t *rawImage = rawProcessor.dcraw_make_mem_image(&errCode);
  35.  
  36. if (!rawImage) {
  37. setLastError(QString("Can not unpack raw image: %1").arg(QString(libraw_strerror(errCode))));
  38. return nullptr;
  39. }
  40.  
  41. if (rawImage->type != LIBRAW_IMAGE_BITMAP) {
  42. setLastError("LibRaw unpacked image into JPEG instead of bitmap, this is not supported yet.");
  43. LibRaw::dcraw_clear_mem(rawImage);
  44. return nullptr;
  45. }
  46.  
  47. if (rawImage->bits == 8) {
  48. // ... No sense for this case ...
  49. } else { // rawImage->bits == 16
  50. RgbBufferFloat *realBuf = new RgbBufferFloat(QSize(rawImage->width, rawImage->height));
  51. if (realBuf->data() == nullptr) {
  52. setLastError("Out of memory");
  53. return nullptr;
  54. }
  55. float *imgPtr = realBuf->data();
  56. unsigned short *rawPtr = reinterpret_cast<unsigned short *>(rawImage->data);
  57. for (unsigned i = 0; i < rawImage->data_size; i += 2) {
  58. *(imgPtr++) = *(rawPtr++) / 65535.0f; // Convert into floating point values normalized to 0..1
  59. }
  60. return realBuf;
  61. }

Forums: 

Thank you for the sample and

Thank you for the sample and for detailed explanation.
Tested with current LibRaw 0.20(beta):
dcraw_emu produces correct pgm file
dcraw_emu -T makes correct tiff file.
So, LibRaw::dcraw_process() and all previous steps are OK.

mem_image_sample.c fails to produce correct results, the problem not in LibRaw::dcraw_make_mem_image() (it is also correct, see below), but in sample source code:

1) write_ppm() do not handle img->colors != 3 case and just returns. This is expected, but need to be fixed.

2) write_jpeg() do not check for colors count, but assumes that 3-color data passed that is wrong.
Quick fixes:
A. replace
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
with
cinfo.in_color_space = img->colors==3?JCS_RGB:JCS_GRAYSCALE; /* colorspace of input image */

B. replace:
row_stride = img->width * 3; /* JSAMPLEs per row in image_buffer */
with:
row_stride = img->width * img->colors; /* JSAMPLEs per row in image_buffer */

Fixed version will be uploaded to github soon (likely tomorrow, we want to fix write_ppm sample code too).

Here are processing results (pgm file from dcraw_emu and .jpg from fixed mem_image_sample): https://www.dropbox.com/sh/a6aksx5opyzeeyv/AACG3f9GCZ703UksKjc5H5Rta?dl=0

-- Alex Tutubalin

Thanks for your fast reply.

Thanks for your fast reply.

I've found what I'm doing wrong. I always assume that resulting image is 3-channel when copying it into my internal RGB buffer for further processing, but this one is obviously 1-channel. Very stupid and obvious error, and I've found it in half of an hour after submitting my first post. Now I check value of rawImage->colors and for 1-channel images I copy value of first channel into the other two. I'll do some performance tests, maybe your solution with setting proper color space will be faster.

Interesting that digiKam gives similar triple-image result when processing my file. digiKam uses LibRaw for the processing of DNG files, and it's behaviour led my thoughts wrong way. Possibly I should report an issue into digiKam bugtracker.

Anyway, thanks again! The problem is solved. Should I somehow close this forum thread?

Exactly same problem present

Exactly same problem present in our mem_image_sample: channel count assumed to be also 3 :)

We usually do not close threads (unless lot of spam come to specific thread).

-- Alex Tutubalin