alpha.c revision 8b720228d581a84fd173b6dcb2fa295b59db489a
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"
19a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "webp/format_constants.h"
20466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora//------------------------------------------------------------------------------
228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// ALPHDecoder object.
238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
248b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraALPHDecoder* ALPHNew(void) {
258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ALPHDecoder* const dec = (ALPHDecoder*)calloc(1, sizeof(*dec));
268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return dec;
278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
298b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroravoid ALPHDelete(ALPHDecoder* const dec) {
308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec != NULL) {
318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LDelete(dec->vp8l_dec_);
328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->vp8l_dec_ = NULL;
338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    free(dec);
348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
36466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Decoding.
398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Initialize alpha decoding by parsing the alpha header and decoding the image
418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// header for alpha data stored using lossless compression.
428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Returns false in case of error in alpha header (data too short, invalid
438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// compression method or filter, error in lossless header data etc).
448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                    size_t data_size, int width, int height, uint8_t* output) {
46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
470406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
480406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int rsrv;
50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
510406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(width > 0 && height > 0);
52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(data != NULL && output != NULL);
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->width_ = width;
558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->height_ = height;
568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (data_size <= ALPHA_HEADER_LEN) {
58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->method_ = (data[0] >> 0) & 0x03;
628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->filter_ = (data[0] >> 2) & 0x03;
638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->pre_processing_ = (data[0] >> 4) & 0x03;
64a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  rsrv = (data[0] >> 6) & 0x03;
658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec->method_ < ALPHA_NO_COMPRESSION ||
668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->method_ > ALPHA_LOSSLESS_COMPRESSION ||
678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->filter_ >= WEBP_FILTER_LAST ||
688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->pre_processing_ > ALPHA_PREPROCESSED_LEVELS ||
69a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      rsrv != 0) {
70a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
71a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
72a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec->method_ == ALPHA_NO_COMPRESSION) {
748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const size_t alpha_decoded_size = dec->width_ * dec->height_;
750406ce1417f76f2034833414dcecc9f56253640cVikas Arora    ok = (alpha_data_size >= alpha_decoded_size);
76a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output);
79a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return ok;
818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha
848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// starting from row number 'row'. It assumes that rows up to (row - 1) have
858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// already been decoded.
868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Returns false in case of bitstream error.
878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ALPHDecoder* const alph_dec = dec->alph_dec_;
898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int width = alph_dec->width_;
908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int height = alph_dec->height_;
918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  WebPUnfilterFunc unfilter_func = WebPUnfilters[alph_dec->filter_];
928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint8_t* const output = dec->alpha_plane_;
938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const size_t offset = row * width;
958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const size_t num_pixels = num_rows * width;
968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN + offset + num_pixels);
978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    memcpy(dec->alpha_plane_ + offset,
988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora           dec->alpha_data_ + ALPHA_HEADER_LEN + offset, num_pixels);
998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {  // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
1008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(alph_dec->vp8l_dec_ != NULL);
1018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
1028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      return 0;
103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (unfilter_func != NULL) {
1078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    unfilter_func(width, height, width, row, num_rows, output);
1088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (alph_dec->pre_processing_ == ALPHA_PREPROCESSED_LEVELS) {
1118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!DequantizeLevels(output, width, height, row, num_rows)) {
1128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      return 0;
113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (row + num_rows == dec->pic_hdr_.height_) {
1178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->is_alpha_decoded_ = 1;
1188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Main entry point.
124466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
125466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraconst uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
126466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                                      int row, int num_rows) {
1270406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int width = dec->pic_hdr_.width_;
1280406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int height = dec->pic_hdr_.height_;
129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (row < 0 || num_rows <= 0 || row + num_rows > height) {
131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return NULL;    // sanity check.
132466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
133466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (row == 0) {
1358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Initialize decoding.
1368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->alpha_plane_ != NULL);
1378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->alph_dec_ = ALPHNew();
1388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (dec->alph_dec_ == NULL) return NULL;
1398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
1408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                  width, height, dec->alpha_plane_)) {
1418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ALPHDelete(dec->alph_dec_);
1428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->alph_dec_ = NULL;
1438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      return NULL;
144466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    }
1458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!dec->is_alpha_decoded_) {
1488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    int ok = 0;
1498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(dec->alph_dec_ != NULL);
1508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = ALPHDecode(dec, row, num_rows);
1518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok || dec->is_alpha_decoded_) {
1528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ALPHDelete(dec->alph_dec_);
1538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dec->alph_dec_ = NULL;
1548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
1558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok) return NULL;  // Error.
156466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Return a pointer to the current decoded row.
1590406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return dec->alpha_plane_ + row * width;
160466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
161466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
162