lossless.h revision 8b720228d581a84fd173b6dcb2fa295b59db489a
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// Image transforms and color space conversion methods for lossless decoder.
11//
12// Authors: Vikas Arora (vikaas.arora@gmail.com)
13//          Jyrki Alakuijala (jyrki@google.com)
14
15#ifndef WEBP_DSP_LOSSLESS_H_
16#define WEBP_DSP_LOSSLESS_H_
17
18#include "webp/types.h"
19#include "webp/decode.h"
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25//------------------------------------------------------------------------------
26//
27
28typedef uint32_t (*VP8LPredClampedAddSubFunc)(uint32_t c0, uint32_t c1,
29                                              uint32_t c2);
30typedef uint32_t (*VP8LPredSelectFunc)(uint32_t c0, uint32_t c1, uint32_t c2);
31typedef void (*VP8LSubtractGreenFromBlueAndRedFunc)(uint32_t* argb_data,
32                                                    int num_pixs);
33typedef void (*VP8LAddGreenToBlueAndRedFunc)(uint32_t* data_start,
34                                             const uint32_t* data_end);
35
36extern VP8LPredClampedAddSubFunc VP8LClampedAddSubtractFull;
37extern VP8LPredClampedAddSubFunc VP8LClampedAddSubtractHalf;
38extern VP8LPredSelectFunc VP8LSelect;
39extern VP8LSubtractGreenFromBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
40extern VP8LAddGreenToBlueAndRedFunc VP8LAddGreenToBlueAndRed;
41
42// Must be called before calling any of the above methods.
43void VP8LDspInit(void);
44
45//------------------------------------------------------------------------------
46// Image transforms.
47
48struct VP8LTransform;  // Defined in dec/vp8li.h.
49
50// Performs inverse transform of data given transform information, start and end
51// rows. Transform will be applied to rows [row_start, row_end[.
52// The *in and *out pointers refer to source and destination data respectively
53// corresponding to the intermediate row (row_start).
54void VP8LInverseTransform(const struct VP8LTransform* const transform,
55                          int row_start, int row_end,
56                          const uint32_t* const in, uint32_t* const out);
57
58// Similar to the static method ColorIndexInverseTransform() that is part of
59// lossless.c, but used only for alpha decoding. It takes uint8_t (rather than
60// uint32_t) arguments for 'src' and 'dst'.
61void VP8LColorIndexInverseTransformAlpha(
62    const struct VP8LTransform* const transform, int y_start, int y_end,
63    const uint8_t* src, uint8_t* dst);
64
65void VP8LResidualImage(int width, int height, int bits,
66                       uint32_t* const argb, uint32_t* const argb_scratch,
67                       uint32_t* const image);
68
69void VP8LColorSpaceTransform(int width, int height, int bits, int step,
70                             uint32_t* const argb, uint32_t* image);
71
72//------------------------------------------------------------------------------
73// Color space conversion.
74
75// Converts from BGRA to other color spaces.
76void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
77                         WEBP_CSP_MODE out_colorspace, uint8_t* const rgba);
78
79//------------------------------------------------------------------------------
80// Misc methods.
81
82// Computes sampled size of 'size' when sampling using 'sampling bits'.
83static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size,
84                                              uint32_t sampling_bits) {
85  return (size + (1 << sampling_bits) - 1) >> sampling_bits;
86}
87
88// Faster logarithm for integers. Small values use a look-up table.
89#define LOG_LOOKUP_IDX_MAX 256
90extern const float kLog2Table[LOG_LOOKUP_IDX_MAX];
91extern const float kSLog2Table[LOG_LOOKUP_IDX_MAX];
92float VP8LFastLog2Slow(int v);
93float VP8LFastSLog2Slow(int v);
94static WEBP_INLINE float VP8LFastLog2(int v) {
95  return (v < LOG_LOOKUP_IDX_MAX) ? kLog2Table[v] : VP8LFastLog2Slow(v);
96}
97// Fast calculation of v * log2(v) for integer input.
98static WEBP_INLINE float VP8LFastSLog2(int v) {
99  return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v);
100}
101
102// -----------------------------------------------------------------------------
103// PrefixEncode()
104
105// use GNU builtins where available.
106#if defined(__GNUC__) && \
107    ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
108static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
109  return 31 ^ __builtin_clz(n);
110}
111#elif defined(_MSC_VER) && _MSC_VER > 1310 && \
112      (defined(_M_X64) || defined(_M_IX86))
113#include <intrin.h>
114#pragma intrinsic(_BitScanReverse)
115
116static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
117  unsigned long first_set_bit;
118  _BitScanReverse(&first_set_bit, n);
119  return first_set_bit;
120}
121#else
122// Returns (int)floor(log2(n)). n must be > 0.
123static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
124  int log = 0;
125  uint32_t value = n;
126  int i;
127
128  for (i = 4; i >= 0; --i) {
129    const int shift = (1 << i);
130    const uint32_t x = value >> shift;
131    if (x != 0) {
132      value = x;
133      log += shift;
134    }
135  }
136  return log;
137}
138#endif
139
140static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
141  const int log_floor = BitsLog2Floor(n);
142  if (n == (n & ~(n - 1)))  // zero or a power of two.
143    return log_floor;
144  else
145    return log_floor + 1;
146}
147
148// Splitting of distance and length codes into prefixes and
149// extra bits. The prefixes are encoded with an entropy code
150// while the extra bits are stored just as normal bits.
151static WEBP_INLINE void VP8LPrefixEncodeBitsNoLUT(int distance, int* const code,
152                                                  int* const extra_bits) {
153  const int highest_bit = BitsLog2Floor(--distance);
154  const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
155  *extra_bits = highest_bit - 1;
156  *code = 2 * highest_bit + second_highest_bit;
157}
158
159static WEBP_INLINE void VP8LPrefixEncodeNoLUT(int distance, int* const code,
160                                              int* const extra_bits,
161                                              int* const extra_bits_value) {
162  const int highest_bit = BitsLog2Floor(--distance);
163  const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
164  *extra_bits = highest_bit - 1;
165  *extra_bits_value = distance & ((1 << *extra_bits) - 1);
166  *code = 2 * highest_bit + second_highest_bit;
167}
168
169#define PREFIX_LOOKUP_IDX_MAX   512
170typedef struct {
171  int8_t code_;
172  int8_t extra_bits_;
173} VP8LPrefixCode;
174
175// These tables are derived using VP8LPrefixEncodeNoLUT.
176extern const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX];
177extern const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX];
178static WEBP_INLINE void VP8LPrefixEncodeBits(int distance, int* const code,
179                                             int* const extra_bits) {
180  if (distance < PREFIX_LOOKUP_IDX_MAX) {
181    const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
182    *code = prefix_code.code_;
183    *extra_bits = prefix_code.extra_bits_;
184  } else {
185    VP8LPrefixEncodeBitsNoLUT(distance, code, extra_bits);
186  }
187}
188
189static WEBP_INLINE void VP8LPrefixEncode(int distance, int* const code,
190                                         int* const extra_bits,
191                                         int* const extra_bits_value) {
192  if (distance < PREFIX_LOOKUP_IDX_MAX) {
193    const VP8LPrefixCode prefix_code = kPrefixEncodeCode[distance];
194    *code = prefix_code.code_;
195    *extra_bits = prefix_code.extra_bits_;
196    *extra_bits_value = kPrefixEncodeExtraBitsValue[distance];
197  } else {
198    VP8LPrefixEncodeNoLUT(distance, code, extra_bits, extra_bits_value);
199  }
200}
201
202// In-place difference of each component with mod 256.
203static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
204  const uint32_t alpha_and_green =
205      0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
206  const uint32_t red_and_blue =
207      0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
208  return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
209}
210
211void VP8LBundleColorMap(const uint8_t* const row, int width,
212                        int xbits, uint32_t* const dst);
213
214//------------------------------------------------------------------------------
215
216#ifdef __cplusplus
217}    // extern "C"
218#endif
219
220#endif  // WEBP_DSP_LOSSLESS_H_
221