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:
Urvang Joshi 2012-04-13 07:01:11 +00:00 committed by James Zern
parent 84547f540c
commit b2f99465a7
4 changed files with 57 additions and 40 deletions

View File

@ -398,44 +398,55 @@ static int GetBestPredictorForTile(int tile_x, int tile_y, int max_tile_size,
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,
uint32_t* const argb_scratch,
uint32_t* const argb) {
int ymax = 1 << bits;
int xmax = 1 << bits;
int y;
const int col_start = tile_x << bits;
const int row_start = tile_y << bits;
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];
if (ymax > ysize - (tile_y << bits)) {
ymax = ysize - (tile_y << bits);
}
if (xmax > xsize - (tile_x << bits)) {
xmax = xsize - (tile_x << bits);
}
uint32_t* const top_row = argb_scratch;
uint32_t* const current_row = argb_scratch + width;
int y;
for (y = 0; y < ymax; ++y) {
const int all_y = (tile_y << bits) + y;
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) {
const int all_x = (tile_x << bits) + x;
const int ix = all_y * xsize + all_x;
const int col = col_start + x;
const int pix = row * width + col;
uint32_t predict;
if (all_y == 0) {
if (all_x == 0) {
if (row == 0) {
if (col == 0) {
predict = ARGB_BLACK;
} else {
predict = argb[ix - 1];
const uint32_t left = current_row[col - 1];
predict = left;
}
} else if (all_x == 0) {
predict = argb[ix - xsize];
} else if (col == 0) {
const uint32_t top = top_row[col];
predict = top;
} 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,
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 tile_xsize = VP8LSubSampleSize(width, 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,
width, height, histo, argb);
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) {
int ix;
int all_x;

View File

@ -38,7 +38,8 @@ void VP8LInverseTransform(const struct VP8LTransform* const transform,
void VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs);
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,
uint32_t* const argb, uint32_t* image);
@ -67,8 +68,10 @@ double VP8LFastLog(int v);
// In-place difference of each component with mod 256.
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 red_and_blue = (a & 0x00ff00ffu) - (b & 0x00ff00ffu);
const uint32_t alpha_and_green =
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);
}
#endif

View File

@ -928,7 +928,8 @@ static int ApplyPredictFilter(VP8LBitWriter* const bw,
const int transform_width = VP8LSubSampleSize(width, 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, 2, 0);
VP8LWriteBits(bw, 4, pred_bits);
@ -1020,9 +1021,7 @@ static WebPEncodingError WriteImage(VP8LEncoder* const enc,
static VP8LEncoder* InitVP8LEncoder(const WebPConfig* const config,
WebPPicture* const picture) {
VP8LEncoder* enc;
enc = (VP8LEncoder*)malloc(sizeof(*enc));
VP8LEncoder* enc = (VP8LEncoder*)malloc(sizeof(*enc));
if (enc == NULL) {
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
return NULL;
@ -1034,8 +1033,6 @@ static VP8LEncoder* InitVP8LEncoder(const WebPConfig* const config,
enc->use_lz77_ = 1;
enc->palette_bits_ = 7;
enc->argb_ = NULL;
// TODO: Use config.quality to initialize histo_bits_ and transform_bits_.
enc->histo_bits_ = 4;
enc->transform_bits_ = 4;
@ -1058,25 +1055,28 @@ static void DeleteVP8LEncoder(VP8LEncoder* enc) {
free(enc);
}
// Allocates the memory for argb (W x H) buffer and transform data.
// Former buffer (argb_) will hold the argb data from successive image
// 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_.
// Allocates the memory for argb (W x H) buffer, 2 rows of context for
// prediction and transform data.
static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
int height, int width) {
WebPEncodingError err = VP8_ENC_OK;
const size_t image_size = height * width;
const size_t argb_scratch_size = 2 * width;
const size_t transform_data_size =
VP8LSubSampleSize(height, enc->transform_bits_) *
VP8LSubSampleSize(width, enc->transform_bits_);
const size_t total_size = image_size + transform_data_size;
enc->argb_ = (uint32_t*)malloc(total_size * sizeof(*enc->argb_));
if (enc->argb_ == NULL) {
const size_t total_size =
image_size + argb_scratch_size + transform_data_size;
uint32_t* mem = (uint32_t*)malloc(total_size * sizeof(*mem));
if (mem == NULL) {
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
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;
Error:

View File

@ -38,6 +38,8 @@ typedef struct {
WebPPicture* pic_; // input picture.
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.
int current_width_; // Corresponds to packed image width.