2012-01-06 23:49:06 +01:00
|
|
|
// Copyright 2011 Google Inc. All Rights Reserved.
|
2011-02-19 08:33:46 +01:00
|
|
|
//
|
|
|
|
// 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/
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Bit writing and boolean coder
|
|
|
|
//
|
|
|
|
// Author: Skal (pascal.massimino@gmail.com)
|
|
|
|
|
2011-09-07 11:26:35 +02:00
|
|
|
#ifndef WEBP_UTILS_BIT_WRITER_H_
|
|
|
|
#define WEBP_UTILS_BIT_WRITER_H_
|
2011-02-19 08:33:46 +01:00
|
|
|
|
2011-09-05 10:33:47 +02:00
|
|
|
#include "../webp/types.h"
|
2011-02-19 08:33:46 +01:00
|
|
|
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2011-08-25 23:22:32 +02:00
|
|
|
//------------------------------------------------------------------------------
|
2011-02-19 08:33:46 +01:00
|
|
|
// Bit-writing
|
|
|
|
|
|
|
|
typedef struct VP8BitWriter VP8BitWriter;
|
|
|
|
struct VP8BitWriter {
|
|
|
|
int32_t range_; // range-1
|
|
|
|
int32_t value_;
|
|
|
|
int run_; // number of outstanding bits
|
|
|
|
int nb_bits_; // number of pending bits
|
2011-12-01 11:24:50 +01:00
|
|
|
uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned.
|
2011-02-19 08:33:46 +01:00
|
|
|
size_t pos_;
|
|
|
|
size_t max_pos_;
|
|
|
|
int error_; // true in case of error
|
|
|
|
};
|
|
|
|
|
2011-12-01 11:24:50 +01:00
|
|
|
// Initialize the object. Allocates some initial memory based on expected_size.
|
2011-02-19 08:33:46 +01:00
|
|
|
int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size);
|
2011-12-01 11:24:50 +01:00
|
|
|
// Finalize the bitstream coding. Returns a pointer to the internal buffer.
|
2011-02-19 08:33:46 +01:00
|
|
|
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw);
|
2011-12-01 11:24:50 +01:00
|
|
|
// Release any pending memory and zeroes the object. Not a mandatory call.
|
|
|
|
// Only useful in case of error, when the internal buffer hasn't been grabbed!
|
|
|
|
void VP8BitWriterWipeOut(VP8BitWriter* const bw);
|
|
|
|
|
2011-02-19 08:33:46 +01:00
|
|
|
int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
|
|
|
|
int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
|
|
|
|
void VP8PutValue(VP8BitWriter* const bw, int value, int nb_bits);
|
|
|
|
void VP8PutSignedValue(VP8BitWriter* const bw, int value, int nb_bits);
|
2011-12-01 11:24:50 +01:00
|
|
|
|
|
|
|
// Appends some bytes to the internal buffer. Data is copied.
|
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 VP8BitWriterAppend(VP8BitWriter* const bw,
|
|
|
|
const uint8_t* data, size_t size);
|
2011-02-19 08:33:46 +01:00
|
|
|
|
|
|
|
// return approximate write position (in bits)
|
2011-11-05 03:44:57 +01:00
|
|
|
static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
|
2011-02-19 08:33:46 +01:00
|
|
|
return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_;
|
|
|
|
}
|
|
|
|
|
2011-12-01 11:24:50 +01:00
|
|
|
// Returns a pointer to the internal buffer.
|
2011-11-05 03:44:57 +01:00
|
|
|
static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) {
|
2011-02-19 08:33:46 +01:00
|
|
|
return bw->buf_;
|
|
|
|
}
|
2011-12-01 11:24:50 +01:00
|
|
|
// Returns the size of the internal buffer.
|
2011-11-05 03:44:57 +01:00
|
|
|
static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
|
2011-02-19 08:33:46 +01:00
|
|
|
return bw->pos_;
|
|
|
|
}
|
|
|
|
|
2012-03-28 13:07:42 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// 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_;
|
|
|
|
}
|
|
|
|
|
2012-04-02 12:58:36 +02:00
|
|
|
// Returns 0 in case of memory allocation error.
|
2012-03-28 13:07:42 +02:00
|
|
|
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.
|
|
|
|
//
|
2012-04-02 12:58:36 +02:00
|
|
|
// VP8LBitWriter's error_ flag is set in case of memory allocation error.
|
2012-03-28 13:07:42 +02:00
|
|
|
void VP8LWriteBits(VP8LBitWriter* const bw, int n_bits, uint32_t bits);
|
|
|
|
|
2011-08-25 23:22:32 +02:00
|
|
|
//------------------------------------------------------------------------------
|
2011-02-19 08:33:46 +01:00
|
|
|
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
|
|
} // extern "C"
|
|
|
|
#endif
|
|
|
|
|
2011-09-07 11:26:35 +02:00
|
|
|
#endif /* WEBP_UTILS_BIT_WRITER_H_ */
|