mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 12:28:26 +01:00
Fix CopyTileWithPrediction()
so that it uses original values of left, top etc for prediction rather than the predicted values of the same. Also, do some renaming in the same to make it more readable. Change-Id: I2fe94e35a6700bd437f5c601e2af12323bf32445
This commit is contained in:
parent
84547f540c
commit
b2f99465a7
@ -398,44 +398,55 @@ static int GetBestPredictorForTile(int tile_x, int tile_y, int max_tile_size,
|
|||||||
return best_mode;
|
return best_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyTileWithPrediction(int xsize, int ysize,
|
static void CopyTileWithPrediction(int width, int height,
|
||||||
int tile_x, int tile_y, int bits, int mode,
|
int tile_x, int tile_y, int bits, int mode,
|
||||||
|
uint32_t* const argb_scratch,
|
||||||
uint32_t* const argb) {
|
uint32_t* const argb) {
|
||||||
int ymax = 1 << bits;
|
const int col_start = tile_x << bits;
|
||||||
int xmax = 1 << bits;
|
const int row_start = tile_y << bits;
|
||||||
int y;
|
const int transform_size = 1 << bits;
|
||||||
|
const int ymax = (transform_size <= height - row_start) ?
|
||||||
|
transform_size : height - row_start;
|
||||||
|
const int xmax = (transform_size <= width - col_start) ?
|
||||||
|
transform_size : width - col_start;
|
||||||
const PredictorFunc pred_func = kPredictors[mode];
|
const PredictorFunc pred_func = kPredictors[mode];
|
||||||
if (ymax > ysize - (tile_y << bits)) {
|
uint32_t* const top_row = argb_scratch;
|
||||||
ymax = ysize - (tile_y << bits);
|
uint32_t* const current_row = argb_scratch + width;
|
||||||
}
|
|
||||||
if (xmax > xsize - (tile_x << bits)) {
|
int y;
|
||||||
xmax = xsize - (tile_x << bits);
|
|
||||||
}
|
|
||||||
for (y = 0; y < ymax; ++y) {
|
for (y = 0; y < ymax; ++y) {
|
||||||
const int all_y = (tile_y << bits) + y;
|
|
||||||
int x;
|
int x;
|
||||||
|
const int row = row_start + y;
|
||||||
|
// Update current_row & top_row.
|
||||||
|
if (row > 0) {
|
||||||
|
memcpy(top_row, current_row, width * sizeof(*top_row));
|
||||||
|
}
|
||||||
|
memcpy(current_row, &argb[row * width], width * sizeof(*current_row));
|
||||||
for (x = 0; x < xmax; ++x) {
|
for (x = 0; x < xmax; ++x) {
|
||||||
const int all_x = (tile_x << bits) + x;
|
const int col = col_start + x;
|
||||||
const int ix = all_y * xsize + all_x;
|
const int pix = row * width + col;
|
||||||
uint32_t predict;
|
uint32_t predict;
|
||||||
if (all_y == 0) {
|
if (row == 0) {
|
||||||
if (all_x == 0) {
|
if (col == 0) {
|
||||||
predict = ARGB_BLACK;
|
predict = ARGB_BLACK;
|
||||||
} else {
|
} else {
|
||||||
predict = argb[ix - 1];
|
const uint32_t left = current_row[col - 1];
|
||||||
|
predict = left;
|
||||||
}
|
}
|
||||||
} else if (all_x == 0) {
|
} else if (col == 0) {
|
||||||
predict = argb[ix - xsize];
|
const uint32_t top = top_row[col];
|
||||||
|
predict = top;
|
||||||
} else {
|
} else {
|
||||||
predict = pred_func(argb + ix, argb + ix - xsize);
|
predict = pred_func(argb + pix, top_row + col);
|
||||||
}
|
}
|
||||||
argb[ix] = VP8LSubPixels(argb[ix], predict);
|
argb[pix] = VP8LSubPixels(argb[pix], predict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LResidualImage(int width, int height, int bits,
|
void VP8LResidualImage(int width, int height, int bits,
|
||||||
uint32_t* const argb, uint32_t* const image) {
|
uint32_t* const argb, uint32_t* const argb_scratch,
|
||||||
|
uint32_t* const image) {
|
||||||
const int max_tile_size = 1 << bits;
|
const int max_tile_size = 1 << bits;
|
||||||
const int tile_xsize = VP8LSubSampleSize(width, bits);
|
const int tile_xsize = VP8LSubSampleSize(width, bits);
|
||||||
const int tile_ysize = VP8LSubSampleSize(height, bits);
|
const int tile_ysize = VP8LSubSampleSize(height, bits);
|
||||||
@ -456,7 +467,8 @@ void VP8LResidualImage(int width, int height, int bits,
|
|||||||
pred = GetBestPredictorForTile(tile_x, tile_y, max_tile_size,
|
pred = GetBestPredictorForTile(tile_x, tile_y, max_tile_size,
|
||||||
width, height, histo, argb);
|
width, height, histo, argb);
|
||||||
image[tile_y * tile_xsize + tile_x] = 0xff000000u | (pred << 8);
|
image[tile_y * tile_xsize + tile_x] = 0xff000000u | (pred << 8);
|
||||||
CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred, argb);
|
CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
|
||||||
|
argb_scratch, argb);
|
||||||
for (y = 0; y < max_tile_size; ++y) {
|
for (y = 0; y < max_tile_size; ++y) {
|
||||||
int ix;
|
int ix;
|
||||||
int all_x;
|
int all_x;
|
||||||
|
@ -38,7 +38,8 @@ void VP8LInverseTransform(const struct VP8LTransform* const transform,
|
|||||||
void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs);
|
void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs);
|
||||||
|
|
||||||
void VP8LResidualImage(int width, int height, int bits,
|
void VP8LResidualImage(int width, int height, int bits,
|
||||||
uint32_t* const argb, uint32_t* const image);
|
uint32_t* const argb, uint32_t* const argb_scratch,
|
||||||
|
uint32_t* const image);
|
||||||
|
|
||||||
void VP8LColorSpaceTransform(int width, int height, int bits, int step,
|
void VP8LColorSpaceTransform(int width, int height, int bits, int step,
|
||||||
uint32_t* const argb, uint32_t* image);
|
uint32_t* const argb, uint32_t* image);
|
||||||
@ -67,8 +68,10 @@ double VP8LFastLog(int v);
|
|||||||
|
|
||||||
// In-place difference of each component with mod 256.
|
// In-place difference of each component with mod 256.
|
||||||
static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
|
static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
|
||||||
const uint32_t alpha_and_green = (a & 0xff00ff00u) - (b & 0xff00ff00u);
|
const uint32_t alpha_and_green =
|
||||||
const uint32_t red_and_blue = (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
|
0x00ff00ffu + (a & 0xff00ff00u) - (b & 0xff00ff00u);
|
||||||
|
const uint32_t red_and_blue =
|
||||||
|
0xff00ff00u + (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
|
||||||
return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
|
return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -928,7 +928,8 @@ static int ApplyPredictFilter(VP8LBitWriter* const bw,
|
|||||||
const int transform_width = VP8LSubSampleSize(width, pred_bits);
|
const int transform_width = VP8LSubSampleSize(width, pred_bits);
|
||||||
const int transform_height = VP8LSubSampleSize(height, pred_bits);
|
const int transform_height = VP8LSubSampleSize(height, pred_bits);
|
||||||
|
|
||||||
VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->transform_data_);
|
VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
|
||||||
|
enc->transform_data_);
|
||||||
VP8LWriteBits(bw, 1, 1);
|
VP8LWriteBits(bw, 1, 1);
|
||||||
VP8LWriteBits(bw, 2, 0);
|
VP8LWriteBits(bw, 2, 0);
|
||||||
VP8LWriteBits(bw, 4, pred_bits);
|
VP8LWriteBits(bw, 4, pred_bits);
|
||||||
@ -1020,9 +1021,7 @@ static WebPEncodingError WriteImage(VP8LEncoder* const enc,
|
|||||||
|
|
||||||
static VP8LEncoder* InitVP8LEncoder(const WebPConfig* const config,
|
static VP8LEncoder* InitVP8LEncoder(const WebPConfig* const config,
|
||||||
WebPPicture* const picture) {
|
WebPPicture* const picture) {
|
||||||
VP8LEncoder* enc;
|
VP8LEncoder* enc = (VP8LEncoder*)malloc(sizeof(*enc));
|
||||||
|
|
||||||
enc = (VP8LEncoder*)malloc(sizeof(*enc));
|
|
||||||
if (enc == NULL) {
|
if (enc == NULL) {
|
||||||
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1034,8 +1033,6 @@ static VP8LEncoder* InitVP8LEncoder(const WebPConfig* const config,
|
|||||||
enc->use_lz77_ = 1;
|
enc->use_lz77_ = 1;
|
||||||
enc->palette_bits_ = 7;
|
enc->palette_bits_ = 7;
|
||||||
|
|
||||||
enc->argb_ = NULL;
|
|
||||||
|
|
||||||
// TODO: Use config.quality to initialize histo_bits_ and transform_bits_.
|
// TODO: Use config.quality to initialize histo_bits_ and transform_bits_.
|
||||||
enc->histo_bits_ = 4;
|
enc->histo_bits_ = 4;
|
||||||
enc->transform_bits_ = 4;
|
enc->transform_bits_ = 4;
|
||||||
@ -1058,25 +1055,28 @@ static void DeleteVP8LEncoder(VP8LEncoder* enc) {
|
|||||||
free(enc);
|
free(enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocates the memory for argb (W x H) buffer and transform data.
|
// Allocates the memory for argb (W x H) buffer, 2 rows of context for
|
||||||
// Former buffer (argb_) will hold the argb data from successive image
|
// prediction and transform data.
|
||||||
// transformtions and later corresponds to prediction data (uint32) used
|
|
||||||
// for every image tile corresponding to the transformed argb_.
|
|
||||||
// The dimension of this square tile is 2^transform_bits_.
|
|
||||||
static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
|
static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
|
||||||
int height, int width) {
|
int height, int width) {
|
||||||
WebPEncodingError err = VP8_ENC_OK;
|
WebPEncodingError err = VP8_ENC_OK;
|
||||||
const size_t image_size = height * width;
|
const size_t image_size = height * width;
|
||||||
|
const size_t argb_scratch_size = 2 * width;
|
||||||
const size_t transform_data_size =
|
const size_t transform_data_size =
|
||||||
VP8LSubSampleSize(height, enc->transform_bits_) *
|
VP8LSubSampleSize(height, enc->transform_bits_) *
|
||||||
VP8LSubSampleSize(width, enc->transform_bits_);
|
VP8LSubSampleSize(width, enc->transform_bits_);
|
||||||
const size_t total_size = image_size + transform_data_size;
|
const size_t total_size =
|
||||||
enc->argb_ = (uint32_t*)malloc(total_size * sizeof(*enc->argb_));
|
image_size + argb_scratch_size + transform_data_size;
|
||||||
if (enc->argb_ == NULL) {
|
uint32_t* mem = (uint32_t*)malloc(total_size * sizeof(*mem));
|
||||||
|
if (mem == NULL) {
|
||||||
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
enc->transform_data_ = enc->argb_ + image_size;
|
enc->argb_ = mem;
|
||||||
|
mem += image_size;
|
||||||
|
enc->argb_scratch_ = mem;
|
||||||
|
mem += argb_scratch_size;
|
||||||
|
enc->transform_data_ = mem;
|
||||||
enc->current_width_ = width;
|
enc->current_width_ = width;
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
|
@ -38,6 +38,8 @@ typedef struct {
|
|||||||
WebPPicture* pic_; // input picture.
|
WebPPicture* pic_; // input picture.
|
||||||
|
|
||||||
uint32_t* argb_; // Transformed argb image data.
|
uint32_t* argb_; // Transformed argb image data.
|
||||||
|
uint32_t* argb_scratch_; // Scratch memory for current and top row.
|
||||||
|
// (used for prediction).
|
||||||
uint32_t* transform_data_; // Scratch memory for transform data.
|
uint32_t* transform_data_; // Scratch memory for transform data.
|
||||||
int current_width_; // Corresponds to packed image width.
|
int current_width_; // Corresponds to packed image width.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user