mirror of
https://github.com/webmproject/libwebp.git
synced 2025-04-19 23:36:45 +02:00
mux,cosmetics: rm struct member '_' suffix
This is a follow up to: ee8e8c62 Fix member naming for VP8LHistogram This better matches Google style and clears some clang-tidy warnings. Change-Id: I9774ed6182ee4d872551aea56390fc0662cf0925
This commit is contained in:
parent
3f54b1aa12
commit
24262266d0
File diff suppressed because it is too large
Load Diff
@ -22,8 +22,8 @@
|
|||||||
static void MuxInit(WebPMux* const mux) {
|
static void MuxInit(WebPMux* const mux) {
|
||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
memset(mux, 0, sizeof(*mux));
|
memset(mux, 0, sizeof(*mux));
|
||||||
mux->canvas_width_ = 0; // just to be explicit
|
mux->canvas_width = 0; // just to be explicit
|
||||||
mux->canvas_height_ = 0;
|
mux->canvas_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebPMux* WebPNewInternal(int version) {
|
WebPMux* WebPNewInternal(int version) {
|
||||||
@ -45,13 +45,13 @@ static void DeleteAllImages(WebPMuxImage** const wpi_list) {
|
|||||||
|
|
||||||
static void MuxRelease(WebPMux* const mux) {
|
static void MuxRelease(WebPMux* const mux) {
|
||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
DeleteAllImages(&mux->images_);
|
DeleteAllImages(&mux->images);
|
||||||
ChunkListDelete(&mux->vp8x_);
|
ChunkListDelete(&mux->vp8x);
|
||||||
ChunkListDelete(&mux->iccp_);
|
ChunkListDelete(&mux->iccp);
|
||||||
ChunkListDelete(&mux->anim_);
|
ChunkListDelete(&mux->anim);
|
||||||
ChunkListDelete(&mux->exif_);
|
ChunkListDelete(&mux->exif);
|
||||||
ChunkListDelete(&mux->xmp_);
|
ChunkListDelete(&mux->xmp);
|
||||||
ChunkListDelete(&mux->unknown_);
|
ChunkListDelete(&mux->unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPMuxDelete(WebPMux* mux) {
|
void WebPMuxDelete(WebPMux* mux) {
|
||||||
@ -86,12 +86,12 @@ static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag,
|
|||||||
assert(!IsWPI(kChunks[idx].id));
|
assert(!IsWPI(kChunks[idx].id));
|
||||||
|
|
||||||
ChunkInit(&chunk);
|
ChunkInit(&chunk);
|
||||||
SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
|
SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x);
|
||||||
SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
|
SWITCH_ID_LIST(IDX_ICCP, &mux->iccp);
|
||||||
SWITCH_ID_LIST(IDX_ANIM, &mux->anim_);
|
SWITCH_ID_LIST(IDX_ANIM, &mux->anim);
|
||||||
SWITCH_ID_LIST(IDX_EXIF, &mux->exif_);
|
SWITCH_ID_LIST(IDX_EXIF, &mux->exif);
|
||||||
SWITCH_ID_LIST(IDX_XMP, &mux->xmp_);
|
SWITCH_ID_LIST(IDX_XMP, &mux->xmp);
|
||||||
SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_);
|
SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#undef SWITCH_ID_LIST
|
#undef SWITCH_ID_LIST
|
||||||
@ -141,11 +141,11 @@ static WebPMuxError GetImageData(const WebPData* const bitstream,
|
|||||||
const WebPMuxImage* wpi;
|
const WebPMuxImage* wpi;
|
||||||
WebPMux* const mux = WebPMuxCreate(bitstream, 0);
|
WebPMux* const mux = WebPMuxCreate(bitstream, 0);
|
||||||
if (mux == NULL) return WEBP_MUX_BAD_DATA;
|
if (mux == NULL) return WEBP_MUX_BAD_DATA;
|
||||||
wpi = mux->images_;
|
wpi = mux->images;
|
||||||
assert(wpi != NULL && wpi->img_ != NULL);
|
assert(wpi != NULL && wpi->img != NULL);
|
||||||
*image = wpi->img_->data_;
|
*image = wpi->img->data;
|
||||||
if (wpi->alpha_ != NULL) {
|
if (wpi->alpha != NULL) {
|
||||||
*alpha = wpi->alpha_->data_;
|
*alpha = wpi->alpha->data;
|
||||||
}
|
}
|
||||||
WebPMuxDelete(mux);
|
WebPMuxDelete(mux);
|
||||||
}
|
}
|
||||||
@ -158,11 +158,11 @@ static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) {
|
|||||||
assert(chunk_list);
|
assert(chunk_list);
|
||||||
while (*chunk_list) {
|
while (*chunk_list) {
|
||||||
WebPChunk* const chunk = *chunk_list;
|
WebPChunk* const chunk = *chunk_list;
|
||||||
if (chunk->tag_ == tag) {
|
if (chunk->tag == tag) {
|
||||||
*chunk_list = ChunkDelete(chunk);
|
*chunk_list = ChunkDelete(chunk);
|
||||||
err = WEBP_MUX_OK;
|
err = WEBP_MUX_OK;
|
||||||
} else {
|
} else {
|
||||||
chunk_list = &chunk->next_;
|
chunk_list = &chunk->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@ -213,8 +213,8 @@ static WebPMuxError AddDataToChunkList(
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracts image & alpha data from the given bitstream and then sets wpi.alpha_
|
// Extracts image & alpha data from the given bitstream and then sets wpi.alpha
|
||||||
// and wpi.img_ appropriately.
|
// and wpi.img appropriately.
|
||||||
static WebPMuxError SetAlphaAndImageChunks(
|
static WebPMuxError SetAlphaAndImageChunks(
|
||||||
const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) {
|
const WebPData* const bitstream, int copy_data, WebPMuxImage* const wpi) {
|
||||||
int is_lossless = 0;
|
int is_lossless = 0;
|
||||||
@ -225,10 +225,10 @@ static WebPMuxError SetAlphaAndImageChunks(
|
|||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
if (alpha.bytes != NULL) {
|
if (alpha.bytes != NULL) {
|
||||||
err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag,
|
err = AddDataToChunkList(&alpha, copy_data, kChunks[IDX_ALPHA].tag,
|
||||||
&wpi->alpha_);
|
&wpi->alpha);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
}
|
}
|
||||||
err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img_);
|
err = AddDataToChunkList(&image, copy_data, image_tag, &wpi->img);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT;
|
return MuxImageFinalize(wpi) ? WEBP_MUX_OK : WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
@ -243,9 +243,9 @@ WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream,
|
|||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mux->images_ != NULL) {
|
if (mux->images != NULL) {
|
||||||
// Only one 'simple image' can be added in mux. So, remove present images.
|
// Only one 'simple image' can be added in mux. So, remove present images.
|
||||||
DeleteAllImages(&mux->images_);
|
DeleteAllImages(&mux->images);
|
||||||
}
|
}
|
||||||
|
|
||||||
MuxImageInit(&wpi);
|
MuxImageInit(&wpi);
|
||||||
@ -253,7 +253,7 @@ WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream,
|
|||||||
if (err != WEBP_MUX_OK) goto Err;
|
if (err != WEBP_MUX_OK) goto Err;
|
||||||
|
|
||||||
// Add this WebPMuxImage to mux.
|
// Add this WebPMuxImage to mux.
|
||||||
err = MuxImagePush(&wpi, &mux->images_);
|
err = MuxImagePush(&wpi, &mux->images);
|
||||||
if (err != WEBP_MUX_OK) goto Err;
|
if (err != WEBP_MUX_OK) goto Err;
|
||||||
|
|
||||||
// All is well.
|
// All is well.
|
||||||
@ -278,10 +278,10 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
|
|||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mux->images_ != NULL) {
|
if (mux->images != NULL) {
|
||||||
const WebPMuxImage* const image = mux->images_;
|
const WebPMuxImage* const image = mux->images;
|
||||||
const uint32_t image_id = (image->header_ != NULL) ?
|
const uint32_t image_id = (image->header != NULL) ?
|
||||||
ChunkGetIdFromTag(image->header_->tag_) : WEBP_CHUNK_IMAGE;
|
ChunkGetIdFromTag(image->header->tag) : WEBP_CHUNK_IMAGE;
|
||||||
if (image_id != info->id) {
|
if (image_id != info->id) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types.
|
return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types.
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
|
|||||||
MuxImageInit(&wpi);
|
MuxImageInit(&wpi);
|
||||||
err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi);
|
err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi);
|
||||||
if (err != WEBP_MUX_OK) goto Err;
|
if (err != WEBP_MUX_OK) goto Err;
|
||||||
assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
|
assert(wpi.img != NULL); // As SetAlphaAndImageChunks() was successful.
|
||||||
|
|
||||||
{
|
{
|
||||||
WebPData frame;
|
WebPData frame;
|
||||||
@ -305,16 +305,16 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
|
|||||||
err = WEBP_MUX_INVALID_ARGUMENT;
|
err = WEBP_MUX_INVALID_ARGUMENT;
|
||||||
goto Err;
|
goto Err;
|
||||||
}
|
}
|
||||||
err = CreateFrameData(wpi.width_, wpi.height_, &tmp, &frame);
|
err = CreateFrameData(wpi.width, wpi.height, &tmp, &frame);
|
||||||
if (err != WEBP_MUX_OK) goto Err;
|
if (err != WEBP_MUX_OK) goto Err;
|
||||||
// Add frame chunk (with copy_data = 1).
|
// Add frame chunk (with copy_data = 1).
|
||||||
err = AddDataToChunkList(&frame, 1, tag, &wpi.header_);
|
err = AddDataToChunkList(&frame, 1, tag, &wpi.header);
|
||||||
WebPDataClear(&frame); // frame owned by wpi.header_ now.
|
WebPDataClear(&frame); // frame owned by wpi.header now.
|
||||||
if (err != WEBP_MUX_OK) goto Err;
|
if (err != WEBP_MUX_OK) goto Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this WebPMuxImage to mux.
|
// Add this WebPMuxImage to mux.
|
||||||
err = MuxImagePush(&wpi, &mux->images_);
|
err = MuxImagePush(&wpi, &mux->images);
|
||||||
if (err != WEBP_MUX_OK) goto Err;
|
if (err != WEBP_MUX_OK) goto Err;
|
||||||
|
|
||||||
// All is well.
|
// All is well.
|
||||||
@ -367,8 +367,8 @@ WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
|
|||||||
err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag);
|
err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag);
|
||||||
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
|
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
|
||||||
|
|
||||||
mux->canvas_width_ = width;
|
mux->canvas_width = width;
|
||||||
mux->canvas_height_ = height;
|
mux->canvas_height = height;
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ WebPMuxError WebPMuxDeleteChunk(WebPMux* mux, const char fourcc[4]) {
|
|||||||
|
|
||||||
WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
|
WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
|
||||||
if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
return MuxImageDeleteNth(&mux->images_, nth);
|
return MuxImageDeleteNth(&mux->images, nth);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -391,9 +391,9 @@ WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
|
|||||||
static WebPMuxError GetFrameInfo(
|
static WebPMuxError GetFrameInfo(
|
||||||
const WebPChunk* const frame_chunk,
|
const WebPChunk* const frame_chunk,
|
||||||
int* const x_offset, int* const y_offset, int* const duration) {
|
int* const x_offset, int* const y_offset, int* const duration) {
|
||||||
const WebPData* const data = &frame_chunk->data_;
|
const WebPData* const data = &frame_chunk->data;
|
||||||
const size_t expected_data_size = ANMF_CHUNK_SIZE;
|
const size_t expected_data_size = ANMF_CHUNK_SIZE;
|
||||||
assert(frame_chunk->tag_ == kChunks[IDX_ANMF].tag);
|
assert(frame_chunk->tag == kChunks[IDX_ANMF].tag);
|
||||||
assert(frame_chunk != NULL);
|
assert(frame_chunk != NULL);
|
||||||
if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
|
if (data->size != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
|
||||||
@ -407,7 +407,7 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
|
|||||||
int* const x_offset, int* const y_offset,
|
int* const x_offset, int* const y_offset,
|
||||||
int* const duration,
|
int* const duration,
|
||||||
int* const width, int* const height) {
|
int* const width, int* const height) {
|
||||||
const WebPChunk* const frame_chunk = wpi->header_;
|
const WebPChunk* const frame_chunk = wpi->header;
|
||||||
WebPMuxError err;
|
WebPMuxError err;
|
||||||
assert(wpi != NULL);
|
assert(wpi != NULL);
|
||||||
assert(frame_chunk != NULL);
|
assert(frame_chunk != NULL);
|
||||||
@ -417,8 +417,8 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
|
|||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
|
|
||||||
// Get width and height from VP8/VP8L chunk.
|
// Get width and height from VP8/VP8L chunk.
|
||||||
if (width != NULL) *width = wpi->width_;
|
if (width != NULL) *width = wpi->width;
|
||||||
if (height != NULL) *height = wpi->height_;
|
if (height != NULL) *height = wpi->height;
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,16 +429,16 @@ static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
|
|||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
assert(width != NULL && height != NULL);
|
assert(width != NULL && height != NULL);
|
||||||
|
|
||||||
wpi = mux->images_;
|
wpi = mux->images;
|
||||||
assert(wpi != NULL);
|
assert(wpi != NULL);
|
||||||
assert(wpi->img_ != NULL);
|
assert(wpi->img != NULL);
|
||||||
|
|
||||||
if (wpi->next_ != NULL) {
|
if (wpi->next != NULL) {
|
||||||
int max_x = 0, max_y = 0;
|
int max_x = 0, max_y = 0;
|
||||||
// if we have a chain of wpi's, header_ is necessarily set
|
// if we have a chain of wpi's, header is necessarily set
|
||||||
assert(wpi->header_ != NULL);
|
assert(wpi->header != NULL);
|
||||||
// Aggregate the bounding box for animation frames.
|
// Aggregate the bounding box for animation frames.
|
||||||
for (; wpi != NULL; wpi = wpi->next_) {
|
for (; wpi != NULL; wpi = wpi->next) {
|
||||||
int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0;
|
int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0;
|
||||||
const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
|
const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
|
||||||
&duration, &w, &h);
|
&duration, &w, &h);
|
||||||
@ -455,8 +455,8 @@ static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
|
|||||||
*height = max_y;
|
*height = max_y;
|
||||||
} else {
|
} else {
|
||||||
// For a single image, canvas dimensions are same as image dimensions.
|
// For a single image, canvas dimensions are same as image dimensions.
|
||||||
*width = wpi->width_;
|
*width = wpi->width;
|
||||||
*height = wpi->height_;
|
*height = wpi->height;
|
||||||
}
|
}
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
@ -476,9 +476,9 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
|
|||||||
const WebPMuxImage* images = NULL;
|
const WebPMuxImage* images = NULL;
|
||||||
|
|
||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
images = mux->images_; // First image.
|
images = mux->images; // First image.
|
||||||
if (images == NULL || images->img_ == NULL ||
|
if (images == NULL || images->img == NULL ||
|
||||||
images->img_->data_.bytes == NULL) {
|
images->img->data.bytes == NULL) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,17 +488,17 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
|
|||||||
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
|
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
|
||||||
|
|
||||||
// Set flags.
|
// Set flags.
|
||||||
if (mux->iccp_ != NULL && mux->iccp_->data_.bytes != NULL) {
|
if (mux->iccp != NULL && mux->iccp->data.bytes != NULL) {
|
||||||
flags |= ICCP_FLAG;
|
flags |= ICCP_FLAG;
|
||||||
}
|
}
|
||||||
if (mux->exif_ != NULL && mux->exif_->data_.bytes != NULL) {
|
if (mux->exif != NULL && mux->exif->data.bytes != NULL) {
|
||||||
flags |= EXIF_FLAG;
|
flags |= EXIF_FLAG;
|
||||||
}
|
}
|
||||||
if (mux->xmp_ != NULL && mux->xmp_->data_.bytes != NULL) {
|
if (mux->xmp != NULL && mux->xmp->data.bytes != NULL) {
|
||||||
flags |= XMP_FLAG;
|
flags |= XMP_FLAG;
|
||||||
}
|
}
|
||||||
if (images->header_ != NULL) {
|
if (images->header != NULL) {
|
||||||
if (images->header_->tag_ == kChunks[IDX_ANMF].tag) {
|
if (images->header->tag == kChunks[IDX_ANMF].tag) {
|
||||||
// This is an image with animation.
|
// This is an image with animation.
|
||||||
flags |= ANIMATION_FLAG;
|
flags |= ANIMATION_FLAG;
|
||||||
}
|
}
|
||||||
@ -517,15 +517,15 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
|
|||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) {
|
if (mux->canvas_width != 0 || mux->canvas_height != 0) {
|
||||||
if (width > mux->canvas_width_ || height > mux->canvas_height_) {
|
if (width > mux->canvas_width || height > mux->canvas_height) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
width = mux->canvas_width_;
|
width = mux->canvas_width;
|
||||||
height = mux->canvas_height_;
|
height = mux->canvas_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags == 0 && mux->unknown_ == NULL) {
|
if (flags == 0 && mux->unknown == NULL) {
|
||||||
// For simple file format, VP8X chunk should not be added.
|
// For simple file format, VP8X chunk should not be added.
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
@ -556,17 +556,17 @@ static WebPMuxError MuxCleanup(WebPMux* const mux) {
|
|||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
if (num_frames == 1) {
|
if (num_frames == 1) {
|
||||||
WebPMuxImage* frame = NULL;
|
WebPMuxImage* frame = NULL;
|
||||||
err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame);
|
err = MuxImageGetNth((const WebPMuxImage**)&mux->images, 1, &frame);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
// We know that one frame does exist.
|
// We know that one frame does exist.
|
||||||
assert(frame != NULL);
|
assert(frame != NULL);
|
||||||
if (frame->header_ != NULL &&
|
if (frame->header != NULL &&
|
||||||
((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) ||
|
((mux->canvas_width == 0 && mux->canvas_height == 0) ||
|
||||||
(frame->width_ == mux->canvas_width_ &&
|
(frame->width == mux->canvas_width &&
|
||||||
frame->height_ == mux->canvas_height_))) {
|
frame->height == mux->canvas_height))) {
|
||||||
assert(frame->header_->tag_ == kChunks[IDX_ANMF].tag);
|
assert(frame->header->tag == kChunks[IDX_ANMF].tag);
|
||||||
ChunkDelete(frame->header_); // Removes ANMF chunk.
|
ChunkDelete(frame->header); // Removes ANMF chunk.
|
||||||
frame->header_ = NULL;
|
frame->header = NULL;
|
||||||
num_frames = 0;
|
num_frames = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,7 +585,7 @@ static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) {
|
|||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
while (wpi_list != NULL) {
|
while (wpi_list != NULL) {
|
||||||
size += MuxImageDiskSize(wpi_list);
|
size += MuxImageDiskSize(wpi_list);
|
||||||
wpi_list = wpi_list->next_;
|
wpi_list = wpi_list->next;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -594,7 +594,7 @@ static size_t ImageListDiskSize(const WebPMuxImage* wpi_list) {
|
|||||||
static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
|
static uint8_t* ImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
|
||||||
while (wpi_list != NULL) {
|
while (wpi_list != NULL) {
|
||||||
dst = MuxImageEmit(wpi_list, dst);
|
dst = MuxImageEmit(wpi_list, dst);
|
||||||
wpi_list = wpi_list->next_;
|
wpi_list = wpi_list->next;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -622,23 +622,23 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) {
|
|||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
|
|
||||||
// Allocate data.
|
// Allocate data.
|
||||||
size = ChunkListDiskSize(mux->vp8x_) + ChunkListDiskSize(mux->iccp_)
|
size = ChunkListDiskSize(mux->vp8x) + ChunkListDiskSize(mux->iccp)
|
||||||
+ ChunkListDiskSize(mux->anim_) + ImageListDiskSize(mux->images_)
|
+ ChunkListDiskSize(mux->anim) + ImageListDiskSize(mux->images)
|
||||||
+ ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_)
|
+ ChunkListDiskSize(mux->exif) + ChunkListDiskSize(mux->xmp)
|
||||||
+ ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE;
|
+ ChunkListDiskSize(mux->unknown) + RIFF_HEADER_SIZE;
|
||||||
|
|
||||||
data = (uint8_t*)WebPSafeMalloc(1ULL, size);
|
data = (uint8_t*)WebPSafeMalloc(1ULL, size);
|
||||||
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
|
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||||
|
|
||||||
// Emit header & chunks.
|
// Emit header & chunks.
|
||||||
dst = MuxEmitRiffHeader(data, size);
|
dst = MuxEmitRiffHeader(data, size);
|
||||||
dst = ChunkListEmit(mux->vp8x_, dst);
|
dst = ChunkListEmit(mux->vp8x, dst);
|
||||||
dst = ChunkListEmit(mux->iccp_, dst);
|
dst = ChunkListEmit(mux->iccp, dst);
|
||||||
dst = ChunkListEmit(mux->anim_, dst);
|
dst = ChunkListEmit(mux->anim, dst);
|
||||||
dst = ImageListEmit(mux->images_, dst);
|
dst = ImageListEmit(mux->images, dst);
|
||||||
dst = ChunkListEmit(mux->exif_, dst);
|
dst = ChunkListEmit(mux->exif, dst);
|
||||||
dst = ChunkListEmit(mux->xmp_, dst);
|
dst = ChunkListEmit(mux->xmp, dst);
|
||||||
dst = ChunkListEmit(mux->unknown_, dst);
|
dst = ChunkListEmit(mux->unknown, dst);
|
||||||
assert(dst == data + size);
|
assert(dst == data + size);
|
||||||
|
|
||||||
// Validate mux.
|
// Validate mux.
|
||||||
|
@ -34,41 +34,41 @@ extern "C" {
|
|||||||
// Chunk object.
|
// Chunk object.
|
||||||
typedef struct WebPChunk WebPChunk;
|
typedef struct WebPChunk WebPChunk;
|
||||||
struct WebPChunk {
|
struct WebPChunk {
|
||||||
uint32_t tag_;
|
uint32_t tag;
|
||||||
int owner_; // True if *data_ memory is owned internally.
|
int owner; // True if *data memory is owned internally.
|
||||||
// VP8X, ANIM, and other internally created chunks
|
// VP8X, ANIM, and other internally created chunks
|
||||||
// like ANMF are always owned.
|
// like ANMF are always owned.
|
||||||
WebPData data_;
|
WebPData data;
|
||||||
WebPChunk* next_;
|
WebPChunk* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
// MuxImage object. Store a full WebP image (including ANMF chunk, ALPH
|
// MuxImage object. Store a full WebP image (including ANMF chunk, ALPH
|
||||||
// chunk and VP8/VP8L chunk),
|
// chunk and VP8/VP8L chunk),
|
||||||
typedef struct WebPMuxImage WebPMuxImage;
|
typedef struct WebPMuxImage WebPMuxImage;
|
||||||
struct WebPMuxImage {
|
struct WebPMuxImage {
|
||||||
WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF.
|
WebPChunk* header; // Corresponds to WEBP_CHUNK_ANMF.
|
||||||
WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA.
|
WebPChunk* alpha; // Corresponds to WEBP_CHUNK_ALPHA.
|
||||||
WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE.
|
WebPChunk* img; // Corresponds to WEBP_CHUNK_IMAGE.
|
||||||
WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN.
|
WebPChunk* unknown; // Corresponds to WEBP_CHUNK_UNKNOWN.
|
||||||
int width_;
|
int width;
|
||||||
int height_;
|
int height;
|
||||||
int has_alpha_; // Through ALPH chunk or as part of VP8L.
|
int has_alpha; // Through ALPH chunk or as part of VP8L.
|
||||||
int is_partial_; // True if only some of the chunks are filled.
|
int is_partial; // True if only some of the chunks are filled.
|
||||||
WebPMuxImage* next_;
|
WebPMuxImage* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Main mux object. Stores data chunks.
|
// Main mux object. Stores data chunks.
|
||||||
struct WebPMux {
|
struct WebPMux {
|
||||||
WebPMuxImage* images_;
|
WebPMuxImage* images;
|
||||||
WebPChunk* iccp_;
|
WebPChunk* iccp;
|
||||||
WebPChunk* exif_;
|
WebPChunk* exif;
|
||||||
WebPChunk* xmp_;
|
WebPChunk* xmp;
|
||||||
WebPChunk* anim_;
|
WebPChunk* anim;
|
||||||
WebPChunk* vp8x_;
|
WebPChunk* vp8x;
|
||||||
|
|
||||||
WebPChunk* unknown_;
|
WebPChunk* unknown;
|
||||||
int canvas_width_;
|
int canvas_width;
|
||||||
int canvas_height_;
|
int canvas_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only.
|
// CHUNK_INDEX enum: used for indexing within 'kChunks' (defined below) only.
|
||||||
@ -136,10 +136,10 @@ WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list);
|
|||||||
// *chunk_list.
|
// *chunk_list.
|
||||||
WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list);
|
WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list);
|
||||||
|
|
||||||
// Releases chunk and returns chunk->next_.
|
// Releases chunk and returns chunk->next.
|
||||||
WebPChunk* ChunkRelease(WebPChunk* const chunk);
|
WebPChunk* ChunkRelease(WebPChunk* const chunk);
|
||||||
|
|
||||||
// Deletes given chunk & returns chunk->next_.
|
// Deletes given chunk & returns chunk->next.
|
||||||
WebPChunk* ChunkDelete(WebPChunk* const chunk);
|
WebPChunk* ChunkDelete(WebPChunk* const chunk);
|
||||||
|
|
||||||
// Deletes all chunks in the given chunk list.
|
// Deletes all chunks in the given chunk list.
|
||||||
@ -153,7 +153,7 @@ static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
|
|||||||
|
|
||||||
// Size of a chunk including header and padding.
|
// Size of a chunk including header and padding.
|
||||||
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
|
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
|
||||||
const size_t data_size = chunk->data_.size;
|
const size_t data_size = chunk->data.size;
|
||||||
return SizeWithPadding(data_size);
|
return SizeWithPadding(data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,16 +45,16 @@ int WebPGetMuxVersion(void) {
|
|||||||
void ChunkInit(WebPChunk* const chunk) {
|
void ChunkInit(WebPChunk* const chunk) {
|
||||||
assert(chunk);
|
assert(chunk);
|
||||||
memset(chunk, 0, sizeof(*chunk));
|
memset(chunk, 0, sizeof(*chunk));
|
||||||
chunk->tag_ = NIL_TAG;
|
chunk->tag = NIL_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebPChunk* ChunkRelease(WebPChunk* const chunk) {
|
WebPChunk* ChunkRelease(WebPChunk* const chunk) {
|
||||||
WebPChunk* next;
|
WebPChunk* next;
|
||||||
if (chunk == NULL) return NULL;
|
if (chunk == NULL) return NULL;
|
||||||
if (chunk->owner_) {
|
if (chunk->owner) {
|
||||||
WebPDataClear(&chunk->data_);
|
WebPDataClear(&chunk->data);
|
||||||
}
|
}
|
||||||
next = chunk->next_;
|
next = chunk->next;
|
||||||
ChunkInit(chunk);
|
ChunkInit(chunk);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@ -92,8 +92,8 @@ CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) {
|
|||||||
|
|
||||||
// Returns next chunk in the chunk list with the given tag.
|
// Returns next chunk in the chunk list with the given tag.
|
||||||
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
|
||||||
while (chunk != NULL && chunk->tag_ != tag) {
|
while (chunk != NULL && chunk->tag != tag) {
|
||||||
chunk = chunk->next_;
|
chunk = chunk->next;
|
||||||
}
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
|
|||||||
if (first == NULL) return NULL;
|
if (first == NULL) return NULL;
|
||||||
|
|
||||||
while (--iter != 0) {
|
while (--iter != 0) {
|
||||||
WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
|
WebPChunk* next_chunk = ChunkSearchNextInList(first->next, tag);
|
||||||
if (next_chunk == NULL) break;
|
if (next_chunk == NULL) break;
|
||||||
first = next_chunk;
|
first = next_chunk;
|
||||||
}
|
}
|
||||||
@ -125,13 +125,13 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
|
|||||||
|
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
if (copy_data) { // Copy data.
|
if (copy_data) { // Copy data.
|
||||||
if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR;
|
if (!WebPDataCopy(data, &chunk->data)) return WEBP_MUX_MEMORY_ERROR;
|
||||||
chunk->owner_ = 1; // Chunk is owner of data.
|
chunk->owner = 1; // Chunk is owner of data.
|
||||||
} else { // Don't copy data.
|
} else { // Don't copy data.
|
||||||
chunk->data_ = *data;
|
chunk->data = *data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunk->tag_ = tag;
|
chunk->tag = tag;
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +147,8 @@ WebPMuxError ChunkSetHead(WebPChunk* const chunk,
|
|||||||
new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk));
|
new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk));
|
||||||
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
|
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||||
*new_chunk = *chunk;
|
*new_chunk = *chunk;
|
||||||
chunk->owner_ = 0;
|
chunk->owner = 0;
|
||||||
new_chunk->next_ = NULL;
|
new_chunk->next = NULL;
|
||||||
*chunk_list = new_chunk;
|
*chunk_list = new_chunk;
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
@ -162,9 +162,9 @@ WebPMuxError ChunkAppend(WebPChunk* const chunk,
|
|||||||
err = ChunkSetHead(chunk, *chunk_list);
|
err = ChunkSetHead(chunk, *chunk_list);
|
||||||
} else {
|
} else {
|
||||||
WebPChunk* last_chunk = **chunk_list;
|
WebPChunk* last_chunk = **chunk_list;
|
||||||
while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_;
|
while (last_chunk->next != NULL) last_chunk = last_chunk->next;
|
||||||
err = ChunkSetHead(chunk, &last_chunk->next_);
|
err = ChunkSetHead(chunk, &last_chunk->next);
|
||||||
if (err == WEBP_MUX_OK) *chunk_list = &last_chunk->next_;
|
if (err == WEBP_MUX_OK) *chunk_list = &last_chunk->next;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -188,13 +188,13 @@ void ChunkListDelete(WebPChunk** const chunk_list) {
|
|||||||
// Chunk serialization methods.
|
// Chunk serialization methods.
|
||||||
|
|
||||||
static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
|
static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
|
||||||
const size_t chunk_size = chunk->data_.size;
|
const size_t chunk_size = chunk->data.size;
|
||||||
assert(chunk);
|
assert(chunk);
|
||||||
assert(chunk->tag_ != NIL_TAG);
|
assert(chunk->tag != NIL_TAG);
|
||||||
PutLE32(dst + 0, chunk->tag_);
|
PutLE32(dst + 0, chunk->tag);
|
||||||
PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size);
|
PutLE32(dst + TAG_SIZE, (uint32_t)chunk_size);
|
||||||
assert(chunk_size == (uint32_t)chunk_size);
|
assert(chunk_size == (uint32_t)chunk_size);
|
||||||
memcpy(dst + CHUNK_HEADER_SIZE, chunk->data_.bytes, chunk_size);
|
memcpy(dst + CHUNK_HEADER_SIZE, chunk->data.bytes, chunk_size);
|
||||||
if (chunk_size & 1)
|
if (chunk_size & 1)
|
||||||
dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding.
|
dst[CHUNK_HEADER_SIZE + chunk_size] = 0; // Add padding.
|
||||||
return dst + ChunkDiskSize(chunk);
|
return dst + ChunkDiskSize(chunk);
|
||||||
@ -203,7 +203,7 @@ static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
|
|||||||
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
|
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
|
||||||
while (chunk_list != NULL) {
|
while (chunk_list != NULL) {
|
||||||
dst = ChunkEmit(chunk_list, dst);
|
dst = ChunkEmit(chunk_list, dst);
|
||||||
chunk_list = chunk_list->next_;
|
chunk_list = chunk_list->next;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ size_t ChunkListDiskSize(const WebPChunk* chunk_list) {
|
|||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
while (chunk_list != NULL) {
|
while (chunk_list != NULL) {
|
||||||
size += ChunkDiskSize(chunk_list);
|
size += ChunkDiskSize(chunk_list);
|
||||||
chunk_list = chunk_list->next_;
|
chunk_list = chunk_list->next;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -228,14 +228,14 @@ void MuxImageInit(WebPMuxImage* const wpi) {
|
|||||||
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
|
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
|
||||||
WebPMuxImage* next;
|
WebPMuxImage* next;
|
||||||
if (wpi == NULL) return NULL;
|
if (wpi == NULL) return NULL;
|
||||||
// There should be at most one chunk of header_, alpha_, img_ but we call
|
// There should be at most one chunk of 'header', 'alpha', 'img' but we call
|
||||||
// ChunkListDelete to be safe
|
// ChunkListDelete to be safe
|
||||||
ChunkListDelete(&wpi->header_);
|
ChunkListDelete(&wpi->header);
|
||||||
ChunkListDelete(&wpi->alpha_);
|
ChunkListDelete(&wpi->alpha);
|
||||||
ChunkListDelete(&wpi->img_);
|
ChunkListDelete(&wpi->img);
|
||||||
ChunkListDelete(&wpi->unknown_);
|
ChunkListDelete(&wpi->unknown);
|
||||||
|
|
||||||
next = wpi->next_;
|
next = wpi->next;
|
||||||
MuxImageInit(wpi);
|
MuxImageInit(wpi);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@ -248,9 +248,9 @@ static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi,
|
|||||||
WebPChunkId id) {
|
WebPChunkId id) {
|
||||||
assert(wpi != NULL);
|
assert(wpi != NULL);
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case WEBP_CHUNK_ANMF: return (WebPChunk**)&wpi->header_;
|
case WEBP_CHUNK_ANMF: return (WebPChunk**)&wpi->header;
|
||||||
case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
|
case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha;
|
||||||
case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
|
case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img;
|
||||||
default: return NULL;
|
default: return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,13 +258,13 @@ static WebPChunk** GetChunkListFromId(const WebPMuxImage* const wpi,
|
|||||||
int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) {
|
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) {
|
||||||
if (id == WEBP_CHUNK_NIL) {
|
if (id == WEBP_CHUNK_NIL) {
|
||||||
++count; // Special case: count all images.
|
++count; // Special case: count all images.
|
||||||
} else {
|
} else {
|
||||||
const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id);
|
const WebPChunk* const wpi_chunk = *GetChunkListFromId(current, id);
|
||||||
if (wpi_chunk != NULL) {
|
if (wpi_chunk != NULL) {
|
||||||
const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag_);
|
const WebPChunkId wpi_chunk_id = ChunkGetIdFromTag(wpi_chunk->tag);
|
||||||
if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'.
|
if (wpi_chunk_id == id) ++count; // Count images with a matching 'id'.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ int MuxImageCount(const WebPMuxImage* wpi_list, WebPChunkId id) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 true if nth image was found.
|
// 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,
|
||||||
@ -290,7 +290,7 @@ static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth,
|
|||||||
WebPMuxImage* const cur_wpi = *wpi_list;
|
WebPMuxImage* const cur_wpi = *wpi_list;
|
||||||
++count;
|
++count;
|
||||||
if (count == nth) return 1; // Found.
|
if (count == nth) return 1; // Found.
|
||||||
wpi_list = &cur_wpi->next_;
|
wpi_list = &cur_wpi->next;
|
||||||
*location = wpi_list;
|
*location = wpi_list;
|
||||||
}
|
}
|
||||||
return 0; // Not found.
|
return 0; // Not found.
|
||||||
@ -304,17 +304,17 @@ WebPMuxError MuxImagePush(const WebPMuxImage* wpi, WebPMuxImage** wpi_list) {
|
|||||||
|
|
||||||
while (*wpi_list != NULL) {
|
while (*wpi_list != NULL) {
|
||||||
WebPMuxImage* const cur_wpi = *wpi_list;
|
WebPMuxImage* const cur_wpi = *wpi_list;
|
||||||
if (cur_wpi->next_ == NULL) break;
|
if (cur_wpi->next == NULL) break;
|
||||||
wpi_list = &cur_wpi->next_;
|
wpi_list = &cur_wpi->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi));
|
new_wpi = (WebPMuxImage*)WebPSafeMalloc(1ULL, sizeof(*new_wpi));
|
||||||
if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR;
|
if (new_wpi == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||||
*new_wpi = *wpi;
|
*new_wpi = *wpi;
|
||||||
new_wpi->next_ = NULL;
|
new_wpi->next = NULL;
|
||||||
|
|
||||||
if (*wpi_list != NULL) {
|
if (*wpi_list != NULL) {
|
||||||
(*wpi_list)->next_ = new_wpi;
|
(*wpi_list)->next = new_wpi;
|
||||||
} else {
|
} else {
|
||||||
*wpi_list = new_wpi;
|
*wpi_list = new_wpi;
|
||||||
}
|
}
|
||||||
@ -361,23 +361,23 @@ WebPMuxError MuxImageGetNth(const WebPMuxImage** wpi_list, uint32_t nth,
|
|||||||
// Size of an image.
|
// Size of an image.
|
||||||
size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
|
size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
if (wpi->header_ != NULL) size += ChunkDiskSize(wpi->header_);
|
if (wpi->header != NULL) size += ChunkDiskSize(wpi->header);
|
||||||
if (wpi->alpha_ != NULL) size += ChunkDiskSize(wpi->alpha_);
|
if (wpi->alpha != NULL) size += ChunkDiskSize(wpi->alpha);
|
||||||
if (wpi->img_ != NULL) size += ChunkDiskSize(wpi->img_);
|
if (wpi->img != NULL) size += ChunkDiskSize(wpi->img);
|
||||||
if (wpi->unknown_ != NULL) size += ChunkListDiskSize(wpi->unknown_);
|
if (wpi->unknown != NULL) size += ChunkListDiskSize(wpi->unknown);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case as ANMF chunk encapsulates other image chunks.
|
// Special case as ANMF chunk encapsulates other image chunks.
|
||||||
static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
|
static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
|
||||||
size_t total_size, uint8_t* dst) {
|
size_t total_size, uint8_t* dst) {
|
||||||
const size_t header_size = header->data_.size;
|
const size_t header_size = header->data.size;
|
||||||
const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE;
|
const size_t offset_to_next = total_size - CHUNK_HEADER_SIZE;
|
||||||
assert(header->tag_ == kChunks[IDX_ANMF].tag);
|
assert(header->tag == kChunks[IDX_ANMF].tag);
|
||||||
PutLE32(dst + 0, header->tag_);
|
PutLE32(dst + 0, header->tag);
|
||||||
PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next);
|
PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next);
|
||||||
assert(header_size == (uint32_t)header_size);
|
assert(header_size == (uint32_t)header_size);
|
||||||
memcpy(dst + CHUNK_HEADER_SIZE, header->data_.bytes, header_size);
|
memcpy(dst + CHUNK_HEADER_SIZE, header->data.bytes, header_size);
|
||||||
if (header_size & 1) {
|
if (header_size & 1) {
|
||||||
dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding.
|
dst[CHUNK_HEADER_SIZE + header_size] = 0; // Add padding.
|
||||||
}
|
}
|
||||||
@ -390,12 +390,12 @@ uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
|
|||||||
// 2. ALPH chunk (if present).
|
// 2. ALPH chunk (if present).
|
||||||
// 3. VP8/VP8L chunk.
|
// 3. VP8/VP8L chunk.
|
||||||
assert(wpi);
|
assert(wpi);
|
||||||
if (wpi->header_ != NULL) {
|
if (wpi->header != NULL) {
|
||||||
dst = ChunkEmitSpecial(wpi->header_, MuxImageDiskSize(wpi), dst);
|
dst = ChunkEmitSpecial(wpi->header, MuxImageDiskSize(wpi), dst);
|
||||||
}
|
}
|
||||||
if (wpi->alpha_ != NULL) dst = ChunkEmit(wpi->alpha_, dst);
|
if (wpi->alpha != NULL) dst = ChunkEmit(wpi->alpha, dst);
|
||||||
if (wpi->img_ != NULL) dst = ChunkEmit(wpi->img_, dst);
|
if (wpi->img != NULL) dst = ChunkEmit(wpi->img, dst);
|
||||||
if (wpi->unknown_ != NULL) dst = ChunkListEmit(wpi->unknown_, dst);
|
if (wpi->unknown != NULL) dst = ChunkListEmit(wpi->unknown, dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +404,8 @@ uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
|
|||||||
|
|
||||||
int MuxHasAlpha(const WebPMuxImage* images) {
|
int MuxHasAlpha(const WebPMuxImage* images) {
|
||||||
while (images != NULL) {
|
while (images != NULL) {
|
||||||
if (images->has_alpha_) return 1;
|
if (images->has_alpha) return 1;
|
||||||
images = images->next_;
|
images = images->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -421,12 +421,12 @@ uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) {
|
|||||||
WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
|
WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
|
||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x_;
|
case WEBP_CHUNK_VP8X: return (WebPChunk**)&mux->vp8x;
|
||||||
case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp_;
|
case WEBP_CHUNK_ICCP: return (WebPChunk**)&mux->iccp;
|
||||||
case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_;
|
case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim;
|
||||||
case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_;
|
case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif;
|
||||||
case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_;
|
case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp;
|
||||||
default: return (WebPChunk**)&mux->unknown_;
|
default: return (WebPChunk**)&mux->unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +470,7 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
|
|||||||
if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
|
||||||
// Verify mux has at least one image.
|
// Verify mux has at least one image.
|
||||||
if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
if (mux->images == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
|
||||||
err = WebPMuxGetFeatures(mux, &flags);
|
err = WebPMuxGetFeatures(mux, &flags);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
@ -503,15 +503,15 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
|
|||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if (!has_animation) {
|
if (!has_animation) {
|
||||||
const WebPMuxImage* images = mux->images_;
|
const WebPMuxImage* images = mux->images;
|
||||||
// There can be only one image.
|
// There can be only one image.
|
||||||
if (images == NULL || images->next_ != NULL) {
|
if (images == NULL || images->next != NULL) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
// Size must match.
|
// Size must match.
|
||||||
if (mux->canvas_width_ > 0) {
|
if (mux->canvas_width > 0) {
|
||||||
if (images->width_ != mux->canvas_width_ ||
|
if (images->width != mux->canvas_width ||
|
||||||
images->height_ != mux->canvas_height_) {
|
images->height != mux->canvas_height) {
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -519,7 +519,7 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify either VP8X chunk is present OR there is only one elem in
|
// Verify either VP8X chunk is present OR there is only one elem in
|
||||||
// mux->images_.
|
// mux->images.
|
||||||
err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x);
|
err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images);
|
err = ValidateChunk(mux, IDX_VP8, NO_FLAG, flags, -1, &num_images);
|
||||||
@ -528,7 +528,7 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
|
|||||||
|
|
||||||
// ALPHA_FLAG & alpha chunk(s) are consistent.
|
// ALPHA_FLAG & alpha chunk(s) are consistent.
|
||||||
// Note: ALPHA_FLAG can be set when there is actually no Alpha data present.
|
// Note: ALPHA_FLAG can be set when there is actually no Alpha data present.
|
||||||
if (MuxHasAlpha(mux->images_)) {
|
if (MuxHasAlpha(mux->images)) {
|
||||||
if (num_vp8x > 0) {
|
if (num_vp8x > 0) {
|
||||||
// VP8X chunk is present, so it should contain ALPHA_FLAG.
|
// VP8X chunk is present, so it should contain ALPHA_FLAG.
|
||||||
if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT;
|
if (!(flags & ALPHA_FLAG)) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \
|
const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \
|
||||||
kChunks[(INDEX)].tag); \
|
kChunks[(INDEX)].tag); \
|
||||||
if (chunk) { \
|
if (chunk) { \
|
||||||
*data = chunk->data_; \
|
*data = chunk->data; \
|
||||||
return WEBP_MUX_OK; \
|
return WEBP_MUX_OK; \
|
||||||
} else { \
|
} else { \
|
||||||
return WEBP_MUX_NOT_FOUND; \
|
return WEBP_MUX_NOT_FOUND; \
|
||||||
@ -41,11 +41,11 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
|
|||||||
assert(!IsWPI(kChunks[idx].id));
|
assert(!IsWPI(kChunks[idx].id));
|
||||||
WebPDataInit(data);
|
WebPDataInit(data);
|
||||||
|
|
||||||
SWITCH_ID_LIST(IDX_VP8X, mux->vp8x_);
|
SWITCH_ID_LIST(IDX_VP8X, mux->vp8x);
|
||||||
SWITCH_ID_LIST(IDX_ICCP, mux->iccp_);
|
SWITCH_ID_LIST(IDX_ICCP, mux->iccp);
|
||||||
SWITCH_ID_LIST(IDX_ANIM, mux->anim_);
|
SWITCH_ID_LIST(IDX_ANIM, mux->anim);
|
||||||
SWITCH_ID_LIST(IDX_EXIF, mux->exif_);
|
SWITCH_ID_LIST(IDX_EXIF, mux->exif);
|
||||||
SWITCH_ID_LIST(IDX_XMP, mux->xmp_);
|
SWITCH_ID_LIST(IDX_XMP, mux->xmp);
|
||||||
assert(idx != IDX_UNKNOWN);
|
assert(idx != IDX_UNKNOWN);
|
||||||
return WEBP_MUX_NOT_FOUND;
|
return WEBP_MUX_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@ -77,9 +77,9 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int MuxImageFinalize(WebPMuxImage* const wpi) {
|
int MuxImageFinalize(WebPMuxImage* const wpi) {
|
||||||
const WebPChunk* const img = wpi->img_;
|
const WebPChunk* const img = wpi->img;
|
||||||
const WebPData* const image = &img->data_;
|
const WebPData* const image = &img->data;
|
||||||
const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag);
|
const int is_lossless = (img->tag == kChunks[IDX_VP8L].tag);
|
||||||
int w, h;
|
int w, h;
|
||||||
int vp8l_has_alpha = 0;
|
int vp8l_has_alpha = 0;
|
||||||
const int ok = is_lossless ?
|
const int ok = is_lossless ?
|
||||||
@ -88,29 +88,29 @@ int MuxImageFinalize(WebPMuxImage* const wpi) {
|
|||||||
assert(img != NULL);
|
assert(img != NULL);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
// Ignore ALPH chunk accompanying VP8L.
|
// Ignore ALPH chunk accompanying VP8L.
|
||||||
if (is_lossless && (wpi->alpha_ != NULL)) {
|
if (is_lossless && (wpi->alpha != NULL)) {
|
||||||
ChunkDelete(wpi->alpha_);
|
ChunkDelete(wpi->alpha);
|
||||||
wpi->alpha_ = NULL;
|
wpi->alpha = NULL;
|
||||||
}
|
}
|
||||||
wpi->width_ = w;
|
wpi->width = w;
|
||||||
wpi->height_ = h;
|
wpi->height = h;
|
||||||
wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL);
|
wpi->has_alpha = vp8l_has_alpha || (wpi->alpha != NULL);
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
|
static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
|
||||||
WebPMuxImage* const wpi) {
|
WebPMuxImage* const wpi) {
|
||||||
const uint8_t* bytes = chunk->data_.bytes;
|
const uint8_t* bytes = chunk->data.bytes;
|
||||||
size_t size = chunk->data_.size;
|
size_t size = chunk->data.size;
|
||||||
const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size;
|
const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size;
|
||||||
WebPChunk subchunk;
|
WebPChunk subchunk;
|
||||||
size_t subchunk_size;
|
size_t subchunk_size;
|
||||||
WebPChunk** unknown_chunk_list = &wpi->unknown_;
|
WebPChunk** unknown_chunk_list = &wpi->unknown;
|
||||||
ChunkInit(&subchunk);
|
ChunkInit(&subchunk);
|
||||||
|
|
||||||
assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
|
assert(chunk->tag == kChunks[IDX_ANMF].tag);
|
||||||
assert(!wpi->is_partial_);
|
assert(!wpi->is_partial);
|
||||||
|
|
||||||
// ANMF.
|
// ANMF.
|
||||||
{
|
{
|
||||||
@ -120,12 +120,12 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
|
|||||||
// be at least 'hdr_size'.
|
// be at least 'hdr_size'.
|
||||||
if (size < hdr_size) goto Fail;
|
if (size < hdr_size) goto Fail;
|
||||||
if (ChunkAssignData(&subchunk, &temp, copy_data,
|
if (ChunkAssignData(&subchunk, &temp, copy_data,
|
||||||
chunk->tag_) != WEBP_MUX_OK) {
|
chunk->tag) != WEBP_MUX_OK) {
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ChunkSetHead(&subchunk, &wpi->header_) != WEBP_MUX_OK) goto Fail;
|
if (ChunkSetHead(&subchunk, &wpi->header) != WEBP_MUX_OK) goto Fail;
|
||||||
wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
|
wpi->is_partial = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
|
||||||
|
|
||||||
// Rest of the chunks.
|
// Rest of the chunks.
|
||||||
subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE;
|
subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE;
|
||||||
@ -138,20 +138,20 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
|
|||||||
copy_data) != WEBP_MUX_OK) {
|
copy_data) != WEBP_MUX_OK) {
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
switch (ChunkGetIdFromTag(subchunk.tag_)) {
|
switch (ChunkGetIdFromTag(subchunk.tag)) {
|
||||||
case WEBP_CHUNK_ALPHA:
|
case WEBP_CHUNK_ALPHA:
|
||||||
if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
|
if (wpi->alpha != NULL) goto Fail; // Consecutive ALPH chunks.
|
||||||
if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail;
|
if (ChunkSetHead(&subchunk, &wpi->alpha) != WEBP_MUX_OK) goto Fail;
|
||||||
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
|
wpi->is_partial = 1; // Waiting for a VP8 chunk.
|
||||||
break;
|
break;
|
||||||
case WEBP_CHUNK_IMAGE:
|
case WEBP_CHUNK_IMAGE:
|
||||||
if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed.
|
if (wpi->img != NULL) goto Fail; // Only 1 image chunk allowed.
|
||||||
if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail;
|
if (ChunkSetHead(&subchunk, &wpi->img) != WEBP_MUX_OK) goto Fail;
|
||||||
if (!MuxImageFinalize(wpi)) goto Fail;
|
if (!MuxImageFinalize(wpi)) goto Fail;
|
||||||
wpi->is_partial_ = 0; // wpi is completely filled.
|
wpi->is_partial = 0; // wpi is completely filled.
|
||||||
break;
|
break;
|
||||||
case WEBP_CHUNK_UNKNOWN:
|
case WEBP_CHUNK_UNKNOWN:
|
||||||
if (wpi->is_partial_) {
|
if (wpi->is_partial) {
|
||||||
goto Fail; // Encountered an unknown chunk
|
goto Fail; // Encountered an unknown chunk
|
||||||
// before some image chunks.
|
// before some image chunks.
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
|
|||||||
bytes += subchunk_size;
|
bytes += subchunk_size;
|
||||||
size -= subchunk_size;
|
size -= subchunk_size;
|
||||||
}
|
}
|
||||||
if (wpi->is_partial_) goto Fail;
|
if (wpi->is_partial) goto Fail;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
@ -249,29 +249,29 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
|||||||
goto Err;
|
goto Err;
|
||||||
}
|
}
|
||||||
data_size = ChunkDiskSize(&chunk);
|
data_size = ChunkDiskSize(&chunk);
|
||||||
id = ChunkGetIdFromTag(chunk.tag_);
|
id = ChunkGetIdFromTag(chunk.tag);
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case WEBP_CHUNK_ALPHA:
|
case WEBP_CHUNK_ALPHA:
|
||||||
if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
|
if (wpi->alpha != NULL) goto Err; // Consecutive ALPH chunks.
|
||||||
if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err;
|
if (ChunkSetHead(&chunk, &wpi->alpha) != WEBP_MUX_OK) goto Err;
|
||||||
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
|
wpi->is_partial = 1; // Waiting for a VP8 chunk.
|
||||||
break;
|
break;
|
||||||
case WEBP_CHUNK_IMAGE:
|
case WEBP_CHUNK_IMAGE:
|
||||||
if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err;
|
if (ChunkSetHead(&chunk, &wpi->img) != WEBP_MUX_OK) goto Err;
|
||||||
if (!MuxImageFinalize(wpi)) goto Err;
|
if (!MuxImageFinalize(wpi)) goto Err;
|
||||||
wpi->is_partial_ = 0; // wpi is completely filled.
|
wpi->is_partial = 0; // wpi is completely filled.
|
||||||
PushImage:
|
PushImage:
|
||||||
// Add this to mux->images_ list.
|
// Add this to mux->images list.
|
||||||
if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err;
|
if (MuxImagePush(wpi, &mux->images) != WEBP_MUX_OK) goto Err;
|
||||||
MuxImageInit(wpi); // Reset for reading next image.
|
MuxImageInit(wpi); // Reset for reading next image.
|
||||||
break;
|
break;
|
||||||
case WEBP_CHUNK_ANMF:
|
case WEBP_CHUNK_ANMF:
|
||||||
if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
|
if (wpi->is_partial) goto Err; // Previous wpi is still incomplete.
|
||||||
if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
|
if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
|
||||||
ChunkRelease(&chunk);
|
ChunkRelease(&chunk);
|
||||||
goto PushImage;
|
goto PushImage;
|
||||||
default: // A non-image chunk.
|
default: // A non-image chunk.
|
||||||
if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
|
if (wpi->is_partial) goto Err; // Encountered a non-image chunk before
|
||||||
// getting all chunks of an image.
|
// getting all chunks of an image.
|
||||||
if (chunk_list_ends[id] == NULL) {
|
if (chunk_list_ends[id] == NULL) {
|
||||||
chunk_list_ends[id] =
|
chunk_list_ends[id] =
|
||||||
@ -280,8 +280,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
|||||||
if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err;
|
if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err;
|
||||||
if (id == WEBP_CHUNK_VP8X) { // grab global specs
|
if (id == WEBP_CHUNK_VP8X) { // grab global specs
|
||||||
if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err;
|
if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err;
|
||||||
mux->canvas_width_ = GetLE24(data + 12) + 1;
|
mux->canvas_width = GetLE24(data + 12) + 1;
|
||||||
mux->canvas_height_ = GetLE24(data + 15) + 1;
|
mux->canvas_height = GetLE24(data + 15) + 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Incomplete image.
|
// Incomplete image.
|
||||||
if (wpi->is_partial_) goto Err;
|
if (wpi->is_partial) goto Err;
|
||||||
|
|
||||||
// Validate mux if complete.
|
// Validate mux if complete.
|
||||||
if (MuxValidate(mux) != WEBP_MUX_OK) goto Err;
|
if (MuxValidate(mux) != WEBP_MUX_OK) goto Err;
|
||||||
@ -311,8 +311,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
|||||||
|
|
||||||
// Validates that the given mux has a single image.
|
// Validates that the given mux has a single image.
|
||||||
static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) {
|
static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) {
|
||||||
const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
|
const int num_images = MuxImageCount(mux->images, WEBP_CHUNK_IMAGE);
|
||||||
const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF);
|
const int num_frames = MuxImageCount(mux->images, WEBP_CHUNK_ANMF);
|
||||||
|
|
||||||
if (num_images == 0) {
|
if (num_images == 0) {
|
||||||
// No images in mux.
|
// No images in mux.
|
||||||
@ -342,18 +342,18 @@ static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux,
|
|||||||
w = GetLE24(data.bytes + 4) + 1;
|
w = GetLE24(data.bytes + 4) + 1;
|
||||||
h = GetLE24(data.bytes + 7) + 1;
|
h = GetLE24(data.bytes + 7) + 1;
|
||||||
} else {
|
} else {
|
||||||
const WebPMuxImage* const wpi = mux->images_;
|
const WebPMuxImage* const wpi = mux->images;
|
||||||
// Grab user-forced canvas size as default.
|
// Grab user-forced canvas size as default.
|
||||||
w = mux->canvas_width_;
|
w = mux->canvas_width;
|
||||||
h = mux->canvas_height_;
|
h = mux->canvas_height;
|
||||||
if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) {
|
if (w == 0 && h == 0 && ValidateForSingleImage(mux) == WEBP_MUX_OK) {
|
||||||
// single image and not forced canvas size => use dimension of first frame
|
// single image and not forced canvas size => use dimension of first frame
|
||||||
assert(wpi != NULL);
|
assert(wpi != NULL);
|
||||||
w = wpi->width_;
|
w = wpi->width;
|
||||||
h = wpi->height_;
|
h = wpi->height;
|
||||||
}
|
}
|
||||||
if (wpi != NULL) {
|
if (wpi != NULL) {
|
||||||
if (wpi->has_alpha_) f |= ALPHA_FLAG;
|
if (wpi->has_alpha) f |= ALPHA_FLAG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA;
|
if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA;
|
||||||
@ -396,29 +396,29 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
|
|||||||
uint8_t* dst;
|
uint8_t* dst;
|
||||||
|
|
||||||
// Allocate data.
|
// Allocate data.
|
||||||
const int need_vp8x = (wpi->alpha_ != NULL);
|
const int need_vp8x = (wpi->alpha != NULL);
|
||||||
const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
|
const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
|
||||||
const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0;
|
const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha) : 0;
|
||||||
// Note: No need to output ANMF chunk for a single image.
|
// Note: No need to output ANMF chunk for a single image.
|
||||||
const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
|
const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
|
||||||
ChunkDiskSize(wpi->img_);
|
ChunkDiskSize(wpi->img);
|
||||||
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
|
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
|
||||||
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
|
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
|
||||||
|
|
||||||
// There should be at most one alpha_ chunk and exactly one img_ chunk.
|
// There should be at most one alpha chunk and exactly one img chunk.
|
||||||
assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL);
|
assert(wpi->alpha == NULL || wpi->alpha->next == NULL);
|
||||||
assert(wpi->img_ != NULL && wpi->img_->next_ == NULL);
|
assert(wpi->img != NULL && wpi->img->next == NULL);
|
||||||
|
|
||||||
// Main RIFF header.
|
// Main RIFF header.
|
||||||
dst = MuxEmitRiffHeader(data, size);
|
dst = MuxEmitRiffHeader(data, size);
|
||||||
|
|
||||||
if (need_vp8x) {
|
if (need_vp8x) {
|
||||||
dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X.
|
dst = EmitVP8XChunk(dst, wpi->width, wpi->height, ALPHA_FLAG); // VP8X.
|
||||||
dst = ChunkListEmit(wpi->alpha_, dst); // ALPH.
|
dst = ChunkListEmit(wpi->alpha, dst); // ALPH.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bitstream.
|
// Bitstream.
|
||||||
dst = ChunkListEmit(wpi->img_, dst);
|
dst = ChunkListEmit(wpi->img, dst);
|
||||||
assert(dst == data + size);
|
assert(dst == data + size);
|
||||||
|
|
||||||
// Output.
|
// Output.
|
||||||
@ -441,9 +441,9 @@ WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4],
|
|||||||
return MuxGet(mux, idx, 1, chunk_data);
|
return MuxGet(mux, idx, 1, chunk_data);
|
||||||
} else { // An unknown chunk type.
|
} else { // An unknown chunk type.
|
||||||
const WebPChunk* const chunk =
|
const WebPChunk* const chunk =
|
||||||
ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc));
|
ChunkSearchList(mux->unknown, 1, ChunkGetTagFromFourCC(fourcc));
|
||||||
if (chunk == NULL) return WEBP_MUX_NOT_FOUND;
|
if (chunk == NULL) return WEBP_MUX_NOT_FOUND;
|
||||||
*chunk_data = chunk->data_;
|
*chunk_data = chunk->data;
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -457,18 +457,18 @@ static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
|
|||||||
info->dispose_method = WEBP_MUX_DISPOSE_NONE;
|
info->dispose_method = WEBP_MUX_DISPOSE_NONE;
|
||||||
info->blend_method = WEBP_MUX_BLEND;
|
info->blend_method = WEBP_MUX_BLEND;
|
||||||
// Extract data for related fields.
|
// Extract data for related fields.
|
||||||
info->id = ChunkGetIdFromTag(wpi->img_->tag_);
|
info->id = ChunkGetIdFromTag(wpi->img->tag);
|
||||||
return SynthesizeBitstream(wpi, &info->bitstream);
|
return SynthesizeBitstream(wpi, &info->bitstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WebPMuxError MuxGetFrameInternal(const WebPMuxImage* const wpi,
|
static WebPMuxError MuxGetFrameInternal(const WebPMuxImage* const wpi,
|
||||||
WebPMuxFrameInfo* const frame) {
|
WebPMuxFrameInfo* const frame) {
|
||||||
const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
|
const int is_frame = (wpi->header->tag == kChunks[IDX_ANMF].tag);
|
||||||
const WebPData* frame_data;
|
const WebPData* frame_data;
|
||||||
if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
|
if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
|
assert(wpi->header != NULL); // Already checked by WebPMuxGetFrame().
|
||||||
// Get frame chunk.
|
// Get frame chunk.
|
||||||
frame_data = &wpi->header_->data_;
|
frame_data = &wpi->header->data;
|
||||||
if (frame_data->size < kChunks[IDX_ANMF].size) return WEBP_MUX_BAD_DATA;
|
if (frame_data->size < kChunks[IDX_ANMF].size) return WEBP_MUX_BAD_DATA;
|
||||||
// Extract info.
|
// Extract info.
|
||||||
frame->x_offset = 2 * GetLE24(frame_data->bytes + 0);
|
frame->x_offset = 2 * GetLE24(frame_data->bytes + 0);
|
||||||
@ -480,7 +480,7 @@ static WebPMuxError MuxGetFrameInternal(const WebPMuxImage* const wpi,
|
|||||||
(bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
|
(bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
|
||||||
frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
|
frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
|
||||||
}
|
}
|
||||||
frame->id = ChunkGetIdFromTag(wpi->header_->tag_);
|
frame->id = ChunkGetIdFromTag(wpi->header->tag);
|
||||||
return SynthesizeBitstream(wpi, &frame->bitstream);
|
return SynthesizeBitstream(wpi, &frame->bitstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,11 +494,11 @@ WebPMuxError WebPMuxGetFrame(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the nth WebPMuxImage.
|
// Get the nth WebPMuxImage.
|
||||||
err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi);
|
err = MuxImageGetNth((const WebPMuxImage**)&mux->images, nth, &wpi);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
|
|
||||||
// Get frame info.
|
// Get frame info.
|
||||||
if (wpi->header_ == NULL) {
|
if (wpi->header == NULL) {
|
||||||
return MuxGetImageInternal(wpi, frame);
|
return MuxGetImageInternal(wpi, frame);
|
||||||
} else {
|
} else {
|
||||||
return MuxGetFrameInternal(wpi, frame);
|
return MuxGetFrameInternal(wpi, frame);
|
||||||
@ -535,8 +535,8 @@ static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) {
|
|||||||
static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) {
|
static int CountChunks(const WebPChunk* const chunk_list, uint32_t tag) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
const WebPChunk* current;
|
const WebPChunk* current;
|
||||||
for (current = chunk_list; current != NULL; current = current->next_) {
|
for (current = chunk_list; current != NULL; current = current->next) {
|
||||||
if (tag == NIL_TAG || current->tag_ == tag) {
|
if (tag == NIL_TAG || current->tag == tag) {
|
||||||
count++; // Count chunks whose tags match.
|
count++; // Count chunks whose tags match.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,7 +550,7 @@ WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsWPI(id)) {
|
if (IsWPI(id)) {
|
||||||
*num_elements = MuxImageCount(mux->images_, id);
|
*num_elements = MuxImageCount(mux->images, id);
|
||||||
} else {
|
} else {
|
||||||
WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
|
WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
|
||||||
const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
|
const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user