2012-01-06 23:49:06 +01:00
|
|
|
// Copyright 2010 Google Inc. All Rights Reserved.
|
2010-09-30 15:34:38 +02:00
|
|
|
//
|
2013-06-07 08:05:58 +02:00
|
|
|
// 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.
|
2010-09-30 15:34:38 +02:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
//
|
2013-04-02 01:10:35 +02:00
|
|
|
// Command-line tool for decoding a WebP image.
|
2010-09-30 15:34:38 +02:00
|
|
|
//
|
|
|
|
// Author: Skal (pascal.massimino@gmail.com)
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2011-06-07 02:56:50 +02:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2014-06-11 02:53:44 +02:00
|
|
|
#include "webp/config.h"
|
2011-06-07 02:56:50 +02:00
|
|
|
#endif
|
|
|
|
|
2016-07-22 01:10:05 +02:00
|
|
|
#include "../examples/example_util.h"
|
2016-09-07 07:46:31 +02:00
|
|
|
#include "../imageio/image_enc.h"
|
2016-07-21 03:25:00 +02:00
|
|
|
#include "../imageio/webpdec.h"
|
2012-05-15 22:48:11 +02:00
|
|
|
#include "./stopwatch.h"
|
2010-09-30 15:34:38 +02:00
|
|
|
|
2011-11-04 23:20:08 +01:00
|
|
|
static int verbose = 0;
|
2015-11-20 11:35:03 +01:00
|
|
|
static int quiet = 0;
|
2011-11-04 23:20:08 +01:00
|
|
|
#ifndef WEBP_DLL
|
2013-11-25 23:43:12 +01:00
|
|
|
#ifdef __cplusplus
|
2010-09-30 15:34:38 +02:00
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2011-09-02 23:30:08 +02:00
|
|
|
extern void* VP8GetCPUInfo; // opaque forward declaration.
|
2011-11-04 23:20:08 +01:00
|
|
|
|
2013-11-25 23:43:12 +01:00
|
|
|
#ifdef __cplusplus
|
2011-11-04 23:20:08 +01:00
|
|
|
} // extern "C"
|
2011-07-15 23:53:03 +02:00
|
|
|
#endif
|
2011-11-04 23:20:08 +01:00
|
|
|
#endif // WEBP_DLL
|
2011-06-11 00:10:18 +02:00
|
|
|
|
2011-02-17 00:01:27 +01:00
|
|
|
|
2013-08-19 21:09:37 +02:00
|
|
|
static int SaveOutput(const WebPDecBuffer* const buffer,
|
2016-09-07 07:46:31 +02:00
|
|
|
WebPOutputFileFormat format, const char* const out_file) {
|
|
|
|
const int use_stdout = (out_file != NULL) && !strcmp(out_file, "-");
|
2011-06-20 09:45:15 +02:00
|
|
|
int ok = 1;
|
|
|
|
Stopwatch stop_watch;
|
|
|
|
|
2013-09-12 09:32:28 +02:00
|
|
|
if (verbose) {
|
|
|
|
StopwatchReset(&stop_watch);
|
|
|
|
}
|
2016-09-07 07:46:31 +02:00
|
|
|
ok = WebPSaveImage(buffer, format, out_file);
|
2011-06-20 09:45:15 +02:00
|
|
|
|
|
|
|
if (ok) {
|
2015-11-20 11:35:03 +01:00
|
|
|
if (!quiet) {
|
|
|
|
if (use_stdout) {
|
|
|
|
fprintf(stderr, "Saved to stdout\n");
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Saved file %s\n", out_file);
|
|
|
|
}
|
2013-08-19 21:09:37 +02:00
|
|
|
}
|
2011-06-20 09:45:15 +02:00
|
|
|
if (verbose) {
|
2013-01-21 17:20:14 +01:00
|
|
|
const double write_time = StopwatchReadAndReset(&stop_watch);
|
2013-08-19 21:09:37 +02:00
|
|
|
fprintf(stderr, "Time to write output: %.3fs\n", write_time);
|
2011-06-20 09:45:15 +02:00
|
|
|
}
|
|
|
|
} else {
|
2013-08-21 00:01:23 +02:00
|
|
|
if (use_stdout) {
|
2013-08-20 02:52:33 +02:00
|
|
|
fprintf(stderr, "Error writing to stdout !!\n");
|
2013-08-21 00:01:23 +02:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Error writing file %s !!\n", out_file);
|
2013-08-19 21:09:37 +02:00
|
|
|
}
|
2011-06-20 09:45:15 +02:00
|
|
|
}
|
2013-08-19 21:09:37 +02:00
|
|
|
return ok;
|
2011-06-20 09:45:15 +02:00
|
|
|
}
|
2011-02-01 07:00:33 +01:00
|
|
|
|
2011-03-25 23:04:11 +01:00
|
|
|
static void Help(void) {
|
2011-06-20 09:45:15 +02:00
|
|
|
printf("Usage: dwebp in_file [options] [-o out_file]\n\n"
|
2011-02-01 07:00:33 +01:00
|
|
|
"Decodes the WebP image file to PNG format [Default]\n"
|
|
|
|
"Use following options to convert into alternate image formats:\n"
|
2012-07-21 01:06:06 +02:00
|
|
|
" -pam ......... save the raw RGBA samples as a color PAM\n"
|
|
|
|
" -ppm ......... save the raw RGB samples as a color PPM\n"
|
2013-04-10 03:51:59 +02:00
|
|
|
" -bmp ......... save as uncompressed BMP format\n"
|
2013-05-09 12:57:50 +02:00
|
|
|
" -tiff ........ save as uncompressed TIFF format\n"
|
2011-06-20 09:45:15 +02:00
|
|
|
" -pgm ......... save the raw YUV samples as a grayscale PGM\n"
|
2013-04-10 03:51:59 +02:00
|
|
|
" file with IMC4 layout\n"
|
|
|
|
" -yuv ......... save the raw YUV samples in flat layout\n"
|
2013-01-28 23:22:14 +01:00
|
|
|
"\n"
|
2011-06-20 09:45:15 +02:00
|
|
|
" Other options are:\n"
|
2016-06-23 16:11:47 +02:00
|
|
|
" -version ..... print version number and exit\n"
|
2014-01-16 15:48:43 +01:00
|
|
|
" -nofancy ..... don't use the fancy YUV420 upscaler\n"
|
|
|
|
" -nofilter .... disable in-loop filtering\n"
|
|
|
|
" -nodither .... disable dithering\n"
|
2013-11-26 22:59:02 +01:00
|
|
|
" -dither <d> .. dithering strength (in 0..100)\n"
|
2014-06-18 16:45:34 +02:00
|
|
|
" -alpha_dither use alpha-plane dithering if needed\n"
|
2011-07-22 22:09:10 +02:00
|
|
|
" -mt .......... use multi-threading\n"
|
2011-06-20 09:45:15 +02:00
|
|
|
" -crop <x> <y> <w> <h> ... crop output with the given rectangle\n"
|
2015-08-14 05:54:02 +02:00
|
|
|
" -resize <w> <h> ......... scale the output (*after* any cropping)\n"
|
2014-01-16 15:48:43 +01:00
|
|
|
" -flip ........ flip the output vertically\n"
|
|
|
|
" -alpha ....... only save the alpha plane\n"
|
2013-09-19 13:20:45 +02:00
|
|
|
" -incremental . use incremental decoding (useful for tests)\n"
|
2016-06-23 16:11:47 +02:00
|
|
|
" -h ........... this help message\n"
|
|
|
|
" -v ........... verbose (e.g. print encoding/decoding times)\n"
|
2015-08-18 05:07:46 +02:00
|
|
|
" -quiet ....... quiet mode, don't print anything\n"
|
2011-07-15 23:53:03 +02:00
|
|
|
#ifndef WEBP_DLL
|
2014-01-16 15:48:43 +01:00
|
|
|
" -noasm ....... disable all assembly optimizations\n"
|
2011-07-15 23:53:03 +02:00
|
|
|
#endif
|
2010-12-17 14:53:50 +01:00
|
|
|
);
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
|
2013-08-21 23:56:35 +02:00
|
|
|
static const char* const kFormatType[] = {
|
|
|
|
"unspecified", "lossy", "lossless"
|
|
|
|
};
|
|
|
|
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
static uint8_t* AllocateExternalBuffer(WebPDecoderConfig* config,
|
2016-09-07 07:46:31 +02:00
|
|
|
WebPOutputFileFormat format,
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
int use_external_memory) {
|
|
|
|
uint8_t* external_buffer = NULL;
|
|
|
|
WebPDecBuffer* const output_buffer = &config->output;
|
|
|
|
int w = config->input.width;
|
|
|
|
int h = config->input.height;
|
|
|
|
if (config->options.use_scaling) {
|
|
|
|
w = config->options.scaled_width;
|
|
|
|
h = config->options.scaled_height;
|
|
|
|
} else if (config->options.use_cropping) {
|
|
|
|
w = config->options.crop_width;
|
|
|
|
h = config->options.crop_height;
|
|
|
|
}
|
|
|
|
if (format >= RGB && format <= rgbA_4444) {
|
|
|
|
const int bpp = (format == RGB || format == BGR) ? 3
|
|
|
|
: (format == RGBA_4444 || format == rgbA_4444 ||
|
|
|
|
format == RGB_565) ? 2
|
|
|
|
: 4;
|
|
|
|
uint32_t stride = bpp * w + 7; // <- just for exercising
|
|
|
|
external_buffer = (uint8_t*)malloc(stride * h);
|
|
|
|
if (external_buffer == NULL) return NULL;
|
|
|
|
output_buffer->u.RGBA.stride = stride;
|
|
|
|
output_buffer->u.RGBA.size = stride * h;
|
|
|
|
output_buffer->u.RGBA.rgba = external_buffer;
|
|
|
|
} else { // YUV and YUVA
|
|
|
|
const int has_alpha = WebPIsAlphaMode(output_buffer->colorspace);
|
|
|
|
uint8_t* tmp;
|
|
|
|
uint32_t stride = w + 3;
|
|
|
|
uint32_t uv_stride = (w + 1) / 2 + 13;
|
|
|
|
uint32_t total_size = stride * h * (has_alpha ? 2 : 1)
|
|
|
|
+ 2 * uv_stride * (h + 1) / 2;
|
|
|
|
assert(format >= YUV && format <= YUVA);
|
|
|
|
external_buffer = (uint8_t*)malloc(total_size);
|
|
|
|
if (external_buffer == NULL) return NULL;
|
|
|
|
tmp = external_buffer;
|
|
|
|
output_buffer->u.YUVA.y = tmp;
|
|
|
|
output_buffer->u.YUVA.y_stride = stride;
|
|
|
|
output_buffer->u.YUVA.y_size = stride * h;
|
|
|
|
tmp += output_buffer->u.YUVA.y_size;
|
|
|
|
if (has_alpha) {
|
|
|
|
output_buffer->u.YUVA.a = tmp;
|
|
|
|
output_buffer->u.YUVA.a_stride = stride;
|
|
|
|
output_buffer->u.YUVA.a_size = stride * h;
|
|
|
|
tmp += output_buffer->u.YUVA.a_size;
|
|
|
|
} else {
|
|
|
|
output_buffer->u.YUVA.a = NULL;
|
|
|
|
output_buffer->u.YUVA.a_stride = 0;
|
|
|
|
}
|
|
|
|
output_buffer->u.YUVA.u = tmp;
|
|
|
|
output_buffer->u.YUVA.u_stride = uv_stride;
|
|
|
|
output_buffer->u.YUVA.u_size = uv_stride * (h + 1) / 2;
|
|
|
|
tmp += output_buffer->u.YUVA.u_size;
|
|
|
|
|
|
|
|
output_buffer->u.YUVA.v = tmp;
|
|
|
|
output_buffer->u.YUVA.v_stride = uv_stride;
|
|
|
|
output_buffer->u.YUVA.v_size = uv_stride * (h + 1) / 2;
|
|
|
|
tmp += output_buffer->u.YUVA.v_size;
|
|
|
|
assert(tmp <= external_buffer + total_size);
|
|
|
|
}
|
|
|
|
output_buffer->is_external_memory = use_external_memory;
|
|
|
|
return external_buffer;
|
|
|
|
}
|
|
|
|
|
2011-01-23 21:47:44 +01:00
|
|
|
int main(int argc, const char *argv[]) {
|
2013-08-19 21:09:37 +02:00
|
|
|
int ok = 0;
|
2010-09-30 15:34:38 +02:00
|
|
|
const char *in_file = NULL;
|
|
|
|
const char *out_file = NULL;
|
|
|
|
|
2011-06-20 09:45:15 +02:00
|
|
|
WebPDecoderConfig config;
|
|
|
|
WebPDecBuffer* const output_buffer = &config.output;
|
|
|
|
WebPBitstreamFeatures* const bitstream = &config.input;
|
2016-09-07 07:46:31 +02:00
|
|
|
WebPOutputFileFormat format = PNG;
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
uint8_t* external_buffer = NULL;
|
|
|
|
int use_external_memory = 0;
|
|
|
|
const uint8_t* data = NULL;
|
|
|
|
|
2013-09-19 13:20:45 +02:00
|
|
|
int incremental = 0;
|
2010-09-30 15:34:38 +02:00
|
|
|
int c;
|
2011-06-20 09:45:15 +02:00
|
|
|
|
|
|
|
if (!WebPInitDecoderConfig(&config)) {
|
|
|
|
fprintf(stderr, "Library version mismatch!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-09-30 15:34:38 +02:00
|
|
|
for (c = 1; c < argc; ++c) {
|
2014-09-11 08:35:48 +02:00
|
|
|
int parse_error = 0;
|
2011-02-01 07:00:33 +01:00
|
|
|
if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
2011-03-25 23:04:11 +01:00
|
|
|
Help();
|
2010-09-30 15:34:38 +02:00
|
|
|
return 0;
|
|
|
|
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
|
|
|
out_file = argv[++c];
|
EXPERIMENTAL: add support for alpha channel
This is a (minor) bitstream change: if the 'color_space' bit is set to '1'
(which is normally an undefined/invalid behaviour), we add extra data at the
end of partition #0 (so-called 'extensions')
Namely, we add the size of the extension data as 3 bytes (little-endian),
followed by a set of bits telling which extensions we're incorporating.
The data then _preceeds_ this trailing tags.
This is all experimental, and you'll need to have
'#define WEBP_EXPERIMENTAL_FEATURES' in webp/types.h to enable this code
(at your own risk! :))
Still, this hack produces almost-valid WebP file for decoders that don't
check this color_space bit. In particular, previous 'dwebp' (and for instance
Chrome) will recognize this files and decode them, but without the alpha
of course. Other decoder will just see random extra stuff at the end of
partition #0.
To experiment with the alpha-channel, you need to compile on Unix platform
and use PNGs for input/output.
If 'alpha.png' is a source with alpha channel, then you can try (on Unix):
cwebp alpha.png -o alpha.webp
dwebp alpha.webp -o test.png
cwebp now has a '-noalpha' flag to ignore any alpha information from the
source, if present.
More hacking and experimenting welcome!
Change-Id: I3c7b1fd8411c9e7a9f77690e898479ad85c52f3e
2011-04-26 01:58:04 +02:00
|
|
|
} else if (!strcmp(argv[c], "-alpha")) {
|
|
|
|
format = ALPHA_PLANE_ONLY;
|
2011-06-20 09:45:15 +02:00
|
|
|
} else if (!strcmp(argv[c], "-nofancy")) {
|
|
|
|
config.options.no_fancy_upsampling = 1;
|
|
|
|
} else if (!strcmp(argv[c], "-nofilter")) {
|
|
|
|
config.options.bypass_filtering = 1;
|
2012-07-21 01:06:06 +02:00
|
|
|
} else if (!strcmp(argv[c], "-pam")) {
|
|
|
|
format = PAM;
|
2011-02-01 07:00:33 +01:00
|
|
|
} else if (!strcmp(argv[c], "-ppm")) {
|
|
|
|
format = PPM;
|
2013-04-10 03:51:59 +02:00
|
|
|
} else if (!strcmp(argv[c], "-bmp")) {
|
|
|
|
format = BMP;
|
2013-05-09 12:57:50 +02:00
|
|
|
} else if (!strcmp(argv[c], "-tiff")) {
|
|
|
|
format = TIFF;
|
2015-08-18 05:07:46 +02:00
|
|
|
} else if (!strcmp(argv[c], "-quiet")) {
|
|
|
|
quiet = 1;
|
2011-03-25 00:17:10 +01:00
|
|
|
} else if (!strcmp(argv[c], "-version")) {
|
|
|
|
const int version = WebPGetDecoderVersion();
|
|
|
|
printf("%d.%d.%d\n",
|
2012-01-24 21:46:46 +01:00
|
|
|
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
2011-03-25 00:17:10 +01:00
|
|
|
return 0;
|
2011-02-01 07:00:33 +01:00
|
|
|
} else if (!strcmp(argv[c], "-pgm")) {
|
|
|
|
format = PGM;
|
2013-01-28 23:22:14 +01:00
|
|
|
} else if (!strcmp(argv[c], "-yuv")) {
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
format = RAW_YUV;
|
|
|
|
} else if (!strcmp(argv[c], "-pixel_format") && c < argc - 1) {
|
|
|
|
const char* const fmt = argv[++c];
|
|
|
|
if (!strcmp(fmt, "RGB")) format = RGB;
|
|
|
|
else if (!strcmp(fmt, "RGBA")) format = RGBA;
|
|
|
|
else if (!strcmp(fmt, "BGR")) format = BGR;
|
|
|
|
else if (!strcmp(fmt, "BGRA")) format = BGRA;
|
|
|
|
else if (!strcmp(fmt, "ARGB")) format = ARGB;
|
|
|
|
else if (!strcmp(fmt, "RGBA_4444")) format = RGBA_4444;
|
|
|
|
else if (!strcmp(fmt, "RGB_565")) format = RGB_565;
|
|
|
|
else if (!strcmp(fmt, "rgbA")) format = rgbA;
|
|
|
|
else if (!strcmp(fmt, "bgrA")) format = bgrA;
|
|
|
|
else if (!strcmp(fmt, "Argb")) format = Argb;
|
|
|
|
else if (!strcmp(fmt, "rgbA_4444")) format = rgbA_4444;
|
|
|
|
else if (!strcmp(fmt, "YUV")) format = YUV;
|
|
|
|
else if (!strcmp(fmt, "YUVA")) format = YUVA;
|
|
|
|
else {
|
|
|
|
fprintf(stderr, "Can't parse pixel_format %s\n", fmt);
|
|
|
|
parse_error = 1;
|
|
|
|
}
|
|
|
|
} else if (!strcmp(argv[c], "-external_memory") && c < argc - 1) {
|
|
|
|
use_external_memory = ExUtilGetInt(argv[++c], 0, &parse_error);
|
|
|
|
parse_error |= (use_external_memory > 2 || use_external_memory < 0);
|
|
|
|
if (parse_error) {
|
|
|
|
fprintf(stderr, "Can't parse 'external_memory' value %s\n", argv[c]);
|
|
|
|
}
|
2011-07-22 22:09:10 +02:00
|
|
|
} else if (!strcmp(argv[c], "-mt")) {
|
|
|
|
config.options.use_threads = 1;
|
2014-06-14 00:06:16 +02:00
|
|
|
} else if (!strcmp(argv[c], "-alpha_dither")) {
|
|
|
|
config.options.alpha_dithering_strength = 100;
|
2013-11-26 22:59:02 +01:00
|
|
|
} else if (!strcmp(argv[c], "-nodither")) {
|
|
|
|
config.options.dithering_strength = 0;
|
|
|
|
} else if (!strcmp(argv[c], "-dither") && c < argc - 1) {
|
2014-09-11 08:35:48 +02:00
|
|
|
config.options.dithering_strength =
|
|
|
|
ExUtilGetInt(argv[++c], 0, &parse_error);
|
2011-06-20 09:45:15 +02:00
|
|
|
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
|
|
|
config.options.use_cropping = 1;
|
2014-09-11 08:35:48 +02:00
|
|
|
config.options.crop_left = ExUtilGetInt(argv[++c], 0, &parse_error);
|
|
|
|
config.options.crop_top = ExUtilGetInt(argv[++c], 0, &parse_error);
|
|
|
|
config.options.crop_width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
|
|
|
config.options.crop_height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
2015-08-14 05:54:02 +02:00
|
|
|
} else if ((!strcmp(argv[c], "-scale") || !strcmp(argv[c], "-resize")) &&
|
|
|
|
c < argc - 2) { // '-scale' is left for compatibility
|
2011-06-20 09:45:15 +02:00
|
|
|
config.options.use_scaling = 1;
|
2014-09-11 08:35:48 +02:00
|
|
|
config.options.scaled_width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
|
|
|
config.options.scaled_height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
2014-01-16 15:48:43 +01:00
|
|
|
} else if (!strcmp(argv[c], "-flip")) {
|
|
|
|
config.options.flip = 1;
|
2011-02-17 00:01:27 +01:00
|
|
|
} else if (!strcmp(argv[c], "-v")) {
|
|
|
|
verbose = 1;
|
2011-07-15 23:53:03 +02:00
|
|
|
#ifndef WEBP_DLL
|
2011-06-11 00:10:18 +02:00
|
|
|
} else if (!strcmp(argv[c], "-noasm")) {
|
2011-09-02 23:30:08 +02:00
|
|
|
VP8GetCPUInfo = NULL;
|
2011-07-15 23:53:03 +02:00
|
|
|
#endif
|
2013-09-19 13:20:45 +02:00
|
|
|
} else if (!strcmp(argv[c], "-incremental")) {
|
|
|
|
incremental = 1;
|
2013-12-13 05:20:08 +01:00
|
|
|
} else if (!strcmp(argv[c], "--")) {
|
|
|
|
if (c < argc - 1) in_file = argv[++c];
|
|
|
|
break;
|
2010-09-30 15:34:38 +02:00
|
|
|
} else if (argv[c][0] == '-') {
|
2012-01-24 21:46:46 +01:00
|
|
|
fprintf(stderr, "Unknown option '%s'\n", argv[c]);
|
2011-03-25 23:04:11 +01:00
|
|
|
Help();
|
2010-09-30 15:34:38 +02:00
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
in_file = argv[c];
|
|
|
|
}
|
2014-09-11 08:35:48 +02:00
|
|
|
|
|
|
|
if (parse_error) {
|
|
|
|
Help();
|
|
|
|
return -1;
|
|
|
|
}
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (in_file == NULL) {
|
2012-01-24 21:46:46 +01:00
|
|
|
fprintf(stderr, "missing input file!!\n");
|
2011-03-25 23:04:11 +01:00
|
|
|
Help();
|
2010-09-30 15:34:38 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-08-18 05:07:46 +02:00
|
|
|
if (quiet) verbose = 0;
|
|
|
|
|
2010-09-30 15:34:38 +02:00
|
|
|
{
|
2011-06-20 09:45:15 +02:00
|
|
|
VP8StatusCode status = VP8_STATUS_OK;
|
2012-05-12 01:00:57 +02:00
|
|
|
size_t data_size = 0;
|
2016-07-22 00:53:23 +02:00
|
|
|
if (!LoadWebP(in_file, &data, &data_size, bitstream)) {
|
2014-04-29 02:22:29 +02:00
|
|
|
return -1;
|
2013-03-20 21:05:04 +01:00
|
|
|
}
|
|
|
|
|
2011-02-01 07:00:33 +01:00
|
|
|
switch (format) {
|
|
|
|
case PNG:
|
2011-06-22 03:29:30 +02:00
|
|
|
#ifdef HAVE_WINCODEC_H
|
|
|
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
2011-02-17 00:01:27 +01:00
|
|
|
#else
|
2011-06-20 09:45:15 +02:00
|
|
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB;
|
2011-02-17 00:01:27 +01:00
|
|
|
#endif
|
|
|
|
break;
|
2012-07-21 01:06:06 +02:00
|
|
|
case PAM:
|
|
|
|
output_buffer->colorspace = MODE_RGBA;
|
|
|
|
break;
|
2011-02-01 07:00:33 +01:00
|
|
|
case PPM:
|
2011-06-20 09:45:15 +02:00
|
|
|
output_buffer->colorspace = MODE_RGB; // drops alpha for PPM
|
2011-02-01 07:00:33 +01:00
|
|
|
break;
|
2013-04-10 03:51:59 +02:00
|
|
|
case BMP:
|
|
|
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
|
|
|
|
break;
|
2013-05-09 12:57:50 +02:00
|
|
|
case TIFF: // note: force pre-multiplied alpha
|
|
|
|
output_buffer->colorspace =
|
|
|
|
bitstream->has_alpha ? MODE_rgbA : MODE_RGB;
|
|
|
|
break;
|
2011-02-01 07:00:33 +01:00
|
|
|
case PGM:
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
case RAW_YUV:
|
2011-06-20 09:45:15 +02:00
|
|
|
output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV;
|
2011-02-01 07:00:33 +01:00
|
|
|
break;
|
EXPERIMENTAL: add support for alpha channel
This is a (minor) bitstream change: if the 'color_space' bit is set to '1'
(which is normally an undefined/invalid behaviour), we add extra data at the
end of partition #0 (so-called 'extensions')
Namely, we add the size of the extension data as 3 bytes (little-endian),
followed by a set of bits telling which extensions we're incorporating.
The data then _preceeds_ this trailing tags.
This is all experimental, and you'll need to have
'#define WEBP_EXPERIMENTAL_FEATURES' in webp/types.h to enable this code
(at your own risk! :))
Still, this hack produces almost-valid WebP file for decoders that don't
check this color_space bit. In particular, previous 'dwebp' (and for instance
Chrome) will recognize this files and decode them, but without the alpha
of course. Other decoder will just see random extra stuff at the end of
partition #0.
To experiment with the alpha-channel, you need to compile on Unix platform
and use PNGs for input/output.
If 'alpha.png' is a source with alpha channel, then you can try (on Unix):
cwebp alpha.png -o alpha.webp
dwebp alpha.webp -o test.png
cwebp now has a '-noalpha' flag to ignore any alpha information from the
source, if present.
More hacking and experimenting welcome!
Change-Id: I3c7b1fd8411c9e7a9f77690e898479ad85c52f3e
2011-04-26 01:58:04 +02:00
|
|
|
case ALPHA_PLANE_ONLY:
|
2011-06-20 09:45:15 +02:00
|
|
|
output_buffer->colorspace = MODE_YUVA;
|
EXPERIMENTAL: add support for alpha channel
This is a (minor) bitstream change: if the 'color_space' bit is set to '1'
(which is normally an undefined/invalid behaviour), we add extra data at the
end of partition #0 (so-called 'extensions')
Namely, we add the size of the extension data as 3 bytes (little-endian),
followed by a set of bits telling which extensions we're incorporating.
The data then _preceeds_ this trailing tags.
This is all experimental, and you'll need to have
'#define WEBP_EXPERIMENTAL_FEATURES' in webp/types.h to enable this code
(at your own risk! :))
Still, this hack produces almost-valid WebP file for decoders that don't
check this color_space bit. In particular, previous 'dwebp' (and for instance
Chrome) will recognize this files and decode them, but without the alpha
of course. Other decoder will just see random extra stuff at the end of
partition #0.
To experiment with the alpha-channel, you need to compile on Unix platform
and use PNGs for input/output.
If 'alpha.png' is a source with alpha channel, then you can try (on Unix):
cwebp alpha.png -o alpha.webp
dwebp alpha.webp -o test.png
cwebp now has a '-noalpha' flag to ignore any alpha information from the
source, if present.
More hacking and experimenting welcome!
Change-Id: I3c7b1fd8411c9e7a9f77690e898479ad85c52f3e
2011-04-26 01:58:04 +02:00
|
|
|
break;
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
// forced modes:
|
|
|
|
case RGB: output_buffer->colorspace = MODE_RGB; break;
|
|
|
|
case RGBA: output_buffer->colorspace = MODE_RGBA; break;
|
|
|
|
case BGR: output_buffer->colorspace = MODE_BGR; break;
|
|
|
|
case BGRA: output_buffer->colorspace = MODE_BGRA; break;
|
|
|
|
case ARGB: output_buffer->colorspace = MODE_ARGB; break;
|
|
|
|
case RGBA_4444: output_buffer->colorspace = MODE_RGBA_4444; break;
|
|
|
|
case RGB_565: output_buffer->colorspace = MODE_RGB_565; break;
|
|
|
|
case rgbA: output_buffer->colorspace = MODE_rgbA; break;
|
|
|
|
case bgrA: output_buffer->colorspace = MODE_bgrA; break;
|
|
|
|
case Argb: output_buffer->colorspace = MODE_Argb; break;
|
|
|
|
case rgbA_4444: output_buffer->colorspace = MODE_rgbA_4444; break;
|
|
|
|
case YUV: output_buffer->colorspace = MODE_YUV; break;
|
|
|
|
case YUVA: output_buffer->colorspace = MODE_YUVA; break;
|
|
|
|
default: goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_external_memory > 0 && format >= RGB) {
|
|
|
|
external_buffer = AllocateExternalBuffer(&config, format,
|
|
|
|
use_external_memory);
|
|
|
|
if (external_buffer == NULL) goto Exit;
|
2010-10-31 08:36:33 +01:00
|
|
|
}
|
2013-09-19 13:20:45 +02:00
|
|
|
|
2016-12-12 22:01:36 +01:00
|
|
|
{
|
|
|
|
Stopwatch stop_watch;
|
|
|
|
if (verbose) StopwatchReset(&stop_watch);
|
|
|
|
|
|
|
|
if (incremental) {
|
|
|
|
status = DecodeWebPIncremental(data, data_size, &config);
|
|
|
|
} else {
|
|
|
|
status = DecodeWebP(data, data_size, &config);
|
|
|
|
}
|
|
|
|
if (verbose) {
|
|
|
|
const double decode_time = StopwatchReadAndReset(&stop_watch);
|
|
|
|
fprintf(stderr, "Time to decode picture: %.3fs\n", decode_time);
|
|
|
|
}
|
2014-04-26 23:26:13 +02:00
|
|
|
}
|
2014-04-29 02:22:29 +02:00
|
|
|
|
2011-06-20 09:45:15 +02:00
|
|
|
ok = (status == VP8_STATUS_OK);
|
|
|
|
if (!ok) {
|
2016-07-22 00:53:23 +02:00
|
|
|
PrintWebPError(in_file, status);
|
2013-09-19 13:20:45 +02:00
|
|
|
goto Exit;
|
2011-06-20 09:45:15 +02:00
|
|
|
}
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
|
2013-08-19 21:09:37 +02:00
|
|
|
if (out_file != NULL) {
|
2015-08-18 05:07:46 +02:00
|
|
|
if (!quiet) {
|
|
|
|
fprintf(stderr, "Decoded %s. Dimensions: %d x %d %s. Format: %s. "
|
|
|
|
"Now saving...\n",
|
|
|
|
in_file, output_buffer->width, output_buffer->height,
|
|
|
|
bitstream->has_alpha ? " (with alpha)" : "",
|
|
|
|
kFormatType[bitstream->format]);
|
|
|
|
}
|
2013-08-19 21:09:37 +02:00
|
|
|
ok = SaveOutput(output_buffer, format, out_file);
|
2011-02-17 00:01:27 +01:00
|
|
|
} else {
|
2015-08-18 05:07:46 +02:00
|
|
|
if (!quiet) {
|
|
|
|
fprintf(stderr, "File %s can be decoded "
|
|
|
|
"(dimensions: %d x %d %s. Format: %s).\n",
|
|
|
|
in_file, output_buffer->width, output_buffer->height,
|
|
|
|
bitstream->has_alpha ? " (with alpha)" : "",
|
|
|
|
kFormatType[bitstream->format]);
|
|
|
|
fprintf(stderr, "Nothing written; "
|
|
|
|
"use -o flag to save the result as e.g. PNG.\n");
|
|
|
|
}
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
2013-09-19 13:20:45 +02:00
|
|
|
Exit:
|
2011-06-20 09:45:15 +02:00
|
|
|
WebPFreeDecBuffer(output_buffer);
|
add extra meaning to WebPDecBuffer::is_external_memory
If value is '2', it means the buffer is a 'slow' one, like GPU-mapped memory.
This change is backward compatible (setting is_external_memory to 2
will be a no-op in previous libraries)
dwebp: add flags to force a particular colorspace format
new flags is:
-pixel_format {RGB,RGBA,BGR,BGRA,ARGB,RGBA_4444,RGB_565,
rgbA,bgrA,Argb,rgbA_4444,YUV,YUVA}
and also,external_memory {0,1,2}
These flags are mostly for debuggging purpose, and hence are not documented.
Change-Id: Iac88ce1e10b35163dd7af57f9660f062f5d8ed5e
2016-03-09 08:58:58 +01:00
|
|
|
free((void*)external_buffer);
|
|
|
|
free((void*)data);
|
2013-08-19 21:09:37 +02:00
|
|
|
return ok ? 0 : -1;
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
|
2011-08-25 23:22:32 +02:00
|
|
|
//------------------------------------------------------------------------------
|