mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
webpmux: make more use of WebPData
Add WebPDataCopy and use it in ReadImage which now returns WebPData*s. Update ReadData prototype variables used with it to avoid unnecessary const casting back and forth from void*. Change-Id: I3f83db6729306eab0db9027b68706c8a7005ec10
This commit is contained in:
parent
974aaff360
commit
0f7820e65c
@ -119,6 +119,27 @@ static int IsNotCompatible(int count1, int count2) {
|
|||||||
return (count1 > 0) != (count2 > 0);
|
return (count1 > 0) != (count2 > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate necessary storage for dst then copy the contents of src.
|
||||||
|
// Returns 1 on success.
|
||||||
|
static int WebPDataCopy(const WebPData* const src, WebPData* const dst) {
|
||||||
|
if (src == NULL || dst == NULL) return 0;
|
||||||
|
|
||||||
|
memset(dst, 0, sizeof(*dst));
|
||||||
|
if (src->bytes_ != NULL && src->size_ != 0) {
|
||||||
|
dst->bytes_ = (uint8_t*)malloc(src->size_);
|
||||||
|
if (dst->bytes_ == NULL) return 0;
|
||||||
|
memcpy((void*)dst->bytes_, src->bytes_, src->size_);
|
||||||
|
dst->size_ = src->size_;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees data allocated by WebPDataCopy.
|
||||||
|
static void WebPDataFree(WebPData* const webpdata) {
|
||||||
|
free((void*)webpdata->bytes_);
|
||||||
|
memset(webpdata, 0, sizeof(*webpdata));
|
||||||
|
}
|
||||||
|
|
||||||
#define RETURN_IF_ERROR(ERR_MSG) \
|
#define RETURN_IF_ERROR(ERR_MSG) \
|
||||||
if (err != WEBP_MUX_OK) { \
|
if (err != WEBP_MUX_OK) { \
|
||||||
fprintf(stderr, ERR_MSG); \
|
fprintf(stderr, ERR_MSG); \
|
||||||
@ -210,11 +231,11 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
|
|||||||
printf("Number of tiles: %d\n", nTiles);
|
printf("Number of tiles: %d\n", nTiles);
|
||||||
if (nTiles > 0) {
|
if (nTiles > 0) {
|
||||||
int i;
|
int i;
|
||||||
uint32_t x_offset, y_offset;
|
|
||||||
printf("No.: x_offset y_offset image_size");
|
printf("No.: x_offset y_offset image_size");
|
||||||
if (flag & ALPHA_FLAG) printf(" alpha_size");
|
if (flag & ALPHA_FLAG) printf(" alpha_size");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
for (i = 1; i <= nTiles; i++) {
|
for (i = 1; i <= nTiles; i++) {
|
||||||
|
uint32_t x_offset, y_offset;
|
||||||
WebPData image, alpha;
|
WebPData image, alpha;
|
||||||
err = WebPMuxGetTile(mux, i, &image, &alpha, &x_offset, &y_offset);
|
err = WebPMuxGetTile(mux, i, &image, &alpha, &x_offset, &y_offset);
|
||||||
RETURN_IF_ERROR2("Failed to retrieve tile#%d\n", i);
|
RETURN_IF_ERROR2("Failed to retrieve tile#%d\n", i);
|
||||||
@ -298,7 +319,8 @@ static void PrintHelp(void) {
|
|||||||
printf("\nINPUT & OUTPUT are in webp format.\n");
|
printf("\nINPUT & OUTPUT are in webp format.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadData(const char* filename, void** data_ptr, uint32_t* size_ptr) {
|
static int ReadData(const char* filename,
|
||||||
|
uint8_t** data_ptr, uint32_t* size_ptr) {
|
||||||
void* data = NULL;
|
void* data = NULL;
|
||||||
long size = 0;
|
long size = 0;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
@ -343,19 +365,19 @@ static int ReadData(const char* filename, void** data_ptr, uint32_t* size_ptr) {
|
|||||||
Err:
|
Err:
|
||||||
if (in != stdin) fclose(in);
|
if (in != stdin) fclose(in);
|
||||||
*size_ptr = (uint32_t)size;
|
*size_ptr = (uint32_t)size;
|
||||||
*data_ptr = data;
|
*data_ptr = (uint8_t*)data;
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadFile(const char* const filename, WebPMux** mux) {
|
static int ReadFile(const char* const filename, WebPMux** mux) {
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
void* data = NULL;
|
uint8_t* data = NULL;
|
||||||
WebPMuxState mux_state;
|
WebPMuxState mux_state;
|
||||||
|
|
||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
|
|
||||||
if (!ReadData(filename, &data, &size)) return 0;
|
if (!ReadData(filename, &data, &size)) return 0;
|
||||||
*mux = WebPMuxCreate((const uint8_t*)data, size, 1, &mux_state);
|
*mux = WebPMuxCreate(data, size, 1, &mux_state);
|
||||||
free(data);
|
free(data);
|
||||||
if (*mux != NULL && mux_state == WEBP_MUX_STATE_COMPLETE) return 1;
|
if (*mux != NULL && mux_state == WEBP_MUX_STATE_COMPLETE) return 1;
|
||||||
fprintf(stderr, "Failed to create mux object from file %s. mux_state = %d.\n",
|
fprintf(stderr, "Failed to create mux object from file %s. mux_state = %d.\n",
|
||||||
@ -364,9 +386,8 @@ static int ReadFile(const char* const filename, WebPMux** mux) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ReadImage(const char* filename,
|
static int ReadImage(const char* filename,
|
||||||
const uint8_t** data_ptr, uint32_t* size_ptr,
|
WebPData* const image_ptr, WebPData* const alpha_ptr) {
|
||||||
const uint8_t** alpha_data_ptr, uint32_t* alpha_size_ptr) {
|
uint8_t* data = NULL;
|
||||||
void* data = NULL;
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
WebPData image, alpha;
|
WebPData image, alpha;
|
||||||
WebPMux* mux;
|
WebPMux* mux;
|
||||||
@ -376,7 +397,7 @@ static int ReadImage(const char* filename,
|
|||||||
|
|
||||||
if (!ReadData(filename, &data, &size)) return 0;
|
if (!ReadData(filename, &data, &size)) return 0;
|
||||||
|
|
||||||
mux = WebPMuxCreate((const uint8_t*)data, size, 1, &mux_state);
|
mux = WebPMuxCreate(data, size, 1, &mux_state);
|
||||||
free(data);
|
free(data);
|
||||||
if (mux == NULL || mux_state != WEBP_MUX_STATE_COMPLETE) {
|
if (mux == NULL || mux_state != WEBP_MUX_STATE_COMPLETE) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -386,23 +407,14 @@ static int ReadImage(const char* filename,
|
|||||||
}
|
}
|
||||||
err = WebPMuxGetImage(mux, &image, &alpha);
|
err = WebPMuxGetImage(mux, &image, &alpha);
|
||||||
if (err == WEBP_MUX_OK) {
|
if (err == WEBP_MUX_OK) {
|
||||||
uint8_t* const data_mem = (uint8_t*)malloc(image.size_);
|
ok = 1;
|
||||||
uint8_t* const alpha_mem = (uint8_t*)malloc(alpha.size_);
|
ok &= WebPDataCopy(&image, image_ptr);
|
||||||
if ((data_mem != NULL) && (alpha_mem != NULL)) {
|
ok &= WebPDataCopy(&alpha, alpha_ptr);
|
||||||
memcpy(data_mem, image.bytes_, image.size_);
|
if (!ok) {
|
||||||
memcpy(alpha_mem, alpha.bytes_, alpha.size_);
|
fprintf(stderr, "Error allocating storage for image (%u bytes) "
|
||||||
*data_ptr = data_mem;
|
"and alpha (%u bytes) data\n", image.size_, alpha.size_);
|
||||||
*size_ptr = image.size_;
|
WebPDataFree(image_ptr);
|
||||||
*alpha_data_ptr = alpha_mem;
|
WebPDataFree(alpha_ptr);
|
||||||
*alpha_size_ptr = alpha.size_;
|
|
||||||
ok = 1;
|
|
||||||
} else {
|
|
||||||
free(data_mem);
|
|
||||||
free(alpha_mem);
|
|
||||||
err = WEBP_MUX_MEMORY_ERROR;
|
|
||||||
fprintf(stderr, "Failed to allocate %u bytes to extract image data from"
|
|
||||||
" file %s. Error: %d\n",
|
|
||||||
image.size_ + alpha.size_, filename, err);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Failed to extract image data from file %s. Error: %d\n",
|
fprintf(stderr, "Failed to extract image data from file %s. Error: %d\n",
|
||||||
@ -412,17 +424,17 @@ static int ReadImage(const char* filename,
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int WriteData(const char* filename, const void* data, uint32_t size) {
|
static int WriteData(const char* filename, const WebPData* const webpdata) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb") : stdout;
|
FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb") : stdout;
|
||||||
if (!fout) {
|
if (!fout) {
|
||||||
fprintf(stderr, "Error opening output WebP file %s!\n", filename);
|
fprintf(stderr, "Error opening output WebP file %s!\n", filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (fwrite(data, size, 1, fout) != 1) {
|
if (fwrite(webpdata->bytes_, webpdata->size_, 1, fout) != 1) {
|
||||||
fprintf(stderr, "Error writing file %s!\n", filename);
|
fprintf(stderr, "Error writing file %s!\n", filename);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Saved file %s (%d bytes)\n", filename, size);
|
fprintf(stderr, "Saved file %s (%d bytes)\n", filename, webpdata->size_);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
if (fout != stdout) fclose(fout);
|
if (fout != stdout) fclose(fout);
|
||||||
@ -430,17 +442,17 @@ static int WriteData(const char* filename, const void* data, uint32_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int WriteWebP(WebPMux* const mux, const char* filename) {
|
static int WriteWebP(WebPMux* const mux, const char* filename) {
|
||||||
uint8_t* data = NULL;
|
WebPData webpdata;
|
||||||
uint32_t size = 0;
|
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
WebPMuxError err = WebPMuxAssemble(mux, &data, &size);
|
const WebPMuxError err = WebPMuxAssemble(
|
||||||
|
mux, (uint8_t**)&webpdata.bytes_, &webpdata.size_);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
fprintf(stderr, "Error (%d) assembling the WebP file.\n", err);
|
fprintf(stderr, "Error (%d) assembling the WebP file.\n", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ok = WriteData(filename, data, size);
|
ok = WriteData(filename, &webpdata);
|
||||||
free(data);
|
WebPDataFree(&webpdata);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,16 +838,11 @@ static int GetFrameTile(const WebPMux* mux,
|
|||||||
static int Process(const WebPMuxConfig* config) {
|
static int Process(const WebPMuxConfig* config) {
|
||||||
WebPMux* mux = NULL;
|
WebPMux* mux = NULL;
|
||||||
WebPData webpdata;
|
WebPData webpdata;
|
||||||
const uint8_t* data = NULL;
|
uint8_t* data = NULL;
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
const uint8_t* alpha_data = NULL;
|
|
||||||
uint32_t alpha_size = 0;
|
|
||||||
uint32_t x_offset = 0;
|
uint32_t x_offset = 0;
|
||||||
uint32_t y_offset = 0;
|
uint32_t y_offset = 0;
|
||||||
uint32_t duration = 0;
|
|
||||||
uint32_t loop_count = 0;
|
|
||||||
WebPMuxError err = WEBP_MUX_OK;
|
WebPMuxError err = WEBP_MUX_OK;
|
||||||
long num;
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
const Feature* const feature = &config->feature_;
|
const Feature* const feature = &config->feature_;
|
||||||
@ -858,14 +865,14 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO2("ERROR#%d: Could not get color profile.\n", err, Err2);
|
ERROR_GOTO2("ERROR#%d: Could not get color profile.\n", err, Err2);
|
||||||
}
|
}
|
||||||
ok = WriteData(config->output_, webpdata.bytes_, webpdata.size_);
|
ok = WriteData(config->output_, &webpdata);
|
||||||
break;
|
break;
|
||||||
case FEATURE_XMP:
|
case FEATURE_XMP:
|
||||||
err = WebPMuxGetMetadata(mux, &webpdata);
|
err = WebPMuxGetMetadata(mux, &webpdata);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO2("ERROR#%d: Could not get XMP metadata.\n", err, Err2);
|
ERROR_GOTO2("ERROR#%d: Could not get XMP metadata.\n", err, Err2);
|
||||||
}
|
}
|
||||||
ok = WriteData(config->output_, webpdata.bytes_, webpdata.size_);
|
ok = WriteData(config->output_, &webpdata);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -884,31 +891,31 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
}
|
}
|
||||||
for (index = 0; index < feature->arg_count_; ++index) {
|
for (index = 0; index < feature->arg_count_; ++index) {
|
||||||
if (feature->args_[index].subtype_ == SUBTYPE_LOOP) {
|
if (feature->args_[index].subtype_ == SUBTYPE_LOOP) {
|
||||||
num = strtol(feature->args_[index].params_, NULL, 10);
|
const long num = strtol(feature->args_[index].params_, NULL, 10);
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
ERROR_GOTO1("ERROR: Loop count must be non-negative.\n", Err2);
|
ERROR_GOTO1("ERROR: Loop count must be non-negative.\n", Err2);
|
||||||
} else {
|
|
||||||
loop_count = num;
|
|
||||||
}
|
}
|
||||||
err = WebPMuxSetLoopCount(mux, loop_count);
|
err = WebPMuxSetLoopCount(mux, num);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO2("ERROR#%d: Could not set loop count.\n", err, Err2);
|
ERROR_GOTO2("ERROR#%d: Could not set loop count.\n", err, Err2);
|
||||||
}
|
}
|
||||||
} else if (feature->args_[index].subtype_ == SUBTYPE_FRM) {
|
} else if (feature->args_[index].subtype_ == SUBTYPE_FRM) {
|
||||||
ok = ReadImage(feature->args_[index].filename_,
|
WebPData image, alpha;
|
||||||
&data, &size, &alpha_data, &alpha_size);
|
uint32_t duration;
|
||||||
|
ok = ReadImage(feature->args_[index].filename_, &image, &alpha);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
ok = ParseFrameArgs(feature->args_[index].params_,
|
ok = ParseFrameArgs(feature->args_[index].params_,
|
||||||
&x_offset, &y_offset, &duration);
|
&x_offset, &y_offset, &duration);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
free((void*)data);
|
WebPDataFree(&image);
|
||||||
free((void*)alpha_data);
|
WebPDataFree(&alpha);
|
||||||
ERROR_GOTO1("ERROR: Could not parse frame properties.\n", Err2);
|
ERROR_GOTO1("ERROR: Could not parse frame properties.\n", Err2);
|
||||||
}
|
}
|
||||||
err = WebPMuxAddFrame(mux, 0, data, size, alpha_data, alpha_size,
|
err = WebPMuxAddFrame(mux, 0, image.bytes_, image.size_,
|
||||||
|
alpha.bytes_, alpha.size_,
|
||||||
x_offset, y_offset, duration, 1);
|
x_offset, y_offset, duration, 1);
|
||||||
free((void*)data);
|
WebPDataFree(&image);
|
||||||
free((void*)alpha_data);
|
WebPDataFree(&alpha);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR#%d: Could not add a frame at index %d.\n",
|
ERROR_GOTO3("ERROR#%d: Could not add a frame at index %d.\n",
|
||||||
err, index, Err2);
|
err, index, Err2);
|
||||||
@ -926,20 +933,21 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
WEBP_MUX_MEMORY_ERROR, Err2);
|
WEBP_MUX_MEMORY_ERROR, Err2);
|
||||||
}
|
}
|
||||||
for (index = 0; index < feature->arg_count_; ++index) {
|
for (index = 0; index < feature->arg_count_; ++index) {
|
||||||
ok = ReadImage(feature->args_[index].filename_,
|
WebPData image, alpha;
|
||||||
&data, &size, &alpha_data, &alpha_size);
|
ok = ReadImage(feature->args_[index].filename_, &image, &alpha);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
ok = ParseTileArgs(feature->args_[index].params_, &x_offset,
|
ok = ParseTileArgs(feature->args_[index].params_, &x_offset,
|
||||||
&y_offset);
|
&y_offset);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
free((void*)data);
|
WebPDataFree(&image);
|
||||||
free((void*)alpha_data);
|
WebPDataFree(&alpha);
|
||||||
ERROR_GOTO1("ERROR: Could not parse tile properties.\n", Err2);
|
ERROR_GOTO1("ERROR: Could not parse tile properties.\n", Err2);
|
||||||
}
|
}
|
||||||
err = WebPMuxAddTile(mux, 0, data, size, alpha_data, alpha_size,
|
err = WebPMuxAddTile(mux, 0, image.bytes_, image.size_,
|
||||||
|
alpha.bytes_, alpha.size_,
|
||||||
x_offset, y_offset, 1);
|
x_offset, y_offset, 1);
|
||||||
free((void*)data);
|
WebPDataFree(&image);
|
||||||
free((void*)alpha_data);
|
WebPDataFree(&alpha);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO3("ERROR#%d: Could not add a tile at index %d.\n",
|
ERROR_GOTO3("ERROR#%d: Could not add a tile at index %d.\n",
|
||||||
err, index, Err2);
|
err, index, Err2);
|
||||||
@ -950,7 +958,7 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
case FEATURE_ICCP:
|
case FEATURE_ICCP:
|
||||||
ok = ReadFile(config->input_, &mux);
|
ok = ReadFile(config->input_, &mux);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
ok = ReadData(feature->args_[0].filename_, (void**)&data, &size);
|
ok = ReadData(feature->args_[0].filename_, &data, &size);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
err = WebPMuxSetColorProfile(mux, data, size, 1);
|
err = WebPMuxSetColorProfile(mux, data, size, 1);
|
||||||
free((void*)data);
|
free((void*)data);
|
||||||
@ -962,10 +970,10 @@ static int Process(const WebPMuxConfig* config) {
|
|||||||
case FEATURE_XMP:
|
case FEATURE_XMP:
|
||||||
ok = ReadFile(config->input_, &mux);
|
ok = ReadFile(config->input_, &mux);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
ok = ReadData(feature->args_[0].filename_, (void**)&data, &size);
|
ok = ReadData(feature->args_[0].filename_, &data, &size);
|
||||||
if (!ok) goto Err2;
|
if (!ok) goto Err2;
|
||||||
err = WebPMuxSetMetadata(mux, data, size, 1);
|
err = WebPMuxSetMetadata(mux, data, size, 1);
|
||||||
free((void*)data);
|
free(data);
|
||||||
if (err != WEBP_MUX_OK) {
|
if (err != WEBP_MUX_OK) {
|
||||||
ERROR_GOTO2("ERROR#%d: Could not set XMP metadata.\n", err, Err2);
|
ERROR_GOTO2("ERROR#%d: Could not set XMP metadata.\n", err, Err2);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user