15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2011 Google Inc. All Rights Reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------- 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Alpha-plane decompression. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "./alphai.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8i.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8li.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "../utils/quant_levels_dec.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "../utils/utils.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../webp/format_constants.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//------------------------------------------------------------------------------ 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ALPHDecoder object. 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ALPHDecoder* ALPHNew(void) { 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return dec; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ALPHDelete(ALPHDecoder* const dec) { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (dec != NULL) { 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VP8LDelete(dec->vp8l_dec_); 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->vp8l_dec_ = NULL; 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSafeFree(dec); 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Decoding. 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Initialize alpha decoding by parsing the alpha header and decoding the image 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// header for alpha data stored using lossless compression. 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns false in case of error in alpha header (data too short, invalid 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// compression method or filter, error in lossless header data etc). 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t data_size, int width, int height, uint8_t* output) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ok = 0; 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rsrv; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch assert(width > 0 && height > 0); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(data != NULL && output != NULL); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->width_ = width; 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->height_ = height; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data_size <= ALPHA_HEADER_LEN) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->method_ = (data[0] >> 0) & 0x03; 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->filter_ = (data[0] >> 2) & 0x03; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->pre_processing_ = (data[0] >> 4) & 0x03; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rsrv = (data[0] >> 6) & 0x03; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (dec->method_ < ALPHA_NO_COMPRESSION || 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->method_ > ALPHA_LOSSLESS_COMPRESSION || 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->filter_ >= WEBP_FILTER_LAST || 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS || 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rsrv != 0) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (dec->method_ == ALPHA_NO_COMPRESSION) { 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t alpha_decoded_size = dec->width_ * dec->height_; 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ok = (alpha_data_size >= alpha_decoded_size); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ok; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// starting from row number 'row'. It assumes that rows up to (row - 1) have 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// already been decoded. 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns false in case of bitstream error. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ALPHDecoder* const alph_dec = dec->alph_dec_; 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int width = alph_dec->width_; 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int height = alph_dec->height_; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_]; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8_t* const output = dec->alpha_plane_; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (alph_dec->method_ == ALPHA_NO_COMPRESSION) { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t offset = row * width; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t num_pixels = num_rows * width; 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels); 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) memcpy(dec->alpha_plane_ + offset, 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(alph_dec->vp8l_dec_ != NULL); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (unfilter_func != NULL) { 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unfilter_func(width, height, width, row, num_rows, output); 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (row + num_rows == dec->pic_hdr_.height_) { 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->is_alpha_decoded_ = 1; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 1; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Main entry point. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int row, int num_rows) { 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int width = dec->pic_hdr_.width_; 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int height = dec->pic_hdr_.height_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (row < 0 || num_rows <= 0 || row + num_rows > height) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; // sanity check. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row == 0) { 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Initialize decoding. 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(dec->alpha_plane_ != NULL); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->alph_dec_ = ALPHNew(); 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (dec->alph_dec_ == NULL) return NULL; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_, 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) width, height, dec->alpha_plane_)) { 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ALPHDelete(dec->alph_dec_); 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->alph_dec_ = NULL; 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // if we allowed use of alpha dithering, check whether it's needed at all 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) { 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dec->alpha_dithering_ = 0; // disable dithering 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) num_rows = height; // decode everything in one pass 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!dec->is_alpha_decoded_) { 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int ok = 0; 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(dec->alph_dec_ != NULL); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ok = ALPHDecode(dec, row, num_rows); 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ok && dec->alpha_dithering_ > 0) { 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dec->alpha_dithering_); 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ok || dec->is_alpha_decoded_) { 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ALPHDelete(dec->alph_dec_); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dec->alph_dec_ = NULL; 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ok) return NULL; // Error. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return a pointer to the current decoded row. 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return dec->alpha_plane_ + row * width; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 166