libopenraw  0.3.7
ordiag.cpp
1 /*
2  * libopenraw - ordiag.cpp
3  *
4  * Copyright (C) 2007-2020 Hubert Figuière
5  * Copyright (C) 2008 Novell, Inc.
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 
23 #include <unistd.h>
24 
25 #include <algorithm>
26 #include <iostream>
27 #include <memory>
28 #include <set>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/format.hpp>
33 #include <boost/lexical_cast.hpp>
34 
35 #include <libopenraw/libopenraw.h>
36 
37 #include "dumputils.hpp"
38 
46 class OrDiag
47 {
48 public:
55  OrDiag(std::ostream & out, const std::string & extract_thumbs, bool dev_mode)
56  : m_out(out)
57  , m_extract_all_thumbs(false)
58  , m_dev_mode(dev_mode)
59  {
60  m_extract_all_thumbs = (extract_thumbs == "all");
61  if (!m_extract_all_thumbs) {
62  try {
63  int size = boost::lexical_cast<int>(extract_thumbs);
64  m_thumb_sizes.insert(size);
65  }
66  catch(...) {
67 
68  }
69  }
70  }
71 
72  std::string cfaPatternToString(ORMosaicInfoRef pattern)
73  {
74  if(pattern == NULL) {
75  return "(null)";
76  }
77 
78  std::string out;
79  uint16_t size = 0;
80  const uint8_t* patternPattern
81  = or_mosaicinfo_get_pattern(pattern, &size);
82 
83  for(uint16_t i = 0; i < size; ++i) {
84  switch(patternPattern[i]) {
86  out.push_back('R');
87  break;
89  out.push_back('G');
90  break;
91 
92  case OR_PATTERN_COLOUR_BLUE:
93  out.push_back('B');
94  break;
95 
96  default:
97  out.push_back('*');
98  break;
99  }
100  }
101 
102  return out;
103  }
104  std::string cfaPatternToString(::or_cfa_pattern t)
105  {
106  switch(t) {
107  case OR_CFA_PATTERN_NONE:
108  return "None";
109  break;
111  return "Non RGB 2x2";
112  break;
113  case OR_CFA_PATTERN_RGGB:
114  return "R,G,G,B";
115  break;
116  case OR_CFA_PATTERN_GBRG:
117  return "G,B,R,G";
118  break;
119  case OR_CFA_PATTERN_BGGR:
120  return "B,G,G,R";
121  break;
122  case OR_CFA_PATTERN_GRBG:
123  return "G,R,B,G";
124  break;
125  default:
126  break;
127  }
128  return str(boost::format("Unknown %1%") % t);
129  };
130 
131  std::string dataTypeToString(or_data_type t)
132  {
133  switch(t) {
134  case OR_DATA_TYPE_NONE:
135  return "None";
136  break;
138  return "8bits per channel RGB pixmap";
139  break;
140  case OR_DATA_TYPE_JPEG:
141  return "JPEG data";
142  break;
143  case OR_DATA_TYPE_TIFF:
144  return "TIFF container";
145  break;
146  case OR_DATA_TYPE_PNG:
147  return "PNG container";
148  break;
149  case OR_DATA_TYPE_RAW:
150  return "RAW data";
151  break;
153  return "Compressed RAW data";
154  break;
155  case OR_DATA_TYPE_UNKNOWN:
156  return "Unknown type";
157  break;
158  default:
159  break;
160  }
161  return "Invalid";
162  }
163 
167  std::string extractThumb(ORThumbnailRef thumb)
168  {
169  FILE* f;
170  size_t s;
171  std::string ext;
172  switch(or_thumbnail_format(thumb)) {
174  ext = "ppm";
175  break;
176  case OR_DATA_TYPE_JPEG:
177  ext = "jpg";
178  break;
179  default:
180  break;
181  }
182  if (ext.empty()) {
183  return "";
184  }
185 
186  uint32_t x, y;
187  or_thumbnail_dimensions(thumb, &x, &y);
188  uint32_t dim = std::max(x, y);
189  std::string name(str(boost::format("thumb_%1%.%2%") % dim % ext));
190  f = fopen(name.c_str(), "wb");
192  // ppm preemble.
193  fprintf(f, "P6\n");
194  fprintf(f, "%d %d\n", x, y);
195  fprintf(f, "%d\n", /*(componentsize == 2) ? 0xffff :*/ 0xff);
196  }
197  size_t dataSize = or_thumbnail_data_size(thumb);
198  s = fwrite(or_thumbnail_data(thumb), 1, dataSize, f);
199  if(s != dataSize) {
200  std::cerr << "short write of " << s << " bytes\n";
201  }
202  fclose(f);
203 
204  return name;
205  }
206 
210  {
211  size_t size = 0;
212  const uint32_t * previews = or_rawfile_get_thumbnail_sizes(rf, &size);
213  m_out << boost::format("\tNumber of previews: %1%\n")
214  % size;
215 
216  m_out << "\tAvailable previews:\n";
217  for(size_t i = 0; i < size; i++) {
218 
219  m_out << boost::format("\t\tSize %1%\n") % previews[i];
220 
222  ::or_error err = or_rawfile_get_thumbnail(rf, previews[i], thumb);
223  if (err != OR_ERROR_NONE) {
224  m_out << boost::format("\t\t\tError getting thumbnail %1%\n") % err;
225  }
226  else {
227  m_out << boost::format("\t\t\tFormat %1%\n")
228  % dataTypeToString(or_thumbnail_format(thumb));
229  uint32_t x, y;
230  or_thumbnail_dimensions(thumb, &x, &y);
231  m_out << boost::format("\t\t\tDimensions: width = %1% height = %2%\n")
232  % x % y;
233  m_out << boost::format("\t\t\tByte size: %1%\n")
234  % or_thumbnail_data_size(thumb);
235  }
236  if (m_extract_all_thumbs
237  || m_thumb_sizes.find(previews[i]) != m_thumb_sizes.end()) {
238 
239  std::string name = extractThumb(thumb);
240 
241  m_out << boost::format("\t\t\tOutput as %1%\n") % name;
242  }
243  or_thumbnail_release(thumb);
244  }
245  }
246 
247  void dumpRawData(ORRawFileRef rf)
248  {
250  ::or_error err = or_rawfile_get_rawdata(rf, rd, 0);
251  if (err == OR_ERROR_NONE) {
252  m_out << "\tRAW data\n";
253  or_data_type dataType = or_rawdata_format(rd);
254  m_out << boost::format("\t\tType: %1%")
255  % dataTypeToString(dataType);
256  if(dataType == OR_DATA_TYPE_COMPRESSED_RAW) {
257  m_out << boost::format(" (compression = %1%)\n")
259  }
260  else {
261  m_out << "\n";
262  }
263  m_out << boost::format("\t\tByte size: %1%\n")
264  % or_rawdata_data_size(rd);
265  uint32_t x, y;
266  or_rawdata_dimensions(rd, &x, &y);
267  m_out << boost::format("\t\tDimensions: width = %1% height = %2%\n")
268  % x % y;
269 
270  // Active Area
271  uint32_t aa_x, aa_y, aa_width, aa_height;
272  or_rawdata_get_active_area(rd, &aa_x, &aa_y,
273  &aa_width, &aa_height);
274  m_out <<
275  boost::format("\t\tActive Area (x,y,w,h): %1% %2% %3% %4%\n")
276  % aa_x % aa_y % aa_width % aa_height;
277 
278  // CFA
280  ::or_cfa_pattern patternType
281  = pattern ? or_mosaicinfo_get_type(pattern)
283  m_out << boost::format("\t\tBayer Type: %1%\n")
284  % cfaPatternToString(patternType);
285 
286  if(patternType == OR_CFA_PATTERN_NON_RGB22) {
287  m_out << boost::format("\t\tPattern: %1%\n")
288  % cfaPatternToString(pattern);
289  }
290 
291  m_out << boost::format("\t\tBits per channel: %1%\n")
292  % or_rawdata_bpc(rd);
293  uint16_t black, white;
294  or_rawdata_get_levels(rd, &black, &white);
295  m_out << boost::format(
296  "\t\tValues: black = %1% white = %2%\n") % black % white;
297 
298  uint32_t matrix_size = 0;
299  const double *matrix = or_rawdata_get_colour_matrix(rd, 1, &matrix_size);
300  if (matrix) {
301  m_out << boost::format("\t\tColour Matrix 1: ");
302  for (uint32_t i = 0; i < matrix_size; i++) {
303  if (i > 0) {
304  m_out << ", ";
305  }
306  m_out << matrix[i];
307  }
308  m_out << "\n";
309  }
310  }
311  else {
312  m_out << boost::format("\tNo Raw Data found! (error = %1%)\n")
313  % err;
314  }
315  or_rawdata_release(rd);
316  }
317  void dumpMetaData(ORRawFileRef rf)
318  {
319  int32_t o = or_rawfile_get_orientation(rf);
320  m_out << "\tMeta data\n";
321  m_out << "\t\tMakerNotes\n";
322 
323  auto mnote = or_rawfile_get_ifd(rf, OR_IFD_MNOTE);
324  if (!mnote) {
325  m_out << "\t\t\tNo MakerNote found!\n";
326  } else {
327  const char* makernote_id = or_ifd_get_makernote_id(mnote);
328  m_out << boost::format("\t\t\tType = %1%\n")
329  % (makernote_id ? makernote_id : "(null)");
330  auto num_entries = or_ifd_count_tags(mnote);
331  m_out << boost::format("\t\t\tNum entries = %1%\n")
332  % num_entries;
333  or_ifd_release(mnote);
334  mnote = nullptr;
335  }
336  m_out << boost::format("\t\tOrientation: %1%\n")
337  % o;
338  double matrix[9];
339  uint32_t size = 9;
340 
341 
342  auto origin = or_rawfile_get_colour_matrix_origin(rf);
343  std::string os;
344  switch (origin) {
346  os = "Built-in";
347  break;
349  os = "Provided";
350  break;
351  default:
352  os = "Unknown";
353  }
354  m_out << boost::format("\t\tColour Matrix Origin: %1%\n")
355  % os;
356 
357  ExifLightsourceValue calIll;
359  m_out << boost::format("\t\tCalibration Illuminant 1: %1%\n")
360  % static_cast<int>(calIll);
361 
362  ::or_error err = or_rawfile_get_colourmatrix1(rf, matrix, &size);
363  if(err == OR_ERROR_NONE) {
364  if (m_dev_mode) {
365  std::vector<int64_t> int_matrix;
366  std::transform(&matrix[0], &matrix[9], std::back_inserter(int_matrix),
367  [](double v) -> int64_t { return rintl(v * 10000.0); });
368  m_out << boost::format("\t\tColour Matrix 1: %1%, %2%, %3%, "
369  "%4%, %5%, %6%, %7%, %8%, %9%\n")
370  % int_matrix[0] % int_matrix[1] % int_matrix[2]
371  % int_matrix[3] % int_matrix[4] % int_matrix[5]
372  % int_matrix[6] % int_matrix[7] % int_matrix[8];
373  } else {
374  m_out << boost::format("\t\tColour Matrix 1: %1%, %2%, %3%, "
375  "%4%, %5%, %6%, %7%, %8%, %9%\n")
376  % matrix[0] % matrix[1] % matrix[2]
377  % matrix[3] % matrix[4] % matrix[5]
378  % matrix[6] % matrix[7] % matrix[8];
379  }
380  }
381  else {
382  m_out << "\t\tNo Colour Matrix 1\n";
383  }
384 
386  m_out << boost::format("\t\tCalibration Illuminant 2: %1%\n")
387  % static_cast<int>(calIll);
388 
389  size = 9;
390  err = or_rawfile_get_colourmatrix2(rf, matrix, &size);
391  if(err == OR_ERROR_NONE) {
392  if (m_dev_mode) {
393  std::vector<int64_t> int_matrix;
394  std::transform(&matrix[0], &matrix[9], std::back_inserter(int_matrix),
395  [](double v) -> int64_t { return rintl(v * 10000.0); });
396  m_out << boost::format("\t\tColour Matrix 2: %1%, %2%, %3%, "
397  "%4%, %5%, %6%, %7%, %8%, %9%\n")
398  % int_matrix[0] % int_matrix[1] % int_matrix[2]
399  % int_matrix[3] % int_matrix[4] % int_matrix[5]
400  % int_matrix[6] % int_matrix[7] % int_matrix[8];
401 
402  } else {
403  m_out << boost::format("\t\tColour Matrix 2: %1%, %2%, %3%, "
404  "%4%, %5%, %6%, %7%, %8%, %9%\n")
405  % matrix[0] % matrix[1] % matrix[2]
406  % matrix[3] % matrix[4] % matrix[5]
407  % matrix[6] % matrix[7] % matrix[8];
408  }
409  }
410  else {
411  m_out << "\t\tNo Colour Matrix 2\n";
412  }
413  }
414  void operator()(const std::string &s)
415  {
416  m_out << boost::format("Dumping %1%\n") % s;
417 
419 
420  //std::unique_ptr<RawFile> rf(RawFile::newRawFile(s.c_str()));
421 
422  if (rf == NULL) {
423  m_out << "unrecognized file\n";
424  }
425  else {
426  dump_file_info(m_out, rf, m_dev_mode);
427 
428  dumpPreviews(rf);
429  dumpRawData(rf);
430  dumpMetaData(rf);
431  }
432  or_rawfile_release(rf);
433  }
434 private:
435  std::ostream & m_out;
436  bool m_extract_all_thumbs;
437  bool m_dev_mode;
438  std::set<int> m_thumb_sizes;
439 };
440 
441 
442 void print_help()
443 {
444  std::cerr << "ordiag [-v] [-h] [-t all|<size>] [-d 0-9] [files...]\n";
445  std::cerr << "Print libopenraw diagnostics\n";
446  std::cerr << "\t-h: show this help\n";
447  std::cerr << "\t-D: developer mode: display some data a format suited for development\n";
448  std::cerr << "\t-v: show version\n";
449  std::cerr << "\t-d level: set debug / verbosity to level\n";
450  std::cerr << "\t-t [all|<size>]: extract thumbnails. all or <size>.\n";
451  std::cerr << "\tfiles: the files to diagnose\n";
452 }
453 
454 void print_version()
455 {
456  std::cerr << "ordiag version 0.1 - (c) 2007-2014 Hubert Figuiere\n";
457 }
458 
459 
460 
461 int main(int argc, char **argv)
462 {
463  int done = 0;
464  int dbl = 0;
465  bool dev_mode = false;
466  std::string extract_thumbs;
467  std::vector<std::string> files;
468 
469  int o;
470  while((o = getopt(argc, argv, "hvdDt:")) != -1) {
471  switch (o) {
472  case 'h':
473  print_help();
474  done = 1;
475  break;
476  case 'v':
477  print_version();
478  done = 1;
479  break;
480  case 'D':
481  dev_mode = true;
482  break;
483  case 'd':
484  dbl++;
485  break;
486  case 't':
487  if(optarg) {
488  extract_thumbs = optarg;
489  }
490  else {
491  print_help();
492  done = 1;
493  }
494  break;
495  case '?':
496  break;
497  default:
498  break;
499  }
500  }
501  if (done) {
502  return 1;
503  }
504  for ( ; optind < argc; optind++) {
505  files.push_back(argv[optind]);
506  }
507 
508  if (files.empty()) {
509  std::cerr << "missing file name.\n";
510  if (dbl) {
511  print_version();
512  }
513  print_help();
514  return 1;
515  }
516 
517  if (dbl >=2) {
518  or_debug_set_level(DEBUG2);
519  }
520  // do the business.
521  for_each(files.begin(), files.end(), OrDiag(std::cout, extract_thumbs, dev_mode));
522 
523  return 0;
524 }
525 
527 /*
528  Local Variables:
529  mode:c++
530  c-file-style:"stroustrup"
531  c-file-offsets:((innamespace . 0))
532  indent-tabs-mode:nil
533  fill-column:80
534  End:
535 */
Dump a RawFile. (functor)
Definition: ordiag.cpp:47
std::string extractThumb(ORThumbnailRef thumb)
Extract thumbnail to a file.
Definition: ordiag.cpp:167
OrDiag(std::ostream &out, const std::string &extract_thumbs, bool dev_mode)
Constructor.
Definition: ordiag.cpp:55
void dumpPreviews(ORRawFileRef rf)
Dump the previews of the raw file to the output stream.
Definition: ordiag.cpp:209
API_EXPORT or_cfa_pattern or_mosaicinfo_get_type(ORMosaicInfoRef pattern)
Get the type of the mosaic.
Definition: mosaicinfo.cpp:30
const struct _MosaicInfo * ORMosaicInfoRef
A MosaicInfo object.
Definition: mosaicinfo.h:40
API_EXPORT const uint8_t * or_mosaicinfo_get_pattern(ORMosaicInfoRef pattern, uint16_t *count)
Get the pattern.
Definition: mosaicinfo.cpp:36
struct _RawData * ORRawDataRef
RawData reference.
Definition: types.h:31
or_cfa_pattern
CFA pattern types.
Definition: consts.h:94
API_EXPORT void or_debug_set_level(debug_level lvl)
Set the debug level.
Definition: debug.cpp:32
struct _RawFile * ORRawFileRef
RawFile reference.
Definition: types.h:30
or_data_type
Data types.
Definition: consts.h:80
struct _Thumbnail * ORThumbnailRef
Thumbnail reference.
Definition: types.h:33
or_error
Error codes returned by libopenraw.
Definition: consts.h:42
@ OR_CFA_PATTERN_NON_RGB22
Definition: consts.h:96
@ OR_CFA_PATTERN_NONE
Definition: consts.h:95
@ OR_DATA_TYPE_TIFF
Definition: consts.h:85
@ OR_DATA_TYPE_PNG
Definition: consts.h:86
@ OR_DATA_TYPE_JPEG
Definition: consts.h:84
@ OR_DATA_TYPE_COMPRESSED_RAW
Definition: consts.h:88
@ OR_DATA_TYPE_RAW
Definition: consts.h:87
@ OR_DATA_TYPE_PIXMAP_8RGB
Definition: consts.h:82
@ OR_IFD_MNOTE
MakerNote.
Definition: consts.h:148
@ OR_PATTERN_COLOUR_RED
Definition: consts.h:106
@ OR_PATTERN_COLOUR_GREEN
Definition: consts.h:107
@ OR_RAWFILE_TYPE_UNKNOWN
Definition: consts.h:60
@ OR_COLOUR_MATRIX_BUILTIN
Definition: consts.h:123
@ OR_COLOUR_MATRIX_PROVIDED
Definition: consts.h:124
@ OR_ERROR_NONE
Definition: consts.h:43
API_EXPORT ORIfdDirRef or_rawfile_get_ifd(ORRawFileRef rawfile, or_ifd_dir_type ifd)
Get an IFD directory.
Definition: rawfile.cpp:222
API_EXPORT or_error or_rawfile_release(ORRawFileRef rawfile)
Release the RawFile.
Definition: rawfile.cpp:81
API_EXPORT or_colour_matrix_origin or_rawfile_get_colour_matrix_origin(ORRawFileRef rawfile)
Get the colour matrix origin for file.
Definition: rawfile.cpp:206
API_EXPORT ExifLightsourceValue or_rawfile_get_calibration_illuminant2(ORRawFileRef rawfile)
Get calibration illuminant for the second colour matrix.
Definition: rawfile.cpp:198
API_EXPORT ORRawFileRef or_rawfile_new(const char *filename, or_rawfile_type type)
Create a new RawFile object from a file.
Definition: rawfile.cpp:64
API_EXPORT or_error or_rawfile_get_colourmatrix2(ORRawFileRef rawfile, double *matrix, uint32_t *size)
Get the second colour matrix.
Definition: rawfile.cpp:180
API_EXPORT or_error or_rawfile_get_colourmatrix1(ORRawFileRef rawfile, double *matrix, uint32_t *size)
Get the first colour matrix.
Definition: rawfile.cpp:170
API_EXPORT const uint32_t * or_rawfile_get_thumbnail_sizes(ORRawFileRef rawfile, size_t *size)
Get the the array of thumbnail sizes.
Definition: rawfile.cpp:113
API_EXPORT or_error or_rawfile_get_thumbnail(ORRawFileRef rawfile, uint32_t _preferred_size, ORThumbnailRef thumb)
Get a thumbnail from a RawFile..
Definition: rawfile.cpp:131
API_EXPORT int32_t or_rawfile_get_orientation(ORRawFileRef rawfile)
Get the orientation.
Definition: rawfile.cpp:162
API_EXPORT or_error or_rawfile_get_rawdata(ORRawFileRef rawfile, ORRawDataRef rawdata, uint32_t options)
Get the RawData out of the RawFile.
Definition: rawfile.cpp:142
API_EXPORT ExifLightsourceValue or_rawfile_get_calibration_illuminant1(ORRawFileRef rawfile)
Get calibration illuminant for the first colour matrix.
Definition: rawfile.cpp:190
API_EXPORT void or_rawdata_dimensions(ORRawDataRef rawdata, uint32_t *width, uint32_t *height)
Get the RAW data dimensions in pixels.
Definition: rawdata.cpp:97
API_EXPORT ORRawDataRef or_rawdata_new(void)
Allocate a new RawData.
Definition: rawdata.cpp:62
API_EXPORT const double * or_rawdata_get_colour_matrix(ORRawDataRef rawdata, uint32_t index, uint32_t *size)
Get the colour matrix.
Definition: rawdata.cpp:168
API_EXPORT or_error or_rawdata_get_levels(ORRawDataRef rawdata, uint16_t *black, uint16_t *white)
Return the levels values for the raw data.
Definition: rawdata.cpp:154
API_EXPORT uint32_t or_rawdata_bpc(ORRawDataRef rawdata)
Return the bits per component.
Definition: rawdata.cpp:130
API_EXPORT or_error or_rawdata_get_active_area(ORRawDataRef rawdata, uint32_t *x, uint32_t *y, uint32_t *width, uint32_t *height)
Get the active area for the raw data.
Definition: rawdata.cpp:110
API_EXPORT size_t or_rawdata_data_size(ORRawDataRef rawdata)
Get the size of the RAW data in bytes.
Definition: rawdata.cpp:91
API_EXPORT uint32_t or_rawdata_get_compression(ORRawDataRef rawdata)
Return the compression type for the RawData.
Definition: rawdata.cpp:148
API_EXPORT ORMosaicInfoRef or_rawdata_get_mosaicinfo(ORRawDataRef rawdata)
Return the mosaic info.
Definition: rawdata.cpp:142
API_EXPORT or_data_type or_rawdata_format(ORRawDataRef rawdata)
Get the format of the RAW data.
Definition: rawdata.cpp:79
API_EXPORT or_error or_rawdata_release(ORRawDataRef rawdata)
Release the rawdata.
Definition: rawdata.cpp:69
API_EXPORT ORThumbnailRef or_thumbnail_new(void)
Allocate a Thumbnail object.
Definition: capi.cpp:53
API_EXPORT size_t or_thumbnail_data_size(ORThumbnailRef thumb)
Get the data size.
Definition: capi.cpp:82
API_EXPORT void or_thumbnail_dimensions(ORThumbnailRef thumb, uint32_t *width, uint32_t *height)
Get the Thumbnail dimensions in pixels.
Definition: capi.cpp:88
API_EXPORT or_data_type or_thumbnail_format(ORThumbnailRef thumb)
Get the thumbnail format.
Definition: capi.cpp:70
API_EXPORT void * or_thumbnail_data(ORThumbnailRef thumb)
Get the pointer to the data.
Definition: capi.cpp:76
API_EXPORT or_error or_thumbnail_release(ORThumbnailRef thumb)
Release a Thumbnail object.
Definition: capi.cpp:60
void dump_file_info(std::ostream &out, ORRawFileRef rf, bool dev_mode)
Dump raw file info.
Definition: dumputils.cpp:84