diff --git a/README.mux b/README.mux index 79ea6154..3c9a2d51 100644 --- a/README.mux +++ b/README.mux @@ -77,9 +77,9 @@ profile & XMP metadata. // ... (Prepare image data). WebPMuxSetImage(mux, &image, copy_data); // ... (Prepare ICCP color profile data). - WebPMuxSetColorProfile(mux, &icc_profile, copy_data); + WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); // ... (Prepare XMP metadata). - WebPMuxSetMetadata(mux, &xmp, copy_data); + WebPMuxSetChunk(mux, "META", &xmp, copy_data); // Get data from mux in WebP RIFF format. WebPMuxAssemble(mux, &output_data); WebPMuxDelete(mux); @@ -94,7 +94,7 @@ Example#2 (pseudo code): Get image & color profile data from a WebP file. WebPMux* mux = WebPMuxCreate(&data, copy_data); WebPMuxGetImage(mux, &image); // ... (Consume image; e.g. call WebPDecode() to decode the data). - WebPMuxGetColorProfile(mux, &icc_profile); + WebPMuxGetChunk(mux, "ICCP", &icc_profile); // ... (Consume icc_profile). WebPMuxDelete(mux); free(data); diff --git a/examples/webpmux.c b/examples/webpmux.c index c5454d16..32afd229 100644 --- a/examples/webpmux.c +++ b/examples/webpmux.c @@ -234,14 +234,14 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) { if (flag & ICCP_FLAG) { WebPData icc_profile; - err = WebPMuxGetColorProfile(mux, &icc_profile); + err = WebPMuxGetChunk(mux, "ICCP", &icc_profile); RETURN_IF_ERROR("Failed to retrieve the color profile\n"); printf("Size of the color profile data: %zu\n", icc_profile.size_); } if (flag & META_FLAG) { WebPData metadata; - err = WebPMuxGetMetadata(mux, &metadata); + err = WebPMuxGetChunk(mux, "META", &metadata); RETURN_IF_ERROR("Failed to retrieve the XMP metadata\n"); printf("Size of the XMP metadata: %zu\n", metadata.size_); } @@ -755,7 +755,7 @@ static int Process(const WebPMuxConfig* config) { break; case FEATURE_ICCP: - err = WebPMuxGetColorProfile(mux, &color_profile); + err = WebPMuxGetChunk(mux, "ICCP", &color_profile); if (err != WEBP_MUX_OK) { ERROR_GOTO2("ERROR (%s): Could not get color profile.\n", ErrorString(err), Err2); @@ -763,7 +763,7 @@ static int Process(const WebPMuxConfig* config) { ok = WriteData(config->output_, &color_profile); break; case FEATURE_XMP: - err = WebPMuxGetMetadata(mux, &metadata); + err = WebPMuxGetChunk(mux, "META", &metadata); if (err != WEBP_MUX_OK) { ERROR_GOTO2("ERROR (%s): Could not get XMP metadata.\n", ErrorString(err), Err2); @@ -848,7 +848,7 @@ static int Process(const WebPMuxConfig* config) { if (!ok) goto Err2; ok = ReadFileToWebPData(feature->args_[0].filename_, &color_profile); if (!ok) goto Err2; - err = WebPMuxSetColorProfile(mux, &color_profile, 1); + err = WebPMuxSetChunk(mux, "ICCP", &color_profile, 1); free((void*)color_profile.bytes_); if (err != WEBP_MUX_OK) { ERROR_GOTO2("ERROR (%s): Could not set color profile.\n", @@ -861,7 +861,7 @@ static int Process(const WebPMuxConfig* config) { if (!ok) goto Err2; ok = ReadFileToWebPData(feature->args_[0].filename_, &metadata); if (!ok) goto Err2; - err = WebPMuxSetMetadata(mux, &metadata, 1); + err = WebPMuxSetChunk(mux, "META", &metadata, 1); free((void*)metadata.bytes_); if (err != WEBP_MUX_OK) { ERROR_GOTO2("ERROR (%s): Could not set XMP metadata.\n", @@ -881,14 +881,14 @@ static int Process(const WebPMuxConfig* config) { if (!ok) goto Err2; switch (feature->type_) { case FEATURE_ICCP: - err = WebPMuxDeleteColorProfile(mux); + err = WebPMuxDeleteChunk(mux, "ICCP"); if (err != WEBP_MUX_OK) { ERROR_GOTO2("ERROR (%s): Could not delete color profile.\n", ErrorString(err), Err2); } break; case FEATURE_XMP: - err = WebPMuxDeleteMetadata(mux); + err = WebPMuxDeleteChunk(mux, "META"); if (err != WEBP_MUX_OK) { ERROR_GOTO2("ERROR (%s): Could not delete XMP metadata.\n", ErrorString(err), Err2); diff --git a/src/mux/muxedit.c b/src/mux/muxedit.c index c7b50ae7..6796ac85 100644 --- a/src/mux/muxedit.c +++ b/src/mux/muxedit.c @@ -185,8 +185,8 @@ static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { return err; } -static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, CHUNK_INDEX idx) { - const WebPChunkId id = kChunks[idx].id; +static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) { + const WebPChunkId id = ChunkGetIdFromTag(tag); WebPChunk** chunk_list; if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; @@ -195,11 +195,11 @@ static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, CHUNK_INDEX idx) { chunk_list = MuxGetChunkListFromId(mux, id); if (chunk_list == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return DeleteChunks(chunk_list, kChunks[idx].tag); + return DeleteChunks(chunk_list, tag); } static WebPMuxError DeleteLoopCount(WebPMux* const mux) { - return MuxDeleteAllNamedData(mux, IDX_LOOP); + return MuxDeleteAllNamedData(mux, kChunks[IDX_LOOP].tag); } //------------------------------------------------------------------------------ @@ -260,39 +260,24 @@ WebPMuxError WebPMuxSetImage(WebPMux* mux, return err; } -WebPMuxError WebPMuxSetMetadata(WebPMux* mux, const WebPData* metadata, - int copy_data) { +WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], + const WebPData* chunk_data, int copy_data) { + const CHUNK_INDEX idx = ChunkGetIndexFromFourCC(fourcc); + const uint32_t tag = ChunkGetTagFromFourCC(fourcc); WebPMuxError err; - - if (mux == NULL || metadata == NULL || metadata->bytes_ == NULL || - metadata->size_ > MAX_CHUNK_PAYLOAD) { + if (mux == NULL || chunk_data == NULL || chunk_data->bytes_ == NULL || + chunk_data->size_ > MAX_CHUNK_PAYLOAD) { return WEBP_MUX_INVALID_ARGUMENT; } - // Delete the existing metadata chunk(s). - err = WebPMuxDeleteMetadata(mux); + // Delete existing chunk(s) with the same 'fourcc'. + err = MuxDeleteAllNamedData(mux, tag); if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - // Add the given metadata chunk. - return MuxSet(mux, IDX_META, 1, metadata, copy_data); + // Add the given chunk. + return MuxSet(mux, idx, 1, chunk_data, copy_data); } -WebPMuxError WebPMuxSetColorProfile(WebPMux* mux, const WebPData* color_profile, - int copy_data) { - WebPMuxError err; - - if (mux == NULL || color_profile == NULL || color_profile->bytes_ == NULL || - color_profile->size_ > MAX_CHUNK_PAYLOAD) { - return WEBP_MUX_INVALID_ARGUMENT; - } - - // Delete the existing ICCP chunk(s). - err = WebPMuxDeleteColorProfile(mux); - if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; - - // Add the given ICCP chunk. - return MuxSet(mux, IDX_ICCP, 1, color_profile, copy_data); -} WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, int loop_count) { WebPMuxError err; @@ -437,12 +422,8 @@ WebPMuxError WebPMuxDeleteImage(WebPMux* mux) { return WEBP_MUX_OK; } -WebPMuxError WebPMuxDeleteMetadata(WebPMux* mux) { - return MuxDeleteAllNamedData(mux, IDX_META); -} - -WebPMuxError WebPMuxDeleteColorProfile(WebPMux* mux) { - return MuxDeleteAllNamedData(mux, IDX_ICCP); +WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { + return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); } static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, uint32_t nth, @@ -595,7 +576,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { // If VP8X chunk(s) is(are) already present, remove them (and later add new // VP8X chunk with updated flags). - err = MuxDeleteAllNamedData(mux, IDX_VP8X); + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; // Set flags. diff --git a/src/mux/muxi.h b/src/mux/muxi.h index edd8c368..603e4547 100644 --- a/src/mux/muxi.h +++ b/src/mux/muxi.h @@ -140,6 +140,12 @@ CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); // Get chunk id from chunk tag. Returns WEBP_CHUNK_NIL if not found. WebPChunkId ChunkGetIdFromTag(uint32_t tag); +// Convert a fourcc string to a tag. +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]); + +// Get chunk index from fourcc. Returns IDX_UNKNOWN if given fourcc is unknown. +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]); + // Search for nth chunk with given 'tag' in the chunk list. // nth = 0 means "last of the list". WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag); diff --git a/src/mux/muxinternal.c b/src/mux/muxinternal.c index 165e3ecc..13d9cfe0 100644 --- a/src/mux/muxinternal.c +++ b/src/mux/muxinternal.c @@ -73,6 +73,16 @@ WebPChunkId ChunkGetIdFromTag(uint32_t tag) { return WEBP_CHUNK_NIL; } +uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) { + return MKFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]); +} + +CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) { + const uint32_t tag = ChunkGetTagFromFourCC(fourcc); + const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag); + return (idx == IDX_NIL) ? IDX_UNKNOWN : idx; +} + //------------------------------------------------------------------------------ // Chunk search methods. diff --git a/src/mux/muxread.c b/src/mux/muxread.c index 5d135115..9f08ea32 100644 --- a/src/mux/muxread.c +++ b/src/mux/muxread.c @@ -289,15 +289,21 @@ WebPMuxError WebPMuxGetImage(const WebPMux* mux, WebPData* bitstream) { return SynthesizeBitstream(wpi, bitstream); } -WebPMuxError WebPMuxGetMetadata(const WebPMux* mux, WebPData* metadata) { - if (mux == NULL || metadata == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxGet(mux, IDX_META, 1, metadata); -} - -WebPMuxError WebPMuxGetColorProfile(const WebPMux* mux, - WebPData* color_profile) { - if (mux == NULL || color_profile == NULL) return WEBP_MUX_INVALID_ARGUMENT; - return MuxGet(mux, IDX_ICCP, 1, color_profile); +WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], + WebPData* chunk_data) { + const CHUNK_INDEX idx = ChunkGetIndexFromFourCC(fourcc); + if (mux == NULL || chunk_data == NULL || IsWPI(kChunks[idx].id)) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (idx != IDX_UNKNOWN) { // A known chunk type. + return MuxGet(mux, idx, 1, chunk_data); + } else { // An unknown chunk type. + const WebPChunk* const chunk = + ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc)); + if (chunk == NULL) return WEBP_MUX_NOT_FOUND; + *chunk_data = chunk->data_; + return WEBP_MUX_OK; + } } WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) { diff --git a/src/webp/mux.h b/src/webp/mux.h index cdfc441e..5d3aa1b3 100644 --- a/src/webp/mux.h +++ b/src/webp/mux.h @@ -21,9 +21,9 @@ // // ... (Prepare image data). // WebPMuxSetImage(mux, &image, copy_data); // // ... (Prepare ICCP color profile data). -// WebPMuxSetColorProfile(mux, &icc_profile, copy_data); +// WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); // // ... (Prepare XMP metadata). -// WebPMuxSetMetadata(mux, &xmp, copy_data); +// WebPMuxSetChunk(mux, "META", &xmp, copy_data); // // Get data from mux in WebP RIFF format. // WebPMuxAssemble(mux, &output_data); // WebPMuxDelete(mux); @@ -37,7 +37,7 @@ // WebPMux* mux = WebPMuxCreate(&data, copy_data); // WebPMuxGetImage(mux, &image); // // ... (Consume image; e.g. call WebPDecode() to decode the data). -// WebPMuxGetColorProfile(mux, &icc_profile); +// WebPMuxGetChunk(mux, "ICCP", &icc_profile); // // ... (Consume icc_data). // WebPMuxDelete(mux); // free(data); @@ -191,82 +191,56 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetImage(const WebPMux* mux, WEBP_EXTERN(WebPMuxError) WebPMuxDeleteImage(WebPMux* mux); //------------------------------------------------------------------------------ -// XMP Metadata. +// Chunks. -// Sets the XMP metadata in the mux object. Any existing metadata chunk(s) will -// be removed. +// Note: Only non-image related chunks should be managed through chunk APIs. +// (Image related chunks are: "FRM ", "TILE", "VP8 ", "VP8L" and "ALPH"). + +// Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. +// Any existing chunk(s) with the same id will be removed. // Parameters: -// mux - (in/out) object to which the XMP metadata is to be added -// metadata - (in) the XMP metadata data to be added +// 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. +// chunk_data - (in) the chunk data to be added // copy_data - (in) value 1 indicates given data WILL copied to the mux, and // value 0 indicates data will NOT be copied. // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or metadata is NULL. +// WEBP_MUX_INVALID_ARGUMENT - if mux or chunk_data is NULL +// or if fourcc corresponds to an image chunk. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetMetadata(WebPMux* mux, - const WebPData* metadata, - int copy_data); +WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk( + WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, + int copy_data); -// Gets a reference to the XMP metadata in the mux object. +// Gets a reference to the data of the chunk with id 'fourcc' in the mux object. // The caller should NOT free the returned data. // Parameters: -// mux - (in) object from which the XMP metadata is to be fetched -// metadata - (out) XMP metadata +// 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. +// chunk_data - (out) returned chunk data // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux or metadata is NULL. -// WEBP_MUX_NOT_FOUND - if metadata is not present in mux object. +// WEBP_MUX_INVALID_ARGUMENT - if either mux or chunk_data is NULL +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetMetadata(const WebPMux* mux, - WebPData* metadata); +WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk( + const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); -// Deletes the XMP metadata in the mux object. +// Deletes the chunk with the given 'fourcc' from the mux object. // Parameters: -// mux - (in/out) object from which XMP metadata is to be deleted +// 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. // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// WEBP_MUX_NOT_FOUND - If mux does not contain metadata. +// or if fourcc corresponds to an image chunk. +// WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteMetadata(WebPMux* mux); - -//------------------------------------------------------------------------------ -// ICC Color Profile. - -// Sets the color profile in the mux object. Any existing color profile chunk(s) -// will be removed. -// Parameters: -// mux - (in/out) object to which the color profile is to be added -// color_profile - (in) the color profile data to be added -// copy_data - (in) value 1 indicates given data WILL copied to the mux, and -// value 0 indicates data will NOT be copied. -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux or color_profile is NULL -// WEBP_MUX_MEMORY_ERROR - on memory allocation error -// WEBP_MUX_OK - on success -WEBP_EXTERN(WebPMuxError) WebPMuxSetColorProfile(WebPMux* mux, - const WebPData* color_profile, - int copy_data); - -// Gets a reference to the color profile in the mux object. -// The caller should NOT free the returned data. -// Parameters: -// mux - (in) object from which the color profile data is to be fetched -// color_profile - (out) color profile data -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux or color_profile is NULL. -// WEBP_MUX_NOT_FOUND - if color profile is not present in mux object. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetColorProfile(const WebPMux* mux, - WebPData* color_profile); - -// Deletes the color profile in the mux object. -// Parameters: -// mux - (in/out) object from which color profile is to be deleted -// Returns: -// WEBP_MUX_INVALID_ARGUMENT - if mux is NULL -// WEBP_MUX_NOT_FOUND - If mux does not contain color profile. -// WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteColorProfile(WebPMux* mux); +WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( + WebPMux* mux, const char fourcc[4]); //------------------------------------------------------------------------------ // Animation.