Пример #1
0
		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;
		}
Пример #2
0
		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;
		}
Пример #3
0
        WebPMuxError ValidateForImage(WebPMux* mux)
        {
            int num_vp8 = MuxImageCount(mux.images_, IMAGE_ID);
              int num_frames = MuxImageCount(mux.images_, FRAME_ID);
              int num_tiles = MuxImageCount(mux.images_, TILE_ID);

              if (num_vp8 == 0) {
            // No images in mux.
            return WEBP_MUX_NOT_FOUND;
              } else if (num_vp8 == 1 && num_frames == 0 && num_tiles == 0) {
            // Valid case (single image).
            return WEBP_MUX_OK;
              } else {
            // Frame/Tile case OR an invalid mux.
            return WEBP_MUX_INVALID_ARGUMENT;
              }
        }
Пример #4
0
		// Gets a reference to the nth tile from the mux object.
		// The caller should NOT free the returned data.
		// 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
		//   image - (out) the image data
		//   alpha - (out) the alpha data corresponding to tile image (if present)
		//   x_offset - (out) x-offset of the returned tile
		//   y_offset - (out) y-offset of the returned tile
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either mux, image, x_offset or
		//                               y_offset 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.
		WebPMuxError WebPMuxGetTile(WebPMux* mux, uint nth, WebPData* image, WebPData* alpha, uint* x_offset, uint* y_offset) {
		  return MuxGetFrameTileInternal(mux, nth, image, alpha,
										 x_offset, y_offset, null,
										 kChunks[TILE_ID].chunkTag);
		}
Пример #5
0
		static WebPMuxError MuxGetFrameTileInternal(WebPMux* mux,
													uint nth,
													WebPData* image,
													WebPData* alpha,
													uint* x_offset,
													uint* y_offset,
													uint* duration, uint tag) {
		  byte* frame_tile_data;
		  uint frame_tile_size;
		  WebPMuxError err;
		  WebPMuxImage* wpi;

		  int is_frame = (tag == kChunks[FRAME_ID].chunkTag) ? 1 : 0;
		  TAG_ID id = is_frame ? FRAME_ID : TILE_ID;

		  if (mux == null || image == null ||
			  x_offset == null || y_offset == null || (is_frame && duration == null)) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  // Get the nth WebPMuxImage.
		  err = MuxImageGetNth((WebPMuxImage**)&mux.images_, nth, id, &wpi);
		  if (err != WEBP_MUX_OK) return err;

		  // Get frame chunk.
		  assert(wpi.header_ != null);  // As GetNthImage() already checked header_.
		  frame_tile_data = wpi.header_.data_;
		  frame_tile_size = wpi.header_.payload_size_;

		  if (frame_tile_size < kChunks[id].chunkSize) return WEBP_MUX_BAD_DATA;
		  *x_offset = GetLE32(frame_tile_data + 0);
		  *y_offset = GetLE32(frame_tile_data + 4);
		  if (is_frame) *duration = GetLE32(frame_tile_data + 16);

		  // Get alpha chunk (if present & requested).
		  if (alpha != null) {
			memset(alpha, 0, sizeof(*alpha));
			if (wpi.alpha_ != null) {
			  alpha.bytes_ = wpi.alpha_.data_;
			  alpha.size_ = wpi.alpha_.payload_size_;
			}
		  }

		  // Get image chunk.
		  memset(image, 0, sizeof(*image));
		  if (wpi.vp8_ != null) {
			image.bytes_ = wpi.vp8_.data_;
			image.size_ = wpi.vp8_.payload_size_;
		  }

		  return WEBP_MUX_OK;
		}
Пример #6
0
		// Gets a reference to the color profile in the mux object.
		// The caller should NOT free the returned data.
		// Parameters:
		//   mux - (in) object from which the color profile data is to be fetched
		//   color_profile - (out) color profile data
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either mux or color_profile is null.
		//   WEBP_MUX_NOT_FOUND - if color profile is not present in mux object.
		//   WEBP_MUX_OK - on success.
		WebPMuxError WebPMuxGetColorProfile(WebPMux* mux,
											WebPData* color_profile) {
		  if (mux == null || color_profile == null) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  return MuxGet(mux, ICCP_ID, 1, color_profile);
		}
Пример #7
0
		//------------------------------------------------------------------------------
		// Get API(s).

		// Gets the feature flags from the mux object.
		// Parameters:
		//   mux - (in) object from which the features are to be fetched
		//   flags - (out) the flags specifying which features are present in the
		//           mux object. This will be an OR of various flag values.
		//           Enum 'FeatureFlags' can be used to test for individual flag values.
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if mux is null or flags is null
		//   WEBP_MUX_NOT_FOUND - if VP8X chunk is not present in mux object.
		//   WEBP_MUX_BAD_DATA - if VP8X chunk in mux is invalid.
		//   WEBP_MUX_OK - on success.
		public WebPMuxError WebPMuxGetFeatures(WebPMux* mux, uint* flags) {
		  WebPData data;
		  WebPMuxError err;

		  if (mux == null || flags == null) return WEBP_MUX_INVALID_ARGUMENT;
		  *flags = 0;

		  // Check if VP8X chunk is present.
		  err = MuxGet(mux, VP8X_ID, 1, &data);
		  if (err == WEBP_MUX_NOT_FOUND) {
			// Check if VP8 chunk is present.
			err = WebPMuxGetImage(mux, &data, null);
			if (err == WEBP_MUX_NOT_FOUND &&              // Data not available (yet).
				mux.state_ == WEBP_MUX_STATE_PARTIAL) {  // Incremental case.
			  return WEBP_MUX_NOT_ENOUGH_DATA;
			} else {
			  return err;
			}
		  } else if (err != WEBP_MUX_OK) {
			return err;
		  }

		  // TODO(urvang): Add a '#define CHUNK_SIZE_BYTES 4' and use it instead of
		  // hard-coded value of 4 everywhere.
		  if (data.size_ < 4) return WEBP_MUX_BAD_DATA;

		  // All OK. Fill up flags.
		  *flags = GetLE32(data.bytes_);
		  return WEBP_MUX_OK;
		}
Пример #8
0
		// Sets the color profile in the mux object. Any existing color profile chunk(s)
		// will be removed.
		// Parameters:
		//   mux - (in/out) object to which the color profile is to be added
		//   data - (in) the color profile data to be added
		//   size - (in) size of the color profile 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 is null or data is null
		//   WEBP_MUX_MEMORY_ERROR - on memory allocation error
		//   WEBP_MUX_OK - on success
		WebPMuxError WebPMuxSetColorProfile(WebPMux* mux, byte* data, uint size, int copy_data) {
		  WebPMuxError err;

		  if (mux == null || data == null || size > MAX_CHUNK_PAYLOAD) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  // Delete the existing ICCP chunk(s).
		  err = WebPMuxDeleteColorProfile(mux);
		  if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;

		  // Add the given ICCP chunk.
		  return MuxSet(mux, ICCP_ID, 1, data, size, null, copy_data);
		}
Пример #9
0
		// Sets the animation loop count in the mux object. Any existing loop count
		// value(s) will be removed.
		// Parameters:
		//   mux - (in/out) object in which loop chunk is to be set/added
		//   loop_count - (in) animation loop count value.
		//                Note that loop_count of zero denotes infinite loop.
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if mux is null
		//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.
		//   WEBP_MUX_OK - on success.
		WebPMuxError WebPMuxSetLoopCount(WebPMux* mux, uint loop_count) {
		  WebPMuxError err;
		  byte* data = null;

		  if (mux == null) 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.
		  data = (byte*)malloc(kChunks[LOOP_ID].chunkSize);
		  if (data == null) return WEBP_MUX_MEMORY_ERROR;

		  PutLE32(data, loop_count);
		  err = MuxAddChunk(mux, 1, kChunks[LOOP_ID].chunkTag, data,
							kChunks[LOOP_ID].chunkSize, null, 1);
		  free(data);
		  return err;
		}
Пример #10
0
		//------------------------------------------------------------------------------
		// Set API(s).

		// 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
		//   data - (in) the image data to be set. The data can be either a VP8
		//          bitstream or a single-image WebP file (non-animated & non-tiled)
		//   size - (in) size of the image data
		//   alpha_data - (in) the alpha data corresponding to the image (if present)
		//   alpha_size - (in) size of alpha chunk 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 is null or data is null.
		//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.
		//   WEBP_MUX_OK - on success.
		public WebPMuxError WebPMuxSetImage(WebPMux* mux, byte* data, uint size, byte* alpha_data, uint alpha_size, int copy_data)
		{
		  WebPMuxError err;
		  WebPChunk chunk;
		  WebPMuxImage wpi;
		  WebPData image;
		  int has_alpha = (alpha_data != null && alpha_size != 0);

		  if (mux == null || data == null || size > MAX_CHUNK_PAYLOAD) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  // If given data is for a whole webp file, extract only the VP8 data from it.
		  err = GetImageData(data, size, &image, null);
		  if (err != WEBP_MUX_OK) return err;

		  // Delete the existing images.
		  MuxImageDeleteAll(&mux.images_);

		  MuxImageInit(&wpi);

		  if (has_alpha) {  // Add alpha chunk.
			ChunkInit(&chunk);
			err = ChunkAssignDataImageInfo(&chunk, alpha_data, alpha_size, null,
										   copy_data, kChunks[ALPHA_ID].chunkTag);
			if (err != WEBP_MUX_OK) return err;
			err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
			if (err != WEBP_MUX_OK) return err;
		  }

		  // Add image chunk.
		  ChunkInit(&chunk);
		  err = ChunkAssignDataImageInfo(&chunk, image.bytes_, image.size_, null,
										 copy_data, kChunks[IMAGE_ID].chunkTag);
		  if (err != WEBP_MUX_OK) return err;
		  err = ChunkSetNth(&chunk, &wpi.vp8_, 1);
		  if (err != WEBP_MUX_OK) return err;

		  // Add this image to mux.
		  return MuxImageSetNth(&wpi, &mux.images_, 1);
		}
Пример #11
0
		// Sets the XMP metadata in the mux object. Any existing metadata chunk(s) will
		// be removed.
		// Parameters:
		//   mux - (in/out) object to which the XMP metadata is to be added
		//   data - (in) the XMP metadata data to be added
		//   size - (in) size of the XMP metadata 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 is null or data is null.
		//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.
		//   WEBP_MUX_OK - on success.
		public WebPMuxError WebPMuxSetMetadata(WebPMux* mux, byte* data, uint size, int copy_data) {
		  WebPMuxError err;

		  if (mux == null || data == null || size > MAX_CHUNK_PAYLOAD) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  // Delete the existing metadata chunk(s).
		  err = WebPMuxDeleteMetadata(mux);
		  if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;

		  // Add the given metadata chunk.
		  return MuxSet(mux, META_ID, 1, data, size, null, copy_data);
		}
Пример #12
0
		static WebPMuxError DeleteLoopCount(WebPMux* mux) {
		  return MuxDeleteAllNamedData(mux, kChunks[LOOP_ID].chunkName);
		}
Пример #13
0
		static WebPMuxError MuxDeleteAllNamedData(WebPMux* mux, char* tag) {
		  TAG_ID id;
		  WebPChunk** chunk_list;

		  if (mux == null || tag == null) return WEBP_MUX_INVALID_ARGUMENT;

		  id = ChunkGetIdFromName(tag);
		  if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT;

		  chunk_list = GetChunkListFromId(mux, id);
		  if (chunk_list == null) return WEBP_MUX_INVALID_ARGUMENT;

		  return DeleteChunks(chunk_list, kChunks[id].chunkTag);
		}
Пример #14
0
        WebPMuxError WebPMuxValidate(WebPMux* mux)
        {
            int num_iccp;
              int num_meta;
              int num_loop_chunks;
              int num_frames;
              int num_tiles;
              int num_vp8x;
              int num_images;
              int num_alpha;
              uint flags;
              WebPMuxError err;

              // Verify mux is not null.
              if (mux == null || mux.state_ == WEBP_MUX_STATE_ERROR) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // No further checks if mux is partial.
              if (mux.state_ == WEBP_MUX_STATE_PARTIAL) return WEBP_MUX_OK;

              // Verify mux has at least one image.
              if (mux.images_ == null) return WEBP_MUX_INVALID_ARGUMENT;

              err = WebPMuxGetFeatures(mux, &flags);
              if (err != WEBP_MUX_OK) return err;

              // At most one color profile chunk.
              err = WebPMuxNumNamedElements(mux, kChunks[ICCP_ID].chunkName, &num_iccp);
              if (err != WEBP_MUX_OK) return err;
              if (num_iccp > 1) return WEBP_MUX_INVALID_ARGUMENT;

              // ICCP_FLAG and color profile chunk is consistent.
              if (IsNotCompatible(flags & ICCP_FLAG, num_iccp)) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // At most one XMP metadata.
              err = WebPMuxNumNamedElements(mux, kChunks[META_ID].chunkName, &num_meta);
              if (err != WEBP_MUX_OK) return err;
              if (num_meta > 1) return WEBP_MUX_INVALID_ARGUMENT;

              // META_FLAG and XMP metadata chunk is consistent.
              if (IsNotCompatible(flags & META_FLAG, num_meta)) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // At most one loop chunk.
              err = WebPMuxNumNamedElements(mux, kChunks[LOOP_ID].chunkName,
                                        &num_loop_chunks);
              if (err != WEBP_MUX_OK) return err;
              if (num_loop_chunks > 1) return WEBP_MUX_INVALID_ARGUMENT;

              // Animation: ANIMATION_FLAG, loop chunk and frame chunk(s) are consistent.
              err = WebPMuxNumNamedElements(mux, kChunks[FRAME_ID].chunkName, &num_frames);
              if (err != WEBP_MUX_OK) return err;
              if ((flags & ANIMATION_FLAG) &&
              ((num_loop_chunks == 0) || (num_frames == 0))) {
            return WEBP_MUX_INVALID_ARGUMENT;
              } else if (((num_loop_chunks == 1) || (num_frames > 0)) &&
                     !(flags & ANIMATION_FLAG)) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // Tiling: TILE_FLAG and tile chunk(s) are consistent.
              err = WebPMuxNumNamedElements(mux, kChunks[TILE_ID].chunkName, &num_tiles);
              if (err != WEBP_MUX_OK) return err;
              if (IsNotCompatible(flags & TILE_FLAG, num_tiles)) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // Verify either VP8X chunk is present OR there is only one elem in
              // mux.images_.
              err = WebPMuxNumNamedElements(mux, kChunks[VP8X_ID].chunkName, &num_vp8x);
              if (err != WEBP_MUX_OK) return err;
              err = WebPMuxNumNamedElements(mux, kChunks[IMAGE_ID].chunkName, &num_images);
              if (err != WEBP_MUX_OK) return err;

              if (num_vp8x > 1) {
            return WEBP_MUX_INVALID_ARGUMENT;
              } else if ((num_vp8x == 0) && (num_images != 1)) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // ALPHA_FLAG & alpha chunk(s) are consistent.
              err = WebPMuxNumNamedElements(mux, kChunks[ALPHA_ID].chunkName, &num_alpha);
              if (err != WEBP_MUX_OK) return err;
              if (IsNotCompatible(flags & ALPHA_FLAG, num_alpha)) {
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              // num_images & num_alpha_chunks are consistent.
              if ((num_alpha > 0) && (num_alpha != num_images)) {
            // Note that "num_alpha > 0" is the correct check but "flags && ALPHA_FLAG"
            // is NOT, because ALPHA_FLAG is based on first image only.
            return WEBP_MUX_INVALID_ARGUMENT;
              }

              return WEBP_MUX_OK;
        }
Пример #15
0
		//------------------------------------------------------------------------------
		// Assembly of the WebP RIFF file.

		static WebPMuxError GetImageCanvasHeightWidth(WebPMux* mux,
													  uint flags,
													  uint* width,
													  uint* height) {
		  uint max_x = 0;
		  uint max_y = 0;
		  ulong image_area = 0;
		  WebPMuxImage* wpi = null;

		  assert(mux != null);
		  assert(width && height);

		  wpi = mux.images_;
		  assert(wpi != null);
		  assert(wpi.vp8_ != null);

		  if (wpi.next_) {
			// Aggregate the bounding box for animation frames & tiled images.
			for (; wpi != null; wpi = wpi.next_) {
			  WebPImageInfo* image_info = wpi.vp8_.image_info_;

			  if (image_info != null) {
				uint max_x_pos = image_info.x_offset_ + image_info.width_;
				uint max_y_pos = image_info.y_offset_ + image_info.height_;
				if (max_x_pos < image_info.x_offset_) {  // Overflow occurred.
				  return WEBP_MUX_INVALID_ARGUMENT;
				}
				if (max_y_pos < image_info.y_offset_) {  // Overflow occurred.
				  return WEBP_MUX_INVALID_ARGUMENT;
				}
				if (max_x_pos > max_x) max_x = max_x_pos;
				if (max_y_pos > max_y) max_y = max_y_pos;
				image_area += (image_info.width_ * image_info.height_);
			  }
			}
			*width = max_x;
			*height = max_y;
			// Crude check to validate that there are no image overlaps/holes for tile
			// images. Check that the aggregated image area for individual tiles exactly
			// matches the image area of the constructed canvas. However, the area-match
			// is necessary but not sufficient condition.
			if ((flags & TILE_FLAG) && (image_area != (max_x * max_y))) {
			  *width = 0;
			  *height = 0;
			  return WEBP_MUX_INVALID_ARGUMENT;
			}
		  } else {
			// For a single image, extract the width & height from VP8 image-data.
			int w, h;
			WebPChunk* image_chunk = wpi.vp8_;
			assert(image_chunk != null);
			if (VP8GetInfo(image_chunk.data_, image_chunk.payload_size_,
						   image_chunk.payload_size_, &w, &h)) {
			  *width = w;
			  *height = h;
			}
		  }
		  return WEBP_MUX_OK;
		}
Пример #16
0
		static WebPMuxError MuxAddFrameTileInternal(WebPMux* mux, uint nth,
													byte* data, uint size,
													byte* alpha_data,
													uint alpha_size,
													uint x_offset,
													uint y_offset,
													uint duration,
													int copy_data, uint tag) {
		  WebPChunk chunk;
		  WebPData image;
		  WebPMuxImage wpi;
		  WebPMuxError err;
		  WebPImageInfo* image_info = null;
		  byte* frame_tile_data = null;
		  uint frame_tile_data_size = 0;
		  int is_frame = (tag == kChunks[FRAME_ID].chunkTag) ? 1 : 0;
		  int has_alpha = (alpha_data != null && alpha_size != 0);

		  if (mux == null || data == null || size > MAX_CHUNK_PAYLOAD) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  // If given data is for a whole webp file, extract only the VP8 data from it.
		  err = GetImageData(data, size, &image, null);
		  if (err != WEBP_MUX_OK) return err;

		  ChunkInit(&chunk);
		  MuxImageInit(&wpi);

		  if (has_alpha) {
			// Add alpha chunk.
			err = ChunkAssignDataImageInfo(&chunk, alpha_data, alpha_size, null,
										   copy_data, kChunks[ALPHA_ID].chunkTag);
			if (err != WEBP_MUX_OK) return err;
			err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
			if (err != WEBP_MUX_OK) return err;
			ChunkInit(&chunk);  // chunk owned by wpi.alpha_ now.
		  }

		  // Create image_info object.
		  image_info = CreateImageInfo(x_offset, y_offset, duration,
									   image.bytes_, image.size_);
		  if (image_info == null) {
			MuxImageRelease(&wpi);
			return WEBP_MUX_MEMORY_ERROR;
		  }

		  // Add image chunk.
		  err = ChunkAssignDataImageInfo(&chunk, image.bytes_, image.size_, image_info,
										 copy_data, kChunks[IMAGE_ID].chunkTag);
		  if (err != WEBP_MUX_OK) goto Err;
		  image_info = null;  // Owned by 'chunk' now.
		  err = ChunkSetNth(&chunk, &wpi.vp8_, 1);
		  if (err != WEBP_MUX_OK) goto Err;
		  ChunkInit(&chunk);  // chunk owned by wpi.vp8_ now.

		  // Create frame/tile data from image_info.
		  err = CreateDataFromImageInfo(wpi.vp8_.image_info_, is_frame,
										&frame_tile_data, &frame_tile_data_size);
		  if (err != WEBP_MUX_OK) goto Err;

		  // Add frame/tile chunk (with copy_data = 1).
		  err = ChunkAssignDataImageInfo(&chunk, frame_tile_data, frame_tile_data_size,
										 null, 1, tag);
		  if (err != WEBP_MUX_OK) goto Err;
		  free(frame_tile_data);
		  frame_tile_data = null;
		  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.
		  err = MuxImageSetNth(&wpi, &mux.images_, nth);
		  if (err != WEBP_MUX_OK) goto Err;

		  // All is well.
		  return WEBP_MUX_OK;

		 Err:  // Something bad happened.
		  free(image_info);
		  free(frame_tile_data);
		  ChunkRelease(&chunk);
		  MuxImageRelease(&wpi);
		  return err;
		}
Пример #17
0
		// VP8X format:
		// Total Size : 12,
		// Flags  : 4 bytes,
		// Width  : 4 bytes,
		// Height : 4 bytes.
		static WebPMuxError CreateVP8XChunk(WebPMux* mux) {
		  WebPMuxError err = WEBP_MUX_OK;
		  uint flags = 0;
		  uint width = 0;
		  uint height = 0;
		  byte data[VP8X_CHUNK_SIZE];
Пример #18
0
		// Adds a tile to the mux object.
		// nth=0 has a special meaning - last position.
		// Parameters:
		//   mux - (in/out) object to which a tile is to be added
		//   nth - (in) The position at which the tile is to be added.
		//   data - (in) the raw VP8 image data corresponding to tile image.  The data
		//          can be either a VP8 bitstream or a single-image WebP file
		//          (non-animated & non-tiled)
		//   size - (in) size of tile chunk data
		//   alpha_data - (in) the alpha data corresponding to tile image (if present)
		//   alpha_size - (in) size of alpha chunk data
		//   x_offset - (in) x-offset of the tile to be added
		//   y_offset - (in) y-offset of the tile to be added
		//   copy_data - (in) value 1 indicates given data WILL copied to the mux, and
		//               value 0 indicates data will NOT be copied.
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if mux is null or data is null
		//   WEBP_MUX_NOT_FOUND - If we have less than (nth-1) tiles before adding.
		//   WEBP_MUX_MEMORY_ERROR - on memory allocation error.
		//   WEBP_MUX_OK - on success.
		WebPMuxError WebPMuxAddTile(WebPMux* mux, uint nth, byte* data, uint size, byte* alpha_data, uint alpha_size, uint x_offset, uint y_offset, int copy_data) {
		  return MuxAddFrameTileInternal(mux, nth, data, size, alpha_data, alpha_size,
										 x_offset, y_offset, 1,
										 copy_data, kChunks[TILE_ID].chunkTag);
		}
Пример #19
0
		static WebPMuxError MuxAddChunk(WebPMux* mux, uint nth, uint tag, byte* data, uint size, WebPImageInfo* image_info, int copy_data)
		{
		  TAG_ID id;
		  assert(mux != null);
		  assert(size <= MAX_CHUNK_PAYLOAD);

		  id = ChunkGetIdFromTag(tag);
		  if (id == NIL_ID) return WEBP_MUX_INVALID_PARAMETER;

		  return MuxSet(mux, id, nth, data, size, image_info, copy_data);
		}
Пример #20
0
		//------------------------------------------------------------------------------
		// Delete API(s).

		// 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.
		WebPMuxError WebPMuxDeleteImage(WebPMux* mux) {
		  WebPMuxError err;

		  if (mux == null) return WEBP_MUX_INVALID_ARGUMENT;

		  err = ValidateForImage(mux);
		  if (err != WEBP_MUX_OK) return err;

		  // All Well, delete Image.
		  MuxImageDeleteAll(&mux.images_);
		  return WEBP_MUX_OK;
		}
Пример #21
0
		// Gets a reference to the image in the mux object.
		// The caller should NOT free the returned data.
		// Parameters:
		//   mux - (in) object from which the image is to be fetched
		//   image - (out) the image data
		//   alpha - (out) the alpha data of the image (if present)
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either mux or image 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.
		public WebPMuxError WebPMuxGetImage(WebPMux* mux, WebPData* image, WebPData* alpha) {
		  WebPMuxError err;
		  WebPMuxImage* wpi = null;

		  if (mux == null || image == null) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  memset(image, 0, sizeof(*image));

		  err = ValidateForImage(mux);
		  if (err != WEBP_MUX_OK) return err;

		  // All well. Get the image.
		  err = MuxImageGetNth((WebPMuxImage**)&mux.images_, 1, IMAGE_ID, &wpi);
		  assert(err == WEBP_MUX_OK);  // Already tested above.

		  // Get alpha chunk (if present & requested).
		  if (alpha != null) {
			memset(alpha, 0, sizeof(*alpha));
			if (wpi.alpha_ != null) {
			  alpha.bytes_ = wpi.alpha_.data_;
			  alpha.size_ = wpi.alpha_.payload_size_;
			}
		  }

		  // Get image chunk.
		  if (wpi.vp8_ != null) {
			image.bytes_ = wpi.vp8_.data_;
			image.size_ = wpi.vp8_.payload_size_;
		  }
		  return WEBP_MUX_OK;
		}
Пример #22
0
		// Deletes the XMP metadata in the mux object.
		// Parameters:
		//   mux - (in/out) object from which XMP metadata is to be deleted
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if mux is null
		//   WEBP_MUX_NOT_FOUND - If mux does not contain metadata.
		//   WEBP_MUX_OK - on success.
		WebPMuxError WebPMuxDeleteMetadata(WebPMux* mux) {
		  return MuxDeleteAllNamedData(mux, kChunks[META_ID].chunkName);
		}
Пример #23
0
		// Gets a reference to the XMP metadata in the mux object.
		// The caller should NOT free the returned data.
		// Parameters:
		//   mux - (in) object from which the XMP metadata is to be fetched
		//   metadata - (out) XMP metadata
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either mux or metadata is null.
		//   WEBP_MUX_NOT_FOUND - if metadata is not present in mux object.
		//   WEBP_MUX_OK - on success.
		public WebPMuxError WebPMuxGetMetadata(WebPMux* mux, WebPData* metadata) {
		  if (mux == null || metadata == null) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  return MuxGet(mux, META_ID, 1, metadata);
		}
Пример #24
0
		// Deletes the color profile in the mux object.
		// Parameters:
		//   mux - (in/out) object from which color profile is to be deleted
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if mux is null
		//   WEBP_MUX_NOT_FOUND - If mux does not contain color profile.
		//   WEBP_MUX_OK - on success.
		WebPMuxError WebPMuxDeleteColorProfile(WebPMux* mux) {
		  return MuxDeleteAllNamedData(mux, kChunks[ICCP_ID].chunkName);
		}
Пример #25
0
		// Gets the animation loop count from the mux object.
		// Parameters:
		//   mux - (in) object from which the loop count is to be fetched
		//   loop_count - (out) the loop_count value present in the LOOP chunk
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either of mux or loop_count is null
		//   WEBP_MUX_NOT_FOUND - if loop chunk is not present in mux object.
		//   WEBP_MUX_OK - on success.
		WebPMuxError WebPMuxGetLoopCount(WebPMux* mux, uint* loop_count) {
		  WebPData image;
		  WebPMuxError err;

		  if (mux == null || loop_count == null) return WEBP_MUX_INVALID_ARGUMENT;

		  err = MuxGet(mux, LOOP_ID, 1, &image);
		  if (err != WEBP_MUX_OK) return err;
		  if (image.size_ < kChunks[LOOP_ID].chunkSize) return WEBP_MUX_BAD_DATA;
		  *loop_count = GetLE32(image.bytes_);

		  return WEBP_MUX_OK;
		}
Пример #26
0
		static WebPMuxError DeleteFrameTileInternal(WebPMux* mux,
													uint nth,
													char* tag) {
		  TAG_ID id;
		  if (mux == null) return WEBP_MUX_INVALID_ARGUMENT;

		  id = ChunkGetIdFromName(tag);
		  assert(id == FRAME_ID || id == TILE_ID);
		  return MuxImageDeleteNth(&mux.images_, nth, id);
		}
Пример #27
0
		// Gets a reference to the nth animation frame from the mux object.
		// The caller should NOT free the returned data.
		// 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 frame in the mux object
		//   image - (out) the image data
		//   alpha - (out) the alpha data corresponding to frame image (if present)
		//   x_offset - (out) x-offset of the returned frame
		//   y_offset - (out) y-offset of the returned frame
		//   duration - (out) duration of the returned frame (in milliseconds)
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either mux, image, x_offset,
		//                               y_offset, or duration is null
		//   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_OK - on success.
		WebPMuxError WebPMuxGetFrame(WebPMux* mux, uint nth, WebPData* image, WebPData* alpha, uint* x_offset, uint* y_offset, uint* duration) {
		  return MuxGetFrameTileInternal(mux, nth, image, alpha,
										 x_offset, y_offset, duration,
										 kChunks[FRAME_ID].chunkTag);
		}
Пример #28
0
		// 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.
		WebPMuxError WebPMuxDeleteTile(WebPMux* mux, uint nth) {
		  return DeleteFrameTileInternal(mux, nth, kChunks[TILE_ID].chunkName);
		}
Пример #29
0
		// Gets number of chunks having tag value tag in the mux object.
		// Parameters:
		//   mux - (in) object from which the info is to be fetched
		//   tag - (in) tag name specifying the type of chunk
		//   num_elements - (out) number of chunks corresponding to the specified tag
		// Returns:
		//   WEBP_MUX_INVALID_ARGUMENT - if either mux, tag or num_elements is null
		//   WEBP_MUX_OK - on success.
		public WebPMuxError WebPMuxNumNamedElements(WebPMux* mux, char* tag,
											 int* num_elements) {
		  TAG_ID id;
		  WebPChunk** chunk_list;

		  if (mux == null || tag == null || num_elements == null) {
			return WEBP_MUX_INVALID_ARGUMENT;
		  }

		  id = ChunkGetIdFromName(tag);
		  if (IsWPI(id)) {
			*num_elements = MuxImageCount(mux.images_, id);
		  } else {
			chunk_list = GetChunkListFromId(mux, id);
			if (chunk_list == null) {
			  *num_elements = 0;
			} else {
			  *num_elements = CountChunks(*chunk_list, kChunks[id].chunkTag);
			}
		  }

		  return WEBP_MUX_OK;
		}
Пример #30
0
 //------------------------------------------------------------------------------
 // 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;
       }
 }