libwebp interface changes for lossless encoding.

Change-Id: I703a1a18347acf78378cb23fddc6e5ca6dc6a0bb
This commit is contained in:
Vikas Arora 2012-03-28 11:07:42 +00:00 committed by James Zern
parent c04eb7be9d
commit 227110c4c3
8 changed files with 648 additions and 158 deletions

View File

@ -44,6 +44,7 @@ int WebPConfigInitInternal(WebPConfig* const config,
config->alpha_compression = 1; config->alpha_compression = 1;
config->alpha_filtering = 1; config->alpha_filtering = 1;
config->alpha_quality = 100; config->alpha_quality = 100;
config->lossless = 0;
// TODO(skal): tune. // TODO(skal): tune.
switch (preset) { switch (preset) {
@ -116,6 +117,8 @@ int WebPValidateConfig(const WebPConfig* const config) {
return 0; return 0;
if (config->alpha_quality < 0 || config->alpha_quality > 100) if (config->alpha_quality < 0 || config->alpha_quality > 100)
return 0; return 0;
if (config->lossless < 0 || config->lossless > 1)
return 0;
return 1; return 1;
} }

View File

@ -32,6 +32,8 @@ int WebPPictureAlloc(WebPPicture* const picture) {
const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT; const int has_alpha = picture->colorspace & WEBP_CSP_ALPHA_BIT;
const int width = picture->width; const int width = picture->width;
const int height = picture->height; const int height = picture->height;
if (!picture->use_argb_input) {
const int y_stride = width; const int y_stride = width;
const int uv_width = HALVE(width); const int uv_width = HALVE(width);
const int uv_height = HALVE(height); const int uv_height = HALVE(height);
@ -102,6 +104,17 @@ int WebPPictureAlloc(WebPPicture* const picture) {
picture->v0 = mem; picture->v0 = mem;
mem += uv0_size; mem += uv0_size;
} }
} else {
if (width <= 0 || height <= 0 ||
width >= 0x4000 || height >= 0x4000) {
return 0;
}
WebPPictureFree(picture); // erase previous buffer
picture->argb = (uint32_t*)malloc(width * height *
sizeof(*picture->argb));
if (picture->argb == NULL) return 0;
picture->argb_stride = width;
}
} }
return 1; return 1;
} }
@ -114,12 +127,14 @@ static void WebPPictureGrabSpecs(const WebPPicture* const src,
dst->y = dst->u = dst->v = NULL; dst->y = dst->u = dst->v = NULL;
dst->u0 = dst->v0 = NULL; dst->u0 = dst->v0 = NULL;
dst->a = NULL; dst->a = NULL;
dst->argb = NULL;
} }
// Release memory owned by 'picture'. // Release memory owned by 'picture'.
void WebPPictureFree(WebPPicture* const picture) { void WebPPictureFree(WebPPicture* const picture) {
if (picture != NULL) { if (picture != NULL) {
free(picture->y); free(picture->y);
free(picture->argb);
WebPPictureGrabSpecs(NULL, picture); WebPPictureGrabSpecs(NULL, picture);
} }
} }
@ -144,6 +159,7 @@ int WebPPictureCopy(const WebPPicture* const src, WebPPicture* const dst) {
WebPPictureGrabSpecs(src, dst); WebPPictureGrabSpecs(src, dst);
if (!WebPPictureAlloc(dst)) return 0; if (!WebPPictureAlloc(dst)) return 0;
if (!src->use_argb_input) {
CopyPlane(src->y, src->y_stride, CopyPlane(src->y, src->y_stride,
dst->y, dst->y_stride, dst->width, dst->height); dst->y, dst->y_stride, dst->width, dst->height);
CopyPlane(src->u, src->uv_stride, CopyPlane(src->u, src->uv_stride,
@ -166,6 +182,11 @@ int WebPPictureCopy(const WebPPicture* const src, WebPPicture* const dst) {
dst->v0, dst->uv0_stride, uv0_width, dst->height); dst->v0, dst->uv0_stride, uv0_width, dst->height);
} }
#endif #endif
} else {
CopyPlane((uint8_t*)src->argb, 4 * src->argb_stride,
(uint8_t*)dst->argb, 4 * dst->argb_stride,
4 * dst->width, dst->height);
}
return 1; return 1;
} }
@ -438,6 +459,7 @@ static int Import(WebPPicture* const picture,
const int width = picture->width; const int width = picture->width;
const int height = picture->height; const int height = picture->height;
if (!picture->use_argb_input) {
// Import luma plane // Import luma plane
for (y = 0; y < height; ++y) { for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
@ -499,6 +521,29 @@ static int Import(WebPPicture* const picture,
} }
} }
} }
} else {
if (!import_alpha) {
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
const int offset = step * x + y * rgb_stride;
const uint32_t argb = 0xff000000 | (r_ptr[offset] << 16) |
(g_ptr[offset] << 8) | (b_ptr[offset]);
picture->argb[x + y * picture->argb_stride] = argb;
}
}
} else {
const uint8_t* const a_ptr = rgb + 3;
assert(step >= 4);
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
const int offset = step * x + y * rgb_stride;
const uint32_t argb = (a_ptr[offset] << 24) | (r_ptr[offset] << 16) |
(g_ptr[offset] << 8) | (b_ptr[offset]);
picture->argb[x + y * picture->argb_stride] = argb;
}
}
}
}
return 1; return 1;
} }
#undef SUM4 #undef SUM4

230
src/enc/vp8l.c Normal file
View File

@ -0,0 +1,230 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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/
// -----------------------------------------------------------------------------
//
// main entry for the decoder
//
// Author: Vikas Arora (vikaas.arora@gmail.com)
//
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "./vp8enci.h"
#include "./vp8li.h"
#include "../utils/bit_writer.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static const uint32_t kImageSizeBits = 14;
static int VP8LEncAnalyze(VP8LEncoder* const enc) {
(void)enc;
return 1;
}
static int EncodeImageInternal(VP8LEncoder* const enc) {
(void)enc;
return 1;
}
static int CreatePalette(VP8LEncoder* const enc) {
(void)enc;
return 1;
}
static void EvalSubtractGreen(VP8LEncoder* const enc) {
(void)enc;
}
static int ApplyPredictFilter(VP8LEncoder* const enc) {
(void)enc;
return 1;
}
static int ApplyCrossColorFilter(VP8LEncoder* const enc) {
(void)enc;
return 1;
}
static void EvalEmergingPalette(VP8LEncoder* const enc) {
(void)enc;
}
static void PutLE32(uint8_t* const data, uint32_t val) {
data[0] = (val >> 0) & 0xff;
data[1] = (val >> 8) & 0xff;
data[2] = (val >> 16) & 0xff;
data[3] = (val >> 24) & 0xff;
}
static WebPEncodingError WriteRiffHeader(VP8LEncoder* const enc,
size_t riff_size, size_t vp8l_size) {
const WebPPicture* const pic = enc->pic_;
uint8_t riff[HEADER_SIZE + SIGNATURE_SIZE] = {
'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
'V', 'P', '8', 'L', 0, 0, 0, 0, LOSSLESS_MAGIC_BYTE,
};
if (riff_size < (vp8l_size + TAG_SIZE + CHUNK_HEADER_SIZE)) {
return VP8_ENC_ERROR_INVALID_CONFIGURATION;
}
PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
if (!pic->writer(riff, sizeof(riff), pic)) {
return VP8_ENC_ERROR_BAD_WRITE;
}
return VP8_ENC_OK;
}
static WebPEncodingError WriteImage(VP8LEncoder* const enc) {
size_t riff_size, vp8l_size, webpll_size, pad;
WebPPicture* const pic = enc->pic_;
WebPEncodingError err = VP8_ENC_OK;
const uint8_t* const webpll_data = VP8LBitWriterFinish(&enc->bw_);
webpll_size = VP8LBitWriterNumBytes(&enc->bw_);
vp8l_size = SIGNATURE_SIZE + webpll_size;
pad = vp8l_size & 1;
vp8l_size += pad;
riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size;
err = WriteRiffHeader(enc, riff_size, vp8l_size);
if (err != VP8_ENC_OK) goto Error;
if (!pic->writer(webpll_data, webpll_size, pic)) {
err = VP8_ENC_ERROR_BAD_WRITE;
goto Error;
}
if (pad) {
const uint8_t pad_byte[1] = { 0 };
if (!pic->writer(pad_byte, 1, pic)) {
err = VP8_ENC_ERROR_BAD_WRITE;
goto Error;
}
}
return VP8_ENC_OK;
Error:
WebPEncodingSetError(pic, err);
return err;
}
static VP8LEncoder* InitVP8LEncoder(const WebPConfig* const config,
WebPPicture* const picture) {
VP8LEncoder* enc;
const int kEstmatedEncodeSize = (picture->width * picture->height) >> 1;
(void)config;
enc = (VP8LEncoder*)malloc(sizeof(*enc));
if (enc == NULL) {
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
return NULL;
}
enc->pic_ = picture;
enc->use_lz77_ = 1;
enc->palette_bits_ = 7;
// TODO: Use config.quality to initialize histo_bits_ and transform_bits_.
enc->histo_bits_ = 4;
enc->transform_bits_ = 4;
VP8LBitWriterInit(&enc->bw_, kEstmatedEncodeSize);
return enc;
}
static WebPEncodingError WriteImageSize(VP8LEncoder* const enc) {
WebPEncodingError status = VP8_ENC_OK;
WebPPicture* const pic = enc->pic_;
const int width = pic->width - 1;
const int height = pic->height - 1;
if (width < 0x4000 && height < 0x4000) {
VP8LWriteBits(&enc->bw_, kImageSizeBits, width);
VP8LWriteBits(&enc->bw_, kImageSizeBits, height);
} else {
status = VP8_ENC_ERROR_BAD_DIMENSION;
}
return status;
}
static void DeleteVP8LEncoder(VP8LEncoder* enc) {
free(enc);
}
int VP8LEncodeImage(const WebPConfig* const config,
WebPPicture* const picture) {
int ok = 0;
VP8LEncoder* enc = NULL;
WebPEncodingError err = VP8_ENC_OK;
if (config == NULL || picture == NULL) return 0;
if (picture->argb == NULL) return 0;
enc = InitVP8LEncoder(config, picture);
if (enc == NULL) goto Error;
// ---------------------------------------------------------------------------
// Analyze image (entropy, num_palettes etc)
if (!VP8LEncAnalyze(enc)) goto Error;
if (enc->use_palette_) {
CreatePalette(enc);
}
// Write image size.
err = WriteImageSize(enc);
if (err != VP8_ENC_OK) {
ok = 0;
goto Error;
}
// ---------------------------------------------------------------------------
// Apply transforms and write transform data.
EvalSubtractGreen(enc);
if (enc->use_predict_) {
if (!ApplyPredictFilter(enc)) goto Error;
}
if (enc->use_cross_color_) {
if (!ApplyCrossColorFilter(enc)) goto Error;
}
if (enc->use_emerging_palette_) {
EvalEmergingPalette(enc);
}
// ---------------------------------------------------------------------------
// Encode and write the transformed image.
ok = EncodeImageInternal(enc);
if (!ok) goto Error;
err = WriteImage(enc);
if (err != VP8_ENC_OK) {
ok = 0;
goto Error;
}
Error:
VP8LBitWriterDestroy(&enc->bw_);
DeleteVP8LEncoder(enc);
if (!ok) {
// TODO(vikasa): err is not set for all error paths. Set default err.
if (err == VP8_ENC_OK) err = VP8_ENC_ERROR_BAD_WRITE;
WebPEncodingSetError(picture, err);
}
return ok;
}
//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

69
src/enc/vp8li.h Normal file
View File

@ -0,0 +1,69 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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/
// -----------------------------------------------------------------------------
//
// Lossless encoder: internal header.
//
// Author: Vikas Arora(vikaas.arora@gmail.com)
#ifndef WEBP_ENC_VP8LI_H_
#define WEBP_ENC_VP8LI_H_
#include "../webp/encode.h"
#include "../utils/bit_writer.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
// TODO(vikasa): factorize these with ones used in lossless decoder.
#define TAG_SIZE 4
#define CHUNK_HEADER_SIZE 8
#define RIFF_HEADER_SIZE 12
#define HEADER_SIZE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE)
#define SIGNATURE_SIZE 1
#define LOSSLESS_MAGIC_BYTE 0x64
typedef struct {
const WebPConfig* config_; // user configuration and parameters
WebPPicture* pic_; // input / output picture
// Encoding parameters derived from quality parameter.
int use_lz77_;
int palette_bits_;
int histo_bits_;
int transform_bits_;
// Encoding parameters derived from image characteristics.
int predicted_bits_;
int non_predicted_bits_;
int use_palette_;
int num_palette_colors;
int use_predict_;
int use_cross_color_;
int use_emerging_palette_;
VP8LBitWriter bw_;
} VP8LEncoder;
//------------------------------------------------------------------------------
// internal functions. Not public.
// in vp8l.c
// Encodes the picture.
// Returns 0 if config or picture is NULL or picture doesn't have valid argb
// input.
int VP8LEncodeImage(const WebPConfig* const config,
WebPPicture* const picture);
//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif
#endif /* WEBP_ENC_VP8LI_H_ */

View File

@ -15,6 +15,7 @@
#include <math.h> #include <math.h>
#include "./vp8enci.h" #include "./vp8enci.h"
#include "./vp8li.h"
// #define PRINT_MEMORY_INFO // #define PRINT_MEMORY_INFO
@ -142,7 +143,7 @@ static void MapConfigToTools(VP8Encoder* const enc) {
// LFStats: 2048 // LFStats: 2048
// Picture size (yuv): 589824 // Picture size (yuv): 589824
static VP8Encoder* InitEncoder(const WebPConfig* const config, static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
WebPPicture* const picture) { WebPPicture* const picture) {
const int use_filter = const int use_filter =
(config->filter_strength > 0) || (config->autofilter > 0); (config->filter_strength > 0) || (config->autofilter > 0);
@ -259,7 +260,7 @@ static VP8Encoder* InitEncoder(const WebPConfig* const config,
return enc; return enc;
} }
static void DeleteEncoder(VP8Encoder* enc) { static void DeleteVP8Encoder(VP8Encoder* enc) {
if (enc) { if (enc) {
VP8EncDeleteAlpha(enc); VP8EncDeleteAlpha(enc);
#ifdef WEBP_EXPERIMENTAL_FEATURES #ifdef WEBP_EXPERIMENTAL_FEATURES
@ -327,7 +328,6 @@ int WebPReportProgress(VP8Encoder* const enc, int percent) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) { int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
VP8Encoder* enc;
int ok; int ok;
if (pic == NULL) if (pic == NULL)
@ -339,12 +339,15 @@ int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
if (pic->width <= 0 || pic->height <= 0) if (pic->width <= 0 || pic->height <= 0)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
if (pic->y == NULL || pic->u == NULL || pic->v == NULL)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
enc = InitEncoder(config, pic); if (!config->lossless) {
VP8Encoder* enc = NULL;
if (pic->y == NULL || pic->u == NULL || pic->v == NULL)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
enc = InitVP8Encoder(config, pic);
if (enc == NULL) return 0; // pic->error is already set. if (enc == NULL) return 0; // pic->error is already set.
// Note: each of the tasks below account for 20% in the progress report. // Note: each of the tasks below account for 20% in the progress report.
ok = VP8EncAnalyze(enc) ok = VP8EncAnalyze(enc)
@ -359,7 +362,13 @@ int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
if (!ok) { if (!ok) {
VP8EncFreeBitWriters(enc); VP8EncFreeBitWriters(enc);
} }
DeleteEncoder(enc); DeleteVP8Encoder(enc);
} else {
if (pic->argb == NULL)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
ok = VP8LEncodeImage(config, pic);
}
return ok; return ok;
} }

View File

@ -8,6 +8,7 @@
// Bit writing and boolean coder // Bit writing and boolean coder
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
// Vikas Arora (vikaas.arora@gmail.com)
#include <assert.h> #include <assert.h>
#include <string.h> // for memcpy() #include <string.h> // for memcpy()
@ -186,6 +187,84 @@ void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
} }
} }
//------------------------------------------------------------------------------
// VP8LBitWriter
// Returns 1 on success.
static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) {
uint8_t* allocated_buf;
size_t allocated_size;
const size_t size_required = VP8LBitWriterNumBytes(bw) + extra_size;
if ((bw->max_bytes_ > 0) && (size_required <= bw->max_bytes_)) return 1;
allocated_size = (3 * bw->max_bytes_) >> 1;
if (allocated_size < size_required) {
allocated_size = size_required;
}
// Make Allocated size multiple of KBs
allocated_size = (((allocated_size >> 10) + 1) << 10);
allocated_buf = (uint8_t*)malloc(allocated_size);
if (allocated_buf == NULL) return 0;
memset(allocated_buf, 0, allocated_size);
if (bw->bit_pos_ > 0) {
memcpy(allocated_buf, bw->buf_, VP8LBitWriterNumBytes(bw));
}
free(bw->buf_);
bw->buf_ = allocated_buf;
bw->max_bytes_ = allocated_size;
return 1;
}
int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
memset(bw, 0, sizeof(*bw));
return VP8LBitWriterResize(bw, expected_size);
}
void VP8LBitWriterDestroy(VP8LBitWriter* const bw) {
if (bw != NULL) {
free(bw->buf_);
memset(bw, 0, sizeof(*bw));
}
}
void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits) {
if (n_bits < 1) return;
#if !defined(__BIG_ENDIAN__)
// Technically, this branch of the code can write up to 25 bits at a time,
// but in deflate, the maximum number of bits written is 16 at a time.
{
uint8_t* p = &bw->buf_[bw->bit_pos_ >> 3];
uint32_t v = *(const uint32_t*)(p);
v |= bits << (bw->bit_pos_ & 7);
*(uint32_t*)(p) = v;
bw->bit_pos_ += n_bits;
}
#else // LITTLE_ENDIAN
// implicit & 0xff is assumed for uint8_t arithmetics
{
uint8_t* p = &bw->buf_[bw->bit_pos_ >> 3];
const int bits_reserved_in_first_byte = (bw->bit_pos_ & 7);
*p++ |= (bits << bits_reserved_in_first_byte);
const int bits_left_to_write = n_bits - 8 + bits_reserved_in_first_byte;
if (bits_left_to_write >= 1) {
*p++ = bits >> (8 - bits_reserved_in_first_byte);
if (bits_left_to_write >= 9) {
*p++ = bits >> (16 - bits_reserved_in_first_byte);
}
}
*p = 0;
bw->bit_pos_ += n_bits;
}
#endif // BIG_ENDIAN
if ((bw->bit_pos_ >> 3) > (bw->max_bytes_ - 8)) {
const size_t kAdditionalBuffer = 32768 + bw->max_bytes_;
if (!VP8LBitWriterResize(bw, kAdditionalBuffer)) {
bw->bit_pos_ = 0;
bw->error_ = 1;
}
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)

View File

@ -64,6 +64,56 @@ static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
return bw->pos_; return bw->pos_;
} }
//------------------------------------------------------------------------------
// VP8LBitWriter
// TODO(vikasa): VP8LBitWriter is copied as-is from lossless code. There's scope
// of re-using VP8BitWriter. Will evaluate once basic lossless encoder is
// implemented.
typedef struct {
uint8_t* buf_;
size_t bit_pos_;
size_t max_bytes_;
// After all bits are written, the caller must observe the state of
// error_. A value of 1 indicates that a memory allocation failure
// has happened during bit writing. A value of 0 indicates successful
// writing of bits.
int error_;
} VP8LBitWriter;
static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) {
return (bw->bit_pos_ + 7) >> 3;
}
static WEBP_INLINE uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
return bw->buf_;
}
// Returns 1 on success.
int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size);
void VP8LBitWriterDestroy(VP8LBitWriter* const bw);
// This function writes bits into bytes in increasing addresses, and within
// a byte least-significant-bit first.
//
// The function can write up to 16 bits in one go with WriteBits
// Example: let's assume that 3 bits (Rs below) have been written already:
//
// BYTE-0 BYTE+1 BYTE+2
//
// 0000 0RRR 0000 0000 0000 0000
//
// Now, we could write 5 or less bits in MSB by just sifting by 3
// and OR'ing to BYTE-0.
//
// For n bits, we take the last 5 bytes, OR that with high bits in BYTE-0,
// and locate the rest in BYTE+1 and BYTE+2.
//
// returns 1 on success.
void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)

View File

@ -76,6 +76,7 @@ typedef struct {
// 0: none, 1: fast, 2: best. Default if 1. // 0: none, 1: fast, 2: best. Default if 1.
int alpha_quality; // Between 0 (smallest size) and 100 (lossless). int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
// Default is 100. // Default is 100.
int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
} WebPConfig; } WebPConfig;
// Enumerate some predefined settings for WebPConfig, depending on the type // Enumerate some predefined settings for WebPConfig, depending on the type
@ -216,6 +217,10 @@ struct WebPPicture {
WebPEncodingError error_code; // error code in case of problem. WebPEncodingError error_code; // error code in case of problem.
WebPProgressHook progress_hook; // if not NULL, called while encoding. WebPProgressHook progress_hook; // if not NULL, called while encoding.
int use_argb_input; // Flag for encoder to read argb pixels as input.
uint32_t* argb; // Pointer to argb (32 bit) plane.
int argb_stride; // This is stride in pixels units, not bytes.
}; };
// Internal, version-checked, entry point // Internal, version-checked, entry point