Home | History | Annotate | Download | only in dec
      1 // Copyright 2011 Google Inc. All Rights Reserved.
      2 //
      3 // This code is licensed under the same terms as WebM:
      4 //  Software License Agreement:  http://www.webmproject.org/license/software/
      5 //  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
      6 // -----------------------------------------------------------------------------
      7 //
      8 // Alpha-plane decompression.
      9 //
     10 // Author: Skal (pascal.massimino (at) gmail.com)
     11 
     12 #include <stdlib.h>
     13 #include "./vp8i.h"
     14 #include "./vp8li.h"
     15 #include "../utils/filters.h"
     16 #include "../utils/quant_levels_dec.h"
     17 #include "webp/format_constants.h"
     18 
     19 #if defined(__cplusplus) || defined(c_plusplus)
     20 extern "C" {
     21 #endif
     22 
     23 // TODO(skal): move to dsp/ ?
     24 static void CopyPlane(const uint8_t* src, int src_stride,
     25                       uint8_t* dst, int dst_stride, int width, int height) {
     26   while (height-- > 0) {
     27     memcpy(dst, src, width);
     28     src += src_stride;
     29     dst += dst_stride;
     30   }
     31 }
     32 
     33 //------------------------------------------------------------------------------
     34 // Decodes the compressed data 'data' of size 'data_size' into the 'output'.
     35 // The 'output' buffer should be pre-allocated and must be of the same
     36 // dimension 'height'x'stride', as that of the image.
     37 //
     38 // Returns 1 on successfully decoding the compressed alpha and
     39 //         0 if either:
     40 //           error in bit-stream header (invalid compression mode or filter), or
     41 //           error returned by appropriate compression method.
     42 
     43 static int DecodeAlpha(const uint8_t* data, size_t data_size,
     44                        int width, int height, int stride, uint8_t* output) {
     45   uint8_t* decoded_data = NULL;
     46   const size_t decoded_size = height * width;
     47   uint8_t* unfiltered_data = NULL;
     48   WEBP_FILTER_TYPE filter;
     49   int pre_processing;
     50   int rsrv;
     51   int ok = 0;
     52   int method;
     53 
     54   assert(width > 0 && height > 0 && stride >= width);
     55   assert(data != NULL && output != NULL);
     56 
     57   if (data_size <= ALPHA_HEADER_LEN) {
     58     return 0;
     59   }
     60 
     61   method = (data[0] >> 0) & 0x03;
     62   filter = (data[0] >> 2) & 0x03;
     63   pre_processing = (data[0] >> 4) & 0x03;
     64   rsrv = (data[0] >> 6) & 0x03;
     65   if (method < ALPHA_NO_COMPRESSION ||
     66       method > ALPHA_LOSSLESS_COMPRESSION ||
     67       filter >= WEBP_FILTER_LAST ||
     68       pre_processing > ALPHA_PREPROCESSED_LEVELS ||
     69       rsrv != 0) {
     70     return 0;
     71   }
     72 
     73   if (method == ALPHA_NO_COMPRESSION) {
     74     ok = (data_size >= decoded_size);
     75     decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN;
     76   } else {
     77     decoded_data = (uint8_t*)malloc(decoded_size);
     78     if (decoded_data == NULL) return 0;
     79     ok = VP8LDecodeAlphaImageStream(width, height,
     80                                     data + ALPHA_HEADER_LEN,
     81                                     data_size - ALPHA_HEADER_LEN,
     82                                     decoded_data);
     83   }
     84 
     85   if (ok) {
     86     WebPFilterFunc unfilter_func = WebPUnfilters[filter];
     87     if (unfilter_func != NULL) {
     88       unfiltered_data = (uint8_t*)malloc(decoded_size);
     89       if (unfiltered_data == NULL) {
     90         ok = 0;
     91         goto Error;
     92       }
     93       // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
     94       // and apply filter per image-row.
     95       unfilter_func(decoded_data, width, height, 1, width, unfiltered_data);
     96       // Construct raw_data (height x stride) from alpha data (height x width).
     97       CopyPlane(unfiltered_data, width, output, stride, width, height);
     98       free(unfiltered_data);
     99     } else {
    100       // Construct raw_data (height x stride) from alpha data (height x width).
    101       CopyPlane(decoded_data, width, output, stride, width, height);
    102     }
    103     if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
    104       ok = DequantizeLevels(decoded_data, width, height);
    105     }
    106   }
    107 
    108  Error:
    109   if (method != ALPHA_NO_COMPRESSION) {
    110     free(decoded_data);
    111   }
    112   return ok;
    113 }
    114 
    115 //------------------------------------------------------------------------------
    116 
    117 const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
    118                                       int row, int num_rows) {
    119   const int stride = dec->pic_hdr_.width_;
    120 
    121   if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) {
    122     return NULL;    // sanity check.
    123   }
    124 
    125   if (row == 0) {
    126     // Decode everything during the first call.
    127     if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_,
    128                      dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride,
    129                      dec->alpha_plane_)) {
    130       // TODO(urvang): Add a test where DecodeAlpha fails to test this.
    131       return NULL;  // Error.
    132     }
    133   }
    134 
    135   // Return a pointer to the current decoded row.
    136   return dec->alpha_plane_ + row * stride;
    137 }
    138 
    139 #if defined(__cplusplus) || defined(c_plusplus)
    140 }    // extern "C"
    141 #endif
    142