mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
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:
parent
aa809cfeb3
commit
95ecccf6dc
@ -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);
|
||||||
|
@ -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_;
|
||||||
|
@ -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,8 +1468,9 @@ 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);
|
||||||
|
WebPUnfilters[alph_dec->filter_](width, dec->io_->height, width,
|
||||||
dec->last_row_, num_rows, output);
|
dec->last_row_, num_rows, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user