diff --git a/examples/vwebp.c b/examples/vwebp.c index a2046fd2..61189105 100644 --- a/examples/vwebp.c +++ b/examples/vwebp.c @@ -304,7 +304,7 @@ int main(int argc, char *argv[]) { if (mux_err != WEBP_MUX_OK && mux_err != WEBP_MUX_NOT_FOUND) { goto Error; } - mux_err = WebPMuxNumNamedElements(kParams.mux, "image", + mux_err = WebPMuxNumChunks(kParams.mux, WEBP_CHUNK_IMAGE, &kParams.frame_max); if (mux_err != WEBP_MUX_OK) { goto Error; diff --git a/examples/webpmux.c b/examples/webpmux.c index 6abca107..f05178a0 100644 --- a/examples/webpmux.c +++ b/examples/webpmux.c @@ -195,7 +195,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) { RETURN_IF_ERROR("Failed to retrieve loop count\n"); printf("Loop Count : %d\n", loop_count); - err = WebPMuxNumNamedElements(mux, "frame", &nFrames); + err = WebPMuxNumChunks(mux, WEBP_CHUNK_FRAME, &nFrames); RETURN_IF_ERROR("Failed to retrieve number of frames\n"); printf("Number of frames: %d\n", nFrames); @@ -220,7 +220,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) { if (flag & TILE_FLAG) { int nTiles; - err = WebPMuxNumNamedElements(mux, "tile", &nTiles); + err = WebPMuxNumChunks(mux, WEBP_CHUNK_TILE, &nTiles); RETURN_IF_ERROR("Failed to retrieve number of tiles\n"); printf("Number of tiles: %d\n", nTiles); diff --git a/src/mux/muxedit.c b/src/mux/muxedit.c index 74fac063..29513d93 100644 --- a/src/mux/muxedit.c +++ b/src/mux/muxedit.c @@ -205,13 +205,11 @@ static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) { return err; } -static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, - const char* const name) { - const CHUNK_INDEX idx = ChunkGetIndexFromName(name); - const TAG_ID id = kChunks[idx].id; +static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, CHUNK_INDEX idx) { + const WebPChunkId id = kChunks[idx].id; WebPChunk** chunk_list; - if (mux == NULL || name == NULL) return WEBP_MUX_INVALID_ARGUMENT; + if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT; chunk_list = MuxGetChunkListFromId(mux, id); @@ -221,7 +219,7 @@ static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, } static WebPMuxError DeleteLoopCount(WebPMux* const mux) { - return MuxDeleteAllNamedData(mux, kChunks[IDX_LOOP].name); + return MuxDeleteAllNamedData(mux, IDX_LOOP); } //------------------------------------------------------------------------------ @@ -462,18 +460,16 @@ WebPMuxError WebPMuxDeleteImage(WebPMux* const mux) { } WebPMuxError WebPMuxDeleteMetadata(WebPMux* const mux) { - return MuxDeleteAllNamedData(mux, kChunks[IDX_META].name); + return MuxDeleteAllNamedData(mux, IDX_META); } WebPMuxError WebPMuxDeleteColorProfile(WebPMux* const mux) { - return MuxDeleteAllNamedData(mux, kChunks[IDX_ICCP].name); + return MuxDeleteAllNamedData(mux, IDX_ICCP); } -static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, - uint32_t nth, - const char* const name) { - const CHUNK_INDEX idx = ChunkGetIndexFromName(name); - const TAG_ID id = kChunks[idx].id; +static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, uint32_t nth, + CHUNK_INDEX idx) { + const WebPChunkId id = kChunks[idx].id; if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; assert(idx == IDX_FRAME || idx == IDX_TILE); @@ -481,11 +477,11 @@ static WebPMuxError DeleteFrameTileInternal(WebPMux* const mux, } WebPMuxError WebPMuxDeleteFrame(WebPMux* const mux, uint32_t nth) { - return DeleteFrameTileInternal(mux, nth, kChunks[IDX_FRAME].name); + return DeleteFrameTileInternal(mux, nth, IDX_FRAME); } WebPMuxError WebPMuxDeleteTile(WebPMux* const mux, uint32_t nth) { - return DeleteFrameTileInternal(mux, nth, kChunks[IDX_TILE].name); + return DeleteFrameTileInternal(mux, nth, IDX_TILE); } //------------------------------------------------------------------------------ @@ -589,7 +585,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, kChunks[IDX_VP8X].name); + err = MuxDeleteAllNamedData(mux, IDX_VP8X); if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; // Set flags. @@ -636,8 +632,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { PutLE32(data + 4, width); // canvas width. PutLE32(data + 8, height); // canvas height. - err = MuxAddChunk(mux, 1, kChunks[IDX_VP8X].tag, data, data_size, - NULL, 1); + err = MuxAddChunk(mux, 1, kChunks[IDX_VP8X].tag, data, data_size, NULL, 1); return err; } @@ -655,12 +650,10 @@ WebPMuxError WebPMuxAssemble(WebPMux* const mux, } // Remove LOOP chunk if unnecessary. - err = WebPMuxNumNamedElements(mux, kChunks[IDX_LOOP].name, - &num_loop_chunks); + err = WebPMuxNumChunks(mux, kChunks[IDX_LOOP].id, &num_loop_chunks); if (err != WEBP_MUX_OK) return err; if (num_loop_chunks >= 1) { - err = WebPMuxNumNamedElements(mux, kChunks[IDX_FRAME].name, - &num_frames); + err = WebPMuxNumChunks(mux, kChunks[IDX_FRAME].id, &num_frames); if (err != WEBP_MUX_OK) return err; if (num_frames == 0) { err = DeleteLoopCount(mux); diff --git a/src/mux/muxi.h b/src/mux/muxi.h index 045877f3..3dfd0001 100644 --- a/src/mux/muxi.h +++ b/src/mux/muxi.h @@ -51,9 +51,9 @@ struct WebPChunk { // chunk and VP8/VP8L chunk), typedef struct WebPMuxImage WebPMuxImage; struct WebPMuxImage { - WebPChunk* header_; // Corresponds to FRAME_ID/TILE_ID. - WebPChunk* alpha_; // Corresponds to ALPHA_ID. - WebPChunk* img_; // Corresponds to IMAGE_ID. + WebPChunk* header_; // Corresponds to WEBP_CHUNK_FRAME/WEBP_CHUNK_TILE. + WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA. + WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE. int is_partial_; // True if only some of the chunks are filled. WebPMuxImage* next_; }; @@ -69,24 +69,10 @@ struct WebPMux { WebPChunk* unknown_; }; -// TAG_ID enum: used to assign an ID to each type of chunk. -typedef enum { - VP8X_ID, - ICCP_ID, - LOOP_ID, - FRAME_ID, - TILE_ID, - ALPHA_ID, - IMAGE_ID, - META_ID, - UNKNOWN_ID, - NIL_ID -} TAG_ID; - // CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only. -// Note: the reason for having two enums ('TAG_ID' and 'CHUNK_INDEX') is to -// allow two different chunks to have the same id (e.g. TAG_ID 'IMAGE_ID' can -// correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). +// Note: the reason for having two enums ('WebPChunkId' and 'CHUNK_INDEX') is to +// allow two different chunks to have the same id (e.g. WebPChunkId +// 'WEBP_CHUNK_IMAGE' can correspond to CHUNK_INDEX 'IDX_VP8' or 'IDX_VP8L'). typedef enum { IDX_VP8X = 0, IDX_ICCP, @@ -109,9 +95,8 @@ typedef enum { ((uint32_t)c1 | (c2 << 8) | (c3 << 16) | (c4 << 24)) typedef struct { - const char* name; uint32_t tag; - TAG_ID id; + WebPChunkId id; uint32_t size; } ChunkInfo; @@ -144,17 +129,11 @@ static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { // Initialize. void ChunkInit(WebPChunk* const chunk); -// Get chunk index from chunk name. -// Returns IDX_NIL if chunk name is NULL or not found. -CHUNK_INDEX ChunkGetIndexFromName(const char* const name); - -// Get chunk index from chunk tag. -// Returns IDX_NIL if not found. +// Get chunk index from chunk tag. Returns IDX_NIL if not found. CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag); -// Get chunk id from chunk tag. -// Returns NIL_ID if not found. -TAG_ID ChunkGetIdFromTag(uint32_t tag); +// Get chunk id from chunk tag. Returns WEBP_CHUNK_NIL if not found. +WebPChunkId ChunkGetIdFromTag(uint32_t tag); // Search for nth chunk with given 'tag' in the chunk list. // nth = 0 means "last of the list". @@ -206,28 +185,28 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); void MuxImageDeleteAll(WebPMuxImage** const wpi_list); // Count number of images matching the given tag id in the 'wpi_list'. -int MuxImageCount(WebPMuxImage* const wpi_list, TAG_ID id); +int MuxImageCount(WebPMuxImage* const wpi_list, WebPChunkId id); // Check if given ID corresponds to an image related chunk. -static WEBP_INLINE int IsWPI(TAG_ID id) { +static WEBP_INLINE int IsWPI(WebPChunkId id) { switch (id) { - case FRAME_ID: - case TILE_ID: - case ALPHA_ID: - case IMAGE_ID: return 1; + case WEBP_CHUNK_FRAME: + case WEBP_CHUNK_TILE: + case WEBP_CHUNK_ALPHA: + case WEBP_CHUNK_IMAGE: return 1; default: return 0; } } // Get a reference to appropriate chunk list within an image given chunk tag. static WEBP_INLINE WebPChunk** MuxImageGetListFromId(WebPMuxImage* wpi, - TAG_ID id) { + WebPChunkId id) { assert(wpi != NULL); switch (id) { - case FRAME_ID: - case TILE_ID: return &wpi->header_; - case ALPHA_ID: return &wpi->alpha_; - case IMAGE_ID: return &wpi->img_; + case WEBP_CHUNK_FRAME: + case WEBP_CHUNK_TILE: return &wpi->header_; + case WEBP_CHUNK_ALPHA: return &wpi->alpha_; + case WEBP_CHUNK_IMAGE: return &wpi->img_; default: return NULL; } } @@ -239,11 +218,11 @@ WebPMuxError MuxImageSetNth(const WebPMuxImage* wpi, WebPMuxImage** wpi_list, // Delete nth image in the image list with given tag id. WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, - TAG_ID id); + WebPChunkId id); // Get nth image in the image list with given tag id. WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - TAG_ID id, WebPMuxImage** wpi); + WebPChunkId id, WebPMuxImage** wpi); // Total size of a list of images. size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list); @@ -260,7 +239,7 @@ int MuxHasLosslessImages(const WebPMuxImage* images); // Returns the list where chunk with given ID is to be inserted in mux. // Return value is NULL if this chunk should be inserted in mux->images_ list // or if 'id' is not known. -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, TAG_ID id); +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id); // Validates that the given mux has a single image. WebPMuxError MuxValidateForImage(const WebPMux* const mux); diff --git a/src/mux/muxinternal.c b/src/mux/muxinternal.c index 033628fb..978febf3 100644 --- a/src/mux/muxinternal.c +++ b/src/mux/muxinternal.c @@ -20,18 +20,18 @@ extern "C" { #define UNDEFINED_CHUNK_SIZE (-1) const ChunkInfo kChunks[] = { - {"vp8x", mktag('V', 'P', '8', 'X'), VP8X_ID, VP8X_CHUNK_SIZE}, - {"iccp", mktag('I', 'C', 'C', 'P'), ICCP_ID, UNDEFINED_CHUNK_SIZE}, - {"loop", mktag('L', 'O', 'O', 'P'), LOOP_ID, LOOP_CHUNK_SIZE}, - {"frame", mktag('F', 'R', 'M', ' '), FRAME_ID, FRAME_CHUNK_SIZE}, - {"tile", mktag('T', 'I', 'L', 'E'), TILE_ID, TILE_CHUNK_SIZE}, - {"alpha", mktag('A', 'L', 'P', 'H'), ALPHA_ID, UNDEFINED_CHUNK_SIZE}, - {"image", mktag('V', 'P', '8', ' '), IMAGE_ID, UNDEFINED_CHUNK_SIZE}, - {"image", mktag('V', 'P', '8', 'L'), IMAGE_ID, UNDEFINED_CHUNK_SIZE}, - {"meta", mktag('M', 'E', 'T', 'A'), META_ID, UNDEFINED_CHUNK_SIZE}, - {"unknown", mktag('U', 'N', 'K', 'N'), UNKNOWN_ID, UNDEFINED_CHUNK_SIZE}, + { mktag('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE }, + { mktag('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE }, + { mktag('L', 'O', 'O', 'P'), WEBP_CHUNK_LOOP, LOOP_CHUNK_SIZE }, + { mktag('F', 'R', 'M', ' '), WEBP_CHUNK_FRAME, FRAME_CHUNK_SIZE }, + { mktag('T', 'I', 'L', 'E'), WEBP_CHUNK_TILE, TILE_CHUNK_SIZE }, + { mktag('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE }, + { mktag('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, + { mktag('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE }, + { mktag('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE }, + { mktag('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE }, - {NULL, NIL_TAG, NIL_ID, UNDEFINED_CHUNK_SIZE}, + { NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE } }; //------------------------------------------------------------------------------ @@ -58,15 +58,6 @@ WebPChunk* ChunkRelease(WebPChunk* const chunk) { //------------------------------------------------------------------------------ // Chunk misc methods. -CHUNK_INDEX ChunkGetIndexFromName(const char* const name) { - int i; - if (name == NULL) return IDX_NIL; - for (i = 0; kChunks[i].name != NULL; ++i) { - if (!strcmp(name, kChunks[i].name)) return i; - } - return IDX_NIL; -} - CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) { int i; for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { @@ -75,12 +66,12 @@ CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) { return IDX_NIL; } -TAG_ID ChunkGetIdFromTag(uint32_t tag) { +WebPChunkId ChunkGetIdFromTag(uint32_t tag) { int i; for (i = 0; kChunks[i].tag != NIL_TAG; ++i) { if (tag == kChunks[i].tag) return kChunks[i].id; } - return NIL_ID; + return WEBP_CHUNK_NIL; } //------------------------------------------------------------------------------ @@ -258,13 +249,13 @@ WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) { //------------------------------------------------------------------------------ // MuxImage search methods. -int MuxImageCount(WebPMuxImage* const wpi_list, TAG_ID id) { +int MuxImageCount(WebPMuxImage* const wpi_list, WebPChunkId id) { int count = 0; WebPMuxImage* current; for (current = wpi_list; current != NULL; current = current->next_) { const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id); if (wpi_chunk != NULL) { - const TAG_ID wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); + const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); if (wpi_chunk_id == id) ++count; } } @@ -296,14 +287,16 @@ static int SearchImageToSet(WebPMuxImage** wpi_list, uint32_t nth, // where 'prev_wpi' is the pointer to the image at position (nth - 1). // Returns 1 if nth image with given id was found, 0 otherwise. static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, - TAG_ID id, WebPMuxImage*** const location) { + WebPChunkId id, + WebPMuxImage*** const location) { uint32_t count = 0; assert(wpi_list); *location = wpi_list; // Search makes sense only for the following. - assert(id == FRAME_ID || id == TILE_ID || id == IMAGE_ID); - assert(id != IMAGE_ID || nth == 1); + assert(id == WEBP_CHUNK_FRAME || id == WEBP_CHUNK_TILE || + id == WEBP_CHUNK_IMAGE); + assert(id != WEBP_CHUNK_IMAGE || nth == 1); if (nth == 0) { nth = MuxImageCount(*wpi_list, id); @@ -314,7 +307,7 @@ static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, WebPMuxImage* const cur_wpi = *wpi_list; const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(cur_wpi, id); if (wpi_chunk != NULL) { - const TAG_ID wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); + const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); if (wpi_chunk_id == id) { ++count; if (count == nth) return 1; // Found. @@ -362,7 +355,7 @@ void MuxImageDeleteAll(WebPMuxImage** const wpi_list) { } WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, - TAG_ID id) { + WebPChunkId id) { assert(wpi_list); if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) { return WEBP_MUX_NOT_FOUND; @@ -375,7 +368,7 @@ WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, // MuxImage reader methods. WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, - TAG_ID id, WebPMuxImage** wpi) { + WebPChunkId id, WebPMuxImage** wpi) { assert(wpi_list); assert(wpi); if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, id, @@ -441,22 +434,22 @@ int MuxHasLosslessImages(const WebPMuxImage* images) { //------------------------------------------------------------------------------ // Helper methods for mux. -WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, TAG_ID id) { +WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) { assert(mux != NULL); switch(id) { - case VP8X_ID: return (WebPChunk**)&mux->vp8x_; - case ICCP_ID: return (WebPChunk**)&mux->iccp_; - case LOOP_ID: return (WebPChunk**)&mux->loop_; - case META_ID: return (WebPChunk**)&mux->meta_; - case UNKNOWN_ID: return (WebPChunk**)&mux->unknown_; + 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_UNKNOWN: return (WebPChunk**)&mux->unknown_; default: return NULL; } } WebPMuxError MuxValidateForImage(const WebPMux* const mux) { - const int num_images = MuxImageCount(mux->images_, IMAGE_ID); - const int num_frames = MuxImageCount(mux->images_, FRAME_ID); - const int num_tiles = MuxImageCount(mux->images_, TILE_ID); + const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE); + const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_FRAME); + const int num_tiles = MuxImageCount(mux->images_, WEBP_CHUNK_TILE); if (num_images == 0) { // No images in mux. @@ -485,7 +478,7 @@ static WebPMuxError ValidateChunk(const WebPMux* const mux, CHUNK_INDEX idx, WebPFeatureFlags vp8x_flags, int max, int* num) { const WebPMuxError err = - WebPMuxNumNamedElements(mux, kChunks[idx].name, num); + WebPMuxNumChunks(mux, kChunks[idx].id, num); if (err != WEBP_MUX_OK) return err; if (max > -1 && *num > max) return WEBP_MUX_INVALID_ARGUMENT; if (feature != NO_FLAG && IsNotCompatible(vp8x_flags & feature, *num)) { diff --git a/src/mux/muxread.c b/src/mux/muxread.c index 55375559..9640a238 100644 --- a/src/mux/muxread.c +++ b/src/mux/muxread.c @@ -132,7 +132,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* const bitstream, int copy_data, // Loop over chunks. while (data != end) { - TAG_ID id; + WebPChunkId id; WebPChunk chunk; WebPMuxError err; @@ -149,7 +149,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* const bitstream, int copy_data, if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or // consecutive frame/tile chunks. if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err; - if (id == IMAGE_ID) { + if (id == WEBP_CHUNK_IMAGE) { wpi->is_partial_ = 0; // wpi is completely filled. // Add this to mux->images_ list. if (MuxImageSetNth(wpi, &mux->images_, 0) != WEBP_MUX_OK) goto Err; @@ -224,7 +224,8 @@ WebPMuxError WebPMuxGetImage(const WebPMux* const mux, if (err != WEBP_MUX_OK) return err; // All well. Get the image. - err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, IMAGE_ID, &wpi); + err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, WEBP_CHUNK_IMAGE, + &wpi); assert(err == WEBP_MUX_OK); // Already tested above. // Get alpha chunk (if present & requested). @@ -268,7 +269,7 @@ WebPMuxError WebPMuxGetLoopCount(const WebPMux* const mux, err = MuxGet(mux, IDX_LOOP, 1, &image); if (err != WEBP_MUX_OK) return err; - if (image.size_ < kChunks[LOOP_ID].size) return WEBP_MUX_BAD_DATA; + if (image.size_ < kChunks[WEBP_CHUNK_LOOP].size) return WEBP_MUX_BAD_DATA; *loop_count = GetLE32(image.bytes_); return WEBP_MUX_OK; @@ -283,9 +284,9 @@ static WebPMuxError MuxGetFrameTileInternal( WebPMuxError err; WebPMuxImage* wpi; - const int is_frame = (tag == kChunks[FRAME_ID].tag) ? 1 : 0; + const int is_frame = (tag == kChunks[WEBP_CHUNK_FRAME].tag) ? 1 : 0; const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE; - const TAG_ID id = kChunks[idx].id; + const WebPChunkId id = kChunks[idx].id; if (mux == NULL || image == NULL || x_offset == NULL || y_offset == NULL || (is_frame && duration == NULL)) { @@ -342,6 +343,15 @@ WebPMuxError WebPMuxGetTile(const WebPMux* const mux, uint32_t nth, kChunks[IDX_TILE].tag); } +// Get chunk index from chunk id. Returns IDX_NIL if not found. +static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { + int i; + for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) { + if (id == kChunks[i].id) return i; + } + return IDX_NIL; +} + // Count number of chunks matching 'tag' in the 'chunk_list'. // If tag == NIL_TAG, any tag will be matched. static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) { @@ -355,12 +365,9 @@ static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) { return count; } -WebPMuxError WebPMuxNumNamedElements(const WebPMux* const mux, const char* name, +WebPMuxError WebPMuxNumChunks(const WebPMux* const mux, WebPChunkId id, int* num_elements) { - const CHUNK_INDEX idx = ChunkGetIndexFromName(name); - const TAG_ID id = kChunks[idx].id; - - if (mux == NULL || name == NULL || num_elements == NULL) { + if (mux == NULL || num_elements == NULL) { return WEBP_MUX_INVALID_ARGUMENT; } @@ -371,6 +378,7 @@ WebPMuxError WebPMuxNumNamedElements(const WebPMux* const mux, const char* name, if (chunk_list == NULL) { *num_elements = 0; } else { + const CHUNK_INDEX idx = ChunkGetIndexFromId(id); *num_elements = CountChunks(*chunk_list, kChunks[idx].tag); } } diff --git a/src/webp/mux.h b/src/webp/mux.h index 0aff297c..a8bd4f54 100644 --- a/src/webp/mux.h +++ b/src/webp/mux.h @@ -73,6 +73,20 @@ typedef enum { ALPHA_FLAG = 0x00000010 } WebPFeatureFlags; +// IDs for different types of chunks. +typedef enum { + WEBP_CHUNK_VP8X, // VP8X + WEBP_CHUNK_ICCP, // ICCP + WEBP_CHUNK_LOOP, // LOOP + WEBP_CHUNK_FRAME, // FRM + WEBP_CHUNK_TILE, // TILE + WEBP_CHUNK_ALPHA, // ALPH + WEBP_CHUNK_IMAGE, // VP8/VP8L + WEBP_CHUNK_META, // META + WEBP_CHUNK_UNKNOWN, // Other chunks. + WEBP_CHUNK_NIL +} WebPChunkId; + typedef struct WebPMux WebPMux; // main opaque object. // Data type used to describe 'raw' data, e.g., chunk data @@ -423,16 +437,13 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* const mux, // Gets number of chunks having tag value tag in the mux object. // Parameters: // mux - (in) object from which the info is to be fetched -// name - (in) chunk name specifying the type of chunk -// Can be any of: "vp8x", "iccp", "loop", "frame", "tile", "alpha", -// "image", "meta" or "unknown" -// num_elements - (out) number of chunks corresponding to the specified tag +// id - (in) chunk id specifying the type of chunk +// num_elements - (out) number of chunks with the given chunk id // Returns: -// WEBP_MUX_INVALID_ARGUMENT - if either mux, tag or num_elements is NULL +// WEBP_MUX_INVALID_ARGUMENT - if either mux, or num_elements is NULL // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxNumNamedElements(const WebPMux* const mux, - const char* name, - int* num_elements); +WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* const mux, + WebPChunkId id, int* num_elements); // Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. // This function also validates the mux object.