Support for "Do not blend" in mux and demux libraries

Change-Id: I9566a8e2d059fe1ebd9ca99c7e13311bf3f8f281
This commit is contained in:
Urvang Joshi 2013-08-09 14:09:31 -07:00
parent f486aaa9f8
commit 6284854bd5
7 changed files with 39 additions and 9 deletions

View File

@ -430,6 +430,8 @@ static int ParseFrameArgs(const char* args, WebPMuxFrameInfo* const info) {
// Note: The sanity of the following conversion is checked by
// WebPMuxSetAnimationParams().
info->dispose_method = (WebPMuxAnimDispose)dispose_method;
// TODO(urvang): Add support for parsing blending method too.
info->blend_method = WEBP_MUX_BLEND;
return 1;
}

View File

@ -50,6 +50,7 @@ typedef struct Frame {
int has_alpha_;
int duration_;
WebPMuxAnimDispose dispose_method_;
WebPMuxAnimBlend blend_method_;
int is_fragment_; // this is a frame fragment (and not a full frame).
int frame_num_; // the referent frame number for use in assembling fragments.
int complete_; // img_components_ contains a full image.
@ -303,6 +304,7 @@ static ParseStatus ParseAnimationFrame(
const int has_frames = !!(dmux->feature_flags_ & ANIMATION_FLAG);
const uint32_t anmf_payload_size = frame_chunk_size - ANMF_CHUNK_SIZE;
int added_frame = 0;
int bits;
MemBuffer* const mem = &dmux->mem_;
Frame* frame;
ParseStatus status =
@ -314,7 +316,10 @@ static ParseStatus ParseAnimationFrame(
frame->width_ = 1 + ReadLE24s(mem);
frame->height_ = 1 + ReadLE24s(mem);
frame->duration_ = ReadLE24s(mem);
frame->dispose_method_ = (WebPMuxAnimDispose)(ReadByte(mem) & 1);
bits = ReadByte(mem);
frame->dispose_method_ =
(bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
frame->blend_method_ = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
free(frame);
return PARSE_ERROR;
@ -845,6 +850,7 @@ static int SynthesizeFrame(const WebPDemuxer* const dmux,
iter->has_alpha = fragment->has_alpha_;
iter->duration = fragment->duration_;
iter->dispose_method = fragment->dispose_method_;
iter->blend_method = fragment->blend_method_;
iter->complete = fragment->complete_;
iter->fragment.bytes = payload;
iter->fragment.size = payload_size;

View File

@ -116,7 +116,9 @@ static WebPMuxError CreateFrameFragmentData(
PutLE24(frame_frgm_bytes + 6, width - 1);
PutLE24(frame_frgm_bytes + 9, height - 1);
PutLE24(frame_frgm_bytes + 12, info->duration);
frame_frgm_bytes[15] = (info->dispose_method & 1);
frame_frgm_bytes[15] =
(info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) |
(info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0);
}
frame_frgm->bytes = frame_frgm_bytes;
@ -310,7 +312,8 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
tmp.y_offset &= ~1;
if (!is_frame) { // Reset unused values.
tmp.duration = 1;
tmp.dispose_method = 0;
tmp.dispose_method = WEBP_MUX_DISPOSE_NONE;
tmp.blend_method = WEBP_MUX_BLEND;
}
if (tmp.x_offset < 0 || tmp.x_offset >= MAX_POSITION_OFFSET ||
tmp.y_offset < 0 || tmp.y_offset >= MAX_POSITION_OFFSET ||

View File

@ -426,6 +426,8 @@ static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
info->x_offset = 0;
info->y_offset = 0;
info->duration = 1;
info->dispose_method = WEBP_MUX_DISPOSE_NONE;
info->blend_method = WEBP_MUX_BLEND;
// Extract data for related fields.
info->id = ChunkGetIdFromTag(wpi->img_->tag_);
return SynthesizeBitstream(wpi, &info->bitstream);
@ -446,10 +448,17 @@ static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
// Extract info.
frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0);
frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3);
frame->duration = is_frame ? GetLE24(frame_frgm_data->bytes + 12) : 1;
frame->dispose_method =
is_frame ? (WebPMuxAnimDispose)(frame_frgm_data->bytes[15] & 1)
: WEBP_MUX_DISPOSE_NONE;
if (is_frame) {
const uint8_t bits = frame_frgm_data->bytes[15];
frame->duration = GetLE24(frame_frgm_data->bytes + 12);
frame->dispose_method =
(bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
} else { // Defaults for unused values.
frame->duration = 1;
frame->dispose_method = WEBP_MUX_DISPOSE_NONE;
frame->blend_method = WEBP_MUX_BLEND;
}
frame->id = ChunkGetIdFromTag(wpi->header_->tag_);
return SynthesizeBitstream(wpi, &frame->bitstream);
}

View File

@ -140,8 +140,9 @@ struct WebPIterator {
WebPData fragment; // The frame or fragment given by 'frame_num' and
// 'fragment_num'.
int has_alpha; // True if the frame or fragment contains transparency.
WebPMuxAnimBlend blend_method; // Blend operation for the frame.
uint32_t pad[3]; // padding for later use.
uint32_t pad[2]; // padding for later use.
void* private_; // for internal use only.
};

View File

@ -199,7 +199,8 @@ struct WebPMuxFrameInfo {
WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF,
// WEBP_CHUNK_FRGM or WEBP_CHUNK_IMAGE
WebPMuxAnimDispose dispose_method; // Disposal method for the frame.
uint32_t pad[2]; // padding for later use
WebPMuxAnimBlend blend_method; // Blend operation for the frame.
uint32_t pad[1]; // padding for later use
};
// Sets the (non-animated and non-fragmented) image in the mux object.

View File

@ -26,6 +26,7 @@ extern "C" {
// the types are left here for reference.
// typedef enum WebPFeatureFlags WebPFeatureFlags;
// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;
// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend;
typedef struct WebPData WebPData;
// VP8X Feature Flags.
@ -45,6 +46,13 @@ typedef enum WebPMuxAnimDispose {
WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
} WebPMuxAnimDispose;
// Blend operation (animation only). Indicates how transparent pixels of the
// current frame are blended with those of the previous canvas.
typedef enum WebPMuxAnimBlend {
WEBP_MUX_BLEND, // Blend.
WEBP_MUX_NO_BLEND // Do not blend.
} WebPMuxAnimBlend;
// Data type used to describe 'raw' data, e.g., chunk data
// (ICC profile, metadata) and WebP compressed image data.
struct WebPData {