backward_references_enc.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright 2012 Google Inc. All Rights Reserved.
  2. //
  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. // -----------------------------------------------------------------------------
  9. //
  10. // Author: Jyrki Alakuijala (jyrki@google.com)
  11. //
  12. #ifndef WEBP_ENC_BACKWARD_REFERENCES_ENC_H_
  13. #define WEBP_ENC_BACKWARD_REFERENCES_ENC_H_
  14. #include <assert.h>
  15. #include <stdlib.h>
  16. #include "../webp/types.h"
  17. #include "../webp/encode.h"
  18. #include "../webp/format_constants.h"
  19. #ifdef __cplusplus
  20. extern "C" {
  21. #endif
  22. // The maximum allowed limit is 11.
  23. #define MAX_COLOR_CACHE_BITS 10
  24. // -----------------------------------------------------------------------------
  25. // PixOrCopy
  26. enum Mode {
  27. kLiteral,
  28. kCacheIdx,
  29. kCopy,
  30. kNone
  31. };
  32. typedef struct {
  33. // mode as uint8_t to make the memory layout to be exactly 8 bytes.
  34. uint8_t mode;
  35. uint16_t len;
  36. uint32_t argb_or_distance;
  37. } PixOrCopy;
  38. static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
  39. uint16_t len) {
  40. PixOrCopy retval;
  41. retval.mode = kCopy;
  42. retval.argb_or_distance = distance;
  43. retval.len = len;
  44. return retval;
  45. }
  46. static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) {
  47. PixOrCopy retval;
  48. assert(idx >= 0);
  49. assert(idx < (1 << MAX_COLOR_CACHE_BITS));
  50. retval.mode = kCacheIdx;
  51. retval.argb_or_distance = idx;
  52. retval.len = 1;
  53. return retval;
  54. }
  55. static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) {
  56. PixOrCopy retval;
  57. retval.mode = kLiteral;
  58. retval.argb_or_distance = argb;
  59. retval.len = 1;
  60. return retval;
  61. }
  62. static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) {
  63. return (p->mode == kLiteral);
  64. }
  65. static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) {
  66. return (p->mode == kCacheIdx);
  67. }
  68. static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) {
  69. return (p->mode == kCopy);
  70. }
  71. static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p,
  72. int component) {
  73. assert(p->mode == kLiteral);
  74. return (p->argb_or_distance >> (component * 8)) & 0xff;
  75. }
  76. static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) {
  77. return p->len;
  78. }
  79. static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) {
  80. assert(p->mode == kCacheIdx);
  81. assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS));
  82. return p->argb_or_distance;
  83. }
  84. static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
  85. assert(p->mode == kCopy);
  86. return p->argb_or_distance;
  87. }
  88. // -----------------------------------------------------------------------------
  89. // VP8LHashChain
  90. #define HASH_BITS 18
  91. #define HASH_SIZE (1 << HASH_BITS)
  92. // If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it
  93. // is used in VP8LHashChain.
  94. #define MAX_LENGTH_BITS 12
  95. #define WINDOW_SIZE_BITS 20
  96. // We want the max value to be attainable and stored in MAX_LENGTH_BITS bits.
  97. #define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
  98. #if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
  99. #error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
  100. #endif
  101. typedef struct VP8LHashChain VP8LHashChain;
  102. struct VP8LHashChain {
  103. // The 20 most significant bits contain the offset at which the best match
  104. // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain
  105. // (through WINDOW_SIZE = 1<<20).
  106. // The lower 12 bits contain the length of the match. The 12 bit limit is
  107. // defined in MaxFindCopyLength with MAX_LENGTH=4096.
  108. uint32_t* offset_length_;
  109. // This is the maximum size of the hash_chain that can be constructed.
  110. // Typically this is the pixel count (width x height) for a given image.
  111. int size_;
  112. };
  113. // Must be called first, to set size.
  114. int VP8LHashChainInit(VP8LHashChain* const p, int size);
  115. // Pre-compute the best matches for argb.
  116. int VP8LHashChainFill(VP8LHashChain* const p, int quality,
  117. const uint32_t* const argb, int xsize, int ysize,
  118. int low_effort);
  119. void VP8LHashChainClear(VP8LHashChain* const p); // release memory
  120. static WEBP_INLINE int VP8LHashChainFindOffset(const VP8LHashChain* const p,
  121. const int base_position) {
  122. return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
  123. }
  124. static WEBP_INLINE int VP8LHashChainFindLength(const VP8LHashChain* const p,
  125. const int base_position) {
  126. return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
  127. }
  128. static WEBP_INLINE void VP8LHashChainFindCopy(const VP8LHashChain* const p,
  129. int base_position,
  130. int* const offset_ptr,
  131. int* const length_ptr) {
  132. *offset_ptr = VP8LHashChainFindOffset(p, base_position);
  133. *length_ptr = VP8LHashChainFindLength(p, base_position);
  134. }
  135. // -----------------------------------------------------------------------------
  136. // VP8LBackwardRefs (block-based backward-references storage)
  137. // maximum number of reference blocks the image will be segmented into
  138. #define MAX_REFS_BLOCK_PER_IMAGE 16
  139. typedef struct PixOrCopyBlock PixOrCopyBlock; // forward declaration
  140. typedef struct VP8LBackwardRefs VP8LBackwardRefs;
  141. // Container for blocks chain
  142. struct VP8LBackwardRefs {
  143. int block_size_; // common block-size
  144. int error_; // set to true if some memory error occurred
  145. PixOrCopyBlock* refs_; // list of currently used blocks
  146. PixOrCopyBlock** tail_; // for list recycling
  147. PixOrCopyBlock* free_blocks_; // free-list
  148. PixOrCopyBlock* last_block_; // used for adding new refs (internal)
  149. };
  150. // Initialize the object. 'block_size' is the common block size to store
  151. // references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE).
  152. void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size);
  153. // Release memory for backward references.
  154. void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs);
  155. // Cursor for iterating on references content
  156. typedef struct {
  157. // public:
  158. PixOrCopy* cur_pos; // current position
  159. // private:
  160. PixOrCopyBlock* cur_block_; // current block in the refs list
  161. const PixOrCopy* last_pos_; // sentinel for switching to next block
  162. } VP8LRefsCursor;
  163. // Returns a cursor positioned at the beginning of the references list.
  164. VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs);
  165. // Returns true if cursor is pointing at a valid position.
  166. static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) {
  167. return (c->cur_pos != NULL);
  168. }
  169. // Move to next block of references. Internal, not to be called directly.
  170. void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c);
  171. // Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk().
  172. static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) {
  173. assert(c != NULL);
  174. assert(VP8LRefsCursorOk(c));
  175. if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c);
  176. }
  177. // -----------------------------------------------------------------------------
  178. // Main entry points
  179. enum VP8LLZ77Type {
  180. kLZ77Standard = 1,
  181. kLZ77RLE = 2,
  182. kLZ77Box = 4
  183. };
  184. // Evaluates best possible backward references for specified quality.
  185. // The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache
  186. // bits to use (passing 0 implies disabling the local color cache).
  187. // The optimal cache bits is evaluated and set for the *cache_bits_best
  188. // parameter with the matching refs_best.
  189. // If do_no_cache == 0, refs is an array of 2 values and the best
  190. // VP8LBackwardRefs is put in the first element.
  191. // If do_no_cache != 0, refs is an array of 3 values and the best
  192. // VP8LBackwardRefs is put in the first element, the best value with no-cache in
  193. // the second element.
  194. // In both cases, the last element is used as temporary internally.
  195. WebPEncodingError VP8LGetBackwardReferences(
  196. int width, int height, const uint32_t* const argb, int quality,
  197. int low_effort, int lz77_types_to_try, int cache_bits_max, int do_no_cache,
  198. const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs,
  199. int* const cache_bits_best);
  200. #ifdef __cplusplus
  201. }
  202. #endif
  203. #endif // WEBP_ENC_BACKWARD_REFERENCES_ENC_H_