2010-09-30 15:34:38 +02:00
|
|
|
// Copyright 2010 Google Inc.
|
|
|
|
//
|
|
|
|
// This code is licensed under the same terms as WebM:
|
|
|
|
// Software License Agreement: http://www.webmproject.org/license/software/
|
|
|
|
// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// simple command-line example calling libwebpdecode to
|
|
|
|
// decode a WebP image into a PPM image.
|
|
|
|
//
|
|
|
|
// Compile with: gcc -o dwebp dwebp.c -lwebpdecode
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-02-01 07:00:33 +01:00
|
|
|
#ifdef WEBP_HAVE_PNG
|
|
|
|
#include <png.h>
|
|
|
|
#endif
|
|
|
|
|
2011-06-07 02:56:50 +02:00
|
|
|
#ifdef HAVE_WINCODEC_H
|
|
|
|
#ifdef __MINGW32__
|
|
|
|
#define INITGUID // Without this GUIDs are declared extern and fail to link
|
|
|
|
#endif
|
2011-02-17 00:01:27 +01:00
|
|
|
#define CINTERFACE
|
|
|
|
#define COBJMACROS
|
|
|
|
#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++
|
|
|
|
// code with COBJMACROS.
|
|
|
|
#include <shlwapi.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#include <wincodec.h>
|
|
|
|
#endif
|
|
|
|
|
2010-09-30 15:34:38 +02:00
|
|
|
#include "webp/decode.h"
|
2011-02-17 00:01:27 +01:00
|
|
|
#include "stopwatch.h"
|
2010-09-30 15:34:38 +02:00
|
|
|
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2011-02-17 00:01:27 +01:00
|
|
|
static int verbose = 0;
|
|
|
|
|
2011-06-07 02:56:50 +02:00
|
|
|
#ifdef HAVE_WINCODEC_H
|
2011-02-17 00:01:27 +01:00
|
|
|
|
|
|
|
#define IFS(fn) \
|
|
|
|
do { \
|
|
|
|
if (SUCCEEDED(hr)) \
|
|
|
|
{ \
|
|
|
|
hr = (fn); \
|
|
|
|
if (FAILED(hr) && verbose) \
|
|
|
|
printf(#fn " failed %08x\n", hr); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
#define MAKE_REFGUID(x) (x)
|
|
|
|
#else
|
|
|
|
#define MAKE_REFGUID(x) &(x)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static HRESULT CreateOutputStream(const char* out_file_name, IStream** ppStream) {
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, ppStream));
|
|
|
|
if (FAILED(hr))
|
|
|
|
printf("Error opening output file %s (%08x)\n", out_file_name, hr);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WriteUsingWIC(const char* out_file_name, REFGUID container_guid,
|
|
|
|
unsigned char* rgb, int stride,
|
|
|
|
uint32_t width, uint32_t height) {
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
IWICImagingFactory* pFactory = NULL;
|
|
|
|
IWICBitmapFrameEncode* pFrame = NULL;
|
|
|
|
IWICBitmapEncoder* pEncoder = NULL;
|
|
|
|
IStream* pStream = NULL;
|
|
|
|
GUID pixel_format = GUID_WICPixelFormat24bppBGR;
|
|
|
|
|
|
|
|
IFS(CoInitialize(NULL));
|
|
|
|
IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL,
|
|
|
|
CLSCTX_INPROC_SERVER, MAKE_REFGUID(IID_IWICImagingFactory),
|
|
|
|
(LPVOID*)&pFactory));
|
|
|
|
if (hr == REGDB_E_CLASSNOTREG) {
|
|
|
|
printf("Couldn't access Windows Imaging Component (are you running \n");
|
|
|
|
printf("Windows XP SP3 or newer?). PNG support not available.\n");
|
|
|
|
printf("Use -ppm or -pgm for available PPM and PGM formats.\n");
|
|
|
|
}
|
|
|
|
IFS(CreateOutputStream(out_file_name, &pStream));
|
|
|
|
IFS(IWICImagingFactory_CreateEncoder(pFactory, container_guid, NULL,
|
|
|
|
&pEncoder));
|
2011-02-18 19:26:42 +01:00
|
|
|
IFS(IWICBitmapEncoder_Initialize(pEncoder, pStream,
|
|
|
|
WICBitmapEncoderNoCache));
|
2011-02-17 00:01:27 +01:00
|
|
|
IFS(IWICBitmapEncoder_CreateNewFrame(pEncoder, &pFrame, NULL));
|
|
|
|
IFS(IWICBitmapFrameEncode_Initialize(pFrame, NULL));
|
|
|
|
IFS(IWICBitmapFrameEncode_SetSize(pFrame, width, height));
|
|
|
|
IFS(IWICBitmapFrameEncode_SetPixelFormat(pFrame, &pixel_format));
|
|
|
|
IFS(IWICBitmapFrameEncode_WritePixels(pFrame, height, stride,
|
|
|
|
height * stride, rgb));
|
|
|
|
IFS(IWICBitmapFrameEncode_Commit(pFrame));
|
|
|
|
IFS(IWICBitmapEncoder_Commit(pEncoder));
|
|
|
|
|
|
|
|
if (pFrame != NULL) IUnknown_Release(pFrame);
|
|
|
|
if (pEncoder != NULL) IUnknown_Release(pEncoder);
|
|
|
|
if (pFactory != NULL) IUnknown_Release(pFactory);
|
|
|
|
if (pStream != NULL) IUnknown_Release(pStream);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int WritePNG(const char* out_file_name, unsigned char* rgb, int stride,
|
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
|
|
|
uint32_t width, uint32_t height, int has_alpha) {
|
|
|
|
assert(!has_alpha); // TODO(mikolaj)
|
2011-02-17 00:01:27 +01:00
|
|
|
return SUCCEEDED(WriteUsingWIC(out_file_name,
|
|
|
|
MAKE_REFGUID(GUID_ContainerFormatPng), rgb, stride, width,
|
|
|
|
height));
|
|
|
|
}
|
|
|
|
|
2011-06-07 02:56:50 +02:00
|
|
|
#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H
|
2011-02-01 07:00:33 +01:00
|
|
|
static void PNGAPI error_function(png_structp png, png_const_charp dummy) {
|
2011-03-25 23:04:11 +01:00
|
|
|
(void)dummy; // remove variable-unused warning
|
2011-02-01 07:00:33 +01:00
|
|
|
longjmp(png_jmpbuf(png), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int WritePNG(FILE* out_file, unsigned char* rgb, int stride,
|
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
|
|
|
png_uint_32 width, png_uint_32 height, int has_alpha) {
|
2011-02-01 07:00:33 +01:00
|
|
|
png_structp png;
|
|
|
|
png_infop info;
|
2011-03-25 23:04:11 +01:00
|
|
|
png_uint_32 y;
|
2011-02-01 07:00:33 +01:00
|
|
|
|
|
|
|
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
|
|
|
NULL, error_function, NULL);
|
|
|
|
if (png == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
info = png_create_info_struct(png);
|
|
|
|
if (info == NULL) {
|
|
|
|
png_destroy_write_struct(&png, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (setjmp(png_jmpbuf(png))) {
|
|
|
|
png_destroy_write_struct(&png, &info);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
png_init_io(png, out_file);
|
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
|
|
|
png_set_IHDR(png, info, width, height, 8,
|
|
|
|
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
|
2011-02-01 07:00:33 +01:00
|
|
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
|
|
|
PNG_FILTER_TYPE_DEFAULT);
|
|
|
|
png_write_info(png, info);
|
|
|
|
for (y = 0; y < height; ++y) {
|
|
|
|
png_bytep row = rgb + y * stride;
|
|
|
|
png_write_rows(png, &row, 1);
|
|
|
|
}
|
|
|
|
png_write_end(png, info);
|
|
|
|
png_destroy_write_struct(&png, &info);
|
|
|
|
return 1;
|
|
|
|
}
|
2011-06-07 02:56:50 +02:00
|
|
|
#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG
|
2011-02-01 07:00:33 +01:00
|
|
|
|
|
|
|
typedef uint32_t png_uint_32;
|
|
|
|
|
|
|
|
static int WritePNG(FILE* out_file, unsigned char* rgb, int stride,
|
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
|
|
|
png_uint_32 width, png_uint_32 height, int has_alpha) {
|
2011-02-17 00:01:27 +01:00
|
|
|
printf("PNG support not compiled. Please install the libpng development "
|
|
|
|
"package before building.\n");
|
2011-02-01 07:00:33 +01:00
|
|
|
printf("You can run with -ppm flag to decode in PPM format.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
static int WritePPM(FILE* fout, const unsigned char* rgb,
|
2011-02-17 00:01:27 +01:00
|
|
|
uint32_t width, uint32_t height) {
|
|
|
|
fprintf(fout, "P6\n%d %d\n255\n", width, height);
|
|
|
|
return (fwrite(rgb, width * height, 3, fout) == 3);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static int WriteAlphaPlane(FILE* fout, const unsigned char* rgba,
|
|
|
|
uint32_t width, uint32_t height) {
|
|
|
|
uint32_t y;
|
|
|
|
fprintf(fout, "P5\n%d %d\n255\n", width, height);
|
|
|
|
for (y = 0; y < height; ++y) {
|
|
|
|
const unsigned char* line = rgba + y * (width * 4);
|
|
|
|
uint32_t x;
|
|
|
|
for (x = 0; x < width; ++x) {
|
|
|
|
if (fputc(line[4 * x + 3], fout) == EOF) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-02-17 00:01:27 +01:00
|
|
|
static int WritePGM(FILE* fout,
|
|
|
|
unsigned char* y_plane, unsigned char *u, unsigned char* v,
|
|
|
|
int y_stride, int uv_stride,
|
|
|
|
uint32_t width, uint32_t height) {
|
|
|
|
// Save a grayscale PGM file using the IMC4 layout
|
|
|
|
// (http://www.fourcc.org/yuv.php#IMC4). This is a very
|
|
|
|
// convenient format for viewing the samples, esp. for
|
|
|
|
// odd dimensions.
|
|
|
|
int ok = 1;
|
|
|
|
unsigned int y;
|
|
|
|
const unsigned int uv_width = (width + 1) / 2;
|
|
|
|
const unsigned int uv_height = (height + 1) / 2;
|
|
|
|
const unsigned int out_stride = (width + 1) & ~1;
|
|
|
|
fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height);
|
|
|
|
for (y = 0; ok && y < height; ++y) {
|
|
|
|
ok &= (fwrite(y_plane + y * y_stride, width, 1, fout) == 1);
|
|
|
|
if (width & 1) fputc(0, fout); // padding byte
|
|
|
|
}
|
|
|
|
for (y = 0; ok && y < uv_height; ++y) {
|
|
|
|
ok &= (fwrite(u + y * uv_stride, uv_width, 1, fout) == 1);
|
|
|
|
ok &= (fwrite(v + y * uv_stride, uv_width, 1, fout) == 1);
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2011-02-01 07:00:33 +01:00
|
|
|
typedef enum {
|
|
|
|
PNG = 0,
|
|
|
|
PPM,
|
|
|
|
PGM,
|
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
|
|
|
ALPHA_PLANE_ONLY // this is for experimenting only
|
2011-02-01 07:00:33 +01:00
|
|
|
} OutputFileFormat;
|
|
|
|
|
2011-03-25 23:04:11 +01:00
|
|
|
static void Help(void) {
|
2010-09-30 15:34:38 +02:00
|
|
|
printf("Usage: dwebp "
|
2011-03-25 00:17:10 +01:00
|
|
|
"[in_file] [-h] [-v] [-ppm] [-pgm] [-version] [-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"
|
|
|
|
" -ppm: save the raw RGB samples as color PPM\n"
|
|
|
|
" -pgm: save the raw YUV samples as a grayscale PGM\n"
|
2011-01-03 20:05:13 +01:00
|
|
|
" file with IMC4 layout.\n"
|
2011-03-25 00:17:10 +01:00
|
|
|
" -version: print version number and exit.\n"
|
2011-02-17 00:01:27 +01:00
|
|
|
"Use -v for verbose (e.g. print encoding/decoding times)\n"
|
2010-12-17 14:53:50 +01:00
|
|
|
);
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
|
2011-01-23 21:47:44 +01:00
|
|
|
int main(int argc, const char *argv[]) {
|
2010-09-30 15:34:38 +02:00
|
|
|
const char *in_file = NULL;
|
|
|
|
const char *out_file = NULL;
|
|
|
|
|
2010-10-31 08:36:33 +01:00
|
|
|
int width, height, stride, uv_stride;
|
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
|
|
|
int has_alpha = 0;
|
2010-10-31 08:36:33 +01:00
|
|
|
uint8_t* out = NULL, *u = NULL, *v = NULL;
|
2011-02-01 07:00:33 +01:00
|
|
|
OutputFileFormat format = PNG;
|
2011-02-17 00:01:27 +01:00
|
|
|
Stopwatch stop_watch;
|
2010-09-30 15:34:38 +02:00
|
|
|
int c;
|
|
|
|
for (c = 1; c < argc; ++c) {
|
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-02-01 07:00:33 +01:00
|
|
|
} else if (!strcmp(argv[c], "-ppm")) {
|
|
|
|
format = PPM;
|
2011-03-25 00:17:10 +01:00
|
|
|
} else if (!strcmp(argv[c], "-version")) {
|
|
|
|
const int version = WebPGetDecoderVersion();
|
|
|
|
printf("%d.%d.%d\n",
|
|
|
|
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff);
|
|
|
|
return 0;
|
2011-02-01 07:00:33 +01:00
|
|
|
} else if (!strcmp(argv[c], "-pgm")) {
|
|
|
|
format = PGM;
|
2011-02-17 00:01:27 +01:00
|
|
|
} else if (!strcmp(argv[c], "-v")) {
|
|
|
|
verbose = 1;
|
2010-09-30 15:34:38 +02:00
|
|
|
} else if (argv[c][0] == '-') {
|
|
|
|
printf("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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in_file == NULL) {
|
|
|
|
printf("missing input file!!\n");
|
2011-03-25 23:04:11 +01:00
|
|
|
Help();
|
2010-09-30 15:34:38 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2010-10-31 08:36:33 +01:00
|
|
|
uint32_t data_size = 0;
|
|
|
|
void* data = NULL;
|
2011-02-17 00:01:27 +01:00
|
|
|
int ok;
|
2010-09-30 15:34:38 +02:00
|
|
|
FILE* const in = fopen(in_file, "rb");
|
|
|
|
if (!in) {
|
2011-02-17 00:01:27 +01:00
|
|
|
fprintf(stderr, "cannot open input file '%s'\n", in_file);
|
2010-09-30 15:34:38 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
fseek(in, 0, SEEK_END);
|
|
|
|
data_size = ftell(in);
|
|
|
|
fseek(in, 0, SEEK_SET);
|
|
|
|
data = malloc(data_size);
|
2011-02-17 00:01:27 +01:00
|
|
|
ok = (fread(data, data_size, 1, in) == 1);
|
2010-09-30 15:34:38 +02:00
|
|
|
fclose(in);
|
|
|
|
if (!ok) {
|
|
|
|
free(data);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-02-17 00:01:27 +01:00
|
|
|
if (verbose)
|
|
|
|
StopwatchReadAndReset(&stop_watch);
|
2011-02-01 07:00:33 +01:00
|
|
|
switch (format) {
|
|
|
|
case PNG:
|
2011-02-17 00:01:27 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
out = WebPDecodeBGR((const uint8_t*)data, data_size, &width, &height);
|
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
|
|
|
stride = 3 * width;
|
|
|
|
has_alpha = 0;
|
2011-02-17 00:01:27 +01:00
|
|
|
#else
|
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
|
|
|
out = WebPDecodeRGBA((const uint8_t*)data, data_size, &width, &height);
|
|
|
|
stride = 4 * width;
|
|
|
|
has_alpha = 1;
|
2011-02-17 00:01:27 +01:00
|
|
|
#endif
|
|
|
|
break;
|
2011-02-01 07:00:33 +01:00
|
|
|
case PPM:
|
|
|
|
out = WebPDecodeRGB((const uint8_t*)data, data_size, &width, &height);
|
|
|
|
break;
|
|
|
|
case PGM:
|
|
|
|
out = WebPDecodeYUV((const uint8_t*)data, data_size, &width, &height,
|
|
|
|
&u, &v, &stride, &uv_stride);
|
|
|
|
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:
|
|
|
|
out = WebPDecodeRGBA((const uint8_t*)data, data_size, &width, &height);
|
|
|
|
break;
|
2011-02-01 07:00:33 +01:00
|
|
|
default:
|
|
|
|
free(data);
|
|
|
|
return -1;
|
2010-10-31 08:36:33 +01:00
|
|
|
}
|
2011-02-01 07:00:33 +01:00
|
|
|
|
2011-02-17 00:01:27 +01:00
|
|
|
if (verbose) {
|
|
|
|
const double time = StopwatchReadAndReset(&stop_watch);
|
|
|
|
printf("Time to decode picture: %.3fs\n", time);
|
|
|
|
}
|
|
|
|
|
2010-10-31 08:36:33 +01:00
|
|
|
free(data);
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!out) {
|
2011-02-17 00:01:27 +01:00
|
|
|
fprintf(stderr, "Decoding of %s failed.\n", in_file);
|
2010-09-30 15:34:38 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (out_file) {
|
2011-02-17 00:01:27 +01:00
|
|
|
FILE* fout = NULL;
|
|
|
|
int needs_open_file = 0;
|
2011-02-18 19:26:42 +01:00
|
|
|
|
|
|
|
printf("Decoded %s. Dimensions: %d x %d. Now saving...\n", in_file, width, height);
|
2011-02-17 00:01:27 +01:00
|
|
|
StopwatchReadAndReset(&stop_watch);
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (format != PNG) {
|
|
|
|
needs_open_file = 1;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
needs_open_file = 1;
|
|
|
|
#endif
|
|
|
|
if (needs_open_file) fout = fopen(out_file, "wb");
|
|
|
|
if (!needs_open_file || fout) {
|
2010-12-17 14:53:50 +01:00
|
|
|
int ok = 1;
|
2011-02-01 07:00:33 +01:00
|
|
|
if (format == PNG) {
|
2011-06-07 02:56:50 +02:00
|
|
|
#ifdef HAVE_WINCODEC_H
|
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
|
|
|
ok &= WritePNG(out_file, out, stride, width, height, has_alpha);
|
2011-02-17 00:01:27 +01:00
|
|
|
#else
|
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
|
|
|
ok &= WritePNG(fout, out, stride, width, height, has_alpha);
|
2011-02-17 00:01:27 +01:00
|
|
|
#endif
|
2011-02-01 07:00:33 +01:00
|
|
|
} else if (format == PPM) {
|
2011-02-17 00:01:27 +01:00
|
|
|
ok &= WritePPM(fout, out, width, height);
|
2011-02-01 07:00:33 +01:00
|
|
|
} else if (format == PGM) {
|
2011-02-17 00:01:27 +01:00
|
|
|
ok &= WritePGM(fout, out, u, v, stride, uv_stride, width, height);
|
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 (format == ALPHA_PLANE_ONLY) {
|
|
|
|
ok &= WriteAlphaPlane(fout, out, width, height);
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
2011-02-17 00:01:27 +01:00
|
|
|
if (fout)
|
|
|
|
fclose(fout);
|
2010-12-17 14:53:50 +01:00
|
|
|
if (ok) {
|
|
|
|
printf("Saved file %s\n", out_file);
|
2011-02-17 00:01:27 +01:00
|
|
|
if (verbose) {
|
|
|
|
const double time = StopwatchReadAndReset(&stop_watch);
|
|
|
|
printf("Time to write output: %.3fs\n", time);
|
|
|
|
}
|
2010-12-17 14:53:50 +01:00
|
|
|
} else {
|
2011-02-17 00:01:27 +01:00
|
|
|
fprintf(stderr, "Error writing file %s !!\n", out_file);
|
2010-12-17 14:53:50 +01:00
|
|
|
}
|
2010-09-30 15:34:38 +02:00
|
|
|
} else {
|
2011-02-17 00:01:27 +01:00
|
|
|
fprintf(stderr, "Error opening output file %s\n", out_file);
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
2011-02-17 00:01:27 +01:00
|
|
|
} else {
|
|
|
|
printf("File %s can be decoded (dimensions: %d x %d).\n",
|
|
|
|
in_file, width, height);
|
|
|
|
printf("Nothing written; use -o flag to save the result as e.g. PNG.\n");
|
2010-09-30 15:34:38 +02:00
|
|
|
}
|
|
|
|
free(out);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
|
|
} // extern "C"
|
|
|
|
#endif
|