mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 05:38:22 +01:00
add VP8LEncodeStream() to compress lossless image stream
* RIFF header is omitted * rename NewVP8LEncoder and DeleteVP8Encoder * change the signature to take a "const WebPPicture*" (it was non-const just because we were setting some error potentially) * made the pic_ field const in VP8LEncoder too. * trap the bitwriter::error_ too * simplify some signatures to take WebPPicture* instead of unneeded VP8LEncoder* VP8LEncodeStream() will be called directly to compress alpha channel header-less. Change-Id: Ibceef63d2b3fbc412f0dffc38dc05c2dee6b6bbf
This commit is contained in:
parent
fa8bc3dbca
commit
489ec335a1
112
src/enc/vp8l.c
112
src/enc/vp8l.c
@ -638,9 +638,8 @@ static void PutLE32(uint8_t* const data, uint32_t val) {
|
||||
data[3] = (val >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static WebPEncodingError WriteRiffHeader(const VP8LEncoder* const enc,
|
||||
static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
|
||||
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,
|
||||
@ -653,20 +652,20 @@ static WebPEncodingError WriteRiffHeader(const VP8LEncoder* const enc,
|
||||
return VP8_ENC_OK;
|
||||
}
|
||||
|
||||
static void WriteImageSize(VP8LEncoder* const enc, VP8LBitWriter* const bw) {
|
||||
WebPPicture* const pic = enc->pic_;
|
||||
static int WriteImageSize(const WebPPicture* const pic,
|
||||
VP8LBitWriter* const bw) {
|
||||
const int width = pic->width - 1;
|
||||
const int height = pic->height -1;
|
||||
assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
|
||||
|
||||
VP8LWriteBits(bw, IMAGE_SIZE_BITS, width);
|
||||
VP8LWriteBits(bw, IMAGE_SIZE_BITS, height);
|
||||
return !bw->error_;
|
||||
}
|
||||
|
||||
static WebPEncodingError WriteImage(const VP8LEncoder* const enc,
|
||||
static WebPEncodingError WriteImage(const WebPPicture* const pic,
|
||||
VP8LBitWriter* const bw,
|
||||
size_t* const coded_size) {
|
||||
const WebPPicture* const pic = enc->pic_;
|
||||
WebPEncodingError err = VP8_ENC_OK;
|
||||
const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
|
||||
const size_t webpll_size = VP8LBitWriterNumBytes(bw);
|
||||
@ -674,7 +673,7 @@ static WebPEncodingError WriteImage(const VP8LEncoder* const enc,
|
||||
const size_t pad = vp8l_size & 1;
|
||||
const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
|
||||
|
||||
err = WriteRiffHeader(enc, riff_size, vp8l_size);
|
||||
err = WriteRiffHeader(pic, riff_size, vp8l_size);
|
||||
if (err != VP8_ENC_OK) goto Error;
|
||||
|
||||
if (!pic->writer(webpll_data, webpll_size, pic)) {
|
||||
@ -835,8 +834,8 @@ static void InitEncParams(VP8LEncoder* const enc) {
|
||||
// -----------------------------------------------------------------------------
|
||||
// VP8LEncoder
|
||||
|
||||
static VP8LEncoder* NewVP8LEncoder(const WebPConfig* const config,
|
||||
WebPPicture* const picture) {
|
||||
static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
|
||||
const WebPPicture* const picture) {
|
||||
VP8LEncoder* const enc = (VP8LEncoder*)calloc(1, sizeof(*enc));
|
||||
if (enc == NULL) {
|
||||
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
||||
@ -847,7 +846,7 @@ static VP8LEncoder* NewVP8LEncoder(const WebPConfig* const config,
|
||||
return enc;
|
||||
}
|
||||
|
||||
static void DeleteVP8LEncoder(VP8LEncoder* enc) {
|
||||
static void VP8LEncoderDelete(VP8LEncoder* enc) {
|
||||
free(enc->argb_);
|
||||
free(enc);
|
||||
}
|
||||
@ -855,30 +854,19 @@ static void DeleteVP8LEncoder(VP8LEncoder* enc) {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main call
|
||||
|
||||
int VP8LEncodeImage(const WebPConfig* const config,
|
||||
WebPPicture* const picture) {
|
||||
int ok = 0;
|
||||
int width, height, quality;
|
||||
size_t coded_size;
|
||||
VP8LEncoder* enc = NULL;
|
||||
WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
|
||||
const WebPPicture* const picture,
|
||||
VP8LBitWriter* const bw) {
|
||||
WebPEncodingError err = VP8_ENC_OK;
|
||||
VP8LBitWriter bw;
|
||||
const int quality = config->quality;
|
||||
const int width = picture->width;
|
||||
const int height = picture->height;
|
||||
VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
|
||||
|
||||
if (config == NULL || picture == NULL) return 0;
|
||||
|
||||
if (picture->argb == NULL) {
|
||||
err = VP8_ENC_ERROR_NULL_PARAMETER;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
enc = NewVP8LEncoder(config, picture);
|
||||
if (enc == NULL) {
|
||||
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||
goto Error;
|
||||
}
|
||||
width = picture->width;
|
||||
height = picture->height;
|
||||
quality = config->quality;
|
||||
|
||||
InitEncParams(enc);
|
||||
|
||||
@ -890,12 +878,8 @@ int VP8LEncodeImage(const WebPConfig* const config,
|
||||
goto Error;
|
||||
}
|
||||
|
||||
// Write image size.
|
||||
VP8LBitWriterInit(&bw, (width * height) >> 1);
|
||||
WriteImageSize(enc, &bw);
|
||||
|
||||
if (enc->use_palette_) {
|
||||
err = ApplyPalette(&bw, enc, width, height, quality);
|
||||
err = ApplyPalette(bw, enc, width, height, quality);
|
||||
if (err != VP8_ENC_OK) goto Error;
|
||||
enc->cache_bits_ = 0;
|
||||
}
|
||||
@ -912,27 +896,26 @@ int VP8LEncodeImage(const WebPConfig* const config,
|
||||
// ---------------------------------------------------------------------------
|
||||
// Apply transforms and write transform data.
|
||||
|
||||
if (!EvalAndApplySubtractGreen(enc, enc->current_width_, height, &bw)) {
|
||||
if (!EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw)) {
|
||||
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
if (enc->use_predict_) {
|
||||
if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, &bw)) {
|
||||
if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, bw)) {
|
||||
err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc->use_cross_color_) {
|
||||
if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality,
|
||||
&bw)) {
|
||||
if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw)) {
|
||||
err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
VP8LWriteBits(&bw, 1, !TRANSFORM_PRESENT); // No more transforms.
|
||||
VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT); // No more transforms.
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Estimate the color cache size.
|
||||
@ -948,16 +931,47 @@ int VP8LEncodeImage(const WebPConfig* const config,
|
||||
// ---------------------------------------------------------------------------
|
||||
// Encode and write the transformed image.
|
||||
|
||||
ok = EncodeImageInternal(&bw, enc->argb_, enc->current_width_, height,
|
||||
quality, enc->cache_bits_, enc->histo_bits_);
|
||||
if (!ok) goto Error;
|
||||
|
||||
err = WriteImage(enc, &bw, &coded_size);
|
||||
if (err != VP8_ENC_OK) {
|
||||
ok = 0;
|
||||
if (!EncodeImageInternal(bw, enc->argb_, enc->current_width_, height,
|
||||
quality, enc->cache_bits_, enc->histo_bits_)) {
|
||||
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Error:
|
||||
VP8LEncoderDelete(enc);
|
||||
return err;
|
||||
}
|
||||
|
||||
int VP8LEncodeImage(const WebPConfig* const config,
|
||||
const WebPPicture* const picture) {
|
||||
int width, height;
|
||||
size_t coded_size;
|
||||
WebPEncodingError err = VP8_ENC_OK;
|
||||
VP8LBitWriter bw;
|
||||
|
||||
if (picture == NULL) return 0;
|
||||
|
||||
if (config == NULL || picture->argb == NULL) {
|
||||
err = VP8_ENC_ERROR_NULL_PARAMETER;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
width = picture->width;
|
||||
height = picture->height;
|
||||
|
||||
// Write image size.
|
||||
VP8LBitWriterInit(&bw, (width * height) >> 1);
|
||||
if (!WriteImageSize(picture, &bw)) goto Error;
|
||||
|
||||
// Encode main image stream.
|
||||
err = VP8LEncodeStream(config, picture, &bw);
|
||||
if (err != VP8_ENC_OK) goto Error;
|
||||
|
||||
// Finish the RIFF chunk.
|
||||
err = WriteImage(picture, &bw, &coded_size);
|
||||
if (err != VP8_ENC_OK) goto Error;
|
||||
|
||||
// Collect some stats if needed.
|
||||
if (picture->stats != NULL) {
|
||||
WebPAuxStats* const stats = picture->stats;
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
@ -975,13 +989,13 @@ int VP8LEncodeImage(const WebPConfig* const config,
|
||||
}
|
||||
|
||||
Error:
|
||||
if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||
VP8LBitWriterDestroy(&bw);
|
||||
DeleteVP8LEncoder(enc);
|
||||
if (!ok) {
|
||||
assert(err != VP8_ENC_OK);
|
||||
if (err != VP8_ENC_OK) {
|
||||
WebPEncodingSetError(picture, err);
|
||||
return 0;
|
||||
}
|
||||
return ok;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
const WebPConfig* config_; // user configuration and parameters
|
||||
WebPPicture* pic_; // input picture.
|
||||
const WebPPicture* pic_; // input picture.
|
||||
|
||||
uint32_t* argb_; // Transformed argb image data.
|
||||
uint32_t* argb_scratch_; // Scratch memory for argb rows
|
||||
@ -59,13 +59,16 @@ typedef struct {
|
||||
//------------------------------------------------------------------------------
|
||||
// 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);
|
||||
const WebPPicture* const picture);
|
||||
|
||||
// Encodes the main image stream using the supplied bit writer.
|
||||
WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
|
||||
const WebPPicture* const picture,
|
||||
VP8LBitWriter* const bw);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user