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>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8i.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8li.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../utils/filters.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "../utils/quant_levels_dec.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../webp/format_constants.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__cplusplus) || defined(c_plusplus)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decodes the compressed data 'data' of size 'data_size' into the 'output'.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The 'output' buffer should be pre-allocated and must be of the same
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// dimension 'height'x'width', as that of the image.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns 1 on successfully decoding the compressed alpha and
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         0 if either:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//           error in bit-stream header (invalid compression mode or filter), or
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//           error returned by appropriate compression method.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int DecodeAlpha(const uint8_t* data, size_t data_size,
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       int width, int height, uint8_t* output) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WEBP_FILTER_TYPE filter;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pre_processing;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rsrv;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ok = 0;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int method;
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  assert(width > 0 && height > 0);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(data != NULL && output != NULL);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data_size <= ALPHA_HEADER_LEN) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method = (data[0] >> 0) & 0x03;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter = (data[0] >> 2) & 0x03;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pre_processing = (data[0] >> 4) & 0x03;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rsrv = (data[0] >> 6) & 0x03;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (method < ALPHA_NO_COMPRESSION ||
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      method > ALPHA_LOSSLESS_COMPRESSION ||
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter >= WEBP_FILTER_LAST ||
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pre_processing > ALPHA_PREPROCESSED_LEVELS ||
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rsrv != 0) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (method == ALPHA_NO_COMPRESSION) {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const size_t alpha_decoded_size = height * width;
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ok = (alpha_data_size >= alpha_decoded_size);
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (ok) memcpy(output, alpha_data, alpha_decoded_size);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ok = VP8LDecodeAlphaImageStream(width, height, alpha_data, alpha_data_size,
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    output);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebPUnfilterFunc unfilter_func = WebPUnfilters[filter];
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unfilter_func != NULL) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and apply filter per image-row.
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      unfilter_func(width, height, width, output);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ok = DequantizeLevels(output, width, height);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int row, int num_rows) {
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int width = dec->pic_hdr_.width_;
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int height = dec->pic_hdr_.height_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (row < 0 || num_rows < 0 || row + num_rows > height) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;    // sanity check.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (row == 0) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Decode everything during the first call.
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    assert(!dec->is_alpha_decoded_);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_,
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     width, height, dec->alpha_plane_)) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;  // Error.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dec->is_alpha_decoded_ = 1;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return a pointer to the current decoded row.
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return dec->alpha_plane_ + row * width;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__cplusplus) || defined(c_plusplus)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}    // extern "C"
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
116