• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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/ ?
CopyPlane(const uint8_t * src,int src_stride,uint8_t * dst,int dst_stride,int width,int height)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 
DecodeAlpha(const uint8_t * data,size_t data_size,int width,int height,int stride,uint8_t * output)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 
VP8DecompressAlphaRows(VP8Decoder * const dec,int row,int num_rows)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