blob: ab23c47c4467dc991a269de7dfdadd70778bc650 [file]
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -----------------------------------------------------------------------------
//
// Color Cache for WebP Lossless
//
// Authors: Vincent Rabaud (vrabaud@google.com)
#ifndef WP2_COMMON_LOSSLESS_COLOR_CACHE_H_
#define WP2_COMMON_LOSSLESS_COLOR_CACHE_H_
#include <cassert>
#include <cstdint>
#include <cstring>
#include "src/utils/utils.h"
#include "src/utils/vector.h"
#include "src/wp2/base.h"
namespace WP2L {
// Returns true if the two colors are equal.
template <typename T>
static inline bool ColorEq(const T* color1, const T* color2) {
return (std::memcmp(color1, color2, 4 * sizeof(T)) == 0);
}
template <typename T>
static inline void ColorCopy(const T* color1, T* color2) {
std::memcpy(color2, color1, 4 * sizeof(T));
}
// Color cache that behaves like a map with (key,value), where the key is a
// color and the value whatever uint32_t the user wants.
class ColorCacheMap {
public:
WP2Status Allocate(uint32_t color_num_max);
void Reset();
// Inserts the tuple (color, value). Returns true if the tuple was actually
// inserted, false if it was already present.
bool Insert(const int16_t color[4], uint32_t value);
// Returns whether the cache contains the value, and also gives back the index
// accordingly.
bool Contains(const int16_t color[4], uint32_t* value) const;
// Copy the palette into a buffer.
void GetPalette(int16_t* palette) const;
private:
struct Color {
int16_t color[4];
uint16_t value;
};
WP2::VectorNoCtor<Color> colors_;
WP2::VectorNoCtor<bool> is_present_;
int hash_bits_ = 0;
};
enum class CacheType {
kNone,
kHash,
kFifo,
};
// Color cache and segment cache configs.
struct CacheConfig {
CacheType type; // color cache
uint32_t cache_bits; // color cache
bool use_segment_cache; // segment cache
};
// A generic color cache.
class ColorCache : public WP2Allocable {
public:
virtual ~ColorCache() = default;
virtual void Lookup(uint32_t index, int16_t* dest) const = 0;
// Inserts the color in the cache. Returns true if the color was actually
// inserted, false if it was already present. If false, sets index_ptr to the
// index for this color *prior to inserting*.
virtual bool Insert(const int16_t color[4], uint32_t* index_ptr) = 0;
// Returns whether the cache contains the value, and also gives back the index
// accordingly.
virtual bool Contains(const int16_t color[4], uint32_t* index_ptr) const = 0;
// Returns the range of a color index given the current state of the cache
// (e.g. number of colors in the cache).
virtual uint32_t IndexRange() const = 0;
virtual void Reset() = 0;
};
// Struct that own a color cache pointer.
struct ColorCachePtr {
// Instantiates and inits the color cache based on the given config.
WP2Status Init(CacheConfig config);
~ColorCachePtr() { delete cache; }
ColorCache* operator->() { return cache; }
ColorCache* get() const { return cache; }
ColorCache* cache = nullptr;
};
// Max range of the cache index for the given cache config.
uint32_t GetColorCacheRange(CacheConfig config);
// Very fast hash-based color cache. A given color always has the same index,
// and only gets evicted when a different color with the same hash is inserted.
class HashColorCache : public ColorCache {
public:
// Initializes the color cache with 'hash_bits' bits for the hashes.
// Returns false in case of memory error.
WP2_NO_DISCARD bool Allocate(uint32_t hash_bits);
void Lookup(uint32_t index, int16_t* dest) const override;
bool Insert(const int16_t color[4], uint32_t* index_ptr) override;
bool Contains(const int16_t color[4], uint32_t* index_ptr) const override;
uint32_t IndexRange() const override;
void Reset() override;
private:
WP2::Vector_s16 colors_; // color entries
int hash_bits_ = 0;
};
class FifoColorCache : public ColorCache {
public:
// Initializes the color cache with a size of 1<<cache_bits.
// Returns false in case of memory error.
WP2_NO_DISCARD bool Allocate(uint32_t cache_bits);
void Lookup(uint32_t index, int16_t* dest) const override;
bool Insert(const int16_t color[4], uint32_t* index_ptr) override;
bool Contains(const int16_t color[4], uint32_t* index_ptr) const override;
uint32_t IndexRange() const override;
void Reset() override;
private:
WP2::Vector_s16 colors_; // color entries
uint32_t cache_bits_ = 0;
uint32_t num_colors_ = 0;
};
// Color cache that mixes two other caches.
class HybridColorCache : public ColorCache {
public:
void Init(ColorCache* cache1, ColorCache* cache2);
void Lookup(uint32_t index, int16_t* dest) const override;
bool Insert(const int16_t color[4], uint32_t* index_ptr) override;
bool Contains(const int16_t color[4], uint32_t* index_ptr) const override;
uint32_t IndexRange() const override;
void Reset() override;
private:
ColorCache* cache1_;
ColorCache* cache2_;
};
// A cache for indexed colors (a color is just an uint16_t, so this is
// basically a remapping). Colors start in increasing order, and any color can
// be moved to the front, with all other colors shifted to the back.
class MoveToFrontCache {
public:
// enabled: if false, this cache never actually moves colors
WP2Status Init(bool enabled, uint32_t num_colors);
// Resets colors to the initial sorted order.
void Reset();
// Moves the given color to index 0. Colors that were in front of this one get
// shifted towards the back.
void MoveToFront(uint16_t color);
// Returns the index of this color in the cache.
uint16_t GetIndex(uint16_t color) const;
// Returns the color at this index.
uint16_t GetColor(uint16_t idx) const;
uint16_t num_colors() const { return num_colors_; }
bool enabled() const { return enabled_; }
private:
bool enabled_;
uint16_t num_colors_;
WP2::Vector_u16 colors_;
WP2::Vector_u16 indices_;
};
} // namespace WP2L
#endif // WP2_COMMON_LOSSLESS_COLOR_CACHE_H_