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