1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved.
2466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//
30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license
40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source
50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found
60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may
70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree.
8466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// -----------------------------------------------------------------------------
9466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//
10466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Alpha-plane decompression.
11466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//
12466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Author: Skal (pascal.massimino@gmail.com)
13466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
14466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include <stdlib.h>
158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#include "./alphai.h"
16a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8i.h"
17a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8li.h"
181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include "../utils/quant_levels_dec.h"
19af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora#include "../utils/utils.h"
20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "webp/format_constants.h"
21466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora//------------------------------------------------------------------------------
238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// ALPHDecoder object.
248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
258b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraALPHDecoder* ALPHNew(void) {
26af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return dec;
288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
308b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroravoid ALPHDelete(ALPHDecoder* const dec) {
318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec != NULL) {
328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LDelete(dec->vp8l_dec_);
338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->vp8l_dec_ = NULL;
34af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPSafeFree(dec);
358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
37466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Decoding.
408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Initialize alpha decoding by parsing the alpha header and decoding the image
428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// header for alpha data stored using lossless compression.
438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Returns false in case of error in alpha header (data too short, invalid
448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// compression method or filter, error in lossless header data etc).
458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                    size_t data_size, int width, int height, uint8_t* output) {
47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
480406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
490406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int rsrv;
51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
520406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(width > 0 && height > 0);
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(data != NULL && output != NULL);
54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->width_ = width;
568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->height_ = height;
578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (data_size <= ALPHA_HEADER_LEN) {
59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
61a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->method_ = (data[0] >> 0) & 0x03;
638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->filter_ = (data[0] >> 2) & 0x03;
648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->pre_processing_ = (data[0] >> 4) & 0x03;
65a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  rsrv = (data[0] >> 6) & 0x03;
668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec->method_ < ALPHA_NO_COMPRESSION ||
678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->method_ > ALPHA_LOSSLESS_COMPRESSION ||
688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->filter_ >= WEBP_FILTER_LAST ||
698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS ||
70a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      rsrv != 0) {
71a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
72a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec->method_ == ALPHA_NO_COMPRESSION) {
758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const size_t alpha_decoded_size = dec->width_ * dec->height_;
760406ce1417f76f2034833414dcecc9f56253640cVikas Arora    ok = (alpha_data_size >= alpha_decoded_size);
77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output);
80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return ok;
828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
83a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha
858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// starting from row number 'row'. It assumes that rows up to (row - 1) have
868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// already been decoded.
878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Returns false in case of bitstream error.
888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ALPHDecoder* const alph_dec = dec->alph_dec_;
908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int width = alph_dec->width_;
918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int height = alph_dec->height_;
928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_];
938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint8_t* const output = dec->alpha_plane_;
948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const size_t offset = row * width;
968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const size_t num_pixels = num_rows * width;
978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels);
988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    memcpy(dec->alpha_plane_ + offset,
998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora           dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels);
1008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {  // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
1018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(alph_dec->vp8l_dec_ != NULL);
1028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
1038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      return 0;
104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (unfilter_func != NULL) {
1088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    unfilter_func(width, height, width, row, num_rows, output);
1098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (row + num_rows == dec->pic_hdr_.height_) {
1128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->is_alpha_decoded_ = 1;
1138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Main entry point.
119466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
120466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraconst uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
121466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                                      int row, int num_rows) {
1220406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int width = dec->pic_hdr_.width_;
1230406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int height = dec->pic_hdr_.height_;
124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (row < 0 || num_rows <= 0 || row + num_rows > height) {
126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return NULL;    // sanity check.
127466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
128466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (row == 0) {
1308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Initialize decoding.
1318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->alpha_plane_ != NULL);
1328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->alph_dec_ = ALPHNew();
1338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (dec->alph_dec_ == NULL) return NULL;
1348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
1358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                  width, height, dec->alpha_plane_)) {
1368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ALPHDelete(dec->alph_dec_);
1378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->alph_dec_ = NULL;
1388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      return NULL;
139466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    }
140af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    // if we allowed use of alpha dithering, check whether it's needed at all
141af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
142af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      dec->alpha_dithering_ = 0;  // disable dithering
143af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    } else {
144af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      num_rows = height;          // decode everything in one pass
145af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    }
1468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!dec->is_alpha_decoded_) {
1498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    int ok = 0;
1508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->alph_dec_ != NULL);
1518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = ALPHDecode(dec, row, num_rows);
152af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    if (ok && dec->alpha_dithering_ > 0) {
153af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      ok = WebPDequantizeLevels(dec->alpha_plane_, width, height,
154af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora                                dec->alpha_dithering_);
155af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    }
1568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok || dec->is_alpha_decoded_) {
1578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ALPHDelete(dec->alph_dec_);
1588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->alph_dec_ = NULL;
1598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
1608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok) return NULL;  // Error.
161466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Return a pointer to the current decoded row.
1640406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return dec->alpha_plane_ + row * width;
165466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
166