Home | History | Annotate | Download | only in enc
      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 (at) google.com)
     11 //
     12 
     13 #ifndef WEBP_ENC_BACKWARD_REFERENCES_H_
     14 #define WEBP_ENC_BACKWARD_REFERENCES_H_
     15 
     16 #include <assert.h>
     17 #include <stdlib.h>
     18 #include "../webp/types.h"
     19 #include "../webp/format_constants.h"
     20 
     21 #ifdef __cplusplus
     22 extern "C" {
     23 #endif
     24 
     25 // The maximum allowed limit is 11.
     26 #define MAX_COLOR_CACHE_BITS 10
     27 
     28 // -----------------------------------------------------------------------------
     29 // PixOrCopy
     30 
     31 enum Mode {
     32   kLiteral,
     33   kCacheIdx,
     34   kCopy,
     35   kNone
     36 };
     37 
     38 typedef struct {
     39   // mode as uint8_t to make the memory layout to be exactly 8 bytes.
     40   uint8_t mode;
     41   uint16_t len;
     42   uint32_t argb_or_distance;
     43 } PixOrCopy;
     44 
     45 static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
     46                                                  uint16_t len) {
     47   PixOrCopy retval;
     48   retval.mode = kCopy;
     49   retval.argb_or_distance = distance;
     50   retval.len = len;
     51   return retval;
     52 }
     53 
     54 static WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) {
     55   PixOrCopy retval;
     56   assert(idx >= 0);
     57   assert(idx < (1 << MAX_COLOR_CACHE_BITS));
     58   retval.mode = kCacheIdx;
     59   retval.argb_or_distance = idx;
     60   retval.len = 1;
     61   return retval;
     62 }
     63 
     64 static WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) {
     65   PixOrCopy retval;
     66   retval.mode = kLiteral;
     67   retval.argb_or_distance = argb;
     68   retval.len = 1;
     69   return retval;
     70 }
     71 
     72 static WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) {
     73   return (p->mode == kLiteral);
     74 }
     75 
     76 static WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) {
     77   return (p->mode == kCacheIdx);
     78 }
     79 
     80 static WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) {
     81   return (p->mode == kCopy);
     82 }
     83 
     84 static WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p,
     85                                              int component) {
     86   assert(p->mode == kLiteral);
     87   return (p->argb_or_distance >> (component * 8)) & 0xff;
     88 }
     89 
     90 static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) {
     91   return p->len;
     92 }
     93 
     94 static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) {
     95   assert(p->mode == kLiteral);
     96   return p->argb_or_distance;
     97 }
     98 
     99 static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) {
    100   assert(p->mode == kCacheIdx);
    101   assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS));
    102   return p->argb_or_distance;
    103 }
    104 
    105 static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
    106   assert(p->mode == kCopy);
    107   return p->argb_or_distance;
    108 }
    109 
    110 // -----------------------------------------------------------------------------
    111 // VP8LHashChain
    112 
    113 #define HASH_BITS 18
    114 #define HASH_SIZE (1 << HASH_BITS)
    115 
    116 typedef struct VP8LHashChain VP8LHashChain;
    117 struct VP8LHashChain {
    118   // Stores the most recently added position with the given hash value.
    119   int32_t hash_to_first_index_[HASH_SIZE];
    120   // chain_[pos] stores the previous position with the same hash value
    121   // for every pixel in the image.
    122   int32_t* chain_;
    123   // This is the maximum size of the hash_chain that can be constructed.
    124   // Typically this is the pixel count (width x height) for a given image.
    125   int size_;
    126 };
    127 
    128 // Must be called first, to set size.
    129 int VP8LHashChainInit(VP8LHashChain* const p, int size);
    130 void VP8LHashChainClear(VP8LHashChain* const p);  // release memory
    131 
    132 // -----------------------------------------------------------------------------
    133 // VP8LBackwardRefs (block-based backward-references storage)
    134 
    135 // maximum number of reference blocks the image will be segmented into
    136 #define MAX_REFS_BLOCK_PER_IMAGE 16
    137 
    138 typedef struct PixOrCopyBlock PixOrCopyBlock;   // forward declaration
    139 typedef struct VP8LBackwardRefs VP8LBackwardRefs;
    140 
    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 
    151 // Initialize the object. 'block_size' is the common block size to store
    152 // references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE).
    153 void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size);
    154 // Release memory for backward references.
    155 void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs);
    156 // Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error.
    157 int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
    158                          VP8LBackwardRefs* const dst);
    159 
    160 // Cursor for iterating on references content
    161 typedef struct {
    162   // public:
    163   PixOrCopy* cur_pos;           // current position
    164   // private:
    165   PixOrCopyBlock* cur_block_;   // current block in the refs list
    166   const PixOrCopy* last_pos_;   // sentinel for switching to next block
    167 } VP8LRefsCursor;
    168 
    169 // Returns a cursor positioned at the beginning of the references list.
    170 VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs);
    171 // Returns true if cursor is pointing at a valid position.
    172 static WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) {
    173   return (c->cur_pos != NULL);
    174 }
    175 // Move to next block of references. Internal, not to be called directly.
    176 void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c);
    177 // Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk().
    178 static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) {
    179   assert(c != NULL);
    180   assert(VP8LRefsCursorOk(c));
    181   if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c);
    182 }
    183 
    184 // -----------------------------------------------------------------------------
    185 // Main entry points
    186 
    187 // Evaluates best possible backward references for specified quality.
    188 // The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache
    189 // bits to use (passing 0 implies disabling the local color cache).
    190 // The optimal cache bits is evaluated and set for the *cache_bits parameter.
    191 // The return value is the pointer to the best of the two backward refs viz,
    192 // refs[0] or refs[1].
    193 VP8LBackwardRefs* VP8LGetBackwardReferences(
    194     int width, int height, const uint32_t* const argb, int quality,
    195     int low_effort, int* const cache_bits, VP8LHashChain* const hash_chain,
    196     VP8LBackwardRefs refs[2]);
    197 
    198 #ifdef __cplusplus
    199 }
    200 #endif
    201 
    202 #endif  // WEBP_ENC_BACKWARD_REFERENCES_H_
    203