mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 18:35:41 +01:00 
			
		
		
		
	Mux API change:
Create common APIs for image, frame and tile. Change-Id: I709ad752133094bd5bc89dd9c832ff79802aac68
This commit is contained in:
		| @@ -94,7 +94,7 @@ Example#2 (pseudo code): Get image & color profile data from a WebP file. | |||||||
|   int copy_data = 0; |   int copy_data = 0; | ||||||
|   // ... (Read data from file). |   // ... (Read data from file). | ||||||
|   WebPMux* mux = WebPMuxCreate(&data, copy_data); |   WebPMux* mux = WebPMuxCreate(&data, copy_data); | ||||||
|   WebPMuxGetImage(mux, &image); |   WebPMuxGetFrame(mux, 1, &image); | ||||||
|   // ... (Consume image; e.g. call WebPDecode() to decode the data). |   // ... (Consume image; e.g. call WebPDecode() to decode the data). | ||||||
|   WebPMuxGetChunk(mux, "ICCP", &icc_profile); |   WebPMuxGetChunk(mux, "ICCP", &icc_profile); | ||||||
|   // ... (Consume icc_profile). |   // ... (Consume icc_profile). | ||||||
|   | |||||||
| @@ -142,6 +142,12 @@ static int IsNotCompatible(int count1, int count2) { | |||||||
|     return err;                                                      \ |     return err;                                                      \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | #define RETURN_IF_ERROR3(ERR_MSG, FORMAT_STR1, FORMAT_STR2)          \ | ||||||
|  |   if (err != WEBP_MUX_OK) {                                          \ | ||||||
|  |     fprintf(stderr, ERR_MSG, FORMAT_STR1, FORMAT_STR2);              \ | ||||||
|  |     return err;                                                      \ | ||||||
|  |   } | ||||||
|  |  | ||||||
| #define ERROR_GOTO1(ERR_MSG, LABEL)                                  \ | #define ERROR_GOTO1(ERR_MSG, LABEL)                                  \ | ||||||
|   do {                                                               \ |   do {                                                               \ | ||||||
|     fprintf(stderr, ERR_MSG);                                        \ |     fprintf(stderr, ERR_MSG);                                        \ | ||||||
| @@ -183,51 +189,36 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) { | |||||||
|   if (flag & ALPHA_FLAG)     printf(" transparency"); |   if (flag & ALPHA_FLAG)     printf(" transparency"); | ||||||
|   printf("\n"); |   printf("\n"); | ||||||
|  |  | ||||||
|   if (flag & ANIMATION_FLAG) { |   if ((flag & ANIMATION_FLAG) || (flag & TILE_FLAG)) { | ||||||
|  |     const int is_anim = !!(flag & ANIMATION_FLAG); | ||||||
|  |     const WebPChunkId id = is_anim ? WEBP_CHUNK_FRAME : WEBP_CHUNK_TILE; | ||||||
|  |     const char* const type_str = is_anim ? "frame" : "tile"; | ||||||
|     int nFrames; |     int nFrames; | ||||||
|     int loop_count; |  | ||||||
|     err = WebPMuxGetLoopCount(mux, &loop_count); |  | ||||||
|     RETURN_IF_ERROR("Failed to retrieve loop count\n"); |  | ||||||
|     printf("Loop Count : %d\n", loop_count); |  | ||||||
|  |  | ||||||
|     err = WebPMuxNumChunks(mux, WEBP_CHUNK_FRAME, &nFrames); |     if (is_anim) { | ||||||
|     RETURN_IF_ERROR("Failed to retrieve number of frames\n"); |       int loop_count; | ||||||
|  |       err = WebPMuxGetLoopCount(mux, &loop_count); | ||||||
|  |       RETURN_IF_ERROR("Failed to retrieve loop count\n"); | ||||||
|  |       printf("Loop Count : %d\n", loop_count); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     printf("Number of frames: %d\n", nFrames); |     err = WebPMuxNumChunks(mux, id, &nFrames); | ||||||
|  |     RETURN_IF_ERROR2("Failed to retrieve number of %ss\n", type_str); | ||||||
|  |  | ||||||
|  |     printf("Number of %ss: %d\n", type_str, nFrames); | ||||||
|     if (nFrames > 0) { |     if (nFrames > 0) { | ||||||
|       int i; |       int i; | ||||||
|       printf("No.: x_offset y_offset duration image_size"); |       printf("No.: x_offset y_offset "); | ||||||
|       printf("\n"); |       if (is_anim) printf("duration "); | ||||||
|  |       printf("image_size\n"); | ||||||
|       for (i = 1; i <= nFrames; i++) { |       for (i = 1; i <= nFrames; i++) { | ||||||
|         WebPMuxFrameInfo frame; |         WebPMuxFrameInfo frame; | ||||||
|         err = WebPMuxGetFrame(mux, i, &frame); |         err = WebPMuxGetFrame(mux, i, &frame); | ||||||
|         RETURN_IF_ERROR2("Failed to retrieve frame#%d\n", i); |         RETURN_IF_ERROR3("Failed to retrieve %s#%d\n", type_str, i); | ||||||
|         printf("%3d: %8d %8d %8d %10zu", i, frame.x_offset_, frame.y_offset_, |         printf("%3d: %8d %8d ", i, frame.x_offset_, frame.y_offset_); | ||||||
|                frame.duration_, frame.bitstream_.size_); |         if (is_anim) printf("%8d ", frame.duration_); | ||||||
|  |         printf("%10zu\n", frame.bitstream_.size_); | ||||||
|         WebPDataClear(&frame.bitstream_); |         WebPDataClear(&frame.bitstream_); | ||||||
|         printf("\n"); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (flag & TILE_FLAG) { |  | ||||||
|     int 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); |  | ||||||
|     if (nTiles > 0) { |  | ||||||
|       int i; |  | ||||||
|       printf("No.: x_offset y_offset image_size"); |  | ||||||
|       printf("\n"); |  | ||||||
|       for (i = 1; i <= nTiles; i++) { |  | ||||||
|         WebPMuxFrameInfo tile; |  | ||||||
|         err = WebPMuxGetTile(mux, i, &tile); |  | ||||||
|         RETURN_IF_ERROR2("Failed to retrieve tile#%d\n", i); |  | ||||||
|         printf("%3d: %8d %8d %10zu", |  | ||||||
|                i, tile.x_offset_, tile.y_offset_, tile.bitstream_.size_); |  | ||||||
|         WebPDataClear(&tile.bitstream_); |  | ||||||
|         printf("\n"); |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -247,10 +238,10 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if ((flag & ALPHA_FLAG) && !(flag & (ANIMATION_FLAG | TILE_FLAG))) { |   if ((flag & ALPHA_FLAG) && !(flag & (ANIMATION_FLAG | TILE_FLAG))) { | ||||||
|     WebPData bitstream; |     WebPMuxFrameInfo image; | ||||||
|     err = WebPMuxGetImage(mux, &bitstream); |     err = WebPMuxGetFrame(mux, 1, &image); | ||||||
|     RETURN_IF_ERROR("Failed to retrieve the image\n"); |     RETURN_IF_ERROR("Failed to retrieve the image\n"); | ||||||
|     printf("Size of the image (with alpha): %zu\n", bitstream.size_); |     printf("Size of the image (with alpha): %zu\n", image.bitstream_.size_); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return WEBP_MUX_OK; |   return WEBP_MUX_OK; | ||||||
| @@ -693,6 +684,7 @@ static int GetFrameTile(const WebPMux* mux, | |||||||
|   WebPMux* mux_single = NULL; |   WebPMux* mux_single = NULL; | ||||||
|   long num = 0; |   long num = 0; | ||||||
|   int ok = 1; |   int ok = 1; | ||||||
|  |   const WebPChunkId id = isFrame ? WEBP_CHUNK_FRAME : WEBP_CHUNK_TILE; | ||||||
|   WebPMuxFrameInfo info; |   WebPMuxFrameInfo info; | ||||||
|   WebPDataInit(&info.bitstream_); |   WebPDataInit(&info.bitstream_); | ||||||
|  |  | ||||||
| @@ -701,18 +693,11 @@ static int GetFrameTile(const WebPMux* mux, | |||||||
|     ERROR_GOTO1("ERROR: Frame/Tile index must be non-negative.\n", ErrGet); |     ERROR_GOTO1("ERROR: Frame/Tile index must be non-negative.\n", ErrGet); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (isFrame) { |   err = WebPMuxGetFrame(mux, num, &info); | ||||||
|     err = WebPMuxGetFrame(mux, num, &info); |   if (err == WEBP_MUX_OK && info.id != id) err = WEBP_MUX_NOT_FOUND; | ||||||
|     if (err != WEBP_MUX_OK) { |   if (err != WEBP_MUX_OK) { | ||||||
|       ERROR_GOTO3("ERROR (%s): Could not get frame %ld.\n", |     ERROR_GOTO3("ERROR (%s): Could not get frame %ld.\n", | ||||||
|                   ErrorString(err), num, ErrGet); |                 ErrorString(err), num, ErrGet); | ||||||
|     } |  | ||||||
|   } else { |  | ||||||
|     err = WebPMuxGetTile(mux, num, &info); |  | ||||||
|     if (err != WEBP_MUX_OK) { |  | ||||||
|       ERROR_GOTO3("ERROR (%s): Could not get frame %ld.\n", |  | ||||||
|                   ErrorString(err), num, ErrGet); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   mux_single = WebPMuxNew(); |   mux_single = WebPMuxNew(); | ||||||
| @@ -726,6 +711,7 @@ static int GetFrameTile(const WebPMux* mux, | |||||||
|     ERROR_GOTO2("ERROR (%s): Could not create single image mux object.\n", |     ERROR_GOTO2("ERROR (%s): Could not create single image mux object.\n", | ||||||
|                 ErrorString(err), ErrGet); |                 ErrorString(err), ErrGet); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ok = WriteWebP(mux_single, config->output_); |   ok = WriteWebP(mux_single, config->output_); | ||||||
|  |  | ||||||
|  ErrGet: |  ErrGet: | ||||||
| @@ -808,6 +794,7 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|                 WebPDataClear(&frame.bitstream_); |                 WebPDataClear(&frame.bitstream_); | ||||||
|                 ERROR_GOTO1("ERROR: Could not parse frame properties.\n", Err2); |                 ERROR_GOTO1("ERROR: Could not parse frame properties.\n", Err2); | ||||||
|               } |               } | ||||||
|  |               frame.id = WEBP_CHUNK_FRAME; | ||||||
|               err = WebPMuxPushFrame(mux, &frame, 1); |               err = WebPMuxPushFrame(mux, &frame, 1); | ||||||
|               WebPDataClear(&frame.bitstream_); |               WebPDataClear(&frame.bitstream_); | ||||||
|               if (err != WEBP_MUX_OK) { |               if (err != WEBP_MUX_OK) { | ||||||
| @@ -836,7 +823,8 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|               WebPDataClear(&tile.bitstream_); |               WebPDataClear(&tile.bitstream_); | ||||||
|               ERROR_GOTO1("ERROR: Could not parse tile properties.\n", Err2); |               ERROR_GOTO1("ERROR: Could not parse tile properties.\n", Err2); | ||||||
|             } |             } | ||||||
|             err = WebPMuxPushTile(mux, &tile, 1); |             tile.id = WEBP_CHUNK_TILE; | ||||||
|  |             err = WebPMuxPushFrame(mux, &tile, 1); | ||||||
|             WebPDataClear(&tile.bitstream_); |             WebPDataClear(&tile.bitstream_); | ||||||
|             if (err != WEBP_MUX_OK) { |             if (err != WEBP_MUX_OK) { | ||||||
|               ERROR_GOTO3("ERROR (%s): Could not add a tile at index %d.\n", |               ERROR_GOTO3("ERROR (%s): Could not add a tile at index %d.\n", | ||||||
|   | |||||||
| @@ -205,61 +205,6 @@ static WebPMuxError DeleteLoopCount(WebPMux* const mux) { | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Set API(s). | // Set API(s). | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxSetImage(WebPMux* mux, |  | ||||||
|                              const WebPData* bitstream, int copy_data) { |  | ||||||
|   WebPMuxError err; |  | ||||||
|   WebPChunk chunk; |  | ||||||
|   WebPMuxImage wpi; |  | ||||||
|   WebPData image; |  | ||||||
|   WebPData alpha; |  | ||||||
|   int is_lossless; |  | ||||||
|   int image_tag; |  | ||||||
|  |  | ||||||
|   if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL || |  | ||||||
|       bitstream->size_ > MAX_CHUNK_PAYLOAD) { |  | ||||||
|     return WEBP_MUX_INVALID_ARGUMENT; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // If given data is for a whole webp file, |  | ||||||
|   // extract only the VP8/VP8L data from it. |  | ||||||
|   err = GetImageData(bitstream, &image, &alpha, &is_lossless); |  | ||||||
|   if (err != WEBP_MUX_OK) return err; |  | ||||||
|   image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; |  | ||||||
|  |  | ||||||
|   // Delete the existing images. |  | ||||||
|   MuxImageDeleteAll(&mux->images_); |  | ||||||
|  |  | ||||||
|   MuxImageInit(&wpi); |  | ||||||
|  |  | ||||||
|   if (alpha.bytes_ != NULL) {  // Add alpha chunk. |  | ||||||
|     ChunkInit(&chunk); |  | ||||||
|     err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag); |  | ||||||
|     if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|     err = ChunkSetNth(&chunk, &wpi.alpha_, 1); |  | ||||||
|     if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Add image chunk. |  | ||||||
|   ChunkInit(&chunk); |  | ||||||
|   err = ChunkAssignData(&chunk, &image, copy_data, image_tag); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|   err = ChunkSetNth(&chunk, &wpi.img_, 1); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|  |  | ||||||
|   // Add this image to mux. |  | ||||||
|   err = MuxImagePush(&wpi, &mux->images_); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|  |  | ||||||
|   // All OK. |  | ||||||
|   return WEBP_MUX_OK; |  | ||||||
|  |  | ||||||
|  Err: |  | ||||||
|   // Something bad happened. |  | ||||||
|   ChunkRelease(&chunk); |  | ||||||
|   MuxImageRelease(&wpi); |  | ||||||
|   return err; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], | WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], | ||||||
|                              const WebPData* chunk_data, int copy_data) { |                              const WebPData* chunk_data, int copy_data) { | ||||||
|   const CHUNK_INDEX idx = ChunkGetIndexFromFourCC(fourcc); |   const CHUNK_INDEX idx = ChunkGetIndexFromFourCC(fourcc); | ||||||
| @@ -278,105 +223,60 @@ WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4], | |||||||
|   return MuxSet(mux, idx, 1, chunk_data, copy_data); |   return MuxSet(mux, idx, 1, chunk_data, copy_data); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'. | ||||||
| WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, int loop_count) { | static WebPMuxError AddDataToChunkList( | ||||||
|  |     const WebPData* const data, int copy_data, uint32_t tag, | ||||||
|  |     WebPChunk** chunk_list) { | ||||||
|  |   WebPChunk chunk; | ||||||
|   WebPMuxError err; |   WebPMuxError err; | ||||||
|   uint8_t* data = NULL; |   ChunkInit(&chunk); | ||||||
|  |   err = ChunkAssignData(&chunk, data, copy_data, tag); | ||||||
|   if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; |   if (err != WEBP_MUX_OK) goto Err; | ||||||
|   if (loop_count >= MAX_LOOP_COUNT) return WEBP_MUX_INVALID_ARGUMENT; |   err = ChunkSetNth(&chunk, chunk_list, 1); | ||||||
|  |   if (err != WEBP_MUX_OK) goto Err; | ||||||
|   // Delete the existing LOOP chunk(s). |   return WEBP_MUX_OK; | ||||||
|   err = DeleteLoopCount(mux); |  Err: | ||||||
|   if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; |   ChunkRelease(&chunk); | ||||||
|  |  | ||||||
|   // Add the given loop count. |  | ||||||
|   data = (uint8_t*)malloc(kChunks[IDX_LOOP].size); |  | ||||||
|   if (data == NULL) return WEBP_MUX_MEMORY_ERROR; |  | ||||||
|  |  | ||||||
|   PutLE16(data, loop_count); |  | ||||||
|   err = MuxAddChunk(mux, 1, kChunks[IDX_LOOP].tag, data, |  | ||||||
|                     kChunks[IDX_LOOP].size, 1); |  | ||||||
|   free(data); |  | ||||||
|   return err; |   return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| static WebPMuxError MuxPushFrameTileInternal( | // Extracts image & alpha data from the given bitstream and then sets wpi.alpha_ | ||||||
|     WebPMux* const mux, const WebPMuxFrameInfo* const frame_tile_info, | // and wpi.img_ appropriately. | ||||||
|     int copy_data, uint32_t tag) { | static WebPMuxError SetAlphaAndImageChunks( | ||||||
|   const WebPData* bitstream; |     const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) { | ||||||
|   int x_offset, y_offset, duration; |   int is_lossless = 0; | ||||||
|   WebPChunk chunk; |   WebPData image, alpha; | ||||||
|   WebPData image; |   WebPMuxError err = GetImageData(bitstream, &image, &alpha, &is_lossless); | ||||||
|   WebPData alpha; |   const int image_tag = | ||||||
|  |       is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; | ||||||
|  |   if (err != WEBP_MUX_OK) return err; | ||||||
|  |   if (alpha.bytes_ != NULL) { | ||||||
|  |     err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag, | ||||||
|  |                              &wpi->alpha_); | ||||||
|  |     if (err != WEBP_MUX_OK) return err; | ||||||
|  |   } | ||||||
|  |   return AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream, | ||||||
|  |                              int copy_data) { | ||||||
|   WebPMuxImage wpi; |   WebPMuxImage wpi; | ||||||
|   WebPMuxError err; |   WebPMuxError err; | ||||||
|   WebPData frame_tile; |  | ||||||
|   const int is_frame = (tag == kChunks[IDX_FRAME].tag) ? 1 : 0; |  | ||||||
|   int is_lossless; |  | ||||||
|   int image_tag; |  | ||||||
|  |  | ||||||
|   // Sanity checks. |   // Sanity checks. | ||||||
|   if (mux == NULL || frame_tile_info == NULL) { |   if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL || | ||||||
|  |       bitstream->size_ > MAX_CHUNK_PAYLOAD) { | ||||||
|     return WEBP_MUX_INVALID_ARGUMENT; |     return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bitstream = &frame_tile_info->bitstream_; |   if (mux->images_ != NULL) { | ||||||
|   x_offset = frame_tile_info->x_offset_; |     // Only one 'simple image' can be added in mux. So, remove present images. | ||||||
|   y_offset = frame_tile_info->y_offset_; |     MuxImageDeleteAll(&mux->images_); | ||||||
|   duration = is_frame ? frame_tile_info->duration_ : 1 /* unused */; |  | ||||||
|  |  | ||||||
|   if (bitstream->bytes_ == NULL || bitstream->size_ > MAX_CHUNK_PAYLOAD) { |  | ||||||
|     return WEBP_MUX_INVALID_ARGUMENT; |  | ||||||
|   } |  | ||||||
|   if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET || |  | ||||||
|       y_offset < 0 || y_offset >= MAX_POSITION_OFFSET || |  | ||||||
|       (is_frame && (duration <= 0 || duration > MAX_DURATION))) { |  | ||||||
|     return WEBP_MUX_INVALID_ARGUMENT; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Snap offsets to even positions. |  | ||||||
|   x_offset &= ~1; |  | ||||||
|   y_offset &= ~1; |  | ||||||
|  |  | ||||||
|   // If given data is for a whole webp file, |  | ||||||
|   // extract only the VP8/VP8L data from it. |  | ||||||
|   err = GetImageData(bitstream, &image, &alpha, &is_lossless); |  | ||||||
|   if (err != WEBP_MUX_OK) return err; |  | ||||||
|   image_tag = is_lossless ? kChunks[IDX_VP8L].tag : kChunks[IDX_VP8].tag; |  | ||||||
|  |  | ||||||
|   WebPDataInit(&frame_tile); |  | ||||||
|   ChunkInit(&chunk); |  | ||||||
|   MuxImageInit(&wpi); |   MuxImageInit(&wpi); | ||||||
|  |   err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); | ||||||
|   if (alpha.bytes_ != NULL) { |  | ||||||
|     // Add alpha chunk. |  | ||||||
|     err = ChunkAssignData(&chunk, &alpha, copy_data, kChunks[IDX_ALPHA].tag); |  | ||||||
|     if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|     err = ChunkSetNth(&chunk, &wpi.alpha_, 1); |  | ||||||
|     if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|     ChunkInit(&chunk);  // chunk owned by wpi.alpha_ now. |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Add image chunk. |  | ||||||
|   err = ChunkAssignData(&chunk, &image, copy_data, image_tag); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |   if (err != WEBP_MUX_OK) goto Err; | ||||||
|   err = ChunkSetNth(&chunk, &wpi.img_, 1); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|   ChunkInit(&chunk);  // chunk owned by wpi.img_ now. |  | ||||||
|  |  | ||||||
|   // Create frame/tile data. |  | ||||||
|   err = CreateFrameTileData(&image, x_offset, y_offset, duration, is_lossless, |  | ||||||
|                             is_frame, &frame_tile); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|  |  | ||||||
|   // Add frame/tile chunk (with copy_data = 1). |  | ||||||
|   err = ChunkAssignData(&chunk, &frame_tile, 1, tag); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|   WebPDataClear(&frame_tile); |  | ||||||
|   err = ChunkSetNth(&chunk, &wpi.header_, 1); |  | ||||||
|   if (err != WEBP_MUX_OK) goto Err; |  | ||||||
|   ChunkInit(&chunk);  // chunk owned by wpi.header_ now. |  | ||||||
|  |  | ||||||
|   // Add this WebPMuxImage to mux. |   // Add this WebPMuxImage to mux. | ||||||
|   err = MuxImagePush(&wpi, &mux->images_); |   err = MuxImagePush(&wpi, &mux->images_); | ||||||
| @@ -386,61 +286,103 @@ static WebPMuxError MuxPushFrameTileInternal( | |||||||
|   return WEBP_MUX_OK; |   return WEBP_MUX_OK; | ||||||
|  |  | ||||||
|  Err:  // Something bad happened. |  Err:  // Something bad happened. | ||||||
|   WebPDataClear(&frame_tile); |  | ||||||
|   ChunkRelease(&chunk); |  | ||||||
|   MuxImageRelease(&wpi); |   MuxImageRelease(&wpi); | ||||||
|   return err; |   return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxPushFrame(WebPMux* mux, | WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame, | ||||||
|                               const WebPMuxFrameInfo* frame, |  | ||||||
|                               int copy_data) { |                               int copy_data) { | ||||||
|   return MuxPushFrameTileInternal(mux, frame, copy_data, |   WebPMuxImage wpi; | ||||||
|                                   kChunks[IDX_FRAME].tag); |   WebPMuxError err; | ||||||
|  |   int is_frame; | ||||||
|  |   const WebPData* const bitstream = &frame->bitstream_; | ||||||
|  |  | ||||||
|  |   // Sanity checks. | ||||||
|  |   if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  |   is_frame = (frame->id == WEBP_CHUNK_FRAME); | ||||||
|  |   if (!(is_frame || (frame->id == WEBP_CHUNK_TILE))) { | ||||||
|  |     return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (bitstream->bytes_ == NULL || bitstream->size_ > MAX_CHUNK_PAYLOAD) { | ||||||
|  |     return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (mux->images_ != NULL) { | ||||||
|  |     const WebPMuxImage* const image = mux->images_; | ||||||
|  |     const uint32_t image_id = (image->header_ != NULL) ? | ||||||
|  |         ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE; | ||||||
|  |     if (image_id != frame->id) { | ||||||
|  |       return WEBP_MUX_INVALID_ARGUMENT;  // Conflicting frame types. | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   MuxImageInit(&wpi); | ||||||
|  |   err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi); | ||||||
|  |   if (err != WEBP_MUX_OK) goto Err; | ||||||
|  |   assert(wpi.img_ != NULL);  // As SetAlphaAndImageChunks() was successful. | ||||||
|  |  | ||||||
|  |   { | ||||||
|  |     const int is_lossless = (wpi.img_->tag_ == kChunks[IDX_VP8L].tag); | ||||||
|  |     const int x_offset = frame->x_offset_ & ~1;  // Snap offsets to even. | ||||||
|  |     const int y_offset = frame->y_offset_ & ~1; | ||||||
|  |     const int duration = is_frame ? frame->duration_ : 1 /* unused */; | ||||||
|  |     const uint32_t tag = kChunks[is_frame ? IDX_FRAME : IDX_TILE].tag; | ||||||
|  |     WebPData frame_tile; | ||||||
|  |     if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET || | ||||||
|  |         y_offset < 0 || y_offset >= MAX_POSITION_OFFSET || | ||||||
|  |         (duration <= 0 || duration > MAX_DURATION)) { | ||||||
|  |       err = WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |       goto Err; | ||||||
|  |     } | ||||||
|  |     err = CreateFrameTileData(&wpi.img_->data_, x_offset, y_offset, duration, | ||||||
|  |                               is_lossless, is_frame, &frame_tile); | ||||||
|  |     if (err != WEBP_MUX_OK) goto Err; | ||||||
|  |     // Add frame/tile chunk (with copy_data = 1). | ||||||
|  |     err = AddDataToChunkList(&frame_tile, 1, tag, &wpi.header_); | ||||||
|  |     WebPDataClear(&frame_tile);  // frame_tile owned by wpi.header_ now. | ||||||
|  |     if (err != WEBP_MUX_OK) goto Err; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Add this WebPMuxImage to mux. | ||||||
|  |   err = MuxImagePush(&wpi, &mux->images_); | ||||||
|  |   if (err != WEBP_MUX_OK) goto Err; | ||||||
|  |  | ||||||
|  |   // All is well. | ||||||
|  |   return WEBP_MUX_OK; | ||||||
|  |  | ||||||
|  |  Err:  // Something bad happened. | ||||||
|  |   MuxImageRelease(&wpi); | ||||||
|  |   return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxPushTile(WebPMux* mux, | WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, int loop_count) { | ||||||
|                              const WebPMuxFrameInfo* tile, |   WebPMuxError err; | ||||||
|                              int copy_data) { |   uint8_t data[LOOP_CHUNK_SIZE]; | ||||||
|   return MuxPushFrameTileInternal(mux, tile /*unused duration*/, copy_data, |  | ||||||
|                                   kChunks[IDX_TILE].tag); |   if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |   if (loop_count >= MAX_LOOP_COUNT) return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |  | ||||||
|  |   // Delete the existing LOOP chunk(s). | ||||||
|  |   err = DeleteLoopCount(mux); | ||||||
|  |   if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; | ||||||
|  |  | ||||||
|  |   // Add the given loop count. | ||||||
|  |   PutLE16(data, loop_count); | ||||||
|  |   return MuxAddChunk(mux, 1, kChunks[IDX_LOOP].tag, data, sizeof(data), 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Delete API(s). | // Delete API(s). | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxDeleteImage(WebPMux* mux) { |  | ||||||
|   WebPMuxError err; |  | ||||||
|  |  | ||||||
|   if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; |  | ||||||
|  |  | ||||||
|   err = MuxValidateForImage(mux); |  | ||||||
|   if (err != WEBP_MUX_OK) return err; |  | ||||||
|  |  | ||||||
|   // All well, delete image. |  | ||||||
|   MuxImageDeleteAll(&mux->images_); |  | ||||||
|   return WEBP_MUX_OK; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { | WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) { | ||||||
|   return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); |   return MuxDeleteAllNamedData(mux, ChunkGetTagFromFourCC(fourcc)); | ||||||
| } | } | ||||||
|  |  | ||||||
| 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); |  | ||||||
|   return MuxImageDeleteNth(&mux->images_, nth, id); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { | WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) { | ||||||
|   return DeleteFrameTileInternal(mux, nth, IDX_FRAME); |   if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT; | ||||||
| } |   return MuxImageDeleteNth(&mux->images_, nth); | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxDeleteTile(WebPMux* mux, uint32_t nth) { |  | ||||||
|   return DeleteFrameTileInternal(mux, nth, IDX_TILE); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
|   | |||||||
| @@ -199,6 +199,7 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); | |||||||
| void MuxImageDeleteAll(WebPMuxImage** const wpi_list); | void MuxImageDeleteAll(WebPMuxImage** const wpi_list); | ||||||
|  |  | ||||||
| // Count number of images matching the given tag id in the 'wpi_list'. | // Count number of images matching the given tag id in the 'wpi_list'. | ||||||
|  | // If id == WEBP_CHUNK_NIL, all images will be matched. | ||||||
| int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); | int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id); | ||||||
|  |  | ||||||
| // Check if given ID corresponds to an image related chunk. | // Check if given ID corresponds to an image related chunk. | ||||||
| @@ -228,13 +229,12 @@ static WEBP_INLINE WebPChunk** MuxImageGetListFromId( | |||||||
| // Pushes 'wpi' at the end of 'wpi_list'. | // Pushes 'wpi' at the end of 'wpi_list'. | ||||||
| WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); | WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list); | ||||||
|  |  | ||||||
| // Delete nth image in the image list with given tag id. | // Delete nth image in the image list. | ||||||
| WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, | WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth); | ||||||
|                                WebPChunkId id); |  | ||||||
|  |  | ||||||
| // Get nth image in the image list with given tag id. | // Get nth image in the image list. | ||||||
| WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, | WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, | ||||||
|                             WebPChunkId id, WebPMuxImage** wpi); |                             WebPMuxImage** wpi); | ||||||
|  |  | ||||||
| // Total size of the given image. | // Total size of the given image. | ||||||
| size_t MuxImageDiskSize(const WebPMuxImage* const wpi); | size_t MuxImageDiskSize(const WebPMuxImage* const wpi); | ||||||
|   | |||||||
| @@ -109,7 +109,7 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) { | |||||||
|  |  | ||||||
| // Outputs a pointer to 'prev_chunk->next_', | // Outputs a pointer to 'prev_chunk->next_', | ||||||
| //   where 'prev_chunk' is the pointer to the chunk at position (nth - 1). | //   where 'prev_chunk' is the pointer to the chunk at position (nth - 1). | ||||||
| // Returns 1 if nth chunk was found, 0 otherwise. | // Returns true if nth chunk was found. | ||||||
| static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth, | static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth, | ||||||
|                                 WebPChunk*** const location) { |                                 WebPChunk*** const location) { | ||||||
|   uint32_t count = 0; |   uint32_t count = 0; | ||||||
| @@ -275,10 +275,14 @@ int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { | |||||||
|   int count = 0; |   int count = 0; | ||||||
|   const WebPMuxImage* current; |   const WebPMuxImage* current; | ||||||
|   for (current = wpi_list; current != NULL; current = current->next_) { |   for (current = wpi_list; current != NULL; current = current->next_) { | ||||||
|     const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id); |     if (id == WEBP_CHUNK_NIL) { | ||||||
|     if (wpi_chunk != NULL) { |       ++count;  // Special case: count all images. | ||||||
|       const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); |     } else { | ||||||
|       if (wpi_chunk_id == id) ++count; |       const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(current, id); | ||||||
|  |       if (wpi_chunk != NULL) { | ||||||
|  |         const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); | ||||||
|  |         if (wpi_chunk_id == id) ++count;  // Count images with a matching 'id'. | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return count; |   return count; | ||||||
| @@ -286,34 +290,22 @@ int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) { | |||||||
|  |  | ||||||
| // Outputs a pointer to 'prev_wpi->next_', | // Outputs a pointer to 'prev_wpi->next_', | ||||||
| //   where 'prev_wpi' is the pointer to the image at position (nth - 1). | //   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. | // Returns true if nth image was found. | ||||||
| static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, | static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth, | ||||||
|                                     WebPChunkId id, |  | ||||||
|                                     WebPMuxImage*** const location) { |                                     WebPMuxImage*** const location) { | ||||||
|   uint32_t count = 0; |   uint32_t count = 0; | ||||||
|   assert(wpi_list); |   assert(wpi_list); | ||||||
|   *location = wpi_list; |   *location = wpi_list; | ||||||
|  |  | ||||||
|   // Search makes sense only for the following. |  | ||||||
|   assert(id == WEBP_CHUNK_FRAME || id == WEBP_CHUNK_TILE || |  | ||||||
|          id == WEBP_CHUNK_IMAGE); |  | ||||||
|   assert(id != WEBP_CHUNK_IMAGE || nth == 1); |  | ||||||
|  |  | ||||||
|   if (nth == 0) { |   if (nth == 0) { | ||||||
|     nth = MuxImageCount(*wpi_list, id); |     nth = MuxImageCount(*wpi_list, WEBP_CHUNK_NIL); | ||||||
|     if (nth == 0) return 0;  // Not found. |     if (nth == 0) return 0;  // Not found. | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   while (*wpi_list) { |   while (*wpi_list) { | ||||||
|     WebPMuxImage* const cur_wpi = *wpi_list; |     WebPMuxImage* const cur_wpi = *wpi_list; | ||||||
|     const WebPChunk* const wpi_chunk = *MuxImageGetListFromId(cur_wpi, id); |     ++count; | ||||||
|     if (wpi_chunk != NULL) { |     if (count == nth) return 1;  // Found. | ||||||
|       const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_); |  | ||||||
|       if (wpi_chunk_id == id) { |  | ||||||
|         ++count; |  | ||||||
|         if (count == nth) return 1;  // Found. |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     wpi_list = &cur_wpi->next_; |     wpi_list = &cur_wpi->next_; | ||||||
|     *location = wpi_list; |     *location = wpi_list; | ||||||
|   } |   } | ||||||
| @@ -361,10 +353,9 @@ void MuxImageDeleteAll(WebPMuxImage** const wpi_list) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, | WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth) { | ||||||
|                                WebPChunkId id) { |  | ||||||
|   assert(wpi_list); |   assert(wpi_list); | ||||||
|   if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) { |   if (!SearchImageToGetOrDelete(wpi_list, nth, &wpi_list)) { | ||||||
|     return WEBP_MUX_NOT_FOUND; |     return WEBP_MUX_NOT_FOUND; | ||||||
|   } |   } | ||||||
|   *wpi_list = MuxImageDelete(*wpi_list); |   *wpi_list = MuxImageDelete(*wpi_list); | ||||||
| @@ -375,10 +366,10 @@ WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth, | |||||||
| // MuxImage reader methods. | // MuxImage reader methods. | ||||||
|  |  | ||||||
| WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, | WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth, | ||||||
|                             WebPChunkId id, WebPMuxImage** wpi) { |                             WebPMuxImage** wpi) { | ||||||
|   assert(wpi_list); |   assert(wpi_list); | ||||||
|   assert(wpi); |   assert(wpi); | ||||||
|   if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, id, |   if (!SearchImageToGetOrDelete((WebPMuxImage**)wpi_list, nth, | ||||||
|                                 (WebPMuxImage***)&wpi_list)) { |                                 (WebPMuxImage***)&wpi_list)) { | ||||||
|     return WEBP_MUX_NOT_FOUND; |     return WEBP_MUX_NOT_FOUND; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -190,6 +190,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, | |||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Get API(s). | // Get API(s). | ||||||
|  |  | ||||||
|  | // TODO(urvang): Change the behavior of this to return ALPHA_FLAG when the mux | ||||||
|  | // doesn't contain a VP8X chunk, but does contain a VP8L chunk with real alpha. | ||||||
| WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { | WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { | ||||||
|   WebPData data; |   WebPData data; | ||||||
|   WebPMuxError err; |   WebPMuxError err; | ||||||
| @@ -200,10 +202,7 @@ WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) { | |||||||
|   // Check if VP8X chunk is present. |   // Check if VP8X chunk is present. | ||||||
|   err = MuxGet(mux, IDX_VP8X, 1, &data); |   err = MuxGet(mux, IDX_VP8X, 1, &data); | ||||||
|   if (err == WEBP_MUX_NOT_FOUND) { |   if (err == WEBP_MUX_NOT_FOUND) { | ||||||
|     // Check if VP8/VP8L chunk is present. |     return MuxValidateForImage(mux);  // Check if a single image is present. | ||||||
|     err = WebPMuxGetImage(mux, &data); |  | ||||||
|     WebPDataClear(&data); |  | ||||||
|     return err; |  | ||||||
|   } else if (err != WEBP_MUX_OK) { |   } else if (err != WEBP_MUX_OK) { | ||||||
|     return err; |     return err; | ||||||
|   } |   } | ||||||
| @@ -230,7 +229,7 @@ static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width, | |||||||
| } | } | ||||||
|  |  | ||||||
| // Assemble a single image WebP bitstream from 'wpi'. | // Assemble a single image WebP bitstream from 'wpi'. | ||||||
| static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi, | static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi, | ||||||
|                                         WebPData* const bitstream) { |                                         WebPData* const bitstream) { | ||||||
|   uint8_t* dst; |   uint8_t* dst; | ||||||
|  |  | ||||||
| @@ -270,25 +269,6 @@ static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi, | |||||||
|   return WEBP_MUX_OK; |   return WEBP_MUX_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxGetImage(const WebPMux* mux, WebPData* bitstream) { |  | ||||||
|   WebPMuxError err; |  | ||||||
|   WebPMuxImage* wpi = NULL; |  | ||||||
|  |  | ||||||
|   if (mux == NULL || bitstream == NULL) { |  | ||||||
|     return WEBP_MUX_INVALID_ARGUMENT; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   err = MuxValidateForImage(mux); |  | ||||||
|   if (err != WEBP_MUX_OK) return err; |  | ||||||
|  |  | ||||||
|   // All well. Get the image. |  | ||||||
|   err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, WEBP_CHUNK_IMAGE, |  | ||||||
|                        &wpi); |  | ||||||
|   assert(err == WEBP_MUX_OK);  // Already tested above. |  | ||||||
|  |  | ||||||
|   return SynthesizeBitstream(wpi, bitstream); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], | WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], | ||||||
|                              WebPData* chunk_data) { |                              WebPData* chunk_data) { | ||||||
|   const CHUNK_INDEX idx = ChunkGetIndexFromFourCC(fourcc); |   const CHUNK_INDEX idx = ChunkGetIndexFromFourCC(fourcc); | ||||||
| @@ -306,6 +286,56 @@ WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4], | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi, | ||||||
|  |                                         WebPMuxFrameInfo* const info) { | ||||||
|  |   // Set some defaults for unrelated fields. | ||||||
|  |   info->x_offset_ = 0; | ||||||
|  |   info->y_offset_ = 0; | ||||||
|  |   info->duration_ = 1; | ||||||
|  |   // Extract data for related fields. | ||||||
|  |   info->id = ChunkGetIdFromTag(wpi->img_->tag_); | ||||||
|  |   return SynthesizeBitstream(wpi, &info->bitstream_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static WebPMuxError MuxGetFrameTileInternal(const WebPMuxImage* const wpi, | ||||||
|  |                                             WebPMuxFrameInfo* const frame) { | ||||||
|  |   const int is_frame = (wpi->header_->tag_ == kChunks[IDX_FRAME].tag); | ||||||
|  |   const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE; | ||||||
|  |   const WebPData* frame_tile_data; | ||||||
|  |   assert(wpi->header_ != NULL);  // Already checked by WebPMuxGetFrame(). | ||||||
|  |   // Get frame/tile chunk. | ||||||
|  |   frame_tile_data = &wpi->header_->data_; | ||||||
|  |   if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA; | ||||||
|  |   // Extract info. | ||||||
|  |   frame->x_offset_ = 2 * GetLE24(frame_tile_data->bytes_ + 0); | ||||||
|  |   frame->y_offset_ = 2 * GetLE24(frame_tile_data->bytes_ + 3); | ||||||
|  |   frame->duration_ = is_frame ? 1 + GetLE24(frame_tile_data->bytes_ + 12) : 1; | ||||||
|  |   frame->id = ChunkGetIdFromTag(wpi->header_->tag_); | ||||||
|  |   return SynthesizeBitstream(wpi, &frame->bitstream_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | WebPMuxError WebPMuxGetFrame( | ||||||
|  |     const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) { | ||||||
|  |   WebPMuxError err; | ||||||
|  |   WebPMuxImage* wpi; | ||||||
|  |  | ||||||
|  |   // Sanity checks. | ||||||
|  |   if (mux == NULL || frame == NULL) { | ||||||
|  |     return WEBP_MUX_INVALID_ARGUMENT; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Get the nth WebPMuxImage. | ||||||
|  |   err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi); | ||||||
|  |   if (err != WEBP_MUX_OK) return err; | ||||||
|  |  | ||||||
|  |   // Get frame info. | ||||||
|  |   if (wpi->header_ == NULL) { | ||||||
|  |     return MuxGetImageInternal(wpi, frame); | ||||||
|  |   } else { | ||||||
|  |     return MuxGetFrameTileInternal(wpi, frame); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) { | WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) { | ||||||
|   WebPData image; |   WebPData image; | ||||||
|   WebPMuxError err; |   WebPMuxError err; | ||||||
| @@ -320,49 +350,6 @@ WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) { | |||||||
|   return WEBP_MUX_OK; |   return WEBP_MUX_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| static WebPMuxError MuxGetFrameTileInternal( |  | ||||||
|     const WebPMux* const mux, uint32_t nth, |  | ||||||
|     WebPMuxFrameInfo* const frame_tile_info, uint32_t tag) { |  | ||||||
|   const WebPData* frame_tile_data; |  | ||||||
|   WebPMuxError err; |  | ||||||
|   WebPMuxImage* wpi; |  | ||||||
|  |  | ||||||
|   const int is_frame = (tag == kChunks[WEBP_CHUNK_FRAME].tag) ? 1 : 0; |  | ||||||
|   const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE; |  | ||||||
|   const WebPChunkId id = kChunks[idx].id; |  | ||||||
|  |  | ||||||
|   if (mux == NULL || frame_tile_info == NULL) { |  | ||||||
|     return WEBP_MUX_INVALID_ARGUMENT; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Get the nth WebPMuxImage. |  | ||||||
|   err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, id, &wpi); |  | ||||||
|   if (err != WEBP_MUX_OK) return err; |  | ||||||
|  |  | ||||||
|   // Get frame chunk. |  | ||||||
|   assert(wpi->header_ != NULL);  // As MuxImageGetNth() already checked header_. |  | ||||||
|   frame_tile_data = &wpi->header_->data_; |  | ||||||
|  |  | ||||||
|   if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA; |  | ||||||
|   frame_tile_info->x_offset_ = 2 * GetLE24(frame_tile_data->bytes_ + 0); |  | ||||||
|   frame_tile_info->y_offset_ = 2 * GetLE24(frame_tile_data->bytes_ + 3); |  | ||||||
|   if (is_frame) { |  | ||||||
|     frame_tile_info->duration_ = 1 + GetLE24(frame_tile_data->bytes_ + 12); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return SynthesizeBitstream(wpi, &frame_tile_info->bitstream_); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxGetFrame(const WebPMux* mux, uint32_t nth, |  | ||||||
|                              WebPMuxFrameInfo* frame) { |  | ||||||
|   return MuxGetFrameTileInternal(mux, nth, frame, kChunks[IDX_FRAME].tag); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebPMuxError WebPMuxGetTile(const WebPMux* mux, uint32_t nth, |  | ||||||
|                             WebPMuxFrameInfo* tile) { |  | ||||||
|   return MuxGetFrameTileInternal(mux, nth, tile, kChunks[IDX_TILE].tag); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Get chunk index from chunk id. Returns IDX_NIL if not found. | // Get chunk index from chunk id. Returns IDX_NIL if not found. | ||||||
| static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { | static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) { | ||||||
|   int i; |   int i; | ||||||
|   | |||||||
							
								
								
									
										165
									
								
								src/webp/mux.h
									
									
									
									
									
								
							
							
						
						
									
										165
									
								
								src/webp/mux.h
									
									
									
									
									
								
							| @@ -35,7 +35,7 @@ | |||||||
| //   int copy_data = 0; | //   int copy_data = 0; | ||||||
| //   // ... (Read data from file). | //   // ... (Read data from file). | ||||||
| //   WebPMux* mux = WebPMuxCreate(&data, copy_data); | //   WebPMux* mux = WebPMuxCreate(&data, copy_data); | ||||||
| //   WebPMuxGetImage(mux, &image); | //   WebPMuxGetFrame(mux, 1, &image); | ||||||
| //   // ... (Consume image; e.g. call WebPDecode() to decode the data). | //   // ... (Consume image; e.g. call WebPDecode() to decode the data). | ||||||
| //   WebPMuxGetChunk(mux, "ICCP", &icc_profile); | //   WebPMuxGetChunk(mux, "ICCP", &icc_profile); | ||||||
| //   // ... (Consume icc_data). | //   // ... (Consume icc_data). | ||||||
| @@ -151,8 +151,8 @@ WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int); | |||||||
| // Creates a mux object from raw data given in WebP RIFF format. | // Creates a mux object from raw data given in WebP RIFF format. | ||||||
| // Parameters: | // Parameters: | ||||||
| //   bitstream - (in) the bitstream data in WebP RIFF format | //   bitstream - (in) the bitstream data in WebP RIFF format | ||||||
| //   copy_data - (in) value 1 indicates given data WILL copied to the mux, and | //   copy_data - (in) value 1 indicates given data WILL be copied to the mux | ||||||
| //               value 0 indicates data will NOT be copied. | //               and value 0 indicates data will NOT be copied. | ||||||
| // Returns: | // Returns: | ||||||
| //   A pointer to the mux object created from given data - on success. | //   A pointer to the mux object created from given data - on success. | ||||||
| //   NULL - In case of invalid data or memory error. | //   NULL - In case of invalid data or memory error. | ||||||
| @@ -162,54 +162,12 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, | |||||||
| } | } | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Single Image. | // Non-image chunks. | ||||||
|  |  | ||||||
| // Sets the image in the mux object. Any existing images (including frame/tile) |  | ||||||
| // will be removed. |  | ||||||
| // Parameters: |  | ||||||
| //   mux - (in/out) object in which the image is to be set |  | ||||||
| //   bitstream - (in) can either be a raw VP8/VP8L bitstream or a single-image |  | ||||||
| //               WebP file (non-animated and non-tiled) |  | ||||||
| //   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 is NULL or bitstream is NULL. |  | ||||||
| //   WEBP_MUX_MEMORY_ERROR - on memory allocation error. |  | ||||||
| //   WEBP_MUX_OK - on success. |  | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxSetImage(WebPMux* mux, |  | ||||||
|                                           const WebPData* bitstream, |  | ||||||
|                                           int copy_data); |  | ||||||
|  |  | ||||||
| // Gets image data from the mux object. |  | ||||||
| // The content of 'bitstream' is allocated using malloc(), and NOT |  | ||||||
| // owned by the 'mux' object. It MUST be deallocated by the caller by calling |  | ||||||
| // WebPDataClear(). |  | ||||||
| // Parameters: |  | ||||||
| //   mux - (in) object from which the image is to be fetched |  | ||||||
| //   bitstream - (out) the image data |  | ||||||
| // Returns: |  | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if either mux or bitstream is NULL |  | ||||||
| //                               or if mux contains animation/tiling. |  | ||||||
| //   WEBP_MUX_NOT_FOUND - if image is not present in mux object. |  | ||||||
| //   WEBP_MUX_OK - on success. |  | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxGetImage(const WebPMux* mux, |  | ||||||
|                                           WebPData* bitstream); |  | ||||||
|  |  | ||||||
| // Deletes the image in the mux object. |  | ||||||
| // Parameters: |  | ||||||
| //   mux - (in/out) object from which the image is to be deleted |  | ||||||
| // Returns: |  | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL |  | ||||||
| //                               or if mux contains animation/tiling. |  | ||||||
| //   WEBP_MUX_NOT_FOUND - if image is not present in mux object. |  | ||||||
| //   WEBP_MUX_OK - on success. |  | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxDeleteImage(WebPMux* mux); |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ |  | ||||||
| // Chunks. |  | ||||||
|  |  | ||||||
| // Note: Only non-image related chunks should be managed through chunk APIs. | // Note: Only non-image related chunks should be managed through chunk APIs. | ||||||
| // (Image related chunks are: "FRM ", "TILE", "VP8 ", "VP8L" and "ALPH"). | // (Image related chunks are: "FRM ", "TILE", "VP8 ", "VP8L" and "ALPH"). | ||||||
|  | // To add, get and delete images, use APIs WebPMuxSetImage(), | ||||||
|  | // WebPMuxPushFrame(), WebPMuxGetFrame() and WebPMuxDeleteFrame(). | ||||||
|  |  | ||||||
| // Adds a chunk with id 'fourcc' and data 'chunk_data' in the mux object. | // 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. | // Any existing chunk(s) with the same id will be removed. | ||||||
| @@ -218,8 +176,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteImage(WebPMux* mux); | |||||||
| //   fourcc - (in) a character array containing the fourcc of the given chunk; | //   fourcc - (in) a character array containing the fourcc of the given chunk; | ||||||
| //                 e.g., "ICCP", "META" etc. | //                 e.g., "ICCP", "META" etc. | ||||||
| //   chunk_data - (in) the chunk data to be added | //   chunk_data - (in) the chunk data to be added | ||||||
| //   copy_data - (in) value 1 indicates given data WILL copied to the mux, and | //   copy_data - (in) value 1 indicates given data WILL be copied to the mux | ||||||
| //               value 0 indicates data will NOT be copied. | //               and value 0 indicates data will NOT be copied. | ||||||
| // Returns: | // Returns: | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if mux or chunk_data is NULL | //   WEBP_MUX_INVALID_ARGUMENT - if mux or chunk_data is NULL | ||||||
| //                               or if fourcc corresponds to an image chunk. | //                               or if fourcc corresponds to an image chunk. | ||||||
| @@ -258,26 +216,48 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( | |||||||
|     WebPMux* mux, const char fourcc[4]); |     WebPMux* mux, const char fourcc[4]); | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Animation. | // Images. | ||||||
|  |  | ||||||
| // Encapsulates data about a single frame/tile. | // Encapsulates data about a single frame/tile. | ||||||
| struct WebPMuxFrameInfo { | struct WebPMuxFrameInfo { | ||||||
|   WebPData bitstream_;  // image data: can either be a raw VP8/VP8L bitstream |   WebPData    bitstream_;  // image data: can either be a raw VP8/VP8L bitstream | ||||||
|                         // or a single-image WebP file. |                            // or a single-image WebP file. | ||||||
|   int x_offset_;        // x-offset of the frame. |   int         x_offset_;   // x-offset of the frame. | ||||||
|   int y_offset_;        // y-offset of the frame. |   int         y_offset_;   // y-offset of the frame. | ||||||
|   int duration_;        // duration of the frame (in milliseconds). |   int         duration_;   // duration of the frame (in milliseconds). | ||||||
|   uint32_t pad[3];      // padding for later use |  | ||||||
|  |   WebPChunkId id;          // frame type: should be one of WEBP_CHUNK_FRAME, | ||||||
|  |                            // WEBP_CHUNK_TILE or WEBP_CHUNK_IMAGE | ||||||
|  |   uint32_t pad[3];         // padding for later use | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Adds an animation frame at the end of the mux object. | // Sets the (non-animated and non-tiled) image in the mux object. | ||||||
| // Note: as WebP only supports even offsets, any odd offset will be snapped to | // Note: Any existing images (including frames/tiles) will be removed. | ||||||
| // an even location using: offset &= ~1 |  | ||||||
| // Parameters: | // Parameters: | ||||||
| //   mux - (in/out) object to which an animation frame is to be added | //   mux - (in/out) object in which the image is to be set | ||||||
|  | //   bitstream - (in) can either be a raw VP8/VP8L bitstream or a single-image | ||||||
|  | //               WebP file (non-animated and non-tiled) | ||||||
|  | //   copy_data - (in) value 1 indicates given data WILL be copied to the mux | ||||||
|  | //               and value 0 indicates data will NOT be copied. | ||||||
|  | // Returns: | ||||||
|  | //   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. | ||||||
|  | //   WEBP_MUX_MEMORY_ERROR - on memory allocation error. | ||||||
|  | //   WEBP_MUX_OK - on success. | ||||||
|  | WEBP_EXTERN(WebPMuxError) WebPMuxSetImage( | ||||||
|  |     WebPMux* mux, const WebPData* bitstream, int copy_data); | ||||||
|  |  | ||||||
|  | // Adds a frame at the end of the mux object. | ||||||
|  | // Notes: (1) frame.id should be one of WEBP_CHUNK_FRAME or WEBP_CHUNK_TILE | ||||||
|  | //        (2) For setting a non-animated non-tiled image, use WebPMuxSetImage() | ||||||
|  | //            instead. | ||||||
|  | //        (3) Type of frame being pushed must be same as the frames in mux. | ||||||
|  | //        (4) As WebP only supports even offsets, any odd offset will be snapped | ||||||
|  | //            to an even location using: offset &= ~1 | ||||||
|  | // Parameters: | ||||||
|  | //   mux - (in/out) object to which the frame is to be added | ||||||
| //   frame - (in) frame data. | //   frame - (in) frame data. | ||||||
| //   copy_data - (in) value 1 indicates given data WILL copied to the mux, and | //   copy_data - (in) value 1 indicates given data WILL be copied to the mux | ||||||
| //               value 0 indicates data will NOT be copied. | //               and value 0 indicates data will NOT be copied. | ||||||
| // Returns: | // Returns: | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL | //   WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL | ||||||
| //                               or if content of 'frame' is invalid. | //                               or if content of 'frame' is invalid. | ||||||
| @@ -286,7 +266,7 @@ struct WebPMuxFrameInfo { | |||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( | WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( | ||||||
|     WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); |     WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); | ||||||
|  |  | ||||||
| // Gets the nth animation frame from the mux object. | // Gets the nth frame from the mux object. | ||||||
| // The content of 'frame->bitstream_' is allocated using malloc(), and NOT | // The content of 'frame->bitstream_' is allocated using malloc(), and NOT | ||||||
| // owned by the 'mux' object. It MUST be deallocated by the caller by calling | // owned by the 'mux' object. It MUST be deallocated by the caller by calling | ||||||
| // WebPDataClear(). | // WebPDataClear(). | ||||||
| @@ -296,25 +276,28 @@ WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( | |||||||
| //   nth - (in) index of the frame in the mux object | //   nth - (in) index of the frame in the mux object | ||||||
| //   frame - (out) data of the returned frame | //   frame - (out) data of the returned frame | ||||||
| // Returns: | // Returns: | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL | //   WEBP_MUX_INVALID_ARGUMENT - if mux or frame is NULL. | ||||||
| //   WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. | //   WEBP_MUX_NOT_FOUND - if there are less than nth frames in the mux object. | ||||||
| //   WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. | //   WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. | ||||||
| //   WEBP_MUX_OK - on success. | //   WEBP_MUX_OK - on success. | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( | WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( | ||||||
|     const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); |     const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); | ||||||
|  |  | ||||||
| // Deletes an animation frame from the mux object. | // Deletes a frame from the mux object. | ||||||
| // nth=0 has a special meaning - last position. | // nth=0 has a special meaning - last position. | ||||||
| // Parameters: | // Parameters: | ||||||
| //   mux - (in/out) object from which a frame is to be deleted | //   mux - (in/out) object from which a frame is to be deleted | ||||||
| //   nth - (in) The position from which the frame is to be deleted | //   nth - (in) The position from which the frame is to be deleted | ||||||
| // Returns: | // Returns: | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL | //   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL. | ||||||
| //   WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object | //   WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object | ||||||
| //                        before deletion. | //                        before deletion. | ||||||
| //   WEBP_MUX_OK - on success. | //   WEBP_MUX_OK - on success. | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); | WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); | ||||||
|  |  | ||||||
|  | //------------------------------------------------------------------------------ | ||||||
|  | // Animation. | ||||||
|  |  | ||||||
| // Sets the animation loop count in the mux object. Any existing loop count | // Sets the animation loop count in the mux object. Any existing loop count | ||||||
| // value(s) will be removed. | // value(s) will be removed. | ||||||
| // Parameters: | // Parameters: | ||||||
| @@ -338,54 +321,6 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetLoopCount(WebPMux* mux, int loop_count); | |||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* mux, | WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* mux, | ||||||
|                                               int* loop_count); |                                               int* loop_count); | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ |  | ||||||
| // Tiling. |  | ||||||
|  |  | ||||||
| // Adds a tile at the end of the mux object. |  | ||||||
| // Note: as WebP only supports even offsets, any odd offset will be snapped to |  | ||||||
| // an even location using: offset &= ~1 |  | ||||||
| // Parameters: |  | ||||||
| //   mux - (in/out) object to which a tile is to be added. |  | ||||||
| //   tile - (in) tile data. |  | ||||||
| //   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 tile is NULL |  | ||||||
| //                               or if content of 'tile' is invalid. |  | ||||||
| //   WEBP_MUX_MEMORY_ERROR - on memory allocation error. |  | ||||||
| //   WEBP_MUX_OK - on success. |  | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxPushTile( |  | ||||||
|     WebPMux* mux, const WebPMuxFrameInfo* tile, int copy_data); |  | ||||||
|  |  | ||||||
| // Gets the nth tile from the mux object. |  | ||||||
| // The content of 'tile->bitstream_' is allocated using malloc(), and NOT |  | ||||||
| // owned by the 'mux' object. It MUST be deallocated by the caller by calling |  | ||||||
| // WebPDataClear(). |  | ||||||
| // nth=0 has a special meaning - last position. |  | ||||||
| // Parameters: |  | ||||||
| //   mux - (in) object from which the info is to be fetched |  | ||||||
| //   nth - (in) index of the tile in the mux object |  | ||||||
| //   tile - (out) data of the returned tile |  | ||||||
| // Returns: |  | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if either mux or tile is NULL |  | ||||||
| //   WEBP_MUX_NOT_FOUND - if there are less than nth tiles in the mux object. |  | ||||||
| //   WEBP_MUX_BAD_DATA - if nth tile chunk in mux is invalid. |  | ||||||
| //   WEBP_MUX_OK - on success. |  | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxGetTile( |  | ||||||
|     const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* tile); |  | ||||||
|  |  | ||||||
| // Deletes a tile from the mux object. |  | ||||||
| // nth=0 has a special meaning - last position |  | ||||||
| // Parameters: |  | ||||||
| //   mux - (in/out) object from which a tile is to be deleted |  | ||||||
| //   nth - (in) The position from which the tile is to be deleted |  | ||||||
| // Returns: |  | ||||||
| //   WEBP_MUX_INVALID_ARGUMENT - if mux is NULL |  | ||||||
| //   WEBP_MUX_NOT_FOUND - If there are less than nth tiles in the mux object |  | ||||||
| //                        before deletion. |  | ||||||
| //   WEBP_MUX_OK - on success. |  | ||||||
| WEBP_EXTERN(WebPMuxError) WebPMuxDeleteTile(WebPMux* mux, uint32_t nth); |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Misc Utilities. | // Misc Utilities. | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user