From 96863bb95648575f8528dfa75bbf232c9c4deb40 Mon Sep 17 00:00:00 2001 From: Hombre Date: Mon, 1 Jan 2018 13:51:48 +0100 Subject: [PATCH] Sets UTF-8 as default charset for IPTC + suppress one of the 2 methods for saving TIFF images. --- rtengine/imageio.cc | 380 ++++++++++++++++++++----------------------- rtexif/rtexif.cc | 126 +------------- rtexif/stdattribs.cc | 2 +- 3 files changed, 182 insertions(+), 326 deletions(-) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index ba52c4672..3790f00f6 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -75,15 +75,6 @@ FILE* g_fopen_withBinaryAndLock(const Glib::ustring& fname) return f; } -Glib::ustring to_utf8 (const std::string& str) -{ - try { - return Glib::locale_to_utf8 (str); - } catch (Glib::Error&) { - return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?"); - } -} - } Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."}; @@ -136,13 +127,19 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr iptc = iptc_data_new (); + const unsigned char utf8Esc[] = {0x1B, '%', 'G'}; + IptcDataSet * ds = iptc_dataset_new (); + iptc_dataset_set_tag (ds, IPTC_RECORD_OBJECT_ENV, IPTC_TAG_CHARACTER_SET); + iptc_dataset_set_data (ds, utf8Esc, 3, IPTC_DONT_VALIDATE); + iptc_data_add_dataset (iptc, ds); + iptc_dataset_unref (ds); + for (rtengine::procparams::IPTCPairs::const_iterator i = iptcc.begin(); i != iptcc.end(); ++i) { if (i->first == "Keywords" && !(i->second.empty())) { for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS); - std::string loc = to_utf8(i->second.at(j)); - iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast(64), loc.size()), IPTC_DONT_VALIDATE); + iptc_dataset_set_data (ds, (unsigned char*)i->second.at(j).c_str(), min(static_cast(64), i->second.at(j).bytes()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } @@ -152,8 +149,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY); - std::string loc = to_utf8(i->second.at(j)); - iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast(32), loc.size()), IPTC_DONT_VALIDATE); + iptc_dataset_set_data (ds, (unsigned char*)i->second.at(j).c_str(), min(static_cast(32), i->second.at(j).bytes()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } @@ -165,8 +161,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr if (i->first == strTags[j].field && !(i->second.empty())) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag); - std::string loc = to_utf8(i->second.at(0)); - iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(strTags[j].size, loc.size()), IPTC_DONT_VALIDATE); + iptc_dataset_set_data (ds, (unsigned char*)i->second.at(0).c_str(), min(strTags[j].size, i->second.at(0).bytes()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); } @@ -1121,13 +1116,13 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) int bytes = 0; if (!error && (bytes = iptc_jpeg_ps3_save_iptc (nullptr, 0, iptcdata, size, buffer, 65532)) < 0) { - if (iptcdata) { - iptc_data_free_buf (iptc, iptcdata); - } - error = true; } + if (iptcdata) { + iptc_data_free_buf (iptc, iptcdata); + } + if (!error) { jpeg_write_marker(&cinfo, JPEG_APP0 + 13, buffer, bytes); } @@ -1212,219 +1207,198 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) int lineWidth = width * 3 * bps / 8; unsigned char* linebuffer = new unsigned char[lineWidth]; -// TODO the following needs to be looked into - do we really need two ways to write a Tiff file ? - if (exifRoot && uncompressed) { - FILE *file = g_fopen_withBinaryAndLock (fname); + // little hack to get libTiff to use proper byte order (see TIFFClienOpen()): + const char *mode = !exifRoot ? "w" : (exifRoot->getOrder() == rtexif::INTEL ? "wl" : "wb"); +#ifdef WIN32 + FILE *file = g_fopen_withBinaryAndLock (fname); + int fileno = _fileno(file); + int osfileno = _get_osfhandle(fileno); + TIFF* out = TIFFFdOpen (osfileno, fname.c_str(), mode); +#else + TIFF* out = TIFFOpen(fname.c_str(), mode); + int fileno = TIFFFileno (out); +#endif - if (!file) { - delete [] linebuffer; - return IMIO_CANNOTWRITEFILE; + if (!out) { + delete [] linebuffer; + return IMIO_CANNOTWRITEFILE; + } + + if (pl) { + pl->setProgressStr ("PROGRESSBAR_SAVETIFF"); + pl->setProgress (0.0); + } + + if (exifRoot) { + rtexif::TagDirectory* cl = (const_cast (exifRoot))->clone (nullptr); + + // ------------------ remove some unknown top level tags which produce warnings when opening a tiff (might be useless) ----------------- + + rtexif::Tag *removeTag = cl->getTag (0x9003); + + if (removeTag) { + removeTag->setKeep (false); } - if (pl) { - pl->setProgressStr ("PROGRESSBAR_SAVETIFF"); - pl->setProgress (0.0); + removeTag = cl->getTag (0x9211); + + if (removeTag) { + removeTag->setKeep (false); } - // buffer for the exif and iptc - unsigned int bufferSize; - unsigned char* buffer = nullptr; // buffer will be allocated in createTIFFHeader - unsigned char* iptcdata = nullptr; - unsigned int iptclen = 0; + // ------------------ Apply list of change ----------------- - if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) { + for (auto currExifChange : exifChange) { + cl->applyChange (currExifChange.first, currExifChange.second); + } + + rtexif::Tag *tag = cl->getTag (TIFFTAG_EXIFIFD); + + if (tag && tag->isDirectory()) { + rtexif::TagDirectory *exif = tag->getDirectory(); + + if (exif) { + int exif_size = exif->calculateSize(); + unsigned char *buffer = new unsigned char[exif_size + 8]; + // TIFFOpen writes out the header and sets file pointer at position 8 + + exif->write (8, buffer); + + write (fileno, buffer + 8, exif_size); + + delete [] buffer; + // let libtiff know that scanlines or any other following stuff should go + // at a different offset: + TIFFSetWriteOffset (out, exif_size + 8); + TIFFSetField (out, TIFFTAG_EXIFIFD, 8); + } + } + + //TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed. + + if ((tag = cl->getTag (TIFFTAG_MODEL)) != nullptr) { + TIFFSetField (out, TIFFTAG_MODEL, tag->getValue()); + } + + if ((tag = cl->getTag (TIFFTAG_MAKE)) != nullptr) { + TIFFSetField (out, TIFFTAG_MAKE, tag->getValue()); + } + + if ((tag = cl->getTag (TIFFTAG_DATETIME)) != nullptr) { + TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue()); + } + + if ((tag = cl->getTag (TIFFTAG_ARTIST)) != nullptr) { + TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue()); + } + + if ((tag = cl->getTag (TIFFTAG_COPYRIGHT)) != nullptr) { + TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue()); + } + + delete cl; + } + + unsigned char* iptcdata = nullptr; + unsigned int iptclen = 0; + + if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen)) { + if (iptcdata) { iptc_data_free_buf (iptc, iptcdata); iptcdata = nullptr; } + } - int size = rtexif::ExifManager::createTIFFHeader (exifRoot, exifChange, width, height, bps, profileData, profileLength, (char*)iptcdata, iptclen, buffer, bufferSize); - - if (iptcdata) { - iptc_data_free_buf (iptc, iptcdata); + if (iptcdata) { + rtexif::Tag* iptcTag = new rtexif::Tag (nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData")); + iptcTag->initLongArray((char*)iptcdata, iptclen); +#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ + bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA; +#else + bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL; +#endif + if (needsReverse) { + unsigned char *ptr = iptcTag->getValue(); + for (int a = 0; a < iptcTag->getCount(); ++a) { + unsigned char cc; + cc = ptr[3]; + ptr[3] = ptr[0]; + ptr[0] = cc; + cc = ptr[2]; + ptr[2] = ptr[1]; + ptr[1] = cc; + ptr += 4; + } } + TIFFSetField (out, TIFFTAG_RICHTIFFIPTC, iptcTag->getCount(), (long*)iptcTag->getValue()); + iptc_data_free_buf (iptc, iptcdata); + } - // The maximum lenght is strangely not the same than for the JPEG file... - // Which maximum length is the good one ? - if (size > 0 && size <= static_cast(bufferSize)) { - fwrite (buffer, size, 1, file); - } + TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION); + TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField (out, TIFFTAG_IMAGELENGTH, height); + TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 3); + TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, height); + TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_DEFLATE); + TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, bps == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT); + + if (!uncompressed) { + TIFFSetField (out, TIFFTAG_PREDICTOR, bps == 32 ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL); + } + + if (profileData) { + TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData); + } #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ - bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::MOTOROLA; + bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::MOTOROLA; #else - bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::INTEL; + bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::INTEL; #endif - for (int i = 0; i < height; i++) { - getScanline (i, linebuffer, bps); + for (int row = 0; row < height; row++) { + getScanline (row, linebuffer, bps); - if (needsReverse) { - if (bps == 16) { - for (int i = 0; i < lineWidth; i += 2) { - char c = linebuffer[i]; - linebuffer[i] = linebuffer[i + 1]; - linebuffer[i + 1] = c; - } - } else { - for (int i = 0; i < lineWidth; i += 4) { - std::swap(linebuffer[i], linebuffer[i+3]); - std::swap(linebuffer[i+1], linebuffer[i+2]); - } + if (needsReverse) { + if (bps == 16) { + for (int i = 0; i < lineWidth; i += 2) { + char c = linebuffer[i]; + linebuffer[i] = linebuffer[i + 1]; + linebuffer[i + 1] = c; + } + } else { + for (int i = 0; i < lineWidth; i += 4) { + std::swap(linebuffer[i], linebuffer[i+3]); + std::swap(linebuffer[i+1], linebuffer[i+2]); } } - - fwrite (linebuffer, lineWidth, 1, file); - - if (pl && !(i % 100)) { - pl->setProgress ((double)(i + 1) / height); - } } - if(buffer) { - delete [] buffer; - } - - if (ferror(file)) { - writeOk = false; - } - - fclose (file); - } else { - // little hack to get libTiff to use proper byte order (see TIFFClienOpen()): - const char *mode = !exifRoot ? "w" : (exifRoot->getOrder() == rtexif::INTEL ? "wl" : "wb"); -#ifdef WIN32 - FILE *file = g_fopen_withBinaryAndLock (fname); - int fileno = _fileno(file); - int osfileno = _get_osfhandle(fileno); - TIFF* out = TIFFFdOpen (osfileno, fname.c_str(), mode); -#else - TIFF* out = TIFFOpen(fname.c_str(), mode); - int fileno = TIFFFileno (out); -#endif - - if (!out) { + if (TIFFWriteScanline (out, linebuffer, row, 0) < 0) { + TIFFClose (out); delete [] linebuffer; return IMIO_CANNOTWRITEFILE; } - if (pl) { - pl->setProgressStr ("PROGRESSBAR_SAVETIFF"); - pl->setProgress (0.0); + if (pl && !(row % 100)) { + pl->setProgress ((double)(row + 1) / height); } - - if (exifRoot) { - rtexif::Tag *tag = exifRoot->getTag (TIFFTAG_EXIFIFD); - - if (tag && tag->isDirectory()) { - rtexif::TagDirectory *exif = tag->getDirectory(); - - if (exif) { - int exif_size = exif->calculateSize(); - unsigned char *buffer = new unsigned char[exif_size + 8]; - // TIFFOpen writes out the header and sets file pointer at position 8 - - exif->write (8, buffer); - - write (fileno, buffer + 8, exif_size); - - delete [] buffer; - // let libtiff know that scanlines or any other following stuff should go - // at a different offset: - TIFFSetWriteOffset (out, exif_size + 8); - TIFFSetField (out, TIFFTAG_EXIFIFD, 8); - } - } - -//TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed. - - if ((tag = exifRoot->getTag (TIFFTAG_MODEL)) != nullptr) { - TIFFSetField (out, TIFFTAG_MODEL, tag->getValue()); - } - - if ((tag = exifRoot->getTag (TIFFTAG_MAKE)) != nullptr) { - TIFFSetField (out, TIFFTAG_MAKE, tag->getValue()); - } - - if ((tag = exifRoot->getTag (TIFFTAG_DATETIME)) != nullptr) { - TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue()); - } - - if ((tag = exifRoot->getTag (TIFFTAG_ARTIST)) != nullptr) { - TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue()); - } - - if ((tag = exifRoot->getTag (TIFFTAG_COPYRIGHT)) != nullptr) { - TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue()); - } - - } - - TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION); - TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width); - TIFFSetField (out, TIFFTAG_IMAGELENGTH, height); - TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); - TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 3); - TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, height); - TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, bps); - TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); - TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); - TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_DEFLATE); - TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, bps == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT); - - if (!uncompressed) { - TIFFSetField (out, TIFFTAG_PREDICTOR, bps == 32 ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL); - } - - if (profileData) { - TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData); - } - -#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ - bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::MOTOROLA; -#else - bool needsReverse = (bps == 16 || bps == 32) && exifRoot->getOrder() == rtexif::INTEL; -#endif - - for (int row = 0; row < height; row++) { - getScanline (row, linebuffer, bps); - - if (needsReverse) { - if (bps == 16) { - for (int i = 0; i < lineWidth; i += 2) { - char c = linebuffer[i]; - linebuffer[i] = linebuffer[i + 1]; - linebuffer[i + 1] = c; - } - } else { - for (int i = 0; i < lineWidth; i += 4) { - std::swap(linebuffer[i], linebuffer[i+3]); - std::swap(linebuffer[i+1], linebuffer[i+2]); - } - } - } - - if (TIFFWriteScanline (out, linebuffer, row, 0) < 0) { - TIFFClose (out); - delete [] linebuffer; - return IMIO_CANNOTWRITEFILE; - } - - if (pl && !(row % 100)) { - pl->setProgress ((double)(row + 1) / height); - } - } - - if (TIFFFlush(out) != 1) { - writeOk = false; - } - - TIFFClose (out); -#ifdef WIN32 - fclose (file); -#endif } + if (TIFFFlush(out) != 1) { + writeOk = false; + } + + TIFFClose (out); +#ifdef WIN32 + fclose (file); +#endif + delete [] linebuffer; if (pl) { diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 60f8b6619..6179688ae 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -739,11 +739,12 @@ void TagDirectory::applyChange (std::string name, Glib::ustring value) } else { const TagAttrib* attrib = nullptr; - for (int i = 0; attribs[i].ignore != -1; i++) + for (int i = 0; attribs[i].ignore != -1; i++) { if (!strcmp (attribs[i].name, fseg.c_str())) { attrib = &attribs[i]; break; } + } if (attrib) { Tag* nt = new Tag (this, attrib); @@ -1663,15 +1664,11 @@ void Tag::toString (char* buffer, int ofs) return; } - size_t maxcount = 4; - - if (count < 4) { - maxcount = count; - } + size_t maxcount = rtengine::min(count, 10); strcpy (buffer, ""); - for (ssize_t i = 0; i < std::min(maxcount, valuesize - ofs); i++) { + for (ssize_t i = 0; i < rtengine::min(maxcount, valuesize - ofs); i++) { if (i > 0) { strcat (buffer, ", "); } @@ -3199,121 +3196,6 @@ int ExifManager::createJPEGMarker (const TagDirectory* root, const rtengine::pro return size + 6; } -int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize) -{ - -// write tiff header - int offs = 0; - ByteOrder order = HOSTORDER; - - if (root) { - order = root->getOrder (); - } - - TagDirectory* cl; - - if (root) { - cl = (const_cast (root))->clone (nullptr); - // remove some unknown top level tags which produce warnings when opening a tiff - Tag *removeTag = cl->getTag (0x9003); - - if (removeTag) { - removeTag->setKeep (false); - } - - removeTag = cl->getTag (0x9211); - - if (removeTag) { - removeTag->setKeep (false); - } - } else { - cl = new TagDirectory (nullptr, ifdAttribs, HOSTORDER); - } - -// add tiff strip data - int rps = 8; - int strips = ceil ((double)H / rps); - cl->replaceTag (new Tag (cl, lookupAttrib (ifdAttribs, "RowsPerStrip"), rps, LONG)); - Tag* stripBC = new Tag (cl, lookupAttrib (ifdAttribs, "StripByteCounts")); - stripBC->initInt (0, LONG, strips); - cl->replaceTag (stripBC); - Tag* stripOffs = new Tag (cl, lookupAttrib (ifdAttribs, "StripOffsets")); - stripOffs->initInt (0, LONG, strips); - cl->replaceTag (stripOffs); - Tag *sampleFormat = new Tag (cl, lookupAttrib (ifdAttribs, "SampleFormat"), bps == 32 ? 3 : 1, SHORT); - cl->replaceTag (sampleFormat); - - for (int i = 0; i < strips - 1; i++) { - stripBC->setInt (rps * W * 3 * bps / 8, i * 4); - } - - int remaining = (H - rps * floor ((double)H / rps)) * W * 3 * bps / 8; - - if (remaining) { - stripBC->setInt (remaining, (strips - 1) * 4); - } else { - stripBC->setInt (rps * W * 3 * bps / 8, (strips - 1) * 4); - } - - if (profiledata) { - Tag* icc = new Tag (cl, lookupAttrib (ifdAttribs, "ICCProfile")); - icc->initUndefArray (profiledata, profilelen); - cl->replaceTag (icc); - } - - if (iptcdata) { - Tag* iptc = new Tag (cl, lookupAttrib (ifdAttribs, "IPTCData")); - iptc->initLongArray (iptcdata, iptclen); - cl->replaceTag (iptc); - } - -// apply list of changes - for (rtengine::procparams::ExifPairs::const_iterator i = changeList.begin(); i != changeList.end(); ++i) { - cl->applyChange (i->first, i->second); - } - - // append default properties - const std::vector defTags = getDefaultTIFFTags (cl); - - defTags[0]->setInt (W, 0, LONG); - defTags[1]->setInt (H, 0, LONG); - defTags[8]->initInt (0, SHORT, 3); - - for (int i = 0; i < 3; i++) { - defTags[8]->setInt (bps, i * 2, SHORT); - } - - for (int i = defTags.size() - 1; i >= 0; i--) { - Tag* defTag = defTags[i]; - cl->replaceTag (defTag->clone (cl)); - delete defTag; - } - -// calculate strip offsets - int size = cl->calculateSize (); - int byps = bps / 8; - - for (int i = 0; i < strips; i++) { - stripOffs->setInt (size + 8 + i * rps * W * 3 * byps, i * 4); - } - - cl->sort (); - bufferSize = cl->calculateSize() + 8; - buffer = new unsigned char[bufferSize]; // this has to be deleted in caller - sset2 ((unsigned short)order, buffer + offs, order); - offs += 2; - sset2 (42, buffer + offs, order); - offs += 2; - sset4 (8, buffer + offs, order); - - int endOffs = cl->write (8, buffer); - -// cl->printAll(); - delete cl; - - return endOffs; -} - //----------------------------------------------------------------------------- // global functions to read byteorder dependent data //----------------------------------------------------------------------------- diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index a7e3fe00f..4982b0b81 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -809,10 +809,10 @@ const TagAttrib ifdAttribs[] = { {0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, {0, AC_WRITE, 0, kodakIfdAttribs, 0x8290, AUTO, "KodakIFD", &stdInterpreter}, {0, AC_WRITE, 1, nullptr, 0x8298, AUTO, "Copyright", &stdInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x83BB, AUTO, "IPTCData", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0x8606, AUTO, "LeafData", &stdInterpreter}, // is actually a subdir, but a proprietary format {0, AC_WRITE, 0, exifAttribs, 0x8769, AUTO, "Exif", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x8773, AUTO, "ICCProfile", &stdInterpreter}, - {0, AC_SYSTEM, 0, nullptr, 0x83BB, AUTO, "IPTCData", &stdInterpreter}, {0, AC_WRITE, 0, gpsAttribs, 0x8825, AUTO, "GPSInfo", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},