dwebp: move webp decoding to example_util

this will allow reuse by cwebp

Change-Id: I667252fdacfc5436112d21b040ca299273ec1515
This commit is contained in:
James Zern 2014-04-22 19:33:22 -07:00
parent c0220460e9
commit 4a0e73904d
4 changed files with 112 additions and 46 deletions

View File

@ -14,7 +14,7 @@ endif
noinst_LTLIBRARIES = libexampleutil.la noinst_LTLIBRARIES = libexampleutil.la
libexampleutil_la_SOURCES = example_util.c example_util.h libexampleutil_la_SOURCES = example_util.c example_util.h stopwatch.h
dwebp_SOURCES = dwebp.c stopwatch.h dwebp_SOURCES = dwebp.c stopwatch.h
dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) dwebp_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE)

View File

@ -571,11 +571,6 @@ static void Help(void) {
); );
} }
static const char* const kStatusMessages[] = {
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
};
static const char* const kFormatType[] = { static const char* const kFormatType[] = {
"unspecified", "lossy", "lossless" "unspecified", "lossy", "lossless"
}; };
@ -671,27 +666,11 @@ int main(int argc, const char *argv[]) {
} }
{ {
Stopwatch stop_watch;
VP8StatusCode status = VP8_STATUS_OK; VP8StatusCode status = VP8_STATUS_OK;
size_t data_size = 0; size_t data_size = 0;
const uint8_t* data = NULL; const uint8_t* data = NULL;
if (!ExUtilLoadWebP(in_file, &data, &data_size, bitstream)) {
if (!ExUtilReadFile(in_file, &data, &data_size)) return -1; goto End;
if (verbose) {
StopwatchReset(&stop_watch);
}
status = WebPGetFeatures(data, data_size, bitstream);
if (status != VP8_STATUS_OK) {
goto end;
}
if (bitstream->has_animation) {
fprintf(stderr,
"Error! Decoding of an animated WebP file is not supported.\n"
" Use webpmux to extract the individual frames or\n"
" vwebp to view this image.\n");
} }
switch (format) { switch (format) {
@ -727,31 +706,12 @@ int main(int argc, const char *argv[]) {
return -1; return -1;
} }
// Decoding call. status = ExUtilDecodeWebP(data, data_size, incremental, verbose, &config);
if (!incremental) { End:
status = WebPDecode(data, data_size, &config);
} else {
WebPIDecoder* const idec = WebPIDecode(data, data_size, &config);
if (idec == NULL) {
fprintf(stderr, "Failed during WebPINewDecoder().\n");
status = VP8_STATUS_OUT_OF_MEMORY;
goto end;
} else {
status = WebPIUpdate(idec, data, data_size);
WebPIDelete(idec);
}
}
if (verbose) {
const double decode_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
}
end:
free((void*)data); free((void*)data);
ok = (status == VP8_STATUS_OK); ok = (status == VP8_STATUS_OK);
if (!ok) { if (!ok) {
fprintf(stderr, "Decoding of %s failed.\n", in_file); ExUtilPrintWebPError(in_file, status);
fprintf(stderr, "Status: %d (%s)\n", status, kStatusMessages[status]);
goto Exit; goto Exit;
} }
} }

View File

@ -15,6 +15,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "webp/decode.h"
#include "./stopwatch.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// File I/O // File I/O
@ -107,3 +110,77 @@ int ExUtilWriteFile(const char* const file_name,
return ok; return ok;
} }
//------------------------------------------------------------------------------
// WebP decoding
static const char* const kStatusMessages[] = {
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
};
void ExUtilPrintWebPError(const char* const in_file, int status) {
fprintf(stderr, "Decoding of %s failed.\n", in_file);
fprintf(stderr, "Status: %d", status);
if (status >= VP8_STATUS_OK && status <= VP8_STATUS_NOT_ENOUGH_DATA) {
fprintf(stderr, "(%s)", kStatusMessages[status]);
}
fprintf(stderr, "\n");
}
int ExUtilLoadWebP(const char* const in_file,
const uint8_t** data, size_t* data_size,
WebPBitstreamFeatures* bitstream) {
VP8StatusCode status;
if (!ExUtilReadFile(in_file, data, data_size)) return 0;
status = WebPGetFeatures(*data, *data_size, bitstream);
if (status != VP8_STATUS_OK) {
free((void*)*data);
*data = NULL;
*data_size = 0;
ExUtilPrintWebPError(in_file, status);
return 0;
}
return 1;
}
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
int incremental, int verbose,
WebPDecoderConfig* const config) {
Stopwatch stop_watch;
VP8StatusCode status = VP8_STATUS_OK;
if (config == NULL) return 0;
if (verbose) {
StopwatchReset(&stop_watch);
}
if (config->input.has_animation) {
fprintf(stderr,
"Error! Decoding of an animated WebP file is not supported.\n"
" Use webpmux to extract the individual frames or\n"
" vwebp to view this image.\n");
}
// Decoding call.
if (!incremental) {
status = WebPDecode(data, data_size, config);
} else {
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
if (idec == NULL) {
fprintf(stderr, "Failed during WebPINewDecoder().\n");
return VP8_STATUS_OUT_OF_MEMORY;
} else {
status = WebPIUpdate(idec, data, data_size);
WebPIDelete(idec);
}
}
if (verbose) {
const double decode_time = StopwatchReadAndReset(&stop_watch);
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
}
return status;
}
// -----------------------------------------------------------------------------

View File

@ -19,6 +19,9 @@
extern "C" { extern "C" {
#endif #endif
struct WebPDecoderConfig;
struct WebPBitstreamFeatures;
// Allocates storage for entire file 'file_name' and returns contents and size // Allocates storage for entire file 'file_name' and returns contents and size
// in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should // in 'data' and 'data_size'. Returns 1 on success, 0 otherwise. '*data' should
// be deleted using free(). // be deleted using free().
@ -35,6 +38,32 @@ int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size);
int ExUtilWriteFile(const char* const file_name, int ExUtilWriteFile(const char* const file_name,
const uint8_t* data, size_t data_size); const uint8_t* data, size_t data_size);
//------------------------------------------------------------------------------
// WebP decoding
// Prints an informative error message regarding decode failure of 'in_file'.
// 'status' is treated as a VP8StatusCode and if valid will be printed as a
// text string.
void ExUtilPrintWebPError(const char* const in_file, int status);
// Reads a WebP from 'in_file', returning the contents and size in 'data' and
// 'data_size'. 'bitstream' is populated using WebPGetFeatures().
// Returns true on success.
int ExUtilLoadWebP(const char* const in_file,
const uint8_t** data, size_t* data_size,
struct WebPBitstreamFeatures* bitstream);
// Decodes the WebP contained in 'data'. 'config' is a structure previously
// initialized by WebPInitDecoderConfig(). 'config->output' should have the
// desired colorspace selected. If 'incremental' is set to true the WebP
// incremental decoder will be used. 'verbose' will cause decode timing to be
// reported.
// Returns the decoder status. On success 'config->output' will contain the
// decoded picture.
enum VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
int incremental, int verbose,
struct WebPDecoderConfig* const config);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif