static void DisposeFrame(WebPMuxAnimDispose dispose_method, const WebPFrameRect* const gif_rect, WebPPicture* const frame, WebPPicture* const canvas) { if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { WebPUtilClearPic(frame, NULL); WebPUtilClearPic(canvas, gif_rect); } }
static void DisposeFrameRectangle(int dispose_method, const FrameRect* const rect, WebPPicture* const curr_canvas) { assert(rect != NULL); if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { WebPUtilClearPic(curr_canvas, rect); } }
WebPAnimEncoder* WebPAnimEncoderNewInternal( int width, int height, const WebPAnimEncoderOptions* enc_options, int abi_version) { WebPAnimEncoder* enc; if (WEBP_ABI_IS_INCOMPATIBLE(abi_version, WEBP_MUX_ABI_VERSION)) { return NULL; } if (width <= 0 || height <= 0 || (width * (uint64_t)height) >= MAX_IMAGE_AREA) { return NULL; } enc = (WebPAnimEncoder*)WebPSafeCalloc(1, sizeof(*enc)); if (enc == NULL) return NULL; // sanity inits, so we can call WebPAnimEncoderDelete(): enc->encoded_frames_ = NULL; enc->mux_ = NULL; // Dimensions and options. *(int*)&enc->canvas_width_ = width; *(int*)&enc->canvas_height_ = height; if (enc_options != NULL) { *(WebPAnimEncoderOptions*)&enc->options_ = *enc_options; SanitizeEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); } else { DefaultEncoderOptions((WebPAnimEncoderOptions*)&enc->options_); } // Canvas buffers. if (!WebPPictureInit(&enc->curr_canvas_copy_) || !WebPPictureInit(&enc->prev_canvas_) || !WebPPictureInit(&enc->prev_canvas_disposed_)) { return NULL; } enc->curr_canvas_copy_.width = width; enc->curr_canvas_copy_.height = height; enc->curr_canvas_copy_.use_argb = 1; if (!WebPPictureAlloc(&enc->curr_canvas_copy_) || !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_) || !WebPPictureCopy(&enc->curr_canvas_copy_, &enc->prev_canvas_disposed_)) { goto Err; } WebPUtilClearPic(&enc->prev_canvas_, NULL); enc->curr_canvas_copy_modified_ = 1; // Encoded frames. ResetCounters(enc); // Note: one extra storage is for the previous frame. enc->size_ = enc->options_.kmax - enc->options_.kmin + 1; // We need space for at least 2 frames. But when kmin, kmax are both zero, // enc->size_ will be 1. So we handle that special case below. if (enc->size_ < 2) enc->size_ = 2; enc->encoded_frames_ = (EncodedFrame*)WebPSafeCalloc(enc->size_, sizeof(*enc->encoded_frames_)); if (enc->encoded_frames_ == NULL) goto Err; enc->mux_ = WebPMuxNew(); if (enc->mux_ == NULL) goto Err; enc->count_since_key_frame_ = 0; enc->first_timestamp_ = 0; enc->prev_timestamp_ = 0; enc->prev_candidate_undecided_ = 0; enc->is_first_frame_ = 1; enc->got_null_frame_ = 0; return enc; // All OK. Err: WebPAnimEncoderDelete(enc); return NULL; }