alpha_dec.c (8294B)
1 // Copyright 2011 Google Inc. All Rights Reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the COPYING file in the root of the source 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. 8 // ----------------------------------------------------------------------------- 9 // 10 // Alpha-plane decompression. 11 // 12 // Author: Skal (pascal.massimino@gmail.com) 13 14 #include <assert.h> 15 #include <stdlib.h> 16 17 #include "src/dec/alphai_dec.h" 18 #include "src/dec/vp8_dec.h" 19 #include "src/dec/vp8i_dec.h" 20 #include "src/dec/vp8li_dec.h" 21 #include "src/dec/webpi_dec.h" 22 #include "src/dsp/dsp.h" 23 #include "src/utils/quant_levels_dec_utils.h" 24 #include "src/utils/utils.h" 25 #include "src/webp/decode.h" 26 #include "src/webp/format_constants.h" 27 #include "src/webp/types.h" 28 29 //------------------------------------------------------------------------------ 30 // ALPHDecoder object. 31 32 // Allocates a new alpha decoder instance. 33 WEBP_NODISCARD static ALPHDecoder* ALPHNew(void) { 34 ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec)); 35 return dec; 36 } 37 38 // Clears and deallocates an alpha decoder instance. 39 static void ALPHDelete(ALPHDecoder* const dec) { 40 if (dec != NULL) { 41 VP8LDelete(dec->vp8l_dec); 42 dec->vp8l_dec = NULL; 43 WebPSafeFree(dec); 44 } 45 } 46 47 //------------------------------------------------------------------------------ 48 // Decoding. 49 50 // Initialize alpha decoding by parsing the alpha header and decoding the image 51 // header for alpha data stored using lossless compression. 52 // Returns false in case of error in alpha header (data too short, invalid 53 // compression method or filter, error in lossless header data etc). 54 WEBP_NODISCARD static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data, 55 size_t data_size, const VP8Io* const src_io, 56 uint8_t* output) { 57 int ok = 0; 58 const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; 59 const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; 60 int rsrv; 61 VP8Io* const io = &dec->io; 62 63 assert(data != NULL && output != NULL && src_io != NULL); 64 65 VP8FiltersInit(); 66 dec->output = output; 67 dec->width = src_io->width; 68 dec->height = src_io->height; 69 assert(dec->width > 0 && dec->height > 0); 70 71 if (data_size <= ALPHA_HEADER_LEN) { 72 return 0; 73 } 74 75 dec->method = (data[0] >> 0) & 0x03; 76 dec->filter = (WEBP_FILTER_TYPE)((data[0] >> 2) & 0x03); 77 dec->pre_processing = (data[0] >> 4) & 0x03; 78 rsrv = (data[0] >> 6) & 0x03; 79 if (dec->method < ALPHA_NO_COMPRESSION || 80 dec->method > ALPHA_LOSSLESS_COMPRESSION || 81 dec->filter >= WEBP_FILTER_LAST || 82 dec->pre_processing > ALPHA_PREPROCESSED_LEVELS || 83 rsrv != 0) { 84 return 0; 85 } 86 87 // Copy the necessary parameters from src_io to io 88 if (!VP8InitIo(io)) { 89 return 0; 90 } 91 WebPInitCustomIo(NULL, io); 92 io->opaque = dec; 93 io->width = src_io->width; 94 io->height = src_io->height; 95 96 io->use_cropping = src_io->use_cropping; 97 io->crop_left = src_io->crop_left; 98 io->crop_right = src_io->crop_right; 99 io->crop_top = src_io->crop_top; 100 io->crop_bottom = src_io->crop_bottom; 101 // No need to copy the scaling parameters. 102 103 if (dec->method == ALPHA_NO_COMPRESSION) { 104 const size_t alpha_decoded_size = dec->width * dec->height; 105 ok = (alpha_data_size >= alpha_decoded_size); 106 } else { 107 assert(dec->method == ALPHA_LOSSLESS_COMPRESSION); 108 ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size); 109 } 110 111 return ok; 112 } 113 114 // Decodes, unfilters and dequantizes *at least* 'num_rows' rows of alpha 115 // starting from row number 'row'. It assumes that rows up to (row - 1) have 116 // already been decoded. 117 // Returns false in case of bitstream error. 118 WEBP_NODISCARD static int ALPHDecode(VP8Decoder* const dec, int row, 119 int num_rows) { 120 ALPHDecoder* const alph_dec = dec->alph_dec; 121 const int width = alph_dec->width; 122 const int height = alph_dec->io.crop_bottom; 123 if (alph_dec->method == ALPHA_NO_COMPRESSION) { 124 int y; 125 const uint8_t* prev_line = dec->alpha_prev_line; 126 const uint8_t* deltas = dec->alpha_data + ALPHA_HEADER_LEN + row * width; 127 uint8_t* dst = dec->alpha_plane + row * width; 128 assert(deltas <= &dec->alpha_data[dec->alpha_data_size]); 129 assert(WebPUnfilters[alph_dec->filter] != NULL); 130 for (y = 0; y < num_rows; ++y) { 131 WebPUnfilters[alph_dec->filter](prev_line, deltas, dst, width); 132 prev_line = dst; 133 dst += width; 134 deltas += width; 135 } 136 dec->alpha_prev_line = prev_line; 137 } else { // alph_dec->method == ALPHA_LOSSLESS_COMPRESSION 138 assert(alph_dec->vp8l_dec != NULL); 139 if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) { 140 return 0; 141 } 142 } 143 144 if (row + num_rows >= height) { 145 dec->is_alpha_decoded = 1; 146 } 147 return 1; 148 } 149 150 WEBP_NODISCARD static int AllocateAlphaPlane(VP8Decoder* const dec, 151 const VP8Io* const io) { 152 const int stride = io->width; 153 const int height = io->crop_bottom; 154 const uint64_t alpha_size = (uint64_t)stride * height; 155 assert(dec->alpha_plane_mem == NULL); 156 dec->alpha_plane_mem = 157 (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane)); 158 if (dec->alpha_plane_mem == NULL) { 159 return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, 160 "Alpha decoder initialization failed."); 161 } 162 dec->alpha_plane = dec->alpha_plane_mem; 163 dec->alpha_prev_line = NULL; 164 return 1; 165 } 166 167 void WebPDeallocateAlphaMemory(VP8Decoder* const dec) { 168 assert(dec != NULL); 169 WebPSafeFree(dec->alpha_plane_mem); 170 dec->alpha_plane_mem = NULL; 171 dec->alpha_plane = NULL; 172 ALPHDelete(dec->alph_dec); 173 dec->alph_dec = NULL; 174 } 175 176 //------------------------------------------------------------------------------ 177 // Main entry point. 178 179 WEBP_NODISCARD const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, 180 const VP8Io* const io, 181 int row, int num_rows) { 182 const int width = io->width; 183 const int height = io->crop_bottom; 184 185 assert(dec != NULL && io != NULL); 186 187 if (row < 0 || num_rows <= 0 || row + num_rows > height) { 188 return NULL; 189 } 190 191 if (!dec->is_alpha_decoded) { 192 if (dec->alph_dec == NULL) { // Initialize decoder. 193 dec->alph_dec = ALPHNew(); 194 if (dec->alph_dec == NULL) { 195 VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY, 196 "Alpha decoder initialization failed."); 197 return NULL; 198 } 199 if (!AllocateAlphaPlane(dec, io)) goto Error; 200 if (!ALPHInit(dec->alph_dec, dec->alpha_data, dec->alpha_data_size, 201 io, dec->alpha_plane)) { 202 VP8LDecoder* const vp8l_dec = dec->alph_dec->vp8l_dec; 203 VP8SetError(dec, 204 (vp8l_dec == NULL) ? VP8_STATUS_OUT_OF_MEMORY 205 : vp8l_dec->status, 206 "Alpha decoder initialization failed."); 207 goto Error; 208 } 209 // if we allowed use of alpha dithering, check whether it's needed at all 210 if (dec->alph_dec->pre_processing != ALPHA_PREPROCESSED_LEVELS) { 211 dec->alpha_dithering = 0; // disable dithering 212 } else { 213 num_rows = height - row; // decode everything in one pass 214 } 215 } 216 217 assert(dec->alph_dec != NULL); 218 assert(row + num_rows <= height); 219 if (!ALPHDecode(dec, row, num_rows)) goto Error; 220 221 if (dec->is_alpha_decoded) { // finished? 222 ALPHDelete(dec->alph_dec); 223 dec->alph_dec = NULL; 224 if (dec->alpha_dithering > 0) { 225 uint8_t* const alpha = dec->alpha_plane + io->crop_top * width 226 + io->crop_left; 227 if (!WebPDequantizeLevels(alpha, 228 io->crop_right - io->crop_left, 229 io->crop_bottom - io->crop_top, 230 width, dec->alpha_dithering)) { 231 goto Error; 232 } 233 } 234 } 235 } 236 237 // Return a pointer to the current decoded row. 238 return dec->alpha_plane + row * width; 239 240 Error: 241 WebPDeallocateAlphaMemory(dec); 242 return NULL; 243 }