only apply color-mapping for alpha on the cropped area

This is only possible if the filtering is not VERTICAL or GRADIENT.
Otherwise, we need the spatial predictors and hence need the un-visible
part above crop_top row.

COLOR_INDEX transform is the only transform that is not predicted
from previous row. Applying the same for other transform (spatial
predict, ...) is going to be more involve and use an extra temporary row.

+ remove ApplyInverseTransformsAlpha()
(work is done directly within ExtractPalettedAlphaRows())

+ change back to using filter_ instead of unfilter_func_

Change-Id: I09e57efae4a4af00bde35f21ca6e3d73b35d7d43
This commit is contained in:
Pascal Massimino 2016-04-07 10:21:02 +02:00
parent aa809cfeb3
commit 95ecccf6dc
3 changed files with 37 additions and 39 deletions

View File

@ -52,11 +52,12 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
int rsrv; int rsrv;
int filter;
VP8Io* const io = &dec->io_; VP8Io* const io = &dec->io_;
assert(data != NULL && output != NULL && src_io != NULL); assert(data != NULL && output != NULL && src_io != NULL);
VP8FiltersInit();
dec->output_ = output;
dec->width_ = src_io->width; dec->width_ = src_io->width;
dec->height_ = src_io->height; dec->height_ = src_io->height;
assert(dec->width_ > 0 && dec->height_ > 0); assert(dec->width_ > 0 && dec->height_ > 0);
@ -66,21 +67,17 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
} }
dec->method_ = (data[0] >> 0) & 0x03; dec->method_ = (data[0] >> 0) & 0x03;
filter = (data[0] >> 2) & 0x03; dec->filter_ = (data[0] >> 2) & 0x03;
dec->pre_processing_ = (data[0] >> 4) & 0x03; dec->pre_processing_ = (data[0] >> 4) & 0x03;
rsrv = (data[0] >> 6) & 0x03; rsrv = (data[0] >> 6) & 0x03;
if (dec->method_ < ALPHA_NO_COMPRESSION || if (dec->method_ < ALPHA_NO_COMPRESSION ||
dec->method_ > ALPHA_LOSSLESS_COMPRESSION || dec->method_ > ALPHA_LOSSLESS_COMPRESSION ||
filter >= WEBP_FILTER_LAST || dec->filter_ >= WEBP_FILTER_LAST ||
dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS ||
rsrv != 0) { rsrv != 0) {
return 0; return 0;
} }
VP8FiltersInit();
dec->unfilter_func_ = WebPUnfilters[filter];
dec->output_ = output;
// Copy the necessary parameters from src_io to io // Copy the necessary parameters from src_io to io
VP8InitIo(io); VP8InitIo(io);
WebPInitCustomIo(NULL, io); WebPInitCustomIo(NULL, io);
@ -121,8 +118,9 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels); assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels);
memcpy(dec->alpha_plane_ + offset, memcpy(dec->alpha_plane_ + offset,
dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels); dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels);
if (alph_dec->unfilter_func_ != NULL) { if (WebPUnfilters[alph_dec->filter_] != NULL) {
alph_dec->unfilter_func_(width, height, width, row, num_rows, output); WebPUnfilters[alph_dec->filter_](width, height, width,
row, num_rows, output);
} }
} else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
assert(alph_dec->vp8l_dec_ != NULL); assert(alph_dec->vp8l_dec_ != NULL);

View File

@ -28,7 +28,7 @@ struct ALPHDecoder {
int width_; int width_;
int height_; int height_;
int method_; int method_;
WebPUnfilterFunc unfilter_func_; WEBP_FILTER_TYPE filter_;
int pre_processing_; int pre_processing_;
struct VP8LDecoder* vp8l_dec_; struct VP8LDecoder* vp8l_dec_;
VP8Io io_; VP8Io io_;

View File

@ -714,27 +714,6 @@ static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
} }
} }
// Special method for paletted alpha data.
static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows,
const uint8_t* const rows) {
const ALPHDecoder* const alph_dec = (const ALPHDecoder*)dec->io_->opaque;
const int width = dec->io_->width;
uint8_t* const output = alph_dec->output_;
const int start_row = dec->last_row_;
const int end_row = start_row + num_rows;
const uint8_t* rows_in = rows;
uint8_t* rows_out = output + width * start_row;
VP8LTransform* const transform = &dec->transforms_[0];
assert(dec->next_transform_ == 1);
assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in,
rows_out);
if (alph_dec->unfilter_func_ != NULL) {
alph_dec->unfilter_func_(width, dec->io_->height, width,
start_row, num_rows, output);
}
}
// Processes (transforms, scales & color-converts) the rows decoded after the // Processes (transforms, scales & color-converts) the rows decoded after the
// last call. // last call.
static void ProcessRows(VP8LDecoder* const dec, int row) { static void ProcessRows(VP8LDecoder* const dec, int row) {
@ -793,12 +772,32 @@ static int Is8bOptimizable(const VP8LMetadata* const hdr) {
} }
static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) {
const uint8_t* const in = // For vertical and gradient filtering, we need to decode the part above the
(uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; // crop_top row, in order to have the correct spatial predictors.
const int num_rows = row - dec->last_row_; const ALPHDecoder* const alph_dec = (const ALPHDecoder*)dec->io_->opaque;
const int top_row =
(alph_dec->filter_ == WEBP_FILTER_NONE ||
alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top
: dec->last_row_;
const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;
assert(row <= dec->io_->crop_bottom); assert(row <= dec->io_->crop_bottom);
if (num_rows > 0) { if (row > first_row) {
ApplyInverseTransformsAlpha(dec, num_rows, in); // Special method for paletted alpha data. We only process the cropped area.
const int width = dec->io_->width;
uint8_t* const out = alph_dec->output_ + width * first_row;
const uint8_t* const in =
(uint8_t*)dec->pixels_ + dec->width_ * first_row;
VP8LTransform* const transform = &dec->transforms_[0];
assert(dec->next_transform_ == 1);
assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
VP8LColorIndexInverseTransformAlpha(transform, first_row, row,
in, out);
if (alph_dec->filter_ != WEBP_FILTER_NONE) {
assert(WebPUnfilters[alph_dec->filter_] != NULL);
WebPUnfilters[alph_dec->filter_](width, dec->io_->height, width,
first_row, row - first_row,
alph_dec->output_);
}
} }
dec->last_row_ = dec->last_out_row_ = row; dec->last_row_ = dec->last_out_row_ = row;
} }
@ -1469,9 +1468,10 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
int i; int i;
ApplyInverseTransforms(dec, num_rows, in); ApplyInverseTransforms(dec, num_rows, in);
for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
if (alph_dec->unfilter_func_ != NULL) { if (alph_dec->filter_ != WEBP_FILTER_NONE) {
alph_dec->unfilter_func_(width, dec->io_->height, width, assert(WebPUnfilters[alph_dec->filter_] != NULL);
dec->last_row_, num_rows, output); WebPUnfilters[alph_dec->filter_](width, dec->io_->height, width,
dec->last_row_, num_rows, output);
} }
} }
dec->last_row_ = dec->last_out_row_ = row; dec->last_row_ = dec->last_out_row_ = row;