//------------------------------------------------------------------------------ // MuxImage writer methods. WebPMuxError MuxImageSetNth(WebPMuxImage* wpi, WebPMuxImage** wpi_list, uint nth) { WebPMuxImage* new_wpi; if (!SearchImageToSet(wpi_list, nth, &wpi_list)) { return WEBP_MUX_NOT_FOUND; } new_wpi = (WebPMuxImage*)malloc(sizeof(*new_wpi)); if (new_wpi == null) return WEBP_MUX_MEMORY_ERROR; *new_wpi = *wpi; new_wpi.next_ = *wpi_list; *wpi_list = new_wpi; return WEBP_MUX_OK; }
byte* MuxImageListEmit(WebPMuxImage* wpi_list, byte* dst) { while (wpi_list) { dst = MuxImageEmit(wpi_list, dst); wpi_list = wpi_list.next_; } return dst; }
WebPMuxImage* MuxImageRelease(WebPMuxImage wpi) { WebPMuxImage* next; if (wpi == null) return null; ChunkDelete(wpi.header_); ChunkDelete(wpi.alpha_); ChunkDelete(wpi.vp8_); next = wpi.next_; MuxImageInit(wpi); return next; }
//------------------------------------------------------------------------------ // Life of a MuxImage object. void MuxImageInit(WebPMuxImage wpi) { assert(wpi); memset(wpi, 0, sizeof(*wpi)); }
uint MuxImageListDiskSize(WebPMuxImage* wpi_list) { uint size = 0; while (wpi_list) { size += MuxImageDiskSize(wpi_list); wpi_list = wpi_list.next_; } return size; }
WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint nth, TAG_ID id) { assert(wpi_list); if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) { return WEBP_MUX_NOT_FOUND; } *wpi_list = MuxImageDelete(*wpi_list); return WEBP_MUX_OK; }
//------------------------------------------------------------------------------ // MuxImage reader methods. WebPMuxError MuxImageGetNth(WebPMuxImage** wpi_list, uint nth, TAG_ID id, WebPMuxImage** wpi) { assert(wpi_list); assert(wpi); if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, id, (WebPMuxImage***)&wpi_list)) { return WEBP_MUX_NOT_FOUND; } *wpi = (WebPMuxImage*)*wpi_list; return WEBP_MUX_OK; }
//------------------------------------------------------------------------------ // MuxImage deletion methods. WebPMuxImage* MuxImageDelete(WebPMuxImage* wpi) { // Delete the components of wpi. If wpi is null this is a noop. WebPMuxImage* next = MuxImageRelease(wpi); free(wpi); return next; }
void MuxImageDeleteAll(WebPMuxImage** wpi_list) { while (*wpi_list) { *wpi_list = MuxImageDelete(*wpi_list); } }
//------------------------------------------------------------------------------ // MuxImage search methods. int MuxImageCount(WebPMuxImage* wpi_list, TAG_ID id) { int count = 0; WebPMuxImage* current; for (current = wpi_list; current != null; current = current.next_) { WebPChunk** wpi_chunk_ptr = MuxImageGetListFromId(current, id); assert(wpi_chunk_ptr != null); if (*wpi_chunk_ptr != null && (*wpi_chunk_ptr).tag_ == kChunks[id].chunkTag) { ++count; } } return count; }
// Outputs a pointer to 'prev_wpi.next_', // where 'prev_wpi' is the pointer to the image at position (nth - 1). // Returns 1 if nth image was found, 0 otherwise. static int SearchImageToSet(WebPMuxImage** wpi_list, uint nth, WebPMuxImage*** location) { uint count = 0; assert(wpi_list); *location = wpi_list; while (*wpi_list) { WebPMuxImage* cur_wpi = *wpi_list; ++count; if (count == nth) return 1; // Found. wpi_list = &cur_wpi.next_; *location = wpi_list; } // *chunk_list is ok to be null if adding at last location. return (nth == 0 || (count == nth - 1)) ? 1 : 0; }
// Outputs a pointer to 'prev_wpi.next_', // 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, uint nth, TAG_ID id, WebPMuxImage*** location) { uint 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); if (nth == 0) { nth = MuxImageCount(*wpi_list, id); if (nth == 0) return 0; // Not found. } while (*wpi_list) { WebPMuxImage* cur_wpi = *wpi_list; WebPChunk** wpi_chunk_ptr = MuxImageGetListFromId(cur_wpi, id); assert(wpi_chunk_ptr != null); if ((*wpi_chunk_ptr).tag_ == kChunks[id].chunkTag) { ++count; if (count == nth) return 1; // Found. } wpi_list = &cur_wpi.next_; *location = wpi_list; } return 0; // Not found. }
static byte* MuxImageEmit(WebPMuxImage* wpi, byte* dst) { // Ordering of chunks to be emitted is strictly as follows: // 1. Frame/Tile chunk (if present). // 2. Alpha chunk (if present). // 3. VP8 chunk. assert(wpi); if (wpi.header_ != null) dst = ChunkEmit(wpi.header_, dst); if (wpi.alpha_ != null) dst = ChunkEmit(wpi.alpha_, dst); if (wpi.vp8_ != null) dst = ChunkEmit(wpi.vp8_, dst); return dst; }
//------------------------------------------------------------------------------ // MuxImage serialization methods. // Size of an image. static uint MuxImageDiskSize(WebPMuxImage* wpi) { uint size = 0; if (wpi.header_ != null) size += ChunkDiskSize(wpi.header_); if (wpi.alpha_ != null) size += ChunkDiskSize(wpi.alpha_); if (wpi.vp8_ != null) size += ChunkDiskSize(wpi.vp8_); return size; }