diff options
Diffstat (limited to 'XMPFiles/source/FormatSupport/WEBP_Support.hpp')
-rw-r--r-- | XMPFiles/source/FormatSupport/WEBP_Support.hpp | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/XMPFiles/source/FormatSupport/WEBP_Support.hpp b/XMPFiles/source/FormatSupport/WEBP_Support.hpp new file mode 100644 index 0000000..aebe781 --- /dev/null +++ b/XMPFiles/source/FormatSupport/WEBP_Support.hpp @@ -0,0 +1,174 @@ +#ifndef __WEBP_Support_hpp__ +#define __WEBP_Support_hpp__ 1 + +#include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header. + +#include "public/include/XMP_Const.h" +#include "public/include/XMP_IO.hpp" + +#include "XMPFiles/source/XMPFiles_Impl.hpp" +#include "source/Endian.h" +#include "source/XMPFiles_IO.hpp" + +#include <array> +#include <map> +#include <vector> + +// forward declaration: +class WEBP_MetaHandler; + +namespace WEBP { + +// Read 16, 24 or 32 bits stored in little-endian order. +// +// The inline functions provided in EndianUtils.hpp and XIO.hpp operate on +// pointers to XMP_Uns32, and then flip the bytes if the desired endianness +// differs from the host's. It seems to me that it is much simpler to read +// the data into XMP_Uns8 (i.e. unsigned char) arrays and just use shift +// operators (which operate on values rather than their representation +// in memory) to convert between values and the bytes read from or written to +// a file in a platform-independent way. And besides, WEBP stores dimensions +// in 24 bit LE, and converting that to and from a 32 bit pointer, having to +// account for the platform's endianness, would be a nightmare. +static inline XMP_Uns32 GetLE16(const XMP_Uns8* const data) +{ + return (XMP_Uns32)(data[0] << 0) | (data[1] << 8); +} + +static inline XMP_Uns32 GetLE24(const XMP_Uns8* const data) +{ + return GetLE16(data) | (data[2] << 16); +} + +static inline XMP_Uns32 GetLE32(const XMP_Uns8* const data) +{ + return (XMP_Uns32)GetLE16(data) | (GetLE16(data + 2) << 16); +} + +// Store 16, 24 or 32 bits in little-endian order. +static inline void PutLE16(XMP_Uns8* const data, XMP_Uns32 val) +{ + assert(val < (1 << 16)); + data[0] = (val >> 0); + data[1] = (val >> 8); +} + +static inline void PutLE24(XMP_Uns8* const buf, XMP_Uns32 val) +{ + assert(val < (1 << 24)); + PutLE16(buf, val & 0xffff); + buf[2] = (val >> 16); +} + +static inline void PutLE32(XMP_Uns8* const data, XMP_Uns32 val) +{ + PutLE16(data, (XMP_Uns32)(val & 0xffff)); + PutLE16(data + 2, (XMP_Uns32)(val >> 16)); +} + +#define WEBP_MKFOURCC(a, b, c, d) \ + ((XMP_Uns32)(a) | (b) << 8 | (c) << 16 | (d) << 24) + +// VP8X Feature Flags. +typedef enum FeatureFlagBits { + FRAGMENTS_FLAG_BIT, // Experimental, not enabled by default + ANIMATION_FLAG_BIT, + XMP_FLAG_BIT, + EXIF_FLAG_BIT, + ALPHA_FLAG_BIT, + ICCP_FLAG_BIT +} FeatureFlagBits; + +typedef enum ChunkId { + WEBP_CHUNK_VP8X, // VP8X + WEBP_CHUNK_ICCP, // ICCP + WEBP_CHUNK_ANIM, // ANIM + WEBP_CHUNK_ANMF, // ANMF + WEBP_CHUNK_FRGM, // FRGM + WEBP_CHUNK_ALPHA, // ALPH + WEBP_CHUNK_IMAGE, // VP8/VP8L + WEBP_CHUNK_EXIF, // EXIF + WEBP_CHUNK_XMP, // XMP + WEBP_CHUNK_UNKNOWN, // Other chunks. + WEBP_CHUNK_NIL +} ChunkId; + +const XMP_Uns32 kChunk_RIFF = WEBP_MKFOURCC('R', 'I', 'F', 'F'); +const XMP_Uns32 kChunk_WEBP = WEBP_MKFOURCC('W', 'E', 'B', 'P'); +const XMP_Uns32 kChunk_VP8_ = WEBP_MKFOURCC('V', 'P', '8', ' '); +const XMP_Uns32 kChunk_VP8L = WEBP_MKFOURCC('V', 'P', '8', 'L'); +const XMP_Uns32 kChunk_VP8X = WEBP_MKFOURCC('V', 'P', '8', 'X'); +const XMP_Uns32 kChunk_XMP_ = WEBP_MKFOURCC('X', 'M', 'P', ' '); +const XMP_Uns32 kChunk_ANIM = WEBP_MKFOURCC('A', 'N', 'I', 'M'); +const XMP_Uns32 kChunk_ICCP = WEBP_MKFOURCC('I', 'C', 'C', 'P'); +const XMP_Uns32 kChunk_EXIF = WEBP_MKFOURCC('E', 'X', 'I', 'F'); +const XMP_Uns32 kChunk_ANMF = WEBP_MKFOURCC('A', 'N', 'M', 'F'); +const XMP_Uns32 kChunk_FRGM = WEBP_MKFOURCC('F', 'R', 'G', 'M'); +const XMP_Uns32 kChunk_ALPH = WEBP_MKFOURCC('A', 'L', 'P', 'H'); + +static std::map<XMP_Uns32, ChunkId> chunkMap = { + { kChunk_VP8X, WEBP_CHUNK_VP8X }, { kChunk_ICCP, WEBP_CHUNK_ICCP }, + { kChunk_ANIM, WEBP_CHUNK_ANIM }, { kChunk_ANMF, WEBP_CHUNK_ANMF }, + { kChunk_FRGM, WEBP_CHUNK_FRGM }, { kChunk_ALPH, WEBP_CHUNK_ALPHA }, + { kChunk_VP8_, WEBP_CHUNK_IMAGE }, { kChunk_VP8L, WEBP_CHUNK_IMAGE }, + { kChunk_EXIF, WEBP_CHUNK_EXIF }, { kChunk_XMP_, WEBP_CHUNK_XMP } +}; + +class Container; + +class Chunk { +public: + Chunk(Container* parent, WEBP_MetaHandler* handler); + Chunk(Container* parent, XMP_Uns32 tag); + virtual ~Chunk(); + + virtual void write(WEBP_MetaHandler* handler); + + Container* parent; + XMP_Uns32 tag; + RawDataBlock data; + XMP_Int64 pos; + XMP_Int64 size; + bool needsRewrite; +}; + +class XMPChunk + : public Chunk { +public: + XMPChunk(Container* parent, WEBP_MetaHandler* handler); + XMPChunk(Container* parent); + void write(WEBP_MetaHandler* handler); +}; + +class VP8XChunk + : public Chunk { +public: + VP8XChunk(Container* parent, WEBP_MetaHandler* handler); + VP8XChunk(Container* parent); + bool xmp(); + void xmp(bool); + XMP_Uns32 width(); + XMP_Uns32 height(); + void width(XMP_Uns32); + void height(XMP_Uns32); +}; + +typedef std::array<std::vector<Chunk*>, WEBP_CHUNK_NIL> Chunks; + +class Container + : public Chunk { +public: + Container(WEBP_MetaHandler* handler); + ~Container(); + + void write(WEBP_MetaHandler* handler); + void addChunk(Chunk*); + Chunk* getExifChunk(); + + Chunks chunks; + VP8XChunk* vp8x; +}; + +} // namespace WEBP + +#endif // __WEBP_Support_hpp__ |