| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | // Copyright 2011 Google Inc. All Rights Reserved.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  | // 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/
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | // -----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Alpha-plane decompression.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Author: Skal (pascal.massimino@gmail.com)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include "./vp8i.h"
 | 
					
						
							|  |  |  | #include "./vp8li.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  | #include "../utils/filters.h"
 | 
					
						
							|  |  |  | #include "../utils/quant_levels.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "../webp/format_constants.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  | #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; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //------------------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  | // 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; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   int rsrv; | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   int ok = 0; | 
					
						
							|  |  |  |   int method; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   assert(width > 0 && height > 0 && stride >= width); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   assert(data != NULL && output != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (data_size <= ALPHA_HEADER_LEN) { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   method = (data[0] >> 0) & 0x03; | 
					
						
							|  |  |  |   filter = (data[0] >> 2) & 0x03; | 
					
						
							|  |  |  |   pre_processing = (data[0] >> 4) & 0x03; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   rsrv = (data[0] >> 6) & 0x03; | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   if (method < ALPHA_NO_COMPRESSION || | 
					
						
							|  |  |  |       method > ALPHA_LOSSLESS_COMPRESSION || | 
					
						
							|  |  |  |       filter >= WEBP_FILTER_LAST || | 
					
						
							|  |  |  |       pre_processing > ALPHA_PREPROCESSED_LEVELS || | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |       rsrv != 0) { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   if (method == ALPHA_NO_COMPRESSION) { | 
					
						
							|  |  |  |     ok = (data_size >= decoded_size); | 
					
						
							|  |  |  |     decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |     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); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   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); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |     if (pre_processing == ALPHA_PREPROCESSED_LEVELS) { | 
					
						
							|  |  |  |       ok = DequantizeLevels(decoded_data, width, height); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |  Error: | 
					
						
							|  |  |  |   if (method != ALPHA_NO_COMPRESSION) { | 
					
						
							|  |  |  |     free(decoded_data); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   return ok; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //------------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, | 
					
						
							|  |  |  |                                       int row, int num_rows) { | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   const int stride = dec->pic_hdr_.width_; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     return NULL;    // sanity check.
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (row == 0) { | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |     // 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_)) { | 
					
						
							|  |  |  |       return NULL;  // Error.
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Return a pointer to the current decoded row.
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  |   return dec->alpha_plane_ + row * stride; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 22:37:07 -03:00
										 |  |  | #if defined(__cplusplus) || defined(c_plusplus)
 | 
					
						
							|  |  |  | }    // extern "C"
 | 
					
						
							|  |  |  | #endif
 |