mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-13 06:24:27 +02:00
split example_util.h
move ExUtil*File to imageio_util.h ExUtil*WebP* to webpdec.h string parsing routines remain Change-Id: I0560c4a74e86710d83bc4b5b234f1b5ef9a86f9d
This commit is contained in:
@ -15,6 +15,21 @@ LOCAL_MODULE := example_util
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
################################################################################
|
||||
# libimageio_util
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
imageio_util.c \
|
||||
|
||||
LOCAL_CFLAGS := $(WEBP_CFLAGS)
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
|
||||
|
||||
LOCAL_MODULE := imageio_util
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
################################################################################
|
||||
# libimagedec
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
AM_CPPFLAGS += -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||
noinst_LTLIBRARIES = libexample_util.la libimagedec.la
|
||||
noinst_LTLIBRARIES = libexample_util.la libimageio_util.la libimagedec.la
|
||||
|
||||
noinst_HEADERS =
|
||||
noinst_HEADERS += ../src/webp/decode.h
|
||||
@ -8,6 +8,8 @@ noinst_HEADERS += ../examples/stopwatch.h
|
||||
|
||||
libexample_util_la_SOURCES = example_util.c example_util.h
|
||||
|
||||
libimageio_util_la_SOURCES = imageio_util.c imageio_util.h
|
||||
|
||||
libimagedec_la_SOURCES = image_dec.c image_dec.h
|
||||
libimagedec_la_SOURCES += jpegdec.c jpegdec.h
|
||||
libimagedec_la_SOURCES += metadata.c metadata.h
|
||||
|
@ -12,16 +12,8 @@
|
||||
|
||||
#include "./example_util.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <fcntl.h> // for _O_BINARY
|
||||
#include <io.h> // for _setmode()
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webp/decode.h"
|
||||
#include "../examples/stopwatch.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// String parsing
|
||||
@ -51,231 +43,3 @@ float ExUtilGetFloat(const char* const v, int* const error) {
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// File I/O
|
||||
|
||||
FILE* ExUtilSetBinaryMode(FILE* file) {
|
||||
#if defined(_WIN32)
|
||||
if (_setmode(_fileno(file), _O_BINARY) == -1) {
|
||||
fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return file;
|
||||
}
|
||||
|
||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
||||
static const size_t kBlockSize = 16384; // default initial size
|
||||
size_t max_size = 0;
|
||||
size_t size = 0;
|
||||
uint8_t* input = NULL;
|
||||
|
||||
if (data == NULL || data_size == NULL) return 0;
|
||||
*data = NULL;
|
||||
*data_size = 0;
|
||||
|
||||
if (!ExUtilSetBinaryMode(stdin)) return 0;
|
||||
|
||||
while (!feof(stdin)) {
|
||||
// We double the buffer size each time and read as much as possible.
|
||||
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
|
||||
void* const new_data = realloc(input, max_size + extra_size);
|
||||
if (new_data == NULL) goto Error;
|
||||
input = (uint8_t*)new_data;
|
||||
max_size += extra_size;
|
||||
size += fread(input + size, 1, extra_size, stdin);
|
||||
if (size < max_size) break;
|
||||
}
|
||||
if (ferror(stdin)) goto Error;
|
||||
*data = input;
|
||||
*data_size = size;
|
||||
return 1;
|
||||
|
||||
Error:
|
||||
free(input);
|
||||
fprintf(stderr, "Could not read from stdin\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExUtilReadFile(const char* const file_name,
|
||||
const uint8_t** data, size_t* data_size) {
|
||||
int ok;
|
||||
void* file_data;
|
||||
size_t file_size;
|
||||
FILE* in;
|
||||
const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
|
||||
|
||||
if (from_stdin) return ExUtilReadFromStdin(data, data_size);
|
||||
|
||||
if (data == NULL || data_size == NULL) return 0;
|
||||
*data = NULL;
|
||||
*data_size = 0;
|
||||
|
||||
in = fopen(file_name, "rb");
|
||||
if (in == NULL) {
|
||||
fprintf(stderr, "cannot open input file '%s'\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
fseek(in, 0, SEEK_END);
|
||||
file_size = ftell(in);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
file_data = malloc(file_size);
|
||||
if (file_data == NULL) return 0;
|
||||
ok = (fread(file_data, file_size, 1, in) == 1);
|
||||
fclose(in);
|
||||
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
|
||||
(int)file_size, file_name);
|
||||
free(file_data);
|
||||
return 0;
|
||||
}
|
||||
*data = (uint8_t*)file_data;
|
||||
*data_size = file_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExUtilWriteFile(const char* const file_name,
|
||||
const uint8_t* data, size_t data_size) {
|
||||
int ok;
|
||||
FILE* out;
|
||||
const int to_stdout = (file_name == NULL) || !strcmp(file_name, "-");
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
out = to_stdout ? stdout : fopen(file_name, "wb");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
ok = (fwrite(data, data_size, 1, out) == 1);
|
||||
if (out != stdout) fclose(out);
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// WebP decoding
|
||||
|
||||
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
||||
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
|
||||
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
|
||||
};
|
||||
|
||||
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
WebPBitstreamFeatures local_features;
|
||||
if (!ExUtilReadFile(in_file, data, data_size)) return 0;
|
||||
|
||||
if (bitstream == NULL) {
|
||||
bitstream = &local_features;
|
||||
}
|
||||
|
||||
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 verbose, WebPDecoderConfig* const config) {
|
||||
Stopwatch stop_watch;
|
||||
VP8StatusCode status = VP8_STATUS_OK;
|
||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||
|
||||
PrintAnimationWarning(config);
|
||||
|
||||
StopwatchReset(&stop_watch);
|
||||
|
||||
// Decoding call.
|
||||
status = WebPDecode(data, data_size, config);
|
||||
|
||||
if (verbose) {
|
||||
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
||||
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VP8StatusCode ExUtilDecodeWebPIncremental(
|
||||
const uint8_t* const data, size_t data_size,
|
||||
int verbose, WebPDecoderConfig* const config) {
|
||||
Stopwatch stop_watch;
|
||||
VP8StatusCode status = VP8_STATUS_OK;
|
||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||
|
||||
PrintAnimationWarning(config);
|
||||
|
||||
StopwatchReset(&stop_watch);
|
||||
|
||||
// Decoding call.
|
||||
{
|
||||
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
|
||||
if (idec == NULL) {
|
||||
fprintf(stderr, "Failed during WebPINewDecoder().\n");
|
||||
return VP8_STATUS_OUT_OF_MEMORY;
|
||||
} else {
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
size_t size = 0;
|
||||
const size_t incr = 2 + (data_size / 20);
|
||||
while (size < data_size) {
|
||||
size_t next_size = size + (rand() % incr);
|
||||
if (next_size > data_size) next_size = data_size;
|
||||
status = WebPIUpdate(idec, data, next_size);
|
||||
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) break;
|
||||
size = next_size;
|
||||
}
|
||||
#else
|
||||
status = WebPIUpdate(idec, data, data_size);
|
||||
#endif
|
||||
WebPIDelete(idec);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
||||
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ExUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||
uint8_t* dst, int dst_stride, int width, int height) {
|
||||
while (height-- > 0) {
|
||||
memcpy(dst, src, width * sizeof(*dst));
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -13,8 +13,7 @@
|
||||
#ifndef WEBP_IMAGEIO_EXAMPLE_UTIL_H_
|
||||
#define WEBP_IMAGEIO_EXAMPLE_UTIL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include "webp/decode.h"
|
||||
#include "webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -30,64 +29,6 @@ uint32_t ExUtilGetUInt(const char* const v, int base, int* const error);
|
||||
int ExUtilGetInt(const char* const v, int base, int* const error);
|
||||
float ExUtilGetFloat(const char* const v, int* const error);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// File I/O
|
||||
|
||||
// Reopen file in binary (O_BINARY) mode.
|
||||
// Returns 'file' on success, NULL otherwise.
|
||||
FILE* ExUtilSetBinaryMode(FILE* file);
|
||||
|
||||
// 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
|
||||
// be deleted using free().
|
||||
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
||||
// the function ExUtilReadFromStdin().
|
||||
int ExUtilReadFile(const char* const file_name,
|
||||
const uint8_t** data, size_t* data_size);
|
||||
|
||||
// Same as ExUtilReadFile(), but reads until EOF from stdin instead.
|
||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
||||
|
||||
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
||||
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
||||
int ExUtilWriteFile(const char* const file_name,
|
||||
const uint8_t* data, size_t data_size);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
||||
void ExUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||
uint8_t* dst, int dst_stride, int width, int height);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
||||
// Returns true on success.
|
||||
int ExUtilLoadWebP(const char* const in_file,
|
||||
const uint8_t** data, size_t* data_size,
|
||||
WebPBitstreamFeatures* bitstream);
|
||||
|
||||
// Decodes the WebP contained in 'data'.
|
||||
// 'config' is a structure previously initialized by WebPInitDecoderConfig().
|
||||
// 'config->output' should have the desired colorspace selected. 'verbose' will
|
||||
// cause decode timing to be reported.
|
||||
// Returns the decoder status. On success 'config->output' will contain the
|
||||
// decoded picture.
|
||||
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
|
||||
int verbose, WebPDecoderConfig* const config);
|
||||
|
||||
// Same as ExUtilDecodeWebP(), but using the incremental decoder.
|
||||
VP8StatusCode ExUtilDecodeWebPIncremental(
|
||||
const uint8_t* const data, size_t data_size,
|
||||
int verbose, WebPDecoderConfig* const config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
136
imageio/imageio_util.c
Normal file
136
imageio/imageio_util.c
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Utility functions used by the image decoders.
|
||||
//
|
||||
|
||||
#include "./imageio_util.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <fcntl.h> // for _O_BINARY
|
||||
#include <io.h> // for _setmode()
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// File I/O
|
||||
|
||||
FILE* ExUtilSetBinaryMode(FILE* file) {
|
||||
#if defined(_WIN32)
|
||||
if (_setmode(_fileno(file), _O_BINARY) == -1) {
|
||||
fprintf(stderr, "Failed to reopen file in O_BINARY mode.\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return file;
|
||||
}
|
||||
|
||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size) {
|
||||
static const size_t kBlockSize = 16384; // default initial size
|
||||
size_t max_size = 0;
|
||||
size_t size = 0;
|
||||
uint8_t* input = NULL;
|
||||
|
||||
if (data == NULL || data_size == NULL) return 0;
|
||||
*data = NULL;
|
||||
*data_size = 0;
|
||||
|
||||
if (!ExUtilSetBinaryMode(stdin)) return 0;
|
||||
|
||||
while (!feof(stdin)) {
|
||||
// We double the buffer size each time and read as much as possible.
|
||||
const size_t extra_size = (max_size == 0) ? kBlockSize : max_size;
|
||||
void* const new_data = realloc(input, max_size + extra_size);
|
||||
if (new_data == NULL) goto Error;
|
||||
input = (uint8_t*)new_data;
|
||||
max_size += extra_size;
|
||||
size += fread(input + size, 1, extra_size, stdin);
|
||||
if (size < max_size) break;
|
||||
}
|
||||
if (ferror(stdin)) goto Error;
|
||||
*data = input;
|
||||
*data_size = size;
|
||||
return 1;
|
||||
|
||||
Error:
|
||||
free(input);
|
||||
fprintf(stderr, "Could not read from stdin\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExUtilReadFile(const char* const file_name,
|
||||
const uint8_t** data, size_t* data_size) {
|
||||
int ok;
|
||||
void* file_data;
|
||||
size_t file_size;
|
||||
FILE* in;
|
||||
const int from_stdin = (file_name == NULL) || !strcmp(file_name, "-");
|
||||
|
||||
if (from_stdin) return ExUtilReadFromStdin(data, data_size);
|
||||
|
||||
if (data == NULL || data_size == NULL) return 0;
|
||||
*data = NULL;
|
||||
*data_size = 0;
|
||||
|
||||
in = fopen(file_name, "rb");
|
||||
if (in == NULL) {
|
||||
fprintf(stderr, "cannot open input file '%s'\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
fseek(in, 0, SEEK_END);
|
||||
file_size = ftell(in);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
file_data = malloc(file_size);
|
||||
if (file_data == NULL) return 0;
|
||||
ok = (fread(file_data, file_size, 1, in) == 1);
|
||||
fclose(in);
|
||||
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Could not read %d bytes of data from file %s\n",
|
||||
(int)file_size, file_name);
|
||||
free(file_data);
|
||||
return 0;
|
||||
}
|
||||
*data = (uint8_t*)file_data;
|
||||
*data_size = file_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ExUtilWriteFile(const char* const file_name,
|
||||
const uint8_t* data, size_t data_size) {
|
||||
int ok;
|
||||
FILE* out;
|
||||
const int to_stdout = (file_name == NULL) || !strcmp(file_name, "-");
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
out = to_stdout ? stdout : fopen(file_name, "wb");
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "Error! Cannot open output file '%s'\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
ok = (fwrite(data, data_size, 1, out) == 1);
|
||||
if (out != stdout) fclose(out);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ExUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||
uint8_t* dst, int dst_stride, int width, int height) {
|
||||
while (height-- > 0) {
|
||||
memcpy(dst, src, width * sizeof(*dst));
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
56
imageio/imageio_util.h
Normal file
56
imageio/imageio_util.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the COPYING file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Utility functions used by the image decoders.
|
||||
//
|
||||
|
||||
#ifndef WEBP_IMAGEIO_IMAGEIO_UTIL_H_
|
||||
#define WEBP_IMAGEIO_IMAGEIO_UTIL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include "webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// File I/O
|
||||
|
||||
// Reopen file in binary (O_BINARY) mode.
|
||||
// Returns 'file' on success, NULL otherwise.
|
||||
FILE* ExUtilSetBinaryMode(FILE* file);
|
||||
|
||||
// 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
|
||||
// be deleted using free().
|
||||
// If 'file_name' is NULL or equal to "-", input is read from stdin by calling
|
||||
// the function ExUtilReadFromStdin().
|
||||
int ExUtilReadFile(const char* const file_name,
|
||||
const uint8_t** data, size_t* data_size);
|
||||
|
||||
// Same as ExUtilReadFile(), but reads until EOF from stdin instead.
|
||||
int ExUtilReadFromStdin(const uint8_t** data, size_t* data_size);
|
||||
|
||||
// Write a data segment into a file named 'file_name'. Returns true if ok.
|
||||
// If 'file_name' is NULL or equal to "-", output is written to stdout.
|
||||
int ExUtilWriteFile(const char* const file_name,
|
||||
const uint8_t* data, size_t data_size);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Copy width x height pixels from 'src' to 'dst' honoring the strides.
|
||||
void ExUtilCopyPlane(const uint8_t* src, int src_stride,
|
||||
uint8_t* dst, int dst_stride, int width, int height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBP_IMAGEIO_IMAGEIO_UTIL_H_
|
@ -16,9 +16,124 @@
|
||||
|
||||
#include "webp/decode.h"
|
||||
#include "webp/encode.h"
|
||||
#include "./example_util.h"
|
||||
#include "../examples/stopwatch.h"
|
||||
#include "./imageio_util.h"
|
||||
#include "./metadata.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// WebP decoding
|
||||
|
||||
static const char* const kStatusMessages[VP8_STATUS_NOT_ENOUGH_DATA + 1] = {
|
||||
"OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
|
||||
"UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
|
||||
};
|
||||
|
||||
static void PrintAnimationWarning(const WebPDecoderConfig* const config) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
WebPBitstreamFeatures local_features;
|
||||
if (!ExUtilReadFile(in_file, data, data_size)) return 0;
|
||||
|
||||
if (bitstream == NULL) {
|
||||
bitstream = &local_features;
|
||||
}
|
||||
|
||||
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 verbose, WebPDecoderConfig* const config) {
|
||||
Stopwatch stop_watch;
|
||||
VP8StatusCode status = VP8_STATUS_OK;
|
||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||
|
||||
PrintAnimationWarning(config);
|
||||
|
||||
StopwatchReset(&stop_watch);
|
||||
|
||||
// Decoding call.
|
||||
status = WebPDecode(data, data_size, config);
|
||||
|
||||
if (verbose) {
|
||||
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
||||
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VP8StatusCode ExUtilDecodeWebPIncremental(
|
||||
const uint8_t* const data, size_t data_size,
|
||||
int verbose, WebPDecoderConfig* const config) {
|
||||
Stopwatch stop_watch;
|
||||
VP8StatusCode status = VP8_STATUS_OK;
|
||||
if (config == NULL) return VP8_STATUS_INVALID_PARAM;
|
||||
|
||||
PrintAnimationWarning(config);
|
||||
|
||||
StopwatchReset(&stop_watch);
|
||||
|
||||
// Decoding call.
|
||||
{
|
||||
WebPIDecoder* const idec = WebPIDecode(data, data_size, config);
|
||||
if (idec == NULL) {
|
||||
fprintf(stderr, "Failed during WebPINewDecoder().\n");
|
||||
return VP8_STATUS_OUT_OF_MEMORY;
|
||||
} else {
|
||||
#ifdef WEBP_EXPERIMENTAL_FEATURES
|
||||
size_t size = 0;
|
||||
const size_t incr = 2 + (data_size / 20);
|
||||
while (size < data_size) {
|
||||
size_t next_size = size + (rand() % incr);
|
||||
if (next_size > data_size) next_size = data_size;
|
||||
status = WebPIUpdate(idec, data, next_size);
|
||||
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) break;
|
||||
size = next_size;
|
||||
}
|
||||
#else
|
||||
status = WebPIUpdate(idec, data, data_size);
|
||||
#endif
|
||||
WebPIDelete(idec);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
||||
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
int ReadWebP(const uint8_t* const data, size_t data_size,
|
||||
WebPPicture* const pic,
|
||||
int keep_alpha, Metadata* const metadata) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
#ifndef WEBP_IMAGEIO_WEBPDEC_H_
|
||||
#define WEBP_IMAGEIO_WEBPDEC_H_
|
||||
|
||||
#include "webp/types.h"
|
||||
#include "webp/decode.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -21,6 +21,37 @@ extern "C" {
|
||||
struct Metadata;
|
||||
struct WebPPicture;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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'. If not NULL, 'bitstream' is populated using WebPGetFeatures().
|
||||
// Returns true on success.
|
||||
int ExUtilLoadWebP(const char* const in_file,
|
||||
const uint8_t** data, size_t* data_size,
|
||||
WebPBitstreamFeatures* bitstream);
|
||||
|
||||
// Decodes the WebP contained in 'data'.
|
||||
// 'config' is a structure previously initialized by WebPInitDecoderConfig().
|
||||
// 'config->output' should have the desired colorspace selected. 'verbose' will
|
||||
// cause decode timing to be reported.
|
||||
// Returns the decoder status. On success 'config->output' will contain the
|
||||
// decoded picture.
|
||||
VP8StatusCode ExUtilDecodeWebP(const uint8_t* const data, size_t data_size,
|
||||
int verbose, WebPDecoderConfig* const config);
|
||||
|
||||
// Same as ExUtilDecodeWebP(), but using the incremental decoder.
|
||||
VP8StatusCode ExUtilDecodeWebPIncremental(
|
||||
const uint8_t* const data, size_t data_size,
|
||||
int verbose, WebPDecoderConfig* const config);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Reads a WebP from 'in_file', returning the decoded output in 'pic'.
|
||||
// Output is RGBA or YUVA, depending on pic->use_argb value.
|
||||
// If 'keep_alpha' is true and the WebP has an alpha channel, the output is RGBA
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <wincodec.h>
|
||||
|
||||
#include "webp/encode.h"
|
||||
#include "./example_util.h"
|
||||
#include "./imageio_util.h"
|
||||
#include "./metadata.h"
|
||||
|
||||
#define IFS(fn) \
|
||||
|
Reference in New Issue
Block a user