lossless: 0.13% compression density gain

over a 1000 image corpus

Single photograph benchmark:
Before:
Q=20: 2.560 MP/s
Q=40: 2.593 MP/s
Q=60: 1.795 MP/s
Q=80: 1.603 MP/s
Q=99: 1.122 MP/s

After:
Q=20: 3.334 MP/s
Q=40: 2.464 MP/s
Q=60: 2.009 MP/s
Q=80: 1.871 MP/s
Q=99: 1.163 MP/s

This CL allows for some further improvements that would not be possible
otherwise.

Change-Id: I61ba154beca2266cb96469281cf96e84a4412586
This commit is contained in:
Jyrki Alakuijala 2015-05-29 10:58:34 +00:00 committed by James Zern
parent 64960da9e1
commit 2beef2f245

View File

@ -935,49 +935,55 @@ static float GetPredictionCostCrossColorBlue(
return cur_diff; return cur_diff;
} }
#define kGreenRedToBlueNumAxis 8
#define kGreenRedToBlueMaxIters 7
static void GetBestGreenRedToBlue( static void GetBestGreenRedToBlue(
const uint32_t* argb, int stride, int tile_width, int tile_height, const uint32_t* argb, int stride, int tile_width, int tile_height,
VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
const int accumulated_blue_histo[256], const int accumulated_blue_histo[256],
VP8LMultipliers* const best_tx) { VP8LMultipliers* const best_tx) {
float best_diff = MAX_DIFF_COST; const int8_t offset[kGreenRedToBlueNumAxis][2] =
float cur_diff; {{0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
const int step = (quality < 25) ? 32 : (quality > 50) ? 8 : 16; const int8_t delta_lut[kGreenRedToBlueMaxIters] = { 16, 16, 8, 4, 2, 2, 2 };
const int min_green_to_blue = -32; const int iters =
const int max_green_to_blue = 32; (quality < 25) ? 1 : (quality > 50) ? kGreenRedToBlueMaxIters : 4;
const int min_red_to_blue = -32; int green_to_blue_best = 0;
const int max_red_to_blue = 32; int red_to_blue_best = 0;
const int num_iters = int iter;
(1 + (max_green_to_blue - min_green_to_blue) / step) * // Initial value at origin:
(1 + (max_red_to_blue - min_red_to_blue) / step); float best_diff = GetPredictionCostCrossColorBlue(
// Number of tries to get optimal green_to_blue & red_to_blue color transforms argb, stride, tile_width, tile_height, prev_x, prev_y,
// after finding a local minima. green_to_blue_best, red_to_blue_best, accumulated_blue_histo);
const int max_tries_after_min = 4 + (num_iters >> 2); for (iter = 0; iter < iters; ++iter) {
int num_tries_after_min = 0; const int delta = delta_lut[iter];
int green_to_blue; int axis;
for (green_to_blue = min_green_to_blue; for (axis = 0; axis < kGreenRedToBlueNumAxis; ++axis) {
green_to_blue <= max_green_to_blue && const int green_to_blue_cur =
num_tries_after_min < max_tries_after_min; offset[axis][0] * delta + green_to_blue_best;
green_to_blue += step) { const int red_to_blue_cur = offset[axis][1] * delta + red_to_blue_best;
int red_to_blue; const float cur_diff = GetPredictionCostCrossColorBlue(
for (red_to_blue = min_red_to_blue;
red_to_blue <= max_red_to_blue &&
num_tries_after_min < max_tries_after_min;
red_to_blue += step) {
cur_diff = GetPredictionCostCrossColorBlue(
argb, stride, tile_width, tile_height, prev_x, prev_y, argb, stride, tile_width, tile_height, prev_x, prev_y,
green_to_blue, red_to_blue, accumulated_blue_histo); green_to_blue_cur, red_to_blue_cur, accumulated_blue_histo);
if (cur_diff < best_diff) { if (cur_diff < best_diff) {
best_diff = cur_diff; best_diff = cur_diff;
best_tx->green_to_blue_ = green_to_blue; green_to_blue_best = green_to_blue_cur;
best_tx->red_to_blue_ = red_to_blue; red_to_blue_best = red_to_blue_cur;
num_tries_after_min = 0; }
} else { if (quality < 25 && iter == 4) {
++num_tries_after_min; // Only axis aligned diffs for lower quality.
break; // next iter.
} }
} }
if (delta == 2 && green_to_blue_best == 0 && red_to_blue_best == 0) {
// Further iterations would not help.
break; // out of iter-loop.
}
} }
best_tx->green_to_blue_ = green_to_blue_best;
best_tx->red_to_blue_ = red_to_blue_best;
} }
#undef kGreenRedToBlueMaxIters
#undef kGreenRedToBlueNumAxis
static VP8LMultipliers GetBestColorTransformForTile( static VP8LMultipliers GetBestColorTransformForTile(
int tile_x, int tile_y, int bits, int tile_x, int tile_y, int bits,