Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 56 additions & 42 deletions src/dsp/lossless.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "src/dsp/cpu.h"
#include "src/dsp/dsp.h"
#include "src/dsp/lossless_common.h"
#include "src/utils/bounds_safety.h"
#include "src/utils/endian_inl_utils.h"
#include "src/utils/utils.h"
#include "src/webp/decode.h"
Expand Down Expand Up @@ -111,90 +112,101 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
//------------------------------------------------------------------------------
// Predictors

static uint32_t VP8LPredictor0_C(const uint32_t* const left,
const uint32_t* const top) {
// Note: 'left' is always accessed as a single element (*left); 'top' is
// accessed with negative offsets (top[-1]) in several predictors, hence it
// requires WEBP_BIDI_INDEXABLE. The caller guarantees that top[-1] and top[1]
// are within bounds (i.e. this is never called on the first pixel of a row).
static uint32_t VP8LPredictor0_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
(void)top;
(void)left;
return ARGB_BLACK;
}
static uint32_t VP8LPredictor1_C(const uint32_t* const left,
const uint32_t* const top) {
static uint32_t VP8LPredictor1_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
(void)top;
return *left;
}
uint32_t VP8LPredictor2_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor2_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
(void)left;
return top[0];
}
uint32_t VP8LPredictor3_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor3_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
(void)left;
return top[1];
}
uint32_t VP8LPredictor4_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor4_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
(void)left;
return top[-1];
return top[-1]; // Requires WEBP_BIDI_INDEXABLE: backward access at top[-1]
}
uint32_t VP8LPredictor5_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor5_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Average3(*left, top[0], top[1]);
return pred;
}
uint32_t VP8LPredictor6_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2(*left, top[-1]);
uint32_t VP8LPredictor6_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Average2(*left, top[-1]); // backward access
return pred;
}
uint32_t VP8LPredictor7_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor7_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Average2(*left, top[0]);
return pred;
}
uint32_t VP8LPredictor8_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]);
uint32_t VP8LPredictor8_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Average2(top[-1], top[0]); // backward access
(void)left;
return pred;
}
uint32_t VP8LPredictor9_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor9_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Average2(top[0], top[1]);
(void)left;
return pred;
}
uint32_t VP8LPredictor10_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Average4(*left, top[-1], top[0], top[1]);
uint32_t VP8LPredictor10_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Average4(*left, top[-1], top[0], top[1]); // backward
return pred;
}
uint32_t VP8LPredictor11_C(const uint32_t* const left,
const uint32_t* const top) {
const uint32_t pred = Select(top[0], *left, top[-1]);
uint32_t VP8LPredictor11_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = Select(top[0], *left, top[-1]); // backward access
return pred;
}
uint32_t VP8LPredictor12_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor12_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = ClampedAddSubtractFull(*left, top[0], top[-1]);
return pred;
}
uint32_t VP8LPredictor13_C(const uint32_t* const left,
const uint32_t* const top) {
uint32_t VP8LPredictor13_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top) {
const uint32_t pred = ClampedAddSubtractHalf(*left, top[0], top[-1]);
return pred;
}

static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* WEBP_RESTRICT out) {
// 'out' requires WEBP_BIDI_INDEXABLE: PredictorAdd1_C reads out[-1] as the
// left-neighbor pixel. 'upper' requires WEBP_BIDI_INDEXABLE: GENERATE_PREDICTOR_ADD
// passes 'upper + x' to predictors that may access top[-1].
static void PredictorAdd0_C(const uint32_t* WEBP_BIDI_INDEXABLE in,
const uint32_t* WEBP_BIDI_INDEXABLE upper,
int num_pixels,
uint32_t* WEBP_RESTRICT WEBP_BIDI_INDEXABLE out) {
int x;
(void)upper;
for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK);
}
static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* WEBP_RESTRICT out) {
static void PredictorAdd1_C(const uint32_t* WEBP_BIDI_INDEXABLE in,
const uint32_t* WEBP_BIDI_INDEXABLE upper,
int num_pixels,
uint32_t* WEBP_RESTRICT WEBP_BIDI_INDEXABLE out) {
int i;
uint32_t left = out[-1];
uint32_t left = out[-1]; // Backward access: requires WEBP_BIDI_INDEXABLE
(void)upper;
for (i = 0; i < num_pixels; ++i) {
out[i] = left = VP8LAddPixels(in[i], left);
Expand Down Expand Up @@ -262,8 +274,9 @@ static void PredictorInverseTransform_C(const VP8LTransform* const transform,

// Add green to blue and red channels (i.e. perform the inverse transform of
// 'subtract green').
void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels,
uint32_t* dst) {
void VP8LAddGreenToBlueAndRed_C(const uint32_t* WEBP_BIDI_INDEXABLE src,
int num_pixels,
uint32_t* WEBP_BIDI_INDEXABLE dst) {
int i;
for (i = 0; i < num_pixels; ++i) {
const uint32_t argb = src[i];
Expand All @@ -287,8 +300,9 @@ static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
}

void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
const uint32_t* src, int num_pixels,
uint32_t* dst) {
const uint32_t* WEBP_BIDI_INDEXABLE src,
int num_pixels,
uint32_t* WEBP_BIDI_INDEXABLE dst) {
int i;
for (i = 0; i < num_pixels; ++i) {
const uint32_t argb = src[i];
Expand Down
82 changes: 45 additions & 37 deletions src/dsp/lossless.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define WEBP_DSP_LOSSLESS_H_

#include "src/dsp/dsp.h"
#include "src/utils/bounds_safety.h"
#include "src/webp/decode.h"
#include "src/webp/types.h"

Expand All @@ -28,45 +29,50 @@ extern "C" {
//------------------------------------------------------------------------------
// Decoding

typedef uint32_t (*VP8LPredictorFunc)(const uint32_t* const left,
const uint32_t* const top);
// VP8LPredictorFunc: 'left' is always single-dereferenced (*left only);
// 'top' may be accessed bidirectionally (e.g. top[-1], top[0], top[1]).
typedef uint32_t (*VP8LPredictorFunc)(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
extern VP8LPredictorFunc VP8LPredictors[16];

uint32_t VP8LPredictor2_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor3_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor4_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor5_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor6_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor7_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor8_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor9_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor10_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor11_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor12_C(const uint32_t* const left,
const uint32_t* const top);
uint32_t VP8LPredictor13_C(const uint32_t* const left,
const uint32_t* const top);

// These Add/Sub function expects upper[-1] and out[-1] to be readable.
typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in,
const uint32_t* upper, int num_pixels,
uint32_t* WEBP_RESTRICT out);
uint32_t VP8LPredictor2_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor3_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor4_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor5_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor6_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor7_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor8_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor9_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor10_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor11_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor12_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);
uint32_t VP8LPredictor13_C(const uint32_t* WEBP_SINGLE const left,
const uint32_t* WEBP_BIDI_INDEXABLE const top);

// These Add/Sub functions expect upper[-1] and out[-1] to be readable.
// Hence upper and out require WEBP_BIDI_INDEXABLE (bidirectional indexing).
typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* WEBP_BIDI_INDEXABLE in,
const uint32_t* WEBP_BIDI_INDEXABLE upper,
int num_pixels,
uint32_t* WEBP_RESTRICT WEBP_BIDI_INDEXABLE out);
extern VP8LPredictorAddSubFunc VP8LPredictorsAdd[16];
extern VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16];
extern VP8LPredictorAddSubFunc VP8LPredictorsAdd_SSE[16];

typedef void (*VP8LProcessDecBlueAndRedFunc)(const uint32_t* src,
int num_pixels, uint32_t* dst);
typedef void (*VP8LProcessDecBlueAndRedFunc)(
const uint32_t* WEBP_BIDI_INDEXABLE src, int num_pixels,
uint32_t* WEBP_BIDI_INDEXABLE dst);
extern VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed;
extern VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed_SSE;

Expand Down Expand Up @@ -127,8 +133,9 @@ void VP8LColorIndexInverseTransformAlpha(

// Expose some C-only fallback functions
void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
const uint32_t* src, int num_pixels,
uint32_t* dst);
const uint32_t* WEBP_BIDI_INDEXABLE src,
int num_pixels,
uint32_t* WEBP_BIDI_INDEXABLE dst);

void VP8LConvertBGRAToRGB_C(const uint32_t* WEBP_RESTRICT src, int num_pixels,
uint8_t* WEBP_RESTRICT dst);
Expand All @@ -140,8 +147,9 @@ void VP8LConvertBGRAToRGB565_C(const uint32_t* WEBP_RESTRICT src,
int num_pixels, uint8_t* WEBP_RESTRICT dst);
void VP8LConvertBGRAToBGR_C(const uint32_t* WEBP_RESTRICT src, int num_pixels,
uint8_t* WEBP_RESTRICT dst);
void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels,
uint32_t* dst);
void VP8LAddGreenToBlueAndRed_C(const uint32_t* WEBP_BIDI_INDEXABLE src,
int num_pixels,
uint32_t* WEBP_BIDI_INDEXABLE dst);

// Must be called before calling any of the above methods.
void VP8LDspInit(void);
Expand Down