static WebPMuxError MuxGet(WebPMux* mux, TAG_ID id, uint nth, WebPData* data) { assert(mux != null); memset(data, 0, sizeof(*data)); assert(!IsWPI(id)); SWITCH_ID_LIST(VP8X_ID, mux.vp8x_); SWITCH_ID_LIST(ICCP_ID, mux.iccp_); SWITCH_ID_LIST(LOOP_ID, mux.loop_); SWITCH_ID_LIST(META_ID, mux.meta_); SWITCH_ID_LIST(UNKNOWN_ID, mux.unknown_); return WEBP_MUX_NOT_FOUND; }
static WebPMuxError MuxSet(WebPMux* mux, TAG_ID id, uint nth, byte* data, uint size, WebPImageInfo* image_info, int copy_data) { WebPChunk chunk; WebPMuxError err = WEBP_MUX_NOT_FOUND; if (mux == null) return WEBP_MUX_INVALID_ARGUMENT; assert(!IsWPI(id)); ChunkInit(&chunk); SWITCH_ID_LIST(VP8X_ID, &mux.vp8x_); SWITCH_ID_LIST(ICCP_ID, &mux.iccp_); SWITCH_ID_LIST(LOOP_ID, &mux.loop_); SWITCH_ID_LIST(META_ID, &mux.meta_); if (id == UNKNOWN_ID && size > TAG_SIZE) { // For raw-data unknown chunk, the first four bytes should be the tag to be // used for the chunk. err = ChunkAssignDataImageInfo(&chunk, data + TAG_SIZE, size - TAG_SIZE, image_info, copy_data, GetLE32(data + 0)); if (err == WEBP_MUX_OK) err = ChunkSetNth(&chunk, &mux.unknown_, nth); } return err; }
//------------------------------------------------------------------------------ // 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; }
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 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; }
//------------------------------------------------------------------------------ // Helper methods for mux. WebPChunk** GetChunkListFromId(WebPMux* mux, TAG_ID 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_; default: return null; } }
// 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. }
private static int ParseChunk(byte[] pbuffer, int offset, TAG_ID tagid, Chunk refChunk, byte[] readbuf) { int listtagid; int arraylength; int comtagid = 1; switch (tagid) { case TAG_ID.TAG_BYTE: { if (readbuf != null) { readbuf[0] = pbuffer[offset]; } offset += 1; break; } case TAG_ID.TAG_SHORT: { offset += 2; break; } case TAG_ID.TAG_INT: { offset += 4; break; } case TAG_ID.TAG_LONG: { offset += 8; break; } case TAG_ID.TAG_FLOAT: { offset += 4; break; } case TAG_ID.TAG_DOUBLE: { offset += 8; break; } case TAG_ID.TAG_BYTEARRAY: { arraylength = pbuffer[offset + 0] << 24 | pbuffer[offset + 1] << 16 | pbuffer[offset + 2] << 8 | pbuffer[offset + 3]; offset += 4; if (readbuf != null) { Array.Copy(pbuffer, offset, readbuf, 0, arraylength); } offset += arraylength; break; } case TAG_ID.TAG_STRING: { offset += pbuffer[offset] + 1; break; } case TAG_ID.TAG_LIST: { listtagid = pbuffer[offset]; offset += 1; arraylength = pbuffer[offset + 0] << 24 | pbuffer[offset + 1] << 16 | pbuffer[offset + 2] << 8 | pbuffer[offset + 3]; offset += 4; for (int i = 0; i < arraylength; i++) { offset = ParseChunk(pbuffer, offset, (TAG_ID)listtagid, refChunk, null); } break; } case TAG_ID.TAG_COMPOUND: { while ((TAG_ID)comtagid != TAG_ID.TAG_END) { offset = ReadChunk(pbuffer, offset, refChunk, out comtagid); } break; } case TAG_ID.TAG_INTARRAY: { arraylength = pbuffer[offset + 0] << 24 | pbuffer[offset + 1] << 16 | pbuffer[offset + 2] << 8 | pbuffer[offset + 3]; offset += 4; offset += 4 * arraylength; break; } } return(offset); }