Merge "Chunk fourCCs for XMP/EXIF"

This commit is contained in:
James Zern
2012-11-06 16:17:32 -08:00
committed by Gerrit Code Review
11 changed files with 208 additions and 147 deletions

View File

@ -41,7 +41,7 @@ extern "C" {
// 24..26 Width of the Canvas Image.
// 27..29 Height of the Canvas Image.
// There can be extra chunks after the "VP8X" chunk (ICCP, TILE, FRM, VP8,
// META ...)
// XMP, EXIF ...)
// All sizes are in little-endian order.
// Note: chunk data size must be padded to multiple of 2 when written.

View File

@ -514,8 +514,12 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
store_chunk = !!(dmux->feature_flags_ & ICCP_FLAG);
goto Skip;
}
case MKFOURCC('M', 'E', 'T', 'A'): {
store_chunk = !!(dmux->feature_flags_ & META_FLAG);
case MKFOURCC('X', 'M', 'P', ' '): {
store_chunk = !!(dmux->feature_flags_ & XMP_FLAG);
goto Skip;
}
case MKFOURCC('E', 'X', 'I', 'F'): {
store_chunk = !!(dmux->feature_flags_ & EXIF_FLAG);
goto Skip;
}
Skip:

View File

@ -48,7 +48,8 @@ static void MuxRelease(WebPMux* const mux) {
DeleteAllChunks(&mux->vp8x_);
DeleteAllChunks(&mux->iccp_);
DeleteAllChunks(&mux->loop_);
DeleteAllChunks(&mux->meta_);
DeleteAllChunks(&mux->exif_);
DeleteAllChunks(&mux->xmp_);
DeleteAllChunks(&mux->unknown_);
}
@ -82,7 +83,8 @@ static WebPMuxError MuxSet(WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth,
SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
SWITCH_ID_LIST(IDX_LOOP, &mux->loop_);
SWITCH_ID_LIST(IDX_META, &mux->meta_);
SWITCH_ID_LIST(IDX_EXIF, &mux->exif_);
SWITCH_ID_LIST(IDX_XMP, &mux->xmp_);
if (idx == IDX_UNKNOWN && data->size > TAG_SIZE) {
// For raw-data unknown chunk, the first four bytes should be the tag to be
// used for the chunk.
@ -529,11 +531,12 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) {
flags |= ICCP_FLAG;
}
if (mux->meta_ != NULL && mux->meta_->data_.bytes != NULL) {
flags |= META_FLAG;
if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) {
flags |= EXIF_FLAG;
}
if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) {
flags |= XMP_FLAG;
}
if (images->header_ != NULL) {
if (images->header_->tag_ == kChunks[IDX_FRGM].tag) {
// This is a tiled image.
@ -543,7 +546,6 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
flags |= ANIMATION_FLAG;
}
}
if (MuxImageCount(images, WEBP_CHUNK_ALPHA) > 0) {
flags |= ALPHA_FLAG; // Some images have an alpha channel.
}
@ -610,8 +612,8 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) {
// Allocate data.
size = ChunksListDiskSize(mux->vp8x_) + ChunksListDiskSize(mux->iccp_)
+ ChunksListDiskSize(mux->loop_) + MuxImageListDiskSize(mux->images_)
+ ChunksListDiskSize(mux->meta_) + ChunksListDiskSize(mux->unknown_)
+ RIFF_HEADER_SIZE;
+ ChunksListDiskSize(mux->exif_) + ChunksListDiskSize(mux->xmp_)
+ ChunksListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE;
data = (uint8_t*)malloc(size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
@ -622,7 +624,8 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) {
dst = ChunkListEmit(mux->iccp_, dst);
dst = ChunkListEmit(mux->loop_, dst);
dst = MuxImageListEmit(mux->images_, dst);
dst = ChunkListEmit(mux->meta_, dst);
dst = ChunkListEmit(mux->exif_, dst);
dst = ChunkListEmit(mux->xmp_, dst);
dst = ChunkListEmit(mux->unknown_, dst);
assert(dst == data + size);

View File

@ -51,7 +51,8 @@ struct WebPMuxImage {
struct WebPMux {
WebPMuxImage* images_;
WebPChunk* iccp_;
WebPChunk* meta_;
WebPChunk* exif_;
WebPChunk* xmp_;
WebPChunk* loop_;
WebPChunk* vp8x_;
@ -71,7 +72,8 @@ typedef enum {
IDX_ALPHA,
IDX_VP8,
IDX_VP8L,
IDX_META,
IDX_EXIF,
IDX_XMP,
IDX_UNKNOWN,
IDX_NIL,

View File

@ -28,7 +28,8 @@ const ChunkInfo kChunks[] = {
{ MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
{ NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
@ -446,7 +447,8 @@ WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_;
case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_;
case WEBP_CHUNK_LOOP: return (WebPChunk**)&mux->loop_;
case WEBP_CHUNK_META: return (WebPChunk**)&mux->meta_;
case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_;
case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_;
case WEBP_CHUNK_UNKNOWN: return (WebPChunk**)&mux->unknown_;
default: return NULL;
}
@ -495,7 +497,8 @@ static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx,
WebPMuxError MuxValidate(const WebPMux* const mux) {
int num_iccp;
int num_meta;
int num_exif;
int num_xmp;
int num_loop_chunks;
int num_frames;
int num_tiles;
@ -518,8 +521,12 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
err = ValidateChunk(mux, IDX_ICCP, ICCP_FLAG, flags, 1, &num_iccp);
if (err != WEBP_MUX_OK) return err;
// At most one EXIF metadata.
err = ValidateChunk(mux, IDX_EXIF, EXIF_FLAG, flags, 1, &num_exif);
if (err != WEBP_MUX_OK) return err;
// At most one XMP metadata.
err = ValidateChunk(mux, IDX_META, META_FLAG, flags, 1, &num_meta);
err = ValidateChunk(mux, IDX_XMP, XMP_FLAG, flags, 1, &num_xmp);
if (err != WEBP_MUX_OK) return err;
// Animation: ANIMATION_FLAG, loop chunk and frame chunk(s) are consistent.

View File

@ -42,7 +42,8 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_);
SWITCH_ID_LIST(IDX_ICCP, mux->iccp_);
SWITCH_ID_LIST(IDX_LOOP, mux->loop_);
SWITCH_ID_LIST(IDX_META, mux->meta_);
SWITCH_ID_LIST(IDX_EXIF, mux->exif_);
SWITCH_ID_LIST(IDX_XMP, mux->xmp_);
SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_);
return WEBP_MUX_NOT_FOUND;
}

View File

@ -70,12 +70,14 @@ typedef enum {
#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk.
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
#define TILING_FLAG_BIT 0x01 // Set if tiles are possibly used.
#define ANIMATION_FLAG_BIT 0x02 // Set if some animation is expected
#define ICC_FLAG_BIT 0x04 // Whether ICC is present or not.
#define METADATA_FLAG_BIT 0x08 // Set if some META chunk is possibly present.
#define ALPHA_FLAG_BIT 0x10 // Should be same as the ALPHA_FLAG in mux.h
#define ROTATION_FLAG_BITS 0xe0 // all 3 bits for rotation + symmetry
// VP8X Feature Flags. These should be the same as the corresponding values in
// the 'WebPFeatureFlags' enum defined in mux.h.
#define FRAGMENTS_FLAG_BIT 0x01
#define ANIMATION_FLAG_BIT 0x02
#define XMP_FLAG_BIT 0x04
#define EXIF_FLAG_BIT 0x08
#define ALPHA_FLAG_BIT 0x10
#define ICC_FLAG_BIT 0x20
#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.

View File

@ -11,7 +11,7 @@
// Vikas (vikasa@google.com)
// This API allows manipulation of WebP container images containing features
// like Color profile, XMP metadata, Animation and Tiling.
// like color profile, metadata, animation and tiling.
//
// Code Example#1: Creating a MUX with image data, color profile and XMP
// metadata.
@ -23,7 +23,7 @@
// // ... (Prepare ICCP color profile data).
// WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
// // ... (Prepare XMP metadata).
// WebPMuxSetChunk(mux, "META", &xmp, copy_data);
// WebPMuxSetChunk(mux, "XMP ", &xmp, copy_data);
// // Get data from mux in WebP RIFF format.
// WebPMuxAssemble(mux, &output_data);
// WebPMuxDelete(mux);
@ -84,9 +84,10 @@ enum WebPMuxError {
enum WebPFeatureFlags {
TILE_FLAG = 0x00000001,
ANIMATION_FLAG = 0x00000002,
ICCP_FLAG = 0x00000004,
META_FLAG = 0x00000008,
ALPHA_FLAG = 0x00000010
XMP_FLAG = 0x00000004,
EXIF_FLAG = 0x00000008,
ALPHA_FLAG = 0x00000010,
ICCP_FLAG = 0x00000020
};
// IDs for different types of chunks.
@ -98,7 +99,8 @@ enum WebPChunkId {
WEBP_CHUNK_FRGM, // FRGM
WEBP_CHUNK_ALPHA, // ALPH
WEBP_CHUNK_IMAGE, // VP8/VP8L
WEBP_CHUNK_META, // META
WEBP_CHUNK_EXIF, // EXIF
WEBP_CHUNK_XMP, // XMP
WEBP_CHUNK_UNKNOWN, // Other chunks.
WEBP_CHUNK_NIL
};
@ -174,7 +176,7 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream,
// Parameters:
// mux - (in/out) object to which the chunk is to be added
// fourcc - (in) a character array containing the fourcc of the given chunk;
// e.g., "ICCP", "META" etc.
// e.g., "ICCP", "XMP ", "EXIF" etc.
// chunk_data - (in) the chunk data to be added
// copy_data - (in) value 1 indicates given data WILL be copied to the mux
// and value 0 indicates data will NOT be copied.
@ -192,7 +194,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk(
// Parameters:
// mux - (in) object from which the chunk data is to be fetched
// fourcc - (in) a character array containing the fourcc of the chunk;
// e.g., "ICCP", "META" etc.
// e.g., "ICCP", "XMP ", "EXIF" etc.
// chunk_data - (out) returned chunk data
// Returns:
// WEBP_MUX_INVALID_ARGUMENT - if either mux, fourcc or chunk_data is NULL
@ -206,7 +208,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk(
// Parameters:
// mux - (in/out) object from which the chunk is to be deleted
// fourcc - (in) a character array containing the fourcc of the chunk;
// e.g., "ICCP", "META" etc.
// e.g., "ICCP", "XMP ", "EXIF" etc.
// Returns:
// WEBP_MUX_INVALID_ARGUMENT - if mux or fourcc is NULL
// or if fourcc corresponds to an image chunk.
@ -481,7 +483,7 @@ struct WebPChunkIterator {
// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from
// 'dmux'.
// 'fourcc' is a character array containing the fourcc of the chunk to return,
// e.g., "ICCP", "META", "EXIF", etc.
// e.g., "ICCP", "XMP ", "EXIF", etc.
// Setting 'chunk_number' equal to 0 will return the last chunk in a set.
// Returns true if the chunk is found, false otherwise. Image related chunk
// payloads are accessed through WebPDemuxGetFrame() and related functions.