10406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Copyright 2010 Google Inc. All Rights Reserved. 29aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license 40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source 50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found 60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may 70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree. 89aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// ----------------------------------------------------------------------------- 99aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 100406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Command-line tool for decoding a WebP image. 119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 129aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Author: Skal (pascal.massimino@gmail.com) 139aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <assert.h> 159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <stdio.h> 169aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <stdlib.h> 179aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include <string.h> 189aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 190406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef HAVE_CONFIG_H 200406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include "config.h" 210406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 220406ce1417f76f2034833414dcecc9f56253640cVikas Arora 230406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_HAVE_PNG 240406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include <png.h> 250406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 260406ce1417f76f2034833414dcecc9f56253640cVikas Arora 270406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef HAVE_WINCODEC_H 280406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef __MINGW32__ 290406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define INITGUID // Without this GUIDs are declared extern and fail to link 300406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 310406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define CINTERFACE 320406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define COBJMACROS 330406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define _WIN32_IE 0x500 // Workaround bug in shlwapi.h when compiling C++ 340406ce1417f76f2034833414dcecc9f56253640cVikas Arora // code with COBJMACROS. 350406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include <shlwapi.h> 360406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include <windows.h> 370406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include <wincodec.h> 380406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 390406ce1417f76f2034833414dcecc9f56253640cVikas Arora 409aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#include "webp/decode.h" 410406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include "./example_util.h" 420406ce1417f76f2034833414dcecc9f56253640cVikas Arora#include "./stopwatch.h" 439aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 440406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int verbose = 0; 450406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifndef WEBP_DLL 469aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 479aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern "C" { 489aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 499aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 500406ce1417f76f2034833414dcecc9f56253640cVikas Aroraextern void* VP8GetCPUInfo; // opaque forward declaration. 510406ce1417f76f2034833414dcecc9f56253640cVikas Arora 520406ce1417f76f2034833414dcecc9f56253640cVikas Arora#if defined(__cplusplus) || defined(c_plusplus) 530406ce1417f76f2034833414dcecc9f56253640cVikas Arora} // extern "C" 540406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 550406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif // WEBP_DLL 560406ce1417f76f2034833414dcecc9f56253640cVikas Arora 570406ce1417f76f2034833414dcecc9f56253640cVikas Arora//------------------------------------------------------------------------------ 580406ce1417f76f2034833414dcecc9f56253640cVikas Arora 590406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Output types 600406ce1417f76f2034833414dcecc9f56253640cVikas Aroratypedef enum { 610406ce1417f76f2034833414dcecc9f56253640cVikas Arora PNG = 0, 620406ce1417f76f2034833414dcecc9f56253640cVikas Arora PAM, 630406ce1417f76f2034833414dcecc9f56253640cVikas Arora PPM, 640406ce1417f76f2034833414dcecc9f56253640cVikas Arora PGM, 650406ce1417f76f2034833414dcecc9f56253640cVikas Arora YUV, 660406ce1417f76f2034833414dcecc9f56253640cVikas Arora ALPHA_PLANE_ONLY // this is for experimenting only 670406ce1417f76f2034833414dcecc9f56253640cVikas Arora} OutputFileFormat; 680406ce1417f76f2034833414dcecc9f56253640cVikas Arora 690406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef HAVE_WINCODEC_H 700406ce1417f76f2034833414dcecc9f56253640cVikas Arora 710406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define IFS(fn) \ 720406ce1417f76f2034833414dcecc9f56253640cVikas Arora do { \ 730406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (SUCCEEDED(hr)) { \ 740406ce1417f76f2034833414dcecc9f56253640cVikas Arora hr = (fn); \ 750406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (FAILED(hr)) fprintf(stderr, #fn " failed %08lx\n", hr); \ 760406ce1417f76f2034833414dcecc9f56253640cVikas Arora } \ 770406ce1417f76f2034833414dcecc9f56253640cVikas Arora } while (0) 780406ce1417f76f2034833414dcecc9f56253640cVikas Arora 790406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef __cplusplus 800406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define MAKE_REFGUID(x) (x) 810406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else 820406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define MAKE_REFGUID(x) &(x) 830406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 840406ce1417f76f2034833414dcecc9f56253640cVikas Arora 850406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic HRESULT CreateOutputStream(const char* out_file_name, IStream** stream) { 860406ce1417f76f2034833414dcecc9f56253640cVikas Arora HRESULT hr = S_OK; 870406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(SHCreateStreamOnFileA(out_file_name, STGM_WRITE | STGM_CREATE, stream)); 880406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (FAILED(hr)) { 890406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Error opening output file %s (%08lx)\n", 900406ce1417f76f2034833414dcecc9f56253640cVikas Arora out_file_name, hr); 910406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 920406ce1417f76f2034833414dcecc9f56253640cVikas Arora return hr; 930406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 940406ce1417f76f2034833414dcecc9f56253640cVikas Arora 950406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic HRESULT WriteUsingWIC(const char* out_file_name, REFGUID container_guid, 960406ce1417f76f2034833414dcecc9f56253640cVikas Arora unsigned char* rgb, int stride, 970406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint32_t width, uint32_t height, int has_alpha) { 980406ce1417f76f2034833414dcecc9f56253640cVikas Arora HRESULT hr = S_OK; 990406ce1417f76f2034833414dcecc9f56253640cVikas Arora IWICImagingFactory* factory = NULL; 1000406ce1417f76f2034833414dcecc9f56253640cVikas Arora IWICBitmapFrameEncode* frame = NULL; 1010406ce1417f76f2034833414dcecc9f56253640cVikas Arora IWICBitmapEncoder* encoder = NULL; 1020406ce1417f76f2034833414dcecc9f56253640cVikas Arora IStream* stream = NULL; 1030406ce1417f76f2034833414dcecc9f56253640cVikas Arora WICPixelFormatGUID pixel_format = has_alpha ? GUID_WICPixelFormat32bppBGRA 1040406ce1417f76f2034833414dcecc9f56253640cVikas Arora : GUID_WICPixelFormat24bppBGR; 1050406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1060406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(CoInitialize(NULL)); 1070406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(CoCreateInstance(MAKE_REFGUID(CLSID_WICImagingFactory), NULL, 1080406ce1417f76f2034833414dcecc9f56253640cVikas Arora CLSCTX_INPROC_SERVER, 1090406ce1417f76f2034833414dcecc9f56253640cVikas Arora MAKE_REFGUID(IID_IWICImagingFactory), 1100406ce1417f76f2034833414dcecc9f56253640cVikas Arora (LPVOID*)&factory)); 1110406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (hr == REGDB_E_CLASSNOTREG) { 1120406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, 1130406ce1417f76f2034833414dcecc9f56253640cVikas Arora "Couldn't access Windows Imaging Component (are you running " 1140406ce1417f76f2034833414dcecc9f56253640cVikas Arora "Windows XP SP3 or newer?). PNG support not available. " 1150406ce1417f76f2034833414dcecc9f56253640cVikas Arora "Use -ppm or -pgm for available PPM and PGM formats.\n"); 1160406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 1170406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(CreateOutputStream(out_file_name, &stream)); 1180406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICImagingFactory_CreateEncoder(factory, container_guid, NULL, 1190406ce1417f76f2034833414dcecc9f56253640cVikas Arora &encoder)); 1200406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapEncoder_Initialize(encoder, stream, 1210406ce1417f76f2034833414dcecc9f56253640cVikas Arora WICBitmapEncoderNoCache)); 1220406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapEncoder_CreateNewFrame(encoder, &frame, NULL)); 1230406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapFrameEncode_Initialize(frame, NULL)); 1240406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapFrameEncode_SetSize(frame, width, height)); 1250406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapFrameEncode_SetPixelFormat(frame, &pixel_format)); 1260406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapFrameEncode_WritePixels(frame, height, stride, 1270406ce1417f76f2034833414dcecc9f56253640cVikas Arora height * stride, rgb)); 1280406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapFrameEncode_Commit(frame)); 1290406ce1417f76f2034833414dcecc9f56253640cVikas Arora IFS(IWICBitmapEncoder_Commit(encoder)); 1300406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1310406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (frame != NULL) IUnknown_Release(frame); 1320406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (encoder != NULL) IUnknown_Release(encoder); 1330406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (factory != NULL) IUnknown_Release(factory); 1340406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (stream != NULL) IUnknown_Release(stream); 1350406ce1417f76f2034833414dcecc9f56253640cVikas Arora return hr; 1360406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1370406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1380406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int WritePNG(const char* out_file_name, 1390406ce1417f76f2034833414dcecc9f56253640cVikas Arora const WebPDecBuffer* const buffer) { 1400406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t width = buffer->width; 1410406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t height = buffer->height; 1420406ce1417f76f2034833414dcecc9f56253640cVikas Arora unsigned char* const rgb = buffer->u.RGBA.rgba; 1430406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int stride = buffer->u.RGBA.stride; 1440406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int has_alpha = (buffer->colorspace == MODE_BGRA); 1450406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1460406ce1417f76f2034833414dcecc9f56253640cVikas Arora return SUCCEEDED(WriteUsingWIC(out_file_name, 1470406ce1417f76f2034833414dcecc9f56253640cVikas Arora MAKE_REFGUID(GUID_ContainerFormatPng), 1480406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb, stride, width, height, has_alpha)); 1490406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1500406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1510406ce1417f76f2034833414dcecc9f56253640cVikas Arora#elif defined(WEBP_HAVE_PNG) // !HAVE_WINCODEC_H 1520406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void PNGAPI error_function(png_structp png, png_const_charp dummy) { 1530406ce1417f76f2034833414dcecc9f56253640cVikas Arora (void)dummy; // remove variable-unused warning 1540406ce1417f76f2034833414dcecc9f56253640cVikas Arora longjmp(png_jmpbuf(png), 1); 1550406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1560406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1570406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { 1580406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t width = buffer->width; 1590406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t height = buffer->height; 1600406ce1417f76f2034833414dcecc9f56253640cVikas Arora unsigned char* const rgb = buffer->u.RGBA.rgba; 1610406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int stride = buffer->u.RGBA.stride; 1620406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int has_alpha = (buffer->colorspace == MODE_RGBA); 1630406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_structp png; 1640406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_infop info; 1650406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_uint_32 y; 1660406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1670406ce1417f76f2034833414dcecc9f56253640cVikas Arora png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 1680406ce1417f76f2034833414dcecc9f56253640cVikas Arora NULL, error_function, NULL); 1690406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (png == NULL) { 1700406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 1710406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 1720406ce1417f76f2034833414dcecc9f56253640cVikas Arora info = png_create_info_struct(png); 1730406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (info == NULL) { 1740406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_destroy_write_struct(&png, NULL); 1750406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 1760406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 1770406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (setjmp(png_jmpbuf(png))) { 1780406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_destroy_write_struct(&png, &info); 1790406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 1800406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 1810406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_init_io(png, out_file); 1820406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_set_IHDR(png, info, width, height, 8, 1830406ce1417f76f2034833414dcecc9f56253640cVikas Arora has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB, 1840406ce1417f76f2034833414dcecc9f56253640cVikas Arora PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, 1850406ce1417f76f2034833414dcecc9f56253640cVikas Arora PNG_FILTER_TYPE_DEFAULT); 1860406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_write_info(png, info); 1870406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; y < height; ++y) { 1880406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_bytep row = rgb + y * stride; 1890406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_write_rows(png, &row, 1); 1900406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 1910406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_write_end(png, info); 1920406ce1417f76f2034833414dcecc9f56253640cVikas Arora png_destroy_write_struct(&png, &info); 1930406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 1; 1940406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1950406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else // !HAVE_WINCODEC_H && !WEBP_HAVE_PNG 1960406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int WritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { 1970406ce1417f76f2034833414dcecc9f56253640cVikas Arora (void)out_file; 1980406ce1417f76f2034833414dcecc9f56253640cVikas Arora (void)buffer; 1990406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "PNG support not compiled. Please install the libpng " 2000406ce1417f76f2034833414dcecc9f56253640cVikas Arora "development package before building.\n"); 2010406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "You can run with -ppm flag to decode in PPM format.\n"); 2020406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 2030406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 2040406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 2050406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2060406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int WritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) { 2070406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t width = buffer->width; 2080406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t height = buffer->height; 2090406ce1417f76f2034833414dcecc9f56253640cVikas Arora const unsigned char* const rgb = buffer->u.RGBA.rgba; 2100406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int stride = buffer->u.RGBA.stride; 2110406ce1417f76f2034833414dcecc9f56253640cVikas Arora const size_t bytes_per_px = alpha ? 4 : 3; 2120406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint32_t y; 2130406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2140406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (alpha) { 2150406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n" 2160406ce1417f76f2034833414dcecc9f56253640cVikas Arora "TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height); 2170406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else { 2180406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(fout, "P6\n%d %d\n255\n", width, height); 2190406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2200406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; y < height; ++y) { 2210406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) { 2220406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 2230406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2240406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2250406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 1; 2260406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 2270406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2280406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int WriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) { 2290406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t width = buffer->width; 2300406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint32_t height = buffer->height; 2310406ce1417f76f2034833414dcecc9f56253640cVikas Arora const unsigned char* const a = buffer->u.YUVA.a; 2320406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int a_stride = buffer->u.YUVA.a_stride; 2330406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint32_t y; 2340406ce1417f76f2034833414dcecc9f56253640cVikas Arora assert(a != NULL); 2350406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(fout, "P5\n%d %d\n255\n", width, height); 2360406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; y < height; ++y) { 2370406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (fwrite(a + y * a_stride, width, 1, fout) != 1) { 2380406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 2390406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2400406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2410406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 1; 2420406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 2430406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2440406ce1417f76f2034833414dcecc9f56253640cVikas Arora// format=PGM: save a grayscale PGM file using the IMC4 layout 2450406ce1417f76f2034833414dcecc9f56253640cVikas Arora// (http://www.fourcc.org/yuv.php#IMC4). This is a very convenient format for 2460406ce1417f76f2034833414dcecc9f56253640cVikas Arora// viewing the samples, esp. for odd dimensions. 2470406ce1417f76f2034833414dcecc9f56253640cVikas Arora// format=YUV: just save the Y/U/V/A planes sequentially without header. 2480406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic int WritePGMOrYUV(FILE* fout, const WebPDecBuffer* const buffer, 2490406ce1417f76f2034833414dcecc9f56253640cVikas Arora OutputFileFormat format) { 2500406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int width = buffer->width; 2510406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int height = buffer->height; 2520406ce1417f76f2034833414dcecc9f56253640cVikas Arora const WebPYUVABuffer* const yuv = &buffer->u.YUVA; 2530406ce1417f76f2034833414dcecc9f56253640cVikas Arora int ok = 1; 2540406ce1417f76f2034833414dcecc9f56253640cVikas Arora int y; 2550406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int pad = (format == YUV) ? 0 : 1; 2560406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int uv_width = (width + 1) / 2; 2570406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int uv_height = (height + 1) / 2; 2580406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int out_stride = (width + pad) & ~pad; 2590406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int a_height = yuv->a ? height : 0; 2600406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (format == PGM) { 2610406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(fout, "P5\n%d %d\n255\n", 2620406ce1417f76f2034833414dcecc9f56253640cVikas Arora out_stride, height + uv_height + a_height); 2630406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2640406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; ok && y < height; ++y) { 2650406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1); 2660406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (format == PGM) { 2670406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (width & 1) fputc(0, fout); // padding byte 2680406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2690406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2700406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (format == PGM) { // IMC4 layout 2710406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; ok && y < uv_height; ++y) { 2720406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1); 2730406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1); 2740406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2750406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else { 2760406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; ok && y < uv_height; ++y) { 2770406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1); 2780406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2790406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; ok && y < uv_height; ++y) { 2800406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1); 2810406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2820406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2830406ce1417f76f2034833414dcecc9f56253640cVikas Arora for (y = 0; ok && y < a_height; ++y) { 2840406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1); 2850406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (format == PGM) { 2860406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (width & 1) fputc(0, fout); // padding byte 2870406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2880406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 2890406ce1417f76f2034833414dcecc9f56253640cVikas Arora return ok; 2900406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 2910406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2920406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void SaveOutput(const WebPDecBuffer* const buffer, 2930406ce1417f76f2034833414dcecc9f56253640cVikas Arora OutputFileFormat format, const char* const out_file) { 2940406ce1417f76f2034833414dcecc9f56253640cVikas Arora FILE* fout = NULL; 2950406ce1417f76f2034833414dcecc9f56253640cVikas Arora int needs_open_file = 1; 2960406ce1417f76f2034833414dcecc9f56253640cVikas Arora int ok = 1; 2970406ce1417f76f2034833414dcecc9f56253640cVikas Arora Stopwatch stop_watch; 2980406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2990406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (verbose) 3000406ce1417f76f2034833414dcecc9f56253640cVikas Arora StopwatchReadAndReset(&stop_watch); 3010406ce1417f76f2034833414dcecc9f56253640cVikas Arora 3020406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef HAVE_WINCODEC_H 3030406ce1417f76f2034833414dcecc9f56253640cVikas Arora needs_open_file = (format != PNG); 3040406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 3050406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (needs_open_file) { 3060406ce1417f76f2034833414dcecc9f56253640cVikas Arora fout = fopen(out_file, "wb"); 3070406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!fout) { 3080406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Error opening output file %s\n", out_file); 3090406ce1417f76f2034833414dcecc9f56253640cVikas Arora return; 3100406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3110406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3120406ce1417f76f2034833414dcecc9f56253640cVikas Arora 3130406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (format == PNG) { 3140406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef HAVE_WINCODEC_H 3150406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= WritePNG(out_file, buffer); 3160406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else 3170406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= WritePNG(fout, buffer); 3180406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 3190406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (format == PAM) { 3200406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= WritePPM(fout, buffer, 1); 3210406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (format == PPM) { 3220406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= WritePPM(fout, buffer, 0); 3230406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (format == PGM || format == YUV) { 3240406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= WritePGMOrYUV(fout, buffer, format); 3250406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (format == ALPHA_PLANE_ONLY) { 3260406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok &= WriteAlphaPlane(fout, buffer); 3270406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3280406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (fout) { 3290406ce1417f76f2034833414dcecc9f56253640cVikas Arora fclose(fout); 3300406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3310406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (ok) { 3320406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("Saved file %s\n", out_file); 3330406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (verbose) { 3340406ce1417f76f2034833414dcecc9f56253640cVikas Arora const double write_time = StopwatchReadAndReset(&stop_watch); 3350406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("Time to write output: %.3fs\n", write_time); 3360406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3370406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else { 3380406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Error writing file %s !!\n", out_file); 3390406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3400406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 3419aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 3420406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void Help(void) { 3430406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("Usage: dwebp in_file [options] [-o out_file]\n\n" 3440406ce1417f76f2034833414dcecc9f56253640cVikas Arora "Decodes the WebP image file to PNG format [Default]\n" 3450406ce1417f76f2034833414dcecc9f56253640cVikas Arora "Use following options to convert into alternate image formats:\n" 3460406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -pam ......... save the raw RGBA samples as a color PAM\n" 3470406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -ppm ......... save the raw RGB samples as a color PPM\n" 3480406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -pgm ......... save the raw YUV samples as a grayscale PGM\n" 3490406ce1417f76f2034833414dcecc9f56253640cVikas Arora " file with IMC4 layout.\n" 3500406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -yuv ......... save the raw YUV samples in flat layout.\n" 3510406ce1417f76f2034833414dcecc9f56253640cVikas Arora "\n" 3520406ce1417f76f2034833414dcecc9f56253640cVikas Arora " Other options are:\n" 3530406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -version .... print version number and exit.\n" 3540406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -nofancy ..... don't use the fancy YUV420 upscaler.\n" 3550406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -nofilter .... disable in-loop filtering.\n" 3560406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -mt .......... use multi-threading\n" 3570406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -crop <x> <y> <w> <h> ... crop output with the given rectangle\n" 3580406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -scale <w> <h> .......... scale the output (*after* any cropping)\n" 3590406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -alpha ....... only save the alpha plane.\n" 3600406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -h ....... this help message.\n" 3610406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -v ....... verbose (e.g. print encoding/decoding times)\n" 3620406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifndef WEBP_DLL 3630406ce1417f76f2034833414dcecc9f56253640cVikas Arora " -noasm ....... disable all assembly optimizations.\n" 3640406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 3659aea642eefa7a641ab8b89d953251939221d2719Eric Hassold ); 3669aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 3679aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 3680406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic const char* const kStatusMessages[] = { 3690406ce1417f76f2034833414dcecc9f56253640cVikas Arora "OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR", 3700406ce1417f76f2034833414dcecc9f56253640cVikas Arora "UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA" 3710406ce1417f76f2034833414dcecc9f56253640cVikas Arora}; 3720406ce1417f76f2034833414dcecc9f56253640cVikas Arora 3730406ce1417f76f2034833414dcecc9f56253640cVikas Aroraint main(int argc, const char *argv[]) { 3749aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const char *in_file = NULL; 3759aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const char *out_file = NULL; 3769aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 3770406ce1417f76f2034833414dcecc9f56253640cVikas Arora WebPDecoderConfig config; 3780406ce1417f76f2034833414dcecc9f56253640cVikas Arora WebPDecBuffer* const output_buffer = &config.output; 3790406ce1417f76f2034833414dcecc9f56253640cVikas Arora WebPBitstreamFeatures* const bitstream = &config.input; 3800406ce1417f76f2034833414dcecc9f56253640cVikas Arora OutputFileFormat format = PNG; 3819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold int c; 3820406ce1417f76f2034833414dcecc9f56253640cVikas Arora 3830406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!WebPInitDecoderConfig(&config)) { 3840406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Library version mismatch!\n"); 3850406ce1417f76f2034833414dcecc9f56253640cVikas Arora return -1; 3860406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 3870406ce1417f76f2034833414dcecc9f56253640cVikas Arora 3889aea642eefa7a641ab8b89d953251939221d2719Eric Hassold for (c = 1; c < argc; ++c) { 3890406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { 3900406ce1417f76f2034833414dcecc9f56253640cVikas Arora Help(); 3919aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; 3929aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else if (!strcmp(argv[c], "-o") && c < argc - 1) { 3939aea642eefa7a641ab8b89d953251939221d2719Eric Hassold out_file = argv[++c]; 3940406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-alpha")) { 3950406ce1417f76f2034833414dcecc9f56253640cVikas Arora format = ALPHA_PLANE_ONLY; 3960406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-nofancy")) { 3970406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.no_fancy_upsampling = 1; 3980406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-nofilter")) { 3990406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.bypass_filtering = 1; 4000406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-pam")) { 4010406ce1417f76f2034833414dcecc9f56253640cVikas Arora format = PAM; 4020406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-ppm")) { 4030406ce1417f76f2034833414dcecc9f56253640cVikas Arora format = PPM; 4040406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-version")) { 4050406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int version = WebPGetDecoderVersion(); 4060406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("%d.%d.%d\n", 4070406ce1417f76f2034833414dcecc9f56253640cVikas Arora (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); 4080406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 4090406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-pgm")) { 4100406ce1417f76f2034833414dcecc9f56253640cVikas Arora format = PGM; 4110406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-yuv")) { 4120406ce1417f76f2034833414dcecc9f56253640cVikas Arora format = YUV; 4130406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-mt")) { 4140406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.use_threads = 1; 4150406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-crop") && c < argc - 4) { 4160406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.use_cropping = 1; 4170406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.crop_left = strtol(argv[++c], NULL, 0); 4180406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.crop_top = strtol(argv[++c], NULL, 0); 4190406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.crop_width = strtol(argv[++c], NULL, 0); 4200406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.crop_height = strtol(argv[++c], NULL, 0); 4210406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-scale") && c < argc - 2) { 4220406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.use_scaling = 1; 4230406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.scaled_width = strtol(argv[++c], NULL, 0); 4240406ce1417f76f2034833414dcecc9f56253640cVikas Arora config.options.scaled_height = strtol(argv[++c], NULL, 0); 4250406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-v")) { 4260406ce1417f76f2034833414dcecc9f56253640cVikas Arora verbose = 1; 4270406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifndef WEBP_DLL 4280406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else if (!strcmp(argv[c], "-noasm")) { 4290406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8GetCPUInfo = NULL; 4300406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 4319aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else if (argv[c][0] == '-') { 4320406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Unknown option '%s'\n", argv[c]); 4330406ce1417f76f2034833414dcecc9f56253640cVikas Arora Help(); 4349aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return -1; 4359aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } else { 4369aea642eefa7a641ab8b89d953251939221d2719Eric Hassold in_file = argv[c]; 4379aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 4389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 4399aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 4409aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (in_file == NULL) { 4410406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "missing input file!!\n"); 4420406ce1417f76f2034833414dcecc9f56253640cVikas Arora Help(); 4439aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return -1; 4449aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 4459aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 4469aea642eefa7a641ab8b89d953251939221d2719Eric Hassold { 4470406ce1417f76f2034833414dcecc9f56253640cVikas Arora Stopwatch stop_watch; 4480406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8StatusCode status = VP8_STATUS_OK; 4490406ce1417f76f2034833414dcecc9f56253640cVikas Arora int ok; 4500406ce1417f76f2034833414dcecc9f56253640cVikas Arora size_t data_size = 0; 4510406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t* data = NULL; 4520406ce1417f76f2034833414dcecc9f56253640cVikas Arora 4530406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!ExUtilReadFile(in_file, &data, &data_size)) return -1; 4540406ce1417f76f2034833414dcecc9f56253640cVikas Arora 4550406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (verbose) 4560406ce1417f76f2034833414dcecc9f56253640cVikas Arora StopwatchReadAndReset(&stop_watch); 4570406ce1417f76f2034833414dcecc9f56253640cVikas Arora 4580406ce1417f76f2034833414dcecc9f56253640cVikas Arora status = WebPGetFeatures(data, data_size, bitstream); 4590406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (status != VP8_STATUS_OK) { 4600406ce1417f76f2034833414dcecc9f56253640cVikas Arora goto end; 4619aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 4620406ce1417f76f2034833414dcecc9f56253640cVikas Arora 4630406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (bitstream->has_animation) { 4640406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, 4650406ce1417f76f2034833414dcecc9f56253640cVikas Arora "Error! Decoding of an animated WebP file is not supported.\n" 4660406ce1417f76f2034833414dcecc9f56253640cVikas Arora " Use webpmux to extract the individual frames or\n" 4670406ce1417f76f2034833414dcecc9f56253640cVikas Arora " vwebp to view this image.\n"); 4689aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 4699aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 4700406ce1417f76f2034833414dcecc9f56253640cVikas Arora switch (format) { 4710406ce1417f76f2034833414dcecc9f56253640cVikas Arora case PNG: 4720406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef HAVE_WINCODEC_H 4730406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; 4740406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else 4750406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->colorspace = bitstream->has_alpha ? MODE_RGBA : MODE_RGB; 4760406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 4770406ce1417f76f2034833414dcecc9f56253640cVikas Arora break; 4780406ce1417f76f2034833414dcecc9f56253640cVikas Arora case PAM: 4790406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->colorspace = MODE_RGBA; 4800406ce1417f76f2034833414dcecc9f56253640cVikas Arora break; 4810406ce1417f76f2034833414dcecc9f56253640cVikas Arora case PPM: 4820406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->colorspace = MODE_RGB; // drops alpha for PPM 4830406ce1417f76f2034833414dcecc9f56253640cVikas Arora break; 4840406ce1417f76f2034833414dcecc9f56253640cVikas Arora case PGM: 4850406ce1417f76f2034833414dcecc9f56253640cVikas Arora case YUV: 4860406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->colorspace = bitstream->has_alpha ? MODE_YUVA : MODE_YUV; 4870406ce1417f76f2034833414dcecc9f56253640cVikas Arora break; 4880406ce1417f76f2034833414dcecc9f56253640cVikas Arora case ALPHA_PLANE_ONLY: 4890406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->colorspace = MODE_YUVA; 4900406ce1417f76f2034833414dcecc9f56253640cVikas Arora break; 4910406ce1417f76f2034833414dcecc9f56253640cVikas Arora default: 4920406ce1417f76f2034833414dcecc9f56253640cVikas Arora free((void*)data); 4930406ce1417f76f2034833414dcecc9f56253640cVikas Arora return -1; 4949aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 4950406ce1417f76f2034833414dcecc9f56253640cVikas Arora status = WebPDecode(data, data_size, &config); 4969aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 4970406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (verbose) { 4980406ce1417f76f2034833414dcecc9f56253640cVikas Arora const double decode_time = StopwatchReadAndReset(&stop_watch); 4990406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("Time to decode picture: %.3fs\n", decode_time); 5000406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 5010406ce1417f76f2034833414dcecc9f56253640cVikas Arora end: 5020406ce1417f76f2034833414dcecc9f56253640cVikas Arora free((void*)data); 5030406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok = (status == VP8_STATUS_OK); 5040406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!ok) { 5050406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Decoding of %s failed.\n", in_file); 5060406ce1417f76f2034833414dcecc9f56253640cVikas Arora fprintf(stderr, "Status: %d (%s)\n", status, kStatusMessages[status]); 5070406ce1417f76f2034833414dcecc9f56253640cVikas Arora return -1; 5080406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 5099aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 5109aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 5119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold if (out_file) { 5120406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("Decoded %s. Dimensions: %d x %d%s. Now saving...\n", in_file, 5130406ce1417f76f2034833414dcecc9f56253640cVikas Arora output_buffer->width, output_buffer->height, 5140406ce1417f76f2034833414dcecc9f56253640cVikas Arora bitstream->has_alpha ? " (with alpha)" : ""); 5150406ce1417f76f2034833414dcecc9f56253640cVikas Arora SaveOutput(output_buffer, format, out_file); 5160406ce1417f76f2034833414dcecc9f56253640cVikas Arora } else { 5170406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("File %s can be decoded (dimensions: %d x %d)%s.\n", 5180406ce1417f76f2034833414dcecc9f56253640cVikas Arora in_file, output_buffer->width, output_buffer->height, 5190406ce1417f76f2034833414dcecc9f56253640cVikas Arora bitstream->has_alpha ? " (with alpha)" : ""); 5200406ce1417f76f2034833414dcecc9f56253640cVikas Arora printf("Nothing written; use -o flag to save the result as e.g. PNG.\n"); 5219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold } 5220406ce1417f76f2034833414dcecc9f56253640cVikas Arora WebPFreeDecBuffer(output_buffer); 5239aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 5249aea642eefa7a641ab8b89d953251939221d2719Eric Hassold return 0; 5259aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 5269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 5270406ce1417f76f2034833414dcecc9f56253640cVikas Arora//------------------------------------------------------------------------------ 528