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