// Copyright 2011 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
//  Software License Agreement:  http://www.webmproject.org/license/software/
//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
// Alpha-plane decompression.
//
// Author: Skal (pascal.massimino@gmail.com)

#include <stdlib.h>
#include "./vp8i.h"
#include "./vp8li.h"
#include "../utils/filters.h"
#include "../utils/quant_levels_dec.h"
#include "webp/format_constants.h"

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

// TODO(skal): move to dsp/ ?
static void CopyPlane(const uint8_t* src, int src_stride,
                      uint8_t* dst, int dst_stride, int width, int height) {
  while (height-- > 0) {
    memcpy(dst, src, width);
    src += src_stride;
    dst += dst_stride;
  }
}

//------------------------------------------------------------------------------
// Decodes the compressed data 'data' of size 'data_size' into the 'output'.
// The 'output' buffer should be pre-allocated and must be of the same
// dimension 'height'x'stride', as that of the image.
//
// Returns 1 on successfully decoding the compressed alpha and
//         0 if either:
//           error in bit-stream header (invalid compression mode or filter), or
//           error returned by appropriate compression method.

static int DecodeAlpha(const uint8_t* data, size_t data_size,
                       int width, int height, int stride, uint8_t* output) {
  uint8_t* decoded_data = NULL;
  const size_t decoded_size = height * width;
  uint8_t* unfiltered_data = NULL;
  WEBP_FILTER_TYPE filter;
  int pre_processing;
  int rsrv;
  int ok = 0;
  int method;

  assert(width > 0 && height > 0 && stride >= width);
  assert(data != NULL && output != NULL);

  if (data_size <= ALPHA_HEADER_LEN) {
    return 0;
  }

  method = (data[0] >> 0) & 0x03;
  filter = (data[0] >> 2) & 0x03;
  pre_processing = (data[0] >> 4) & 0x03;
  rsrv = (data[0] >> 6) & 0x03;
  if (method < ALPHA_NO_COMPRESSION ||
      method > ALPHA_LOSSLESS_COMPRESSION ||
      filter >= WEBP_FILTER_LAST ||
      pre_processing > ALPHA_PREPROCESSED_LEVELS ||
      rsrv != 0) {
    return 0;
  }

  if (method == ALPHA_NO_COMPRESSION) {
    ok = (data_size >= decoded_size);
    decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN;
  } else {
    decoded_data = (uint8_t*)malloc(decoded_size);
    if (decoded_data == NULL) return 0;
    ok = VP8LDecodeAlphaImageStream(width, height,
                                    data + ALPHA_HEADER_LEN,
                                    data_size - ALPHA_HEADER_LEN,
                                    decoded_data);
  }

  if (ok) {
    WebPFilterFunc unfilter_func = WebPUnfilters[filter];
    if (unfilter_func != NULL) {
      unfiltered_data = (uint8_t*)malloc(decoded_size);
      if (unfiltered_data == NULL) {
        ok = 0;
        goto Error;
      }
      // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
      // and apply filter per image-row.
      unfilter_func(decoded_data, width, height, 1, width, unfiltered_data);
      // Construct raw_data (height x stride) from alpha data (height x width).
      CopyPlane(unfiltered_data, width, output, stride, width, height);
      free(unfiltered_data);
    } else {
      // Construct raw_data (height x stride) from alpha data (height x width).
      CopyPlane(decoded_data, width, output, stride, width, height);
    }
    if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
      ok = DequantizeLevels(decoded_data, width, height);
    }
  }

 Error:
  if (method != ALPHA_NO_COMPRESSION) {
    free(decoded_data);
  }
  return ok;
}

//------------------------------------------------------------------------------

const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
                                      int row, int num_rows) {
  const int stride = dec->pic_hdr_.width_;

  if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) {
    return NULL;    // sanity check.
  }

  if (row == 0) {
    // Decode everything during the first call.
    if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_,
                     dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride,
                     dec->alpha_plane_)) {
      // TODO(urvang): Add a test where DecodeAlpha fails to test this.
      return NULL;  // Error.
    }
  }

  // Return a pointer to the current decoded row.
  return dec->alpha_plane_ + row * stride;
}

#if defined(__cplusplus) || defined(c_plusplus)
}    // extern "C"
#endif
