1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
|
#ifndef __IPTC_Support_hpp__
#define __IPTC_Support_hpp__ 1
// =================================================================================================
// ADOBE SYSTEMS INCORPORATED
// Copyright 2006 Adobe Systems Incorporated
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it.
// =================================================================================================
#include "XMP_Environment.h" // ! This must be the first include.
#include <map>
#include <stdlib.h>
#include "XMP_Const.h"
#include "XMPFiles_Impl.hpp"
#include "EndianUtils.hpp"
// =================================================================================================
/// \file IPTC_Support.hpp
/// \brief XMPFiles support for IPTC (IIM) DataSets.
///
/// This header provides IPTC (IIM) DataSet support specific to the needs of XMPFiles. This is not
/// intended for general purpose IPTC processing. There is a small tree of derived classes, 1
/// virtual base class and 2 concrete leaf classes:
/// \code
/// IPTC_Manager - The root virtual base class.
/// IPTC_Reader - A derived concrete leaf class for memory-based read-only access.
/// IPTC_Writer - A derived concrete leaf class for memory-based read-write access.
/// \endcode
///
/// \c IPTC_Manager declares all of the public methods except for specialized constructors in the
/// leaf classes. The read-only classes throw an XMP_Error exception for output methods like
/// \c SetDataSet. They return appropriate values for "safe" methods, \c IsChanged will return false
/// for example.
///
/// The IPTC DataSet organization differs from TIFF tags and Photoshop image resources in allowing
/// muultiple occurrences for some IDs. The C++ STL multimap is a natural data structure for IPTC.
///
/// Support is only provided for DataSet 1:90 to decide if local or UTF-8 text encoding is used, and
/// the following text valued DataSets: 2:05, 2:10, 2:15, 2:20, 2:25, 2:40, 2:55, 2:80, 2:85, 2:90,
/// 2:95, 2:101, 2:103, 2:105, 2:110, 2:115, 2:116, 2:120, and 2:122. DataSet 2:00 is ignored when
/// reading but always written.
///
/// \note Unlike the TIFF_Manager and PSIR_Manager class trees, IPTC_Manager only provides in-memory
/// implementations. The total size of IPTC data is small enough to make this reasonable.
///
/// \note These classes are for use only when directly compiled and linked. They should not be
/// packaged in a DLL by themselves. They do not provide any form of C++ ABI protection.
// =================================================================================================
// =================================================================================================
// =================================================================================================
enum { // List of recognized 2:* IIM DataSets. The names are from IIMv4 and IPTC4XMP.
kIPTC_ObjectType = 3,
kIPTC_IntellectualGenre = 4,
kIPTC_Title = 5,
kIPTC_EditStatus = 7,
kIPTC_EditorialUpdate = 8,
kIPTC_Urgency = 10,
kIPTC_SubjectCode = 12,
kIPTC_Category = 15,
kIPTC_SuppCategory = 20,
kIPTC_FixtureIdentifier = 22,
kIPTC_Keyword = 25,
kIPTC_ContentLocCode = 26,
kIPTC_ContentLocName = 27,
kIPTC_ReleaseDate = 30,
kIPTC_ReleaseTime = 35,
kIPTC_ExpDate = 37,
kIPTC_ExpTime = 38,
kIPTC_Instructions = 40,
kIPTC_ActionAdvised = 42,
kIPTC_RefService = 45,
kIPTC_RefDate = 47,
kIPTC_RefNumber = 50,
kIPTC_DateCreated = 55,
kIPTC_TimeCreated = 60,
kIPTC_DigitalCreateDate = 62,
kIPTC_DigitalCreateTime = 63,
kIPTC_OriginProgram = 65,
kIPTC_ProgramVersion = 70,
kIPTC_ObjectCycle = 75,
kIPTC_Creator = 80,
kIPTC_CreatorJobtitle = 85,
kIPTC_City = 90,
kIPTC_Location = 92,
kIPTC_State = 95,
kIPTC_CountryCode = 100,
kIPTC_Country = 101,
kIPTC_JobID = 103,
kIPTC_Headline = 105,
kIPTC_Provider = 110,
kIPTC_Source = 115,
kIPTC_CopyrightNotice = 116,
kIPTC_Contact = 118,
kIPTC_Description = 120,
kIPTC_DescriptionWriter = 122,
kIPTC_RasterizedCaption = 125,
kIPTC_ImageType = 130,
kIPTC_ImageOrientation = 131,
kIPTC_LanguageID = 135,
kIPTC_AudioType = 150,
kIPTC_AudioSampleRate = 151,
kIPTC_AudioSampleRes = 152,
kIPTC_AudioDuration = 153,
kIPTC_AudioOutcue = 154,
kIPTC_PreviewFormat = 200,
kIPTC_PreviewFormatVers = 201,
kIPTC_PreviewData = 202
};
enum { // Forms of mapping legacy IPTC to XMP. Order is significant, see PhotoDataUtils::Import2WayIPTC!
kIPTC_MapSimple, // The XMP is simple, the last DataSet occurrence is kept.
kIPTC_MapLangAlt, // The XMP is a LangAlt x-default item, the last DataSet occurrence is kept.
kIPTC_MapArray, // The XMP is an unordered array, all DataSets are kept.
kIPTC_MapSpecial, // The mapping requires DataSet specific code.
kIPTC_Map3Way, // Has a 3 way mapping between Exif, IPTC, and XMP.
kIPTC_UnmappedText, // A text DataSet that is not mapped to XMP.
kIPTC_UnmappedBin // A binary DataSet that is not mapped to XMP.
};
struct DataSetCharacteristics {
XMP_Uns8 id;
XMP_Uns8 mapForm;
size_t maxLen;
XMP_StringPtr xmpNS;
XMP_StringPtr xmpProp;
};
extern const DataSetCharacteristics kKnownDataSets[];
struct IntellectualGenreMapping {
XMP_StringPtr refNum; // The reference number as a 3 digit string.
XMP_StringPtr name; // The intellectual genre name.
};
extern const IntellectualGenreMapping kIntellectualGenreMappings[];
// =================================================================================================
// IPTC_Manager
// ============
class IPTC_Manager {
public:
// ---------------------------------------------------------------------------------------------
// Types and constants.
struct DataSetInfo {
XMP_Uns8 id;
XMP_Uns32 dataLen;
XMP_Uns8 * dataPtr; // ! The data is read-only. Raw data pointer, beware of character encoding.
DataSetInfo() : id(0), dataLen(0), dataPtr(0) {};
DataSetInfo ( XMP_Uns8 _id, XMP_Uns32 _dataLen, XMP_Uns8 * _dataPtr )
: id(_id), dataLen(_dataLen), dataPtr(_dataPtr) {};
};
// ---------------------------------------------------------------------------------------------
// Parse a binary IPTC (IIM) block.
void ParseMemoryDataSets ( const void* data, XMP_Uns32 length, bool copyData = true );
// ---------------------------------------------------------------------------------------------
// Get the information about a DataSet. Returns the number of occurrences. The "which" parameter
// selects the occurrence, they are numbered from 0 to count-1. Returns 0 if which is too large.
size_t GetDataSet ( XMP_Uns8 id, DataSetInfo* info, size_t which = 0 ) const;
// ---------------------------------------------------------------------------------------------
// Get the value of a text DataSet as UTF-8. The returned pointer must be treated as read-only.
// Calls GetDataSet then does a local to UTF-8 conversion if necessary.
size_t GetDataSet_UTF8 ( XMP_Uns8 id, std::string * utf8Str, size_t which = 0 ) const;
// ---------------------------------------------------------------------------------------------
// Set the value of a text DataSet from a UTF-8 string. Does a UTF-8 to local conversion if
// necessary. If the encoding mode is currently local and this value has round-trip loss, then
// the encoding mode will be changed to UTF-8 and all existing values will be converted.
// Modifies an existing occurrence if "which" is within range. Adds an occurrence if which
// equals the current count, or which is -1 and repeats are allowed. Throws an exception if
// which is too large. The dataPtr provides the raw data, text must be in the right encoding.
virtual void SetDataSet_UTF8 ( XMP_Uns8 id, const void* utf8Ptr, XMP_Uns32 utf8Len, long which = -1 ) = 0;
// ---------------------------------------------------------------------------------------------
// Delete an existing DataSet. Deletes all occurrences if which is -1.
virtual void DeleteDataSet ( XMP_Uns8 id, long which = -1 ) = 0;
// ---------------------------------------------------------------------------------------------
// Determine if any DataSets are changed.
virtual bool IsChanged() = 0;
// ---------------------------------------------------------------------------------------------
// Determine if UTF-8 or local text encoding is being used.
bool UsingUTF8() const { return this->utf8Encoding; };
// --------------------------------------------------
// Update the DataSets to reflect the changed values.
virtual void UpdateMemoryDataSets() = 0;
// ---------------------------------------------------------------------------------------------
// Get the location and size of the full IPTC block. The client must call UpdateMemoryDataSets
// first if appropriate. The returned dataPtr must be treated as read only. It exists until the
// IPTC_Manager destructor is called.
XMP_Uns32 GetBlockInfo ( void** dataPtr ) const
{ if ( dataPtr != 0 ) *dataPtr = this->iptcContent; return this->iptcLength; };
// ---------------------------------------------------------------------------------------------
virtual ~IPTC_Manager() { if ( this->ownedContent ) free ( this->iptcContent ); };
protected:
enum { kMinDataSetSize = 5 }; // 1+1+1+2
typedef std::multimap<XMP_Uns16,DataSetInfo> DataSetMap;
DataSetMap dataSets;
XMP_Uns8* iptcContent;
XMP_Uns32 iptcLength, offset190, length190, offset2xx, length2xx;
bool changed;
bool ownedContent; // True if IPTC_Manager destructor needs to release the content block.
bool utf8Encoding; // True if text values are encoded as UTF-8.
IPTC_Manager() : iptcContent(0), iptcLength(0), offset190(0), length190(0), offset2xx(0), length2xx(0),
changed(false), ownedContent(false), utf8Encoding(false) {};
void DisposeLooseValue ( DataSetInfo & dsInfo );
}; // IPTC_Manager
// =================================================================================================
// =================================================================================================
// =================================================================================================
// IPTC_Reader
// ===========
class IPTC_Reader : public IPTC_Manager {
public:
IPTC_Reader() {};
void SetDataSet_UTF8 ( XMP_Uns8 id, const void* utf8Ptr, XMP_Uns32 utf8Len, long which = -1 ) { NotAppropriate(); };
void DeleteDataSet ( XMP_Uns8 id, long which = -1 ) { NotAppropriate(); };
bool IsChanged() { return false; };
void UpdateMemoryDataSets() { NotAppropriate(); };
virtual ~IPTC_Reader() {};
private:
static inline void NotAppropriate() { XMP_Throw ( "Not appropriate for IPTC_Reader", kXMPErr_InternalFailure ); };
}; // IPTC_Reader
// =================================================================================================
// IPTC_Writer
// ===========
class IPTC_Writer : public IPTC_Manager {
public:
void SetDataSet_UTF8 ( XMP_Uns8 id, const void* utf8Ptr, XMP_Uns32 utf8Len, long which = -1 );
void DeleteDataSet ( XMP_Uns8 id, long which = -1 );
bool IsChanged() { return changed; };
void UpdateMemoryDataSets ();
IPTC_Writer() {};
virtual ~IPTC_Writer();
private:
void ConvertToUTF8();
void ConvertToLocal();
bool CheckRoundTripLoss();
}; // IPTC_Writer
// =================================================================================================
#endif // __IPTC_Support_hpp__
|