"Fossies" - the Fresh Open Source Software Archive

Member "rawtherapee-5.7/rtexif/stdattribs.cc" (10 Sep 2019, 41072 Bytes) of package /linux/misc/rawtherapee-5.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stdattribs.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.6_vs_5.7.

    1 /*
    2  *  This file is part of RawTherapee.
    3  *
    4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
    5  *  Copyright (c)      2010 Oliver Duis <www.oliverduis.de>
    6  *
    7  *  RawTherapee is free software: you can redistribute it and/or modify
    8  *  it under the terms of the GNU General Public License as published by
    9  *  the Free Software Foundation, either version 3 of the License, or
   10  *  (at your option) any later version.
   11  *
   12  *  RawTherapee 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
   15  *  GNU General Public License for more details.
   16  *
   17  *  You should have received a copy of the GNU General Public License
   18  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
   19  */
   20 #ifndef _STDATTRIBS_
   21 #define _STDATTRIBS_
   22 
   23 #include <cstdio>
   24 #include <cstring>
   25 
   26 #include "rtexif.h"
   27 
   28 namespace rtexif
   29 {
   30 
   31 class ColorSpaceInterpreter : public ChoiceInterpreter<>
   32 {
   33 
   34 public:
   35     ColorSpaceInterpreter ()
   36     {
   37         choices[1]      = "sRGB";
   38         choices[2]      = "Adobe RGB";
   39         choices[0xffff] = "Uncalibrated";
   40     }
   41 };
   42 ColorSpaceInterpreter colorSpaceInterpreter;
   43 
   44 class PreviewColorSpaceInterpreter : public ChoiceInterpreter<>
   45 {
   46 
   47 public:
   48     PreviewColorSpaceInterpreter ()
   49     {
   50         choices[0] = "Unknown";
   51         choices[1] = "Gray Gamma 2.2";
   52         choices[2] = "sRGB";
   53         choices[3] = "Adobe RGB";
   54         choices[4] = "ProPhoto RGB";
   55     }
   56 };
   57 PreviewColorSpaceInterpreter previewColorSpaceInterpreter;
   58 
   59 class LinearSRGBInterpreter : public ChoiceInterpreter<>
   60 {
   61 
   62 public:
   63     LinearSRGBInterpreter ()
   64     {
   65         choices[0] = "Linear";
   66         choices[1] = "sRGB";
   67     }
   68 };
   69 LinearSRGBInterpreter linearSRGBInterpreter;
   70 
   71 class DefaultBlackRenderInterpreter : public ChoiceInterpreter<>
   72 {
   73 
   74 public:
   75     DefaultBlackRenderInterpreter ()
   76     {
   77         choices[0] = "Auto";
   78         choices[1] = "None";
   79     }
   80 };
   81 DefaultBlackRenderInterpreter defaultBlackRenderInterpreter;
   82 
   83 class ExposureProgramInterpreter : public ChoiceInterpreter<>
   84 {
   85 
   86 public:
   87     ExposureProgramInterpreter ()
   88     {
   89         choices[0] = "Not defined";
   90         choices[1] = "Manual";
   91         choices[2] = "Normal program";
   92         choices[3] = "Aperture priority";
   93         choices[4] = "Shutter priority";
   94         choices[5] = "Creative program";
   95         choices[6] = "Action program";
   96         choices[7] = "Portrait mode";
   97         choices[8] = "Landscape mode";
   98     }
   99 };
  100 ExposureProgramInterpreter exposureProgramInterpreter;
  101 
  102 class MeteringModeInterpreter : public ChoiceInterpreter<>
  103 {
  104 
  105 public:
  106     MeteringModeInterpreter ()
  107     {
  108         choices[0] = "Unknown";
  109         choices[1] = "Average";
  110         choices[2] = "Center weighted";
  111         choices[3] = "Spot";
  112         choices[4] = "Multispot";
  113         choices[5] = "Pattern";
  114         choices[6] = "Partial";
  115         choices[255] = "Other";
  116     }
  117 };
  118 MeteringModeInterpreter meteringModeInterpreter;
  119 
  120 class ExposureModeInterpreter : public ChoiceInterpreter<>
  121 {
  122 
  123 public:
  124     ExposureModeInterpreter ()
  125     {
  126         choices[0] = "Auto exposure";
  127         choices[1] = "Manual exposure";
  128         choices[2] = "Auto bracket";
  129     }
  130 };
  131 ExposureModeInterpreter exposureModeInterpreter;
  132 
  133 class WhiteBalanceInterpreter : public ChoiceInterpreter<>
  134 {
  135 
  136 public:
  137     WhiteBalanceInterpreter ()
  138     {
  139         choices[0] = "Auto white balance";
  140         choices[1] = "Manual white balance";
  141     }
  142 };
  143 WhiteBalanceInterpreter whiteBalanceInterpreter;
  144 
  145 class SceneCaptureInterpreter : public ChoiceInterpreter<>
  146 {
  147 
  148 public:
  149     SceneCaptureInterpreter ()
  150     {
  151         choices[0] = "Standard";
  152         choices[1] = "Landscape";
  153         choices[2] = "Portrait";
  154         choices[3] = "Night scene";
  155     }
  156 };
  157 SceneCaptureInterpreter sceneCaptureInterpreter;
  158 
  159 class GainControlInterpreter : public ChoiceInterpreter<>
  160 {
  161 
  162 public:
  163     GainControlInterpreter ()
  164     {
  165         choices[0] = "None";
  166         choices[1] = "Low gain up";
  167         choices[2] = "High gain up";
  168         choices[3] = "Low gain down";
  169         choices[4] = "High gain down";
  170     }
  171 };
  172 GainControlInterpreter gainControlInterpreter;
  173 
  174 class ContrastInterpreter : public ChoiceInterpreter<>
  175 {
  176 
  177 public:
  178     ContrastInterpreter ()
  179     {
  180         choices[0] = "Normal";
  181         choices[1] = "Soft";
  182         choices[2] = "Hard";
  183     }
  184 };
  185 ContrastInterpreter contrastInterpreter;
  186 
  187 class SharpnessInterpreter : public ChoiceInterpreter<>
  188 {
  189 
  190 public:
  191     SharpnessInterpreter ()
  192     {
  193         choices[0] = "Normal";
  194         choices[1] = "Soft";
  195         choices[2] = "Hard";
  196     }
  197 };
  198 SharpnessInterpreter sharpnessInterpreter;
  199 
  200 class SaturationInterpreter : public ChoiceInterpreter<>
  201 {
  202 
  203 public:
  204     SaturationInterpreter ()
  205     {
  206         choices[0] = "Normal";
  207         choices[1] = "Low saturation";
  208         choices[2] = "High saturation";
  209     }
  210 };
  211 SaturationInterpreter saturationInterpreter;
  212 
  213 class FlashInterpreter : public ChoiceInterpreter<>
  214 {
  215 
  216 public:
  217     FlashInterpreter ()
  218     {
  219         choices[0x0000] = "Flash did not fire";
  220         choices[0x0001] = "Flash fired";
  221         choices[0x0005] = "Strobe return light not detected";
  222         choices[0x0007] = "Strobe return light detected";
  223         choices[0x0009] = "Flash fired, compulsory flash mode";
  224         choices[0x000D] = "Flash fired, compulsory flash mode, return light not detected";
  225         choices[0x000F] = "Flash fired, compulsory flash mode, return light detected";
  226         choices[0x0010] = "Flash did not fire, compulsory flash mode";
  227         choices[0x0018] = "Flash did not fire, auto mode";
  228         choices[0x0019] = "Flash fired, auto mode";
  229         choices[0x001D] = "Flash fired, auto mode, return light not detected";
  230         choices[0x001F] = "Flash fired, auto mode, return light detected";
  231         choices[0x0020] = "No flash function";
  232         choices[0x0041] = "Flash fired, red-eye reduction mode";
  233         choices[0x0045] = "Flash fired, red-eye reduction mode, return light not detected";
  234         choices[0x0047] = "Flash fired, red-eye reduction mode, return light detected";
  235         choices[0x0049] = "Flash fired, compulsory flash mode, red-eye reduction mode";
  236         choices[0x004D] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
  237         choices[0x004F] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
  238         choices[0x0059] = "Flash fired, auto mode, red-eye reduction mode";
  239         choices[0x005D] = "Flash fired, auto mode, return light not detected, red-eye reduction mode";
  240         choices[0x005F] = "Flash fired, auto mode, return light detected, red-eye reduction mode";
  241     }
  242 };
  243 FlashInterpreter flashInterpreter;
  244 
  245 class LightSourceInterpreter : public ChoiceInterpreter<>
  246 {
  247 
  248 public:
  249     LightSourceInterpreter ()
  250     {
  251         choices[0] = "Unknown";
  252         choices[1] = "Daylight";
  253         choices[2] = "Fluorescent";
  254         choices[3] = "Tungsten";
  255         choices[4] = "Flash";
  256         choices[9] = "Fine weather";
  257         choices[10] = "Cloudy weather";
  258         choices[11] = "Shade";
  259         choices[12] = "Daylight fluorescent";
  260         choices[13] = "Day white fluorescent";
  261         choices[14] = "Cool white fluorescent";
  262         choices[15] = "White fluorescent";
  263         choices[17] = "Standard light A";
  264         choices[18] = "Standard light B";
  265         choices[19] = "Standard light C";
  266         choices[20] = "D55";
  267         choices[21] = "D65";
  268         choices[22] = "D75";
  269         choices[23] = "D50";
  270         choices[24] = "ISO studio tungsten";
  271         choices[255] = "Other light source";
  272     }
  273 };
  274 LightSourceInterpreter lightSourceInterpreter;
  275 
  276 class CompressionInterpreter : public ChoiceInterpreter<>
  277 {
  278 
  279 public:
  280     CompressionInterpreter ()
  281     {
  282         choices[1] = "Uncompressed";
  283         choices[6] = "JPEG Compression";
  284     }
  285 };
  286 CompressionInterpreter compressionInterpreter;
  287 
  288 class PhotometricInterpreter : public ChoiceInterpreter<>
  289 {
  290 
  291 public:
  292     PhotometricInterpreter ()
  293     {
  294         choices[2] = "RGB";
  295         choices[6] = "YCbCr";
  296     }
  297 };
  298 PhotometricInterpreter photometricInterpreter;
  299 
  300 class ProfileEmbedPolicyInterpreter : public ChoiceInterpreter<>
  301 {
  302 
  303 public:
  304     ProfileEmbedPolicyInterpreter ()
  305     {
  306         choices[0] = "Allow Copying";
  307         choices[1] = "Embed if Used";
  308         choices[2] = "Never Embed";
  309         choices[3] = "No Restrictions";
  310     }
  311 };
  312 ProfileEmbedPolicyInterpreter profileEmbedPolicyInterpreter;
  313 
  314 class PlanarConfigInterpreter : public ChoiceInterpreter<>
  315 {
  316 
  317 public:
  318     PlanarConfigInterpreter ()
  319     {
  320         choices[1] = "Chunky format";
  321         choices[2] = "Planar format";
  322     }
  323 };
  324 PlanarConfigInterpreter planarConfigInterpreter;
  325 
  326 class FNumberInterpreter : public Interpreter
  327 {
  328 public:
  329     FNumberInterpreter () {}
  330     std::string toString (const Tag* t) const override
  331     {
  332         char buffer[32];
  333         double v = t->toDouble();
  334 
  335         if ( v < 0. || v > 1000. ) {
  336             return "undef";
  337         }
  338 
  339         sprintf (buffer, "%0.1f", v);
  340         return buffer;
  341     }
  342 };
  343 FNumberInterpreter fNumberInterpreter;
  344 
  345 class ApertureInterpreter : public Interpreter
  346 {
  347 public:
  348     ApertureInterpreter () {}
  349     std::string toString (const Tag* t) const override
  350     {
  351         char buffer[32];
  352         double v = pow (2.0, t->toDouble() / 2.0);
  353 
  354         if ( v < 0. || v > 1000. ) {
  355             return "undef";
  356         }
  357 
  358         sprintf (buffer, "%.1f", v );
  359         return buffer;
  360     }
  361 };
  362 ApertureInterpreter apertureInterpreter;
  363 
  364 class ExposureBiasInterpreter : public Interpreter
  365 {
  366 public:
  367     ExposureBiasInterpreter () {}
  368     std::string toString (const Tag* t) const override
  369     {
  370         char buffer[32];
  371         double v = t->toDouble();
  372 
  373         if ( v < -1000. || v > 1000. ) {
  374             return "undef";
  375         }
  376 
  377         sprintf (buffer, "%+0.2f", v );
  378         return buffer;
  379     }
  380 };
  381 ExposureBiasInterpreter exposureBiasInterpreter;
  382 
  383 class ShutterSpeedInterpreter : public Interpreter
  384 {
  385 public:
  386     ShutterSpeedInterpreter () {}
  387     std::string toString (const Tag* t) const override
  388     {
  389         char buffer[32];
  390         double d = pow (2.0, -t->toDouble());
  391 
  392         if (d > 0.0 && d <= 0.5) {
  393             sprintf (buffer, "1/%.0f", 1.0 / d);
  394         } else {
  395             sprintf (buffer, "%.1f", d);
  396         }
  397 
  398         return buffer;
  399     }
  400 };
  401 ShutterSpeedInterpreter shutterSpeedInterpreter;
  402 
  403 class ExposureTimeInterpreter : public Interpreter
  404 {
  405 public:
  406     ExposureTimeInterpreter () {}
  407     std::string toString (const Tag* t) const override
  408     {
  409         char buffer[32];
  410         double d = t->toDouble();
  411 
  412         if (d > 0.0 && d <= 0.5) {
  413             sprintf (buffer, "1/%.0f", 1.0 / d);
  414         } else {
  415             sprintf (buffer, "%.1f", d);
  416         }
  417 
  418         return buffer;
  419     }
  420 };
  421 ExposureTimeInterpreter exposureTimeInterpreter;
  422 
  423 class FocalLengthInterpreter : public Interpreter
  424 {
  425 public:
  426     FocalLengthInterpreter () {}
  427     std::string toString (const Tag* t) const override
  428     {
  429         char buffer[32];
  430         double v = t->toDouble();
  431 
  432         if ( v > 1000000. || v < 0 ) {
  433             return "undef";
  434         }
  435 
  436         sprintf (buffer, "%.1f", v );
  437         return buffer;
  438     }
  439 };
  440 FocalLengthInterpreter focalLengthInterpreter;
  441 
  442 class UserCommentInterpreter : public Interpreter
  443 {
  444 public:
  445     UserCommentInterpreter () {}
  446     std::string toString (const Tag* t) const override
  447     {
  448         int count = t->getCount();
  449 
  450         if (count <= 8) {
  451             return std::string();
  452         }
  453 
  454         count = std::min (count, 65535); // limit to 65535 chars to avoid crashes in case of corrupted metadata
  455         unsigned char *buffer = new unsigned char[count - 6]; // include 2 ending null chars for UCS-2 string (possibly)
  456         unsigned char *value = t->getValue();
  457 
  458         if (!memcmp(value, "ASCII\0\0\0", 8)) {
  459             memcpy(buffer, value + 8, count - 8);
  460             buffer[count - 8] = '\0';
  461         } else if (!memcmp(value, "UNICODE\0", 8)) {
  462             memcpy(buffer, value + 8, count - 8);
  463             buffer[count - 7] = buffer[count - 8] = '\0';
  464             Glib::ustring tmp1((char*)buffer);
  465 
  466 
  467             bool hasBOM = false;
  468             enum ByteOrder bo = UNKNOWN;
  469             if (count % 2 || (count >= 11 && (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF))) {
  470                 // odd string length can only be UTF-8, don't change anything
  471                 std::string retVal ((char*)buffer + 3);
  472                 delete [] buffer;
  473                 return retVal;
  474             } else if (count >= 10) {
  475                 if (buffer[0] == 0xFF && buffer[1] == 0xFE) {
  476                     bo = INTEL; // little endian
  477                     hasBOM = true;
  478                 } else if (buffer[0] == 0xFE && buffer[1] == 0xFF) {
  479                     bo = MOTOROLA; // big endian
  480                     hasBOM = true;
  481                 }
  482             }
  483             if (bo == UNKNOWN) {
  484                 // auto-detecting byte order; we still don't know if it's UCS-2 or UTF-8
  485                 int a = 0, b = 0, c = 0, d = 0;
  486                 for (int j = 8; j < count; j++) {
  487                     unsigned char cc = value[j];
  488                     if (!(j%2)) {
  489                         // counting zeros for first byte
  490                         if (!cc) {
  491                             ++a;
  492                         }
  493                     } else {
  494                         // counting zeros for second byte
  495                         if (!cc) {
  496                             ++b;
  497                         }
  498                     }
  499                     if (!(cc & 0x80) || ((cc & 0xC0) == 0xC0) || ((cc & 0xC0) == 0x80)) {
  500                         ++c;
  501                     }
  502                     if ((cc & 0xC0) == 0x80) {
  503                         ++d;
  504                     }
  505                 }
  506                 if (c == (count - 8) && d) {
  507                     // this is an UTF-8 string
  508                     std::string retVal ((char*)buffer);
  509                     delete [] buffer;
  510                     return retVal;
  511                 }
  512                 if ((a || b) && a != b) {
  513                     bo = a > b ? MOTOROLA : INTEL;
  514                 }
  515             }
  516             if (bo == UNKNOWN) {
  517                 // assuming platform's byte order
  518 #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
  519                 bo = INTEL;
  520 #else
  521                 bo = MOTOROLA;
  522 #endif
  523             }
  524 
  525             // now swapping if necessary
  526             if (!hasBOM && bo != HOSTORDER) {
  527                 if (t->getOrder() != HOSTORDER) {
  528                     Tag::swapByteOrder2(buffer, count - 8);
  529                 }
  530             }
  531 
  532             glong written;
  533             char* utf8Str = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, &written, nullptr);
  534             delete [] buffer;
  535             buffer = new unsigned char[written + 1];
  536             memcpy(buffer, utf8Str, written);
  537             buffer[written] = 0;
  538             g_free(utf8Str);
  539         } else if (!memcmp(value, "\0\0\0\0\0\0\0\0", 8)) {
  540             // local charset string, whatever it is
  541             memcpy(buffer, value + 8, count - 8);
  542             buffer[count - 7] = buffer[count - 8] = '\0';
  543 
  544             gsize written = 0;
  545             char *utf8Str = g_locale_to_utf8((char*)buffer, count - 8, nullptr, &written, nullptr);
  546             if (utf8Str && written) {
  547                 delete [] buffer;
  548                 size_t length = strlen(utf8Str);
  549                 buffer = new unsigned char[length + 1];
  550                 strcpy((char*)buffer, utf8Str);
  551             } else {
  552                 buffer[0] = 0;
  553             }
  554             if (utf8Str) {
  555                 g_free(utf8Str);
  556             }
  557         } else {
  558             // JIS: unsupported
  559             buffer[0] = 0;
  560         }
  561 
  562         std::string retVal ((char*)buffer);
  563         delete [] buffer;
  564         return retVal;
  565     }
  566     void fromString (Tag* t, const std::string& value) override
  567     {
  568         Glib::ustring tmpStr(value);
  569         t->userCommentFromString (tmpStr);
  570     }
  571 };
  572 UserCommentInterpreter userCommentInterpreter;
  573 
  574 class CFAInterpreter : public Interpreter
  575 {
  576 public:
  577     CFAInterpreter() {}
  578     std::string toString (const Tag* t) const override
  579     {
  580         char colors[] = "RGB";
  581         char buffer[1024];
  582 
  583         for ( int i = 0; i < t->getCount(); i++) {
  584             unsigned char c = t->toInt (i, BYTE);
  585             buffer[i] = c < 3 ? colors[c] : ' ';
  586         }
  587 
  588         buffer[t->getCount()] = 0;
  589         return buffer;
  590     }
  591 };
  592 CFAInterpreter cfaInterpreter;
  593 
  594 class OrientationInterpreter : public ChoiceInterpreter<>
  595 {
  596 public:
  597     OrientationInterpreter ()
  598     {
  599         choices[1] = "Horizontal (normal)";
  600         choices[2] = "Mirror horizontal ";
  601         choices[3] = "Rotate 180";
  602         choices[4] = "Mirror vertical";
  603         choices[5] = "Mirror horizontal and rotate 270 CW";
  604         choices[6] = "Rotate 90 CW";
  605         choices[7] = "Mirror horizontal and rotate 90 CW";
  606         choices[8] = "Rotate 270 CW";
  607         // '9' is an "unofficial" value for Orientation but used by some older cameras that lacks orientation sensor, such as Kodak DCS
  608         choices[9] = "Unknown";
  609     }
  610 };
  611 OrientationInterpreter orientationInterpreter;
  612 
  613 class UnitsInterpreter : public ChoiceInterpreter<>
  614 {
  615 public:
  616     UnitsInterpreter()
  617     {
  618         choices[0] = "Unknown";
  619         choices[1] = "inches";
  620         choices[2] = "cm";
  621     }
  622 };
  623 UnitsInterpreter unitsInterpreter;
  624 
  625 class UTF8BinInterpreter : public Interpreter
  626 {
  627 public:
  628     UTF8BinInterpreter () {}
  629 };
  630 UTF8BinInterpreter utf8BinInterpreter;
  631 
  632 class RawImageSegmentationInterpreter : public Interpreter
  633 {
  634 public:
  635     std::string toString (const Tag* t) const override
  636     {
  637         int segmentNumber = t->toInt(0, SHORT);
  638         int segmentWidth = t->toInt(2, SHORT);
  639         int lastSegmentWidth = t->toInt(4, SHORT);
  640 
  641         char buffer[32];
  642         sprintf (buffer, "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth);
  643         return buffer;
  644     }
  645 };
  646 RawImageSegmentationInterpreter rawImageSegmentationInterpreter;
  647 
  648 const TagAttrib exifAttribs[] = {
  649     {0, AC_SYSTEM,    0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter},
  650     {0, AC_SYSTEM,    0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter},
  651     {0, AC_SYSTEM,    0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter},
  652     {0, AC_SYSTEM,    0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter},
  653     {0, AC_SYSTEM,    0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter},
  654     {0, AC_WRITE,     0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter},
  655     {0, AC_WRITE,     0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter},
  656     {0, AC_WRITE,     0, nullptr, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter},
  657     {0, AC_WRITE,     0, nullptr, 0x829D, AUTO, "FNumber", &fNumberInterpreter},
  658     {0, AC_WRITE,     0, nullptr, 0x8822, AUTO, "ExposureProgram", &exposureProgramInterpreter},
  659     {0, AC_WRITE,     0, nullptr, 0x8824, AUTO, "SpectralSensitivity", &stdInterpreter},
  660     {0, AC_WRITE,     0, nullptr, 0x8827, AUTO, "ISOSpeedRatings", &stdInterpreter},
  661     {0, AC_WRITE,     0, nullptr, 0x8828, AUTO, "OECF", &stdInterpreter},
  662     {0, AC_WRITE,     0, nullptr, 0x8832, AUTO, "RecommendedExposureIndex", &stdInterpreter},
  663     {0, AC_WRITE,     0, nullptr, 0x9000, AUTO, "ExifVersion", &stdInterpreter},
  664     {0, AC_WRITE,     0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter},
  665     {0, AC_WRITE,     0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},
  666     {0, AC_SYSTEM,    0, nullptr, 0x9101, AUTO, "ComponentsConfiguration", &stdInterpreter},
  667     {0, AC_SYSTEM,    0, nullptr, 0x9102, AUTO, "CompressedBitsPerPixel", &stdInterpreter},
  668     {0, AC_WRITE,     0, nullptr, 0x9201, AUTO, "ShutterSpeedValue", &shutterSpeedInterpreter},
  669     {0, AC_WRITE,     0, nullptr, 0x9202, AUTO, "ApertureValue", &apertureInterpreter},
  670     {0, AC_WRITE,     0, nullptr, 0x9203, AUTO, "BrightnessValue", &stdInterpreter},
  671     {0, AC_WRITE,     0, nullptr, 0x9204, AUTO, "ExposureBiasValue", &exposureBiasInterpreter},
  672     {0, AC_WRITE,     0, nullptr, 0x9205, AUTO, "MaxApertureValue", &apertureInterpreter},
  673     {0, AC_WRITE,     0, nullptr, 0x9206, AUTO, "SubjectDistance", &stdInterpreter},
  674     {0, AC_WRITE,     0, nullptr, 0x9207, AUTO, "MeteringMode", &meteringModeInterpreter},
  675     {0, AC_WRITE,     0, nullptr, 0x9208, AUTO, "LightSource", &lightSourceInterpreter},
  676     {0, AC_WRITE,     0, nullptr, 0x9209, AUTO, "Flash", &flashInterpreter},
  677     {0, AC_WRITE,     0, nullptr, 0x920A, AUTO, "FocalLength", &focalLengthInterpreter},
  678     {0, AC_WRITE,     0, nullptr, 0x9214, AUTO, "SubjectArea", &stdInterpreter},
  679     {0, AC_WRITE,     0, nullptr, 0x9215, AUTO, "ExposureIndex", &stdInterpreter}, // Note: exists as 0xA215 too, it should be that way
  680     {0, AC_DONTWRITE, 0, nullptr, 0x9216, AUTO, "TIFFEPSStandardID", &stdInterpreter},
  681     {0, AC_WRITE,     0, nullptr, 0x9217, AUTO, "SensingMethod", &stdInterpreter},
  682     {0, AC_WRITE,     0, nullptr, 0x927C, AUTO, "MakerNote", &stdInterpreter},
  683     {0, AC_WRITE,     1, nullptr, 0x9286, AUTO, "UserComment", &userCommentInterpreter},
  684     {0, AC_WRITE,     0, nullptr, 0x9290, AUTO, "SubSecTime", &stdInterpreter},
  685     {0, AC_WRITE,     0, nullptr, 0x9291, AUTO, "SubSecTimeOriginal", &stdInterpreter},
  686     {0, AC_WRITE,     0, nullptr, 0x9292, AUTO, "SubSecTimeDigitized", &stdInterpreter},
  687     {0, AC_SYSTEM,    0, nullptr, 0xA000, AUTO, "FlashpixVersion", &stdInterpreter},
  688     {0, AC_DONTWRITE, 0, nullptr, 0xA001, AUTO, "ColorSpace", &colorSpaceInterpreter},
  689     {0, AC_SYSTEM,    0, nullptr, 0xA002, AUTO, "PixelXDimension", &stdInterpreter},
  690     {0, AC_SYSTEM,    0, nullptr, 0xA003, AUTO, "PixelYDimension", &stdInterpreter},
  691     {1, AC_DONTWRITE, 0, nullptr, 0xA004, AUTO, "RelatedSoundFile", &stdInterpreter},
  692     {0, AC_SYSTEM,    0, iopAttribs,  0xA005, AUTO, "Interoperability", &stdInterpreter},  // do not enable, as it causes trouble with FUJI files
  693     {0, AC_WRITE,     0, nullptr, 0xA20B, AUTO, "FlashEnergy", &stdInterpreter},
  694     {0, AC_WRITE,     0, nullptr, 0xA20C, AUTO, "SpatialFrequencyResponse", &stdInterpreter},
  695     {0, AC_WRITE,     0, nullptr, 0xA20E, AUTO, "FocalPlaneXResolution", &stdInterpreter},
  696     {0, AC_WRITE,     0, nullptr, 0xA20F, AUTO, "FocalPlaneYResolution", &stdInterpreter},
  697     {0, AC_WRITE,     0, nullptr, 0xA210, AUTO, "FocalPlaneResolutionUnit", &stdInterpreter},
  698     {0, AC_WRITE,     0, nullptr, 0xA214, AUTO, "SubjectLocation", &stdInterpreter},
  699     {0, AC_WRITE,     0, nullptr, 0xA215, AUTO, "ExposureIndex", &stdInterpreter},
  700     {0, AC_WRITE,     0, nullptr, 0xA217, AUTO, "SensingMethod", &stdInterpreter},
  701     {0, AC_WRITE,     0, nullptr, 0xA300, AUTO, "FileSource", &stdInterpreter},
  702     {0, AC_WRITE,     0, nullptr, 0xA301, AUTO, "SceneType", &stdInterpreter},
  703     {0, AC_DONTWRITE, 0, nullptr, 0xA302, AUTO, "CFAPattern", &cfaInterpreter},
  704     {0, AC_WRITE,     0, nullptr, 0xA401, AUTO, "CustomRendered", &stdInterpreter},
  705     {0, AC_WRITE,     0, nullptr, 0xA402, AUTO, "ExposureMode", &exposureModeInterpreter},
  706     {0, AC_WRITE,     0, nullptr, 0xA403, AUTO, "WhiteBalance", &whiteBalanceInterpreter},
  707     {0, AC_WRITE,     0, nullptr, 0xA404, AUTO, "DigitalZoomRatio", &stdInterpreter},
  708     {0, AC_WRITE,     0, nullptr, 0xA405, AUTO, "FocalLengthIn35mmFilm", &stdInterpreter},
  709     {0, AC_WRITE,     0, nullptr, 0xA406, AUTO, "SceneCaptureType", &sceneCaptureInterpreter},
  710     {0, AC_WRITE,     0, nullptr, 0xA407, AUTO, "GainControl", &gainControlInterpreter},
  711     {0, AC_WRITE,     0, nullptr, 0xA408, AUTO, "Contrast", &contrastInterpreter},
  712     {0, AC_WRITE,     0, nullptr, 0xA409, AUTO, "Saturation", &saturationInterpreter},
  713     {0, AC_WRITE,     0, nullptr, 0xA40A, AUTO, "Sharpness", &sharpnessInterpreter},
  714     {0, AC_WRITE,     0, nullptr, 0xA40B, AUTO, "DeviceSettingDescription", &stdInterpreter},
  715     {0, AC_WRITE,     0, nullptr, 0xA40C, AUTO, "SubjectDistanceRange", &stdInterpreter},
  716     {0, AC_WRITE,     0, nullptr, 0xA420, AUTO, "ImageUniqueID", &stdInterpreter},
  717     {0, AC_WRITE,     0, nullptr, 0xA431, AUTO, "SerialNumber", &stdInterpreter},
  718     {0, AC_WRITE,     0, nullptr, 0xA432, AUTO, "LensInfo", &stdInterpreter},
  719     {0, AC_WRITE,     0, nullptr, 0xA433, AUTO, "LensMake", &stdInterpreter},
  720     {0, AC_WRITE,     0, nullptr, 0xA434, AUTO, "LensModel", &stdInterpreter},
  721     {0, AC_WRITE,     0, nullptr, 0xA435, AUTO, "LensSerialNumber", &stdInterpreter},
  722     {0, AC_WRITE,     0, nullptr, 0xA500, AUTO, "Gamma", &stdInterpreter},
  723     {0, AC_WRITE,     0, nullptr, 0xC618, AUTO, "LinearizationTable", &stdInterpreter},
  724     {0, AC_WRITE,     0, nullptr, 0xC619, AUTO, "BlackLevelRepeatDim", &stdInterpreter},
  725     {0, AC_WRITE,     0, nullptr, 0xC61A, AUTO, "BlackLevel", &stdInterpreter},
  726     {0, AC_WRITE,     0, nullptr, 0xC61B, AUTO, "BlackLevelDeltaH", &stdInterpreter},
  727     {0, AC_WRITE,     0, nullptr, 0xC61C, AUTO, "BlackLevelDeltaV", &stdInterpreter},
  728     {0, AC_WRITE,     0, nullptr, 0xC61D, AUTO, "WhiteLevel", &stdInterpreter},
  729     {0, AC_WRITE,     0, nullptr, 0xC61E, AUTO, "DefaultScale", &stdInterpreter},
  730     {0, AC_WRITE,     0, nullptr, 0xC61F, AUTO, "DefaultCropOrigin", &stdInterpreter},
  731     {0, AC_WRITE,     0, nullptr, 0xC620, AUTO, "DefaultCropSize", &stdInterpreter},
  732     {0, AC_WRITE,     0, nullptr, 0xC621, AUTO, "ColorMatrix1", &stdInterpreter},
  733     {0, AC_WRITE,     0, nullptr, 0xC622, AUTO, "ColorMatrix2", &stdInterpreter},
  734     {0, AC_WRITE,     0, nullptr, 0xC623, AUTO, "CameraCalibration1", &stdInterpreter},
  735     {0, AC_WRITE,     0, nullptr, 0xC624, AUTO, "CameraCalibration2", &stdInterpreter},
  736     {0, AC_WRITE,     0, nullptr, 0xC625, AUTO, "ReductionMatrix1", &stdInterpreter},
  737     {0, AC_WRITE,     0, nullptr, 0xC626, AUTO, "ReductionMatrix2", &stdInterpreter},
  738     {0, AC_WRITE,     0, nullptr, 0xC627, AUTO, "AnalogBalance", &stdInterpreter},
  739     {0, AC_WRITE,     0, nullptr, 0xC628, AUTO, "AsShotNeutral", &stdInterpreter},
  740     {0, AC_WRITE,     0, nullptr, 0xC629, AUTO, "AsShotWhiteXY", &stdInterpreter},
  741     {0, AC_WRITE,     0, nullptr, 0xC62A, AUTO, "BaselineExposure", &stdInterpreter},
  742     {0, AC_WRITE,     0, nullptr, 0xC62B, AUTO, "BaselineNoise", &stdInterpreter},
  743     {0, AC_WRITE,     0, nullptr, 0xC62C, AUTO, "BaselineSharpness", &stdInterpreter},
  744     {0, AC_WRITE,     0, nullptr, 0xC62D, AUTO, "BayerGreenSplit", &stdInterpreter},
  745     {0, AC_WRITE,     0, nullptr, 0xC62E, AUTO, "LinearResponseLimit", &stdInterpreter},
  746     {0, AC_WRITE,     0, nullptr, 0xC62F, AUTO, "CameraSerialNumber", &stdInterpreter},
  747     {0, AC_WRITE,     0, nullptr, 0xC630, AUTO, "DNGLensInfo", &stdInterpreter},
  748     {0, AC_WRITE,     0, nullptr, 0xC631, AUTO, "ChromaBlurRadius", &stdInterpreter},
  749     {0, AC_WRITE,     0, nullptr, 0xC632, AUTO, "AntiAliasStrength", &stdInterpreter},
  750     {0, AC_WRITE,     0, nullptr, 0xC633, AUTO, "ShadowScale", &stdInterpreter},
  751     {0, AC_WRITE,     0, nullptr, 0xC65A, AUTO, "CalibrationIlluminant1", &lightSourceInterpreter},
  752     {0, AC_WRITE,     0, nullptr, 0xC65B, AUTO, "CalibrationIlluminant2", &lightSourceInterpreter},
  753     {0, AC_WRITE,     0, nullptr, 0xC65C, AUTO, "BestQualityScale", &stdInterpreter},
  754     {0, AC_WRITE,     0, nullptr, 0xC65D, AUTO, "RawDataUniqueID", &stdInterpreter},
  755     {0, AC_WRITE,     0, nullptr, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter},
  756     {0, AC_WRITE,     0, nullptr, 0xC68D, AUTO, "ActiveArea", &stdInterpreter},
  757     {0, AC_WRITE,     0, nullptr, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter},
  758 //  {0, AC_WRITE,     0, nullptr, 0xC68F, AUTO, "AsShotICCProfile", & ???},
  759     {0, AC_WRITE,     0, nullptr, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter},
  760 //  {0, AC_WRITE,     0, nullptr, 0xC691, AUTO, "CurrentICCProfile", & ???},
  761     {0, AC_WRITE,     0, nullptr, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter},
  762     {0, AC_WRITE,     0, nullptr, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter},
  763     {0, AC_WRITE,     0, nullptr, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter},
  764     {0, AC_WRITE,     0, nullptr, 0xC6F4, AUTO, "ProfileCalibrationSig", &stdInterpreter},
  765     {0, AC_WRITE,     0, nullptr, 0xC6F5, AUTO, "ProfileIFD", &stdInterpreter},
  766     {0, AC_WRITE,     0, nullptr, 0xC6F6, AUTO, "AsShotProfileName", &stdInterpreter},
  767     {0, AC_WRITE,     0, nullptr, 0xC6F7, AUTO, "NoiseReductionApplied", &stdInterpreter},
  768     {0, AC_WRITE,     0, nullptr, 0xC6F8, AUTO, "ProfileName", &stdInterpreter},
  769     {0, AC_WRITE,     0, nullptr, 0xC6F9, AUTO, "ProfileHueSatMapDims", &stdInterpreter},
  770     {0, AC_WRITE,     0, nullptr, 0xC6FA, AUTO, "ProfileHueSatMapData1", &stdInterpreter},
  771     {0, AC_WRITE,     0, nullptr, 0xC6FB, AUTO, "ProfileHueSatMapData2", &stdInterpreter},
  772     {0, AC_WRITE,     0, nullptr, 0xC6FC, AUTO, "ProfileToneCurve", &stdInterpreter},
  773     {0, AC_WRITE,     0, nullptr, 0xC6FD, AUTO, "ProfileEmbedPolicy", &profileEmbedPolicyInterpreter},
  774     {0, AC_WRITE,     0, nullptr, 0xC6FE, AUTO, "ProfileCopyright", &stdInterpreter},
  775     {0, AC_WRITE,     0, nullptr, 0xC714, AUTO, "ForwardMatrix1", &stdInterpreter},
  776     {0, AC_WRITE,     0, nullptr, 0xC715, AUTO, "ForwardMatrix2", &stdInterpreter},
  777     {0, AC_WRITE,     0, nullptr, 0xC716, AUTO, "PreviewApplicationName", &stdInterpreter},
  778     {0, AC_WRITE,     0, nullptr, 0xC717, AUTO, "PreviewApplicationVersion", &stdInterpreter},
  779     {0, AC_WRITE,     0, nullptr, 0xC718, AUTO, "PreviewSettingsName", &stdInterpreter},
  780     {0, AC_WRITE,     0, nullptr, 0xC719, AUTO, "PreviewSettingsDigest", &stdInterpreter},
  781     {0, AC_WRITE,     0, nullptr, 0xC71A, AUTO, "PreviewColorSpace", &previewColorSpaceInterpreter},
  782     {0, AC_WRITE,     0, nullptr, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter},
  783     {0, AC_WRITE,     0, nullptr, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter},
  784     {0, AC_WRITE,     0, nullptr, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter},
  785 //  {0, AC_WRITE,     0, nullptr, 0xC71E, AUTO, "SubTileBlockSize", & ???},
  786 //  {0, AC_WRITE,     0, nullptr, 0xC71F, AUTO, "RowInterleaveFactor", & ???},
  787     {0, AC_WRITE,     0, nullptr, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter},
  788     {0, AC_WRITE,     0, nullptr, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter},
  789 //  {0, AC_WRITE,     0, nullptr, 0xC740, AUTO, "OpcodeList1", & ???},
  790 //  {0, AC_WRITE,     0, nullptr, 0xC741, AUTO, "OpcodeList2", & ???},
  791 //  {0, AC_WRITE,     0, nullptr, 0xC74E, AUTO, "OpcodeList3", & ???},
  792     {0, AC_WRITE,     0, nullptr, 0xC761, AUTO, "NoiseProfile", &stdInterpreter},
  793     {0, AC_WRITE,     0, nullptr, 0xC763, AUTO, "TimeCodes", &stdInterpreter},
  794     {0, AC_WRITE,     0, nullptr, 0xC764, AUTO, "FrameRate", &stdInterpreter},
  795     {0, AC_WRITE,     0, nullptr, 0xC772, AUTO, "TStop", &stdInterpreter},
  796     {0, AC_WRITE,     0, nullptr, 0xC789, AUTO, "ReelName", &stdInterpreter},
  797     {0, AC_WRITE,     0, nullptr, 0xC791, AUTO, "OriginalDefaultFinalSize", &stdInterpreter},
  798     {0, AC_WRITE,     0, nullptr, 0xC792, AUTO, "OriginalBestQualitySize", &stdInterpreter},
  799     {0, AC_WRITE,     0, nullptr, 0xC793, AUTO, "OriginalDefaultCropSize", &stdInterpreter},
  800     {0, AC_WRITE,     0, nullptr, 0xC7A1, AUTO, "CameraLabel", &stdInterpreter},
  801     {0, AC_WRITE,     0, nullptr, 0xC7A3, AUTO, "ProfileHueSatMapEncoding", &linearSRGBInterpreter},
  802     {0, AC_WRITE,     0, nullptr, 0xC7A4, AUTO, "ProfileLookTableEncoding", &linearSRGBInterpreter},
  803     {0, AC_WRITE,     0, nullptr, 0xC7A5, AUTO, "BaselineExposureOffset", &stdInterpreter},
  804     {0, AC_WRITE,     0, nullptr, 0xC7A6, AUTO, "DefaultBlackRender", &defaultBlackRenderInterpreter},
  805     {0, AC_WRITE,     0, nullptr, 0xC7A7, AUTO, "NewRawImageDigest", &stdInterpreter},
  806     {0, AC_WRITE,     0, nullptr, 0xC7A8, AUTO, "RawToPreviewGain", &stdInterpreter},
  807     {0, AC_WRITE,     0, nullptr, 0xC7B5, AUTO, "DefaultUserCrop", &stdInterpreter},
  808     {0, AC_WRITE,     0, nullptr, 0xFDE9, AUTO, "SerialNumber", &stdInterpreter},
  809     {0, AC_WRITE,     0, nullptr, 0xFDEA, AUTO, "Lens", &stdInterpreter},
  810     {0, AC_WRITE,     0, nullptr, 0xFE4C, AUTO, "RawFile", &stdInterpreter},
  811     {0, AC_WRITE,     0, nullptr, 0xFE4D, AUTO, "Converter", &stdInterpreter},
  812     {0, AC_WRITE,     0, nullptr, 0xFE4E, AUTO, "WhiteBalance", &stdInterpreter},
  813     {0, AC_WRITE,     0, nullptr, 0xFE51, AUTO, "Exposure", &stdInterpreter},
  814     {0, AC_WRITE,     0, nullptr, 0xFE52, AUTO, "Shadows", &stdInterpreter},
  815     {0, AC_WRITE,     0, nullptr, 0xFE53, AUTO, "Brightness", &stdInterpreter},
  816     {0, AC_WRITE,     0, nullptr, 0xFE54, AUTO, "Contrast", &stdInterpreter},
  817     {0, AC_WRITE,     0, nullptr, 0xFE55, AUTO, "Saturation", &stdInterpreter},
  818     {0, AC_WRITE,     0, nullptr, 0xFE56, AUTO, "Sharpness", &stdInterpreter},
  819     {0, AC_WRITE,     0, nullptr, 0xFE57, AUTO, "Smoothness", &stdInterpreter},
  820     {0, AC_WRITE,     0, nullptr, 0xFE58, AUTO, "MoireFilter", &stdInterpreter},
  821     { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
  822 };
  823 
  824 
  825 const TagAttrib gpsAttribs[] = {
  826     {0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "GPSVersionID", &stdInterpreter},
  827     {0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "GPSLatitudeRef", &stdInterpreter},
  828     {0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "GPSLatitude", &stdInterpreter},
  829     {0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "GPSLongitudeRef", &stdInterpreter},
  830     {0, AC_WRITE, 0, nullptr, 0x0004, AUTO, "GPSLongitude", &stdInterpreter},
  831     {0, AC_WRITE, 0, nullptr, 0x0005, AUTO, "GPSAltitudeRef", &stdInterpreter},
  832     {0, AC_WRITE, 0, nullptr, 0x0006, AUTO, "GPSAltitude", &stdInterpreter},
  833     {0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "GPSTimeStamp", &stdInterpreter},
  834     {0, AC_WRITE, 0, nullptr, 0x0008, AUTO, "GPSSatelites", &stdInterpreter},
  835     {0, AC_WRITE, 0, nullptr, 0x0009, AUTO, "GPSStatus", &stdInterpreter},
  836     {0, AC_WRITE, 0, nullptr, 0x000a, AUTO, "GPSMeasureMode", &stdInterpreter},
  837     {0, AC_WRITE, 0, nullptr, 0x000b, AUTO, "GPSDOP", &stdInterpreter},
  838     {0, AC_WRITE, 0, nullptr, 0x000c, AUTO, "GPSSpeedRef", &stdInterpreter},
  839     {0, AC_WRITE, 0, nullptr, 0x000d, AUTO, "GPSSpeed", &stdInterpreter},
  840     {0, AC_WRITE, 0, nullptr, 0x000e, AUTO, "GPSTrackRef", &stdInterpreter},
  841     {0, AC_WRITE, 0, nullptr, 0x000f, AUTO, "GPSTrack", &stdInterpreter},
  842     {0, AC_WRITE, 0, nullptr, 0x0010, AUTO, "GPSImgDirectionRef", &stdInterpreter},
  843     {0, AC_WRITE, 0, nullptr, 0x0011, AUTO, "GPSImgDirection", &stdInterpreter},
  844     {0, AC_WRITE, 0, nullptr, 0x0012, AUTO, "GPSMapDatum", &stdInterpreter},
  845     {0, AC_WRITE, 0, nullptr, 0x0013, AUTO, "GPSDestLatitudeRef", &stdInterpreter},
  846     {0, AC_WRITE, 0, nullptr, 0x0014, AUTO, "GPSDestLatitude", &stdInterpreter},
  847     {0, AC_WRITE, 0, nullptr, 0x0015, AUTO, "GPSDestLongitudeRef", &stdInterpreter},
  848     {0, AC_WRITE, 0, nullptr, 0x0016, AUTO, "GPSDestLongitude", &stdInterpreter},
  849     {0, AC_WRITE, 0, nullptr, 0x0017, AUTO, "GPSDestBearingRef", &stdInterpreter},
  850     {0, AC_WRITE, 0, nullptr, 0x0018, AUTO, "GPSDestBearing", &stdInterpreter},
  851     {0, AC_WRITE, 0, nullptr, 0x0019, AUTO, "GPSDestDistanceRef", &stdInterpreter},
  852     {0, AC_WRITE, 0, nullptr, 0x001a, AUTO, "GPSDestDistance", &stdInterpreter},
  853     {0, AC_WRITE, 0, nullptr, 0x001b, AUTO, "GPSProcessingMethod", &stdInterpreter},
  854     {0, AC_WRITE, 0, nullptr, 0x001c, AUTO, "GPSAreaInformation", &stdInterpreter},
  855     {0, AC_WRITE, 0, nullptr, 0x001d, AUTO, "GPSDateStamp", &stdInterpreter},
  856     {0, AC_WRITE, 0, nullptr, 0x001e, AUTO, "GPSDifferential", &stdInterpreter},
  857     { -1, AC_DONTWRITE, 0,  nullptr, 0, AUTO, "", nullptr }
  858 };
  859 
  860 const TagAttrib iopAttribs[] = {
  861     {0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "InteroperabilityIndex", &stdInterpreter},
  862     {0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "InteroperabilityVersion", &stdInterpreter},
  863     { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
  864 };
  865 
  866 const TagAttrib ifdAttribs[] = {
  867     {0, AC_SYSTEM,    0, nullptr, 0x0017, AUTO, "PanaISO", &stdInterpreter},
  868     {0, AC_SYSTEM,    0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter},
  869     {0, AC_SYSTEM,    0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter},
  870     {0, AC_SYSTEM,    0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter},
  871     {0, AC_SYSTEM,    0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter},
  872     {0, AC_SYSTEM,    0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter},
  873     {0, AC_SYSTEM,    0, nullptr, 0x0106, AUTO, "PhotometricInterpretation", &photometricInterpreter},
  874     {0, AC_WRITE,     1, nullptr, 0x010E, AUTO, "ImageDescription", &stdInterpreter},
  875     {0, AC_WRITE,     0, nullptr, 0x010F, AUTO, "Make", &stdInterpreter},
  876     {0, AC_WRITE,     0, nullptr, 0x0110, AUTO, "Model", &stdInterpreter},
  877     {1, AC_DONTWRITE, 0, nullptr, 0x0111, AUTO, "StripOffsets", &stdInterpreter},
  878     {0, AC_SYSTEM,    0, nullptr, 0x0112, AUTO, "Orientation", &orientationInterpreter},
  879     {0, AC_SYSTEM,    0, nullptr, 0x0115, AUTO, "SamplesPerPixel", &stdInterpreter},
  880     {1, AC_DONTWRITE, 0, nullptr, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter},
  881     {1, AC_DONTWRITE, 0, nullptr, 0x0117, AUTO, "StripByteCounts", &stdInterpreter},
  882     {0, AC_SYSTEM,    0, nullptr, 0x011A, AUTO, "XResolution", &stdInterpreter},
  883     {0, AC_SYSTEM,    0, nullptr, 0x011B, AUTO, "YResolution", &stdInterpreter},
  884     {0, AC_SYSTEM,    0, nullptr, 0x011C, AUTO, "PlanarConfiguration", &planarConfigInterpreter},
  885     {0, AC_SYSTEM,    0, nullptr, 0x0128, AUTO, "ResolutionUnit", &unitsInterpreter},
  886     {0, AC_SYSTEM,    0, nullptr, 0x012D, AUTO, "TransferFunction", &stdInterpreter},
  887     {0, AC_SYSTEM,    0, nullptr, 0x0131, AUTO, "Software", &stdInterpreter},
  888     {0, AC_WRITE,     0, nullptr, 0x0132, AUTO, "DateTime", &stdInterpreter},
  889     {0, AC_WRITE,     1, nullptr, 0x013B, AUTO, "Artist", &stdInterpreter},
  890     {0, AC_SYSTEM,    0, nullptr, 0x013E, AUTO, "WhitePoint", &stdInterpreter},
  891     {0, AC_SYSTEM,    0, nullptr, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter},
  892     {0, AC_WRITE,     0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter},
  893     {0, AC_SYSTEM,    0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter},
  894     {0, AC_SYSTEM,    0, nullptr, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter},
  895     {0, AC_SYSTEM,    0, nullptr, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter},
  896     {0, AC_SYSTEM,    0, nullptr, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter},
  897     {0, AC_SYSTEM,    0, nullptr, 0x0212, AUTO, "YCbCrSubSampling", &stdInterpreter},
  898     {0, AC_SYSTEM,    0, nullptr, 0x0213, AUTO, "YCbCrPositioning", &stdInterpreter},
  899     {0, AC_SYSTEM,    0, nullptr, 0x0214, AUTO, "ReferenceBlackWhite", &stdInterpreter},
  900     {0, AC_SYSTEM,    0, nullptr, 0x02bc, AUTO, "ApplicationNotes", &utf8BinInterpreter},  // XMP
  901     {0, AC_WRITE,     0, nullptr, 0x4746, AUTO, "Rating", &stdInterpreter},
  902     {0, AC_WRITE,     0, nullptr, 0x4749, AUTO, "RatingPercent", &stdInterpreter},
  903     {0, AC_WRITE,     0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter},
  904     {0, AC_WRITE,     0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter},
  905     {0, AC_WRITE,     0, kodakIfdAttribs, 0x8290, AUTO, "KodakIFD", &stdInterpreter},
  906     {0, AC_WRITE,     1, nullptr, 0x8298, AUTO, "Copyright", &stdInterpreter},
  907     {0, AC_SYSTEM,    0, nullptr, 0x83BB, AUTO, "IPTCData", &stdInterpreter},
  908     {0, AC_DONTWRITE, 0, nullptr, 0x8606, AUTO, "LeafData", &stdInterpreter}, // is actually a subdir, but a proprietary format
  909     {0, AC_WRITE,     0, exifAttribs, 0x8769, AUTO, "Exif", &stdInterpreter},
  910     {0, AC_SYSTEM,    0, nullptr, 0x8773, AUTO, "ICCProfile", &stdInterpreter},
  911     {0, AC_WRITE,     0, gpsAttribs,  0x8825, AUTO, "GPSInfo", &stdInterpreter},
  912     {0, AC_WRITE,     0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter},
  913     {0, AC_WRITE,     0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},
  914     {0, AC_WRITE,     0, nullptr, 0x9211, AUTO, "ImageNumber", &stdInterpreter},
  915     {0, AC_WRITE,     0, iopAttribs,  0xA005, AUTO, "Interoperability", &stdInterpreter},
  916     {0, AC_DONTWRITE, 0, nullptr, 0xC4A5, AUTO, "PrintIMInformation", &stdInterpreter},
  917     {0, AC_DONTWRITE, 0, nullptr, 0xC612, AUTO, "DNGVersion", &stdInterpreter},
  918     {0, AC_DONTWRITE, 0, nullptr, 0xC613, AUTO, "DNGBackwardVersion", &stdInterpreter},
  919     {0, AC_WRITE,     0, nullptr, 0xC614, AUTO, "UniqueCameraModel", &stdInterpreter},
  920     {0, AC_WRITE,     0, nullptr, 0xC615, AUTO, "LocalizedCameraModel", &stdInterpreter},
  921     {0, AC_WRITE,     0, nullptr, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter},
  922     {0, AC_SYSTEM,    0, nullptr, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter},
  923     {0, AC_DONTWRITE, 0, nullptr, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData
  924     {0, AC_SYSTEM,    0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter},
  925     {0, AC_WRITE,     0, nullptr, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter},
  926     {0, AC_DONTWRITE, 0, nullptr, 0xc761, AUTO, "NoiseProfile", &stdInterpreter},
  927     { -1, AC_DONTWRITE, 0,  nullptr, 0, AUTO, "", nullptr}
  928 };
  929 }
  930 
  931 #endif