1 // Copyright 2012 Google Inc. All Rights Reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
10 // Author: Jyrki Alakuijala (jyrki@google.com)
13 #ifndef WEBP_ENC_BACKWARD_REFERENCES_H_
14 #define WEBP_ENC_BACKWARD_REFERENCES_H_
18 #include "../webp/types.h"
19 #include "../webp/format_constants.h"
25 // The spec allows 11, we use 9 bits to reduce memory consumption in encoding.
26 // Having 9 instead of 11 only removes about 0.25 % of compression density.
27 #define MAX_COLOR_CACHE_BITS 9
29 // Max ever number of codes we'll use:
30 #define PIX_OR_COPY_CODES_MAX \
31 (NUM_LITERAL_CODES + NUM_LENGTH_CODES + (1 << MAX_COLOR_CACHE_BITS))
33 // -----------------------------------------------------------------------------
44 // mode as uint8_t to make the memory layout to be exactly 8 bytes.
47 uint32_t argb_or_distance
;
50 static WEBP_INLINE PixOrCopy
PixOrCopyCreateCopy(uint32_t distance
,
54 retval
.argb_or_distance
= distance
;
59 static WEBP_INLINE PixOrCopy
PixOrCopyCreateCacheIdx(int idx
) {
62 assert(idx
< (1 << MAX_COLOR_CACHE_BITS
));
63 retval
.mode
= kCacheIdx
;
64 retval
.argb_or_distance
= idx
;
69 static WEBP_INLINE PixOrCopy
PixOrCopyCreateLiteral(uint32_t argb
) {
71 retval
.mode
= kLiteral
;
72 retval
.argb_or_distance
= argb
;
77 static WEBP_INLINE
int PixOrCopyIsLiteral(const PixOrCopy
* const p
) {
78 return (p
->mode
== kLiteral
);
81 static WEBP_INLINE
int PixOrCopyIsCacheIdx(const PixOrCopy
* const p
) {
82 return (p
->mode
== kCacheIdx
);
85 static WEBP_INLINE
int PixOrCopyIsCopy(const PixOrCopy
* const p
) {
86 return (p
->mode
== kCopy
);
89 static WEBP_INLINE
uint32_t PixOrCopyLiteral(const PixOrCopy
* const p
,
91 assert(p
->mode
== kLiteral
);
92 return (p
->argb_or_distance
>> (component
* 8)) & 0xff;
95 static WEBP_INLINE
uint32_t PixOrCopyLength(const PixOrCopy
* const p
) {
99 static WEBP_INLINE
uint32_t PixOrCopyArgb(const PixOrCopy
* const p
) {
100 assert(p
->mode
== kLiteral
);
101 return p
->argb_or_distance
;
104 static WEBP_INLINE
uint32_t PixOrCopyCacheIdx(const PixOrCopy
* const p
) {
105 assert(p
->mode
== kCacheIdx
);
106 assert(p
->argb_or_distance
< (1U << MAX_COLOR_CACHE_BITS
));
107 return p
->argb_or_distance
;
110 static WEBP_INLINE
uint32_t PixOrCopyDistance(const PixOrCopy
* const p
) {
111 assert(p
->mode
== kCopy
);
112 return p
->argb_or_distance
;
115 // -----------------------------------------------------------------------------
119 #define HASH_SIZE (1 << HASH_BITS)
121 typedef struct VP8LHashChain VP8LHashChain
;
122 struct VP8LHashChain
{
123 // Stores the most recently added position with the given hash value.
124 int32_t hash_to_first_index_
[HASH_SIZE
];
125 // chain_[pos] stores the previous position with the same hash value
126 // for every pixel in the image.
128 // This is the maximum size of the hash_chain that can be constructed.
129 // Typically this is the pixel count (width x height) for a given image.
133 // Must be called first, to set size.
134 int VP8LHashChainInit(VP8LHashChain
* const p
, int size
);
135 void VP8LHashChainClear(VP8LHashChain
* const p
); // release memory
137 // -----------------------------------------------------------------------------
138 // VP8LBackwardRefs (block-based backward-references storage)
140 // maximum number of reference blocks the image will be segmented into
141 #define MAX_REFS_BLOCK_PER_IMAGE 16
143 typedef struct PixOrCopyBlock PixOrCopyBlock
; // forward declaration
144 typedef struct VP8LBackwardRefs VP8LBackwardRefs
;
146 // Container for blocks chain
147 struct VP8LBackwardRefs
{
148 int block_size_
; // common block-size
149 int error_
; // set to true if some memory error occurred
150 PixOrCopyBlock
* refs_
; // list of currently used blocks
151 PixOrCopyBlock
** tail_
; // for list recycling
152 PixOrCopyBlock
* free_blocks_
; // free-list
153 PixOrCopyBlock
* last_block_
; // used for adding new refs (internal)
156 // Initialize the object. 'block_size' is the common block size to store
157 // references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE).
158 void VP8LBackwardRefsInit(VP8LBackwardRefs
* const refs
, int block_size
);
159 // Release memory for backward references.
160 void VP8LBackwardRefsClear(VP8LBackwardRefs
* const refs
);
161 // Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error.
162 int VP8LBackwardRefsCopy(const VP8LBackwardRefs
* const src
,
163 VP8LBackwardRefs
* const dst
);
165 // Cursor for iterating on references content
168 PixOrCopy
* cur_pos
; // current position
170 PixOrCopyBlock
* cur_block_
; // current block in the refs list
171 const PixOrCopy
* last_pos_
; // sentinel for switching to next block
174 // Returns a cursor positioned at the beginning of the references list.
175 VP8LRefsCursor
VP8LRefsCursorInit(const VP8LBackwardRefs
* const refs
);
176 // Returns true if cursor is pointing at a valid position.
177 static WEBP_INLINE
int VP8LRefsCursorOk(const VP8LRefsCursor
* const c
) {
178 return (c
->cur_pos
!= NULL
);
180 // Move to next block of references. Internal, not to be called directly.
181 void VP8LRefsCursorNextBlock(VP8LRefsCursor
* const c
);
182 // Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk().
183 static WEBP_INLINE
void VP8LRefsCursorNext(VP8LRefsCursor
* const c
) {
185 assert(VP8LRefsCursorOk(c
));
186 if (++c
->cur_pos
== c
->last_pos_
) VP8LRefsCursorNextBlock(c
);
189 // -----------------------------------------------------------------------------
192 // Evaluates best possible backward references for specified quality.
193 // Further optimize for 2D locality if use_2d_locality flag is set.
194 // The return value is the pointer to the best of the two backward refs viz,
195 // refs[0] or refs[1].
196 VP8LBackwardRefs
* VP8LGetBackwardReferences(
197 int width
, int height
, const uint32_t* const argb
, int quality
,
198 int cache_bits
, int use_2d_locality
, VP8LHashChain
* const hash_chain
,
199 VP8LBackwardRefs refs
[2]);
201 // Produce an estimate for a good color cache size for the image.
202 int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb
,
203 int xsize
, int ysize
, int quality
,
204 VP8LHashChain
* const hash_chain
,
205 VP8LBackwardRefs
* const ref
,
206 int* const best_cache_bits
);
212 #endif // WEBP_ENC_BACKWARD_REFERENCES_H_