#ifndef WEBP_ENC_BACKWARD_REFERENCES_ENC_H_
#define WEBP_ENC_BACKWARD_REFERENCES_ENC_H_
#include <assert.h>
#include <stdlib.h>
#include "src/webp/types.h"
#include "src/webp/encode.h"
#include "src/webp/format_constants.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_COLOR_CACHE_BITS 10
enum Mode {
kLiteral,
kCacheIdx,
kCopy,
kNone
};
typedef struct {
uint8_t mode;
uint16_t len;
uint32_t argb_or_distance;
} PixOrCopy;
static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
uint16_t len) {
PixOrCopy retval;
retval.mode = kCopy;
retval.argb_or_distance = distance;
retval.len = len;
return retval;
}
static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) {
PixOrCopy retval;
assert(idx >= 0);
assert(idx < (1 << MAX_COLOR_CACHE_BITS));
retval.mode = kCacheIdx;
retval.argb_or_distance = idx;
retval.len = 1;
return retval;
}
static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) {
PixOrCopy retval;
retval.mode = kLiteral;
retval.argb_or_distance = argb;
retval.len = 1;
return retval;
}
static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) {
return (p->mode == kLiteral);
}
static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) {
return (p->mode == kCacheIdx);
}
static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) {
return (p->mode == kCopy);
}
static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p,
int component) {
assert(p->mode == kLiteral);
return (p->argb_or_distance >> (component * 8)) & 0xff;
}
static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) {
return p->len;
}
static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) {
assert(p->mode == kCacheIdx);
assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS));
return p->argb_or_distance;
}
static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
assert(p->mode == kCopy);
return p->argb_or_distance;
}
#define HASH_BITS 18
#define HASH_SIZE (1 << HASH_BITS)
#define MAX_LENGTH_BITS 12
#define WINDOW_SIZE_BITS 20
#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
#endif
typedef struct VP8LHashChain VP8LHashChain;
struct VP8LHashChain {
uint32_t* offset_length_;
int size_;
};
int VP8LHashChainInit(VP8LHashChain* const p, int size);
int VP8LHashChainFill(VP8LHashChain* const p, int quality,
const uint32_t* const argb, int xsize, int ysize,
int low_effort, const WebPPicture* const pic,
int percent_range, int* const percent);
void VP8LHashChainClear(VP8LHashChain* const p);
static WEBP_INLINE int VP8LHashChainFindOffset(const VP8LHashChain* const p,
const int base_position) {
return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
}
static WEBP_INLINE int VP8LHashChainFindLength(const VP8LHashChain* const p,
const int base_position) {
return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
}
static WEBP_INLINE void VP8LHashChainFindCopy(const VP8LHashChain* const p,
int base_position,
int* const offset_ptr,
int* const length_ptr) {
*offset_ptr = VP8LHashChainFindOffset(p, base_position);
*length_ptr = VP8LHashChainFindLength(p, base_position);
}
#define MAX_REFS_BLOCK_PER_IMAGE 16
typedef struct PixOrCopyBlock PixOrCopyBlock; typedef struct VP8LBackwardRefs VP8LBackwardRefs;
struct VP8LBackwardRefs {
int block_size_; int error_; PixOrCopyBlock* refs_; PixOrCopyBlock** tail_; PixOrCopyBlock* free_blocks_; PixOrCopyBlock* last_block_; };
void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size);
void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs);
typedef struct {
PixOrCopy* cur_pos; PixOrCopyBlock* cur_block_; const PixOrCopy* last_pos_; } VP8LRefsCursor;
VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs);
static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) {
return (c->cur_pos != NULL);
}
void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c);
static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) {
assert(c != NULL);
assert(VP8LRefsCursorOk(c));
if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c);
}
enum VP8LLZ77Type {
kLZ77Standard = 1,
kLZ77RLE = 2,
kLZ77Box = 4
};
int VP8LGetBackwardReferences(
int width, int height, const uint32_t* const argb, int quality,
int low_effort, int lz77_types_to_try, int cache_bits_max, int do_no_cache,
const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs,
int* const cache_bits_best, const WebPPicture* const pic, int percent_range,
int* const percent);
#ifdef __cplusplus
}
#endif
#endif