blob: 6066d26d5ec1308e5ad2ac250a4f159fe36d269e [file] [log] [blame]
// 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
//
// Author: Vincent Rabaud (vrabaud@google.com)
#ifndef WP2_ENC_LOSSLESS_PALETTE_H_
#define WP2_ENC_LOSSLESS_PALETTE_H_
#include "src/common/progress_watcher.h"
#include "src/utils/ans.h"
#include "src/utils/ans_enc.h"
#include "src/utils/vector.h"
#include "src/wp2/base.h"
#include "src/wp2/format_constants.h"
namespace WP2L {
// Forward declare.
class Encoder;
class InternalParams;
class Palette {
public:
// Color sorting technique.
// kLexicographic: colors in lexicographic order
// kMinimalSize: the palette storage size is minimized
// kLuminance: colors are first sorted by alpha, and then by
// luma = 0.299 * R + 0.587 * G + 0.114 * B
// kUndefined: modified Zeng from the paper "On the relation between Memon's
// and the modified Zeng's palette reordering methods".
enum class Sorting {
kLexicographic,
kMinimalSize,
kLuminance,
kModifiedZeng,
kUndefined
};
Palette() : num_colors_(0) {}
void Init(WP2SampleFormat format, bool has_alpha) {
format_ = format;
has_alpha_ = has_alpha;
}
// Populates the palette with colors from the given 'pic'.
// If the unique color count is more than kMaxPaletteSize (or if there is only
// one color), the resulting palette will be disabled (Size() returns 0).
WP2Status AnalyzeAndCreate(const WP2::ArgbBuffer& pic);
// Remaps argb values in 'pic' to packed palettes entries in dst[].
// We assume that all values in 'pic' have a corresponding entry in the
// palette.
// Should be called after calling FindBestMethod() since the order of colors
// can be changed on write.
WP2Status Apply(const WP2::ArgbBuffer& pic, int16_t* dst) const;
// Returns the number of colors in the palette. Returns 0 if AnalyzeAndCreate
// hasn't been called or if it was called on an image with more than
// kMaxPaletteSize unique colors or less than two colors.
uint32_t Size() const { return num_colors_; }
// Try to find the best writing method 'method_'. Might reorder the colors_.
// The storage cost cost_ will be calculated.
// The 'effort' parameter impacts the depth of analyzis to get a better cost.
WP2Status FindBestMethod(const WP2::ArgbBuffer& pic,
const WP2::ProgressRange& progress, Sorting type,
int effort, Encoder* const encoder);
// Returns the bit cost of the current palette, set by FindBestMethod().
float GetCost() const { return cost_; }
// Writes the palette to the provided bitwriter 'enc' according to method_.
WP2Status Write(const WP2::ProgressRange& progress,
WP2::ANSEncBase* const enc, WP2::ANSDictionaries* const dicts,
Encoder* const encoder) const;
// for debugging
const WP2::Vector_s16& GetColors() const { return colors_; }
private:
bool IsGrayScale() const; // returns true if palette is grayscale (r==b==g)
// Sort the palette so that it takes the least space to store.
WP2Status SortMinimalSize(const WP2::ProgressRange& progress, int effort,
float cost_header, Encoder* const encoder,
InternalParams* const params);
// Sort the palette so that it is sorted by luminance.
WP2Status SortLuminance(const WP2::ProgressRange& progress, int effort,
float cost_header, Encoder* const encoder,
InternalParams* const params);
// Sort according to the modified Zeng's method.
WP2Status SortModifiedZeng(const WP2::ArgbBuffer& pic,
const WP2::ProgressRange& progress, int effort,
float cost_header, Encoder* const encoder,
InternalParams* const params);
// try coding a palette 'colors' and if it has a better cost_, set it as the
// new colors_.
WP2Status TryPalette(float cost_header, WP2::Vector_s16& colors,
const WP2::ProgressRange& progress,
Encoder* const encoder, InternalParams* const params,
bool also_as_image = true);
private:
WP2SampleFormat format_;
bool has_alpha_ = false;
bool is_grayscale_ = false;
WP2::Vector_s16 colors_;
uint32_t num_colors_ = 0; // 0 = palette is disabled
uint32_t max_palette_size_ = 0; // depends on picture
bool full_optimize_ = false; // depending on size, do full size-optimization
// The following is updated after calling AnalyzeAndCreate().
enum PaletteStorageMethod {
kMethodVerbatim = 0, // store as-is
kMethodImage, // Store as an image.
// Store as a list of values in range [0:previous value] or [previous
// value:channel_max] (whichever is best according to the sign).
kMethodList
} method_ = kMethodVerbatim;
float cost_;
Sorting sort_type_ = Sorting::kUndefined;
};
} // namespace WP2L
#endif // WP2_ENC_LOSSLESS_PALETTE_H_