| OLD | NEW |
| 1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Use of this source code is governed by a BSD-style license | 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 | 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 | 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
| 8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
| 9 // | 9 // |
| 10 // Everything about WebPDecBuffer | 10 // Everything about WebPDecBuffer |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { | 36 static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { |
| 37 int ok = 1; | 37 int ok = 1; |
| 38 const WEBP_CSP_MODE mode = buffer->colorspace; | 38 const WEBP_CSP_MODE mode = buffer->colorspace; |
| 39 const int width = buffer->width; | 39 const int width = buffer->width; |
| 40 const int height = buffer->height; | 40 const int height = buffer->height; |
| 41 if (!IsValidColorspace(mode)) { | 41 if (!IsValidColorspace(mode)) { |
| 42 ok = 0; | 42 ok = 0; |
| 43 } else if (!WebPIsRGBMode(mode)) { // YUV checks | 43 } else if (!WebPIsRGBMode(mode)) { // YUV checks |
| 44 const WebPYUVABuffer* const buf = &buffer->u.YUVA; | 44 const WebPYUVABuffer* const buf = &buffer->u.YUVA; |
| 45 const uint64_t y_size = (uint64_t)buf->y_stride * height; | 45 const int y_stride = abs(buf->y_stride); |
| 46 const uint64_t u_size = (uint64_t)buf->u_stride * ((height + 1) / 2); | 46 const int u_stride = abs(buf->u_stride); |
| 47 const uint64_t v_size = (uint64_t)buf->v_stride * ((height + 1) / 2); | 47 const int v_stride = abs(buf->v_stride); |
| 48 const uint64_t a_size = (uint64_t)buf->a_stride * height; | 48 const int a_stride = abs(buf->a_stride); |
| 49 const uint64_t y_size = (uint64_t)y_stride * height; |
| 50 const uint64_t u_size = (uint64_t)u_stride * ((height + 1) / 2); |
| 51 const uint64_t v_size = (uint64_t)v_stride * ((height + 1) / 2); |
| 52 const uint64_t a_size = (uint64_t)a_stride * height; |
| 49 ok &= (y_size <= buf->y_size); | 53 ok &= (y_size <= buf->y_size); |
| 50 ok &= (u_size <= buf->u_size); | 54 ok &= (u_size <= buf->u_size); |
| 51 ok &= (v_size <= buf->v_size); | 55 ok &= (v_size <= buf->v_size); |
| 52 ok &= (buf->y_stride >= width); | 56 ok &= (y_stride >= width); |
| 53 ok &= (buf->u_stride >= (width + 1) / 2); | 57 ok &= (u_stride >= (width + 1) / 2); |
| 54 ok &= (buf->v_stride >= (width + 1) / 2); | 58 ok &= (v_stride >= (width + 1) / 2); |
| 55 ok &= (buf->y != NULL); | 59 ok &= (buf->y != NULL); |
| 56 ok &= (buf->u != NULL); | 60 ok &= (buf->u != NULL); |
| 57 ok &= (buf->v != NULL); | 61 ok &= (buf->v != NULL); |
| 58 if (mode == MODE_YUVA) { | 62 if (mode == MODE_YUVA) { |
| 59 ok &= (buf->a_stride >= width); | 63 ok &= (a_stride >= width); |
| 60 ok &= (a_size <= buf->a_size); | 64 ok &= (a_size <= buf->a_size); |
| 61 ok &= (buf->a != NULL); | 65 ok &= (buf->a != NULL); |
| 62 } | 66 } |
| 63 } else { // RGB checks | 67 } else { // RGB checks |
| 64 const WebPRGBABuffer* const buf = &buffer->u.RGBA; | 68 const WebPRGBABuffer* const buf = &buffer->u.RGBA; |
| 65 const uint64_t size = (uint64_t)buf->stride * height; | 69 const int stride = abs(buf->stride); |
| 70 const uint64_t size = (uint64_t)stride * height; |
| 66 ok &= (size <= buf->size); | 71 ok &= (size <= buf->size); |
| 67 ok &= (buf->stride >= width * kModeBpp[mode]); | 72 ok &= (stride >= width * kModeBpp[mode]); |
| 68 ok &= (buf->rgba != NULL); | 73 ok &= (buf->rgba != NULL); |
| 69 } | 74 } |
| 70 return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; | 75 return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM; |
| 71 } | 76 } |
| 72 | 77 |
| 73 static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { | 78 static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { |
| 74 const int w = buffer->width; | 79 const int w = buffer->width; |
| 75 const int h = buffer->height; | 80 const int h = buffer->height; |
| 76 const WEBP_CSP_MODE mode = buffer->colorspace; | 81 const WEBP_CSP_MODE mode = buffer->colorspace; |
| 77 | 82 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 } else { // RGBA initialization | 129 } else { // RGBA initialization |
| 125 WebPRGBABuffer* const buf = &buffer->u.RGBA; | 130 WebPRGBABuffer* const buf = &buffer->u.RGBA; |
| 126 buf->rgba = output; | 131 buf->rgba = output; |
| 127 buf->stride = stride; | 132 buf->stride = stride; |
| 128 buf->size = (size_t)size; | 133 buf->size = (size_t)size; |
| 129 } | 134 } |
| 130 } | 135 } |
| 131 return CheckDecBuffer(buffer); | 136 return CheckDecBuffer(buffer); |
| 132 } | 137 } |
| 133 | 138 |
| 139 VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { |
| 140 if (buffer == NULL) { |
| 141 return VP8_STATUS_INVALID_PARAM; |
| 142 } |
| 143 if (WebPIsRGBMode(buffer->colorspace)) { |
| 144 WebPRGBABuffer* const buf = &buffer->u.RGBA; |
| 145 buf->rgba += (buffer->height - 1) * buf->stride; |
| 146 buf->stride = -buf->stride; |
| 147 } else { |
| 148 WebPYUVABuffer* const buf = &buffer->u.YUVA; |
| 149 const int H = buffer->height; |
| 150 buf->y += (H - 1) * buf->y_stride; |
| 151 buf->y_stride = -buf->y_stride; |
| 152 buf->u += ((H - 1) >> 1) * buf->u_stride; |
| 153 buf->u_stride = -buf->u_stride; |
| 154 buf->v += ((H - 1) >> 1) * buf->v_stride; |
| 155 buf->v_stride = -buf->v_stride; |
| 156 if (buf->a != NULL) { |
| 157 buf->a += (H - 1) * buf->a_stride; |
| 158 buf->a_stride = -buf->a_stride; |
| 159 } |
| 160 } |
| 161 return VP8_STATUS_OK; |
| 162 } |
| 163 |
| 134 VP8StatusCode WebPAllocateDecBuffer(int w, int h, | 164 VP8StatusCode WebPAllocateDecBuffer(int w, int h, |
| 135 const WebPDecoderOptions* const options, | 165 const WebPDecoderOptions* const options, |
| 136 WebPDecBuffer* const out) { | 166 WebPDecBuffer* const out) { |
| 167 VP8StatusCode status; |
| 137 if (out == NULL || w <= 0 || h <= 0) { | 168 if (out == NULL || w <= 0 || h <= 0) { |
| 138 return VP8_STATUS_INVALID_PARAM; | 169 return VP8_STATUS_INVALID_PARAM; |
| 139 } | 170 } |
| 140 if (options != NULL) { // First, apply options if there is any. | 171 if (options != NULL) { // First, apply options if there is any. |
| 141 if (options->use_cropping) { | 172 if (options->use_cropping) { |
| 142 const int cw = options->crop_width; | 173 const int cw = options->crop_width; |
| 143 const int ch = options->crop_height; | 174 const int ch = options->crop_height; |
| 144 const int x = options->crop_left & ~1; | 175 const int x = options->crop_left & ~1; |
| 145 const int y = options->crop_top & ~1; | 176 const int y = options->crop_top & ~1; |
| 146 if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) { | 177 if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) { |
| 147 return VP8_STATUS_INVALID_PARAM; // out of frame boundary. | 178 return VP8_STATUS_INVALID_PARAM; // out of frame boundary. |
| 148 } | 179 } |
| 149 w = cw; | 180 w = cw; |
| 150 h = ch; | 181 h = ch; |
| 151 } | 182 } |
| 152 if (options->use_scaling) { | 183 if (options->use_scaling) { |
| 153 if (options->scaled_width <= 0 || options->scaled_height <= 0) { | 184 if (options->scaled_width <= 0 || options->scaled_height <= 0) { |
| 154 return VP8_STATUS_INVALID_PARAM; | 185 return VP8_STATUS_INVALID_PARAM; |
| 155 } | 186 } |
| 156 w = options->scaled_width; | 187 w = options->scaled_width; |
| 157 h = options->scaled_height; | 188 h = options->scaled_height; |
| 158 } | 189 } |
| 159 } | 190 } |
| 160 out->width = w; | 191 out->width = w; |
| 161 out->height = h; | 192 out->height = h; |
| 162 | 193 |
| 163 // Then, allocate buffer for real | 194 // Then, allocate buffer for real. |
| 164 return AllocateBuffer(out); | 195 status = AllocateBuffer(out); |
| 196 if (status != VP8_STATUS_OK) return status; |
| 197 |
| 198 #if WEBP_DECODER_ABI_VERSION > 0x0203 |
| 199 // Use the stride trick if vertical flip is needed. |
| 200 if (options != NULL && options->flip) { |
| 201 status = WebPFlipBuffer(out); |
| 202 } |
| 203 #endif |
| 204 return status; |
| 165 } | 205 } |
| 166 | 206 |
| 167 //------------------------------------------------------------------------------ | 207 //------------------------------------------------------------------------------ |
| 168 // constructors / destructors | 208 // constructors / destructors |
| 169 | 209 |
| 170 int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) { | 210 int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) { |
| 171 if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { | 211 if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { |
| 172 return 0; // version mismatch | 212 return 0; // version mismatch |
| 173 } | 213 } |
| 174 if (buffer == NULL) return 0; | 214 if (buffer == NULL) return 0; |
| 175 memset(buffer, 0, sizeof(*buffer)); | 215 memset(buffer, 0, sizeof(*buffer)); |
| 176 return 1; | 216 return 1; |
| 177 } | 217 } |
| 178 | 218 |
| 179 void WebPFreeDecBuffer(WebPDecBuffer* buffer) { | 219 void WebPFreeDecBuffer(WebPDecBuffer* buffer) { |
| 180 if (buffer != NULL) { | 220 if (buffer != NULL) { |
| 181 if (!buffer->is_external_memory) | 221 if (!buffer->is_external_memory) { |
| 182 free(buffer->private_memory); | 222 WebPSafeFree(buffer->private_memory); |
| 223 } |
| 183 buffer->private_memory = NULL; | 224 buffer->private_memory = NULL; |
| 184 } | 225 } |
| 185 } | 226 } |
| 186 | 227 |
| 187 void WebPCopyDecBuffer(const WebPDecBuffer* const src, | 228 void WebPCopyDecBuffer(const WebPDecBuffer* const src, |
| 188 WebPDecBuffer* const dst) { | 229 WebPDecBuffer* const dst) { |
| 189 if (src != NULL && dst != NULL) { | 230 if (src != NULL && dst != NULL) { |
| 190 *dst = *src; | 231 *dst = *src; |
| 191 if (src->private_memory != NULL) { | 232 if (src->private_memory != NULL) { |
| 192 dst->is_external_memory = 1; // dst buffer doesn't own the memory. | 233 dst->is_external_memory = 1; // dst buffer doesn't own the memory. |
| 193 dst->private_memory = NULL; | 234 dst->private_memory = NULL; |
| 194 } | 235 } |
| 195 } | 236 } |
| 196 } | 237 } |
| 197 | 238 |
| 198 // Copy and transfer ownership from src to dst (beware of parameter order!) | 239 // Copy and transfer ownership from src to dst (beware of parameter order!) |
| 199 void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) { | 240 void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) { |
| 200 if (src != NULL && dst != NULL) { | 241 if (src != NULL && dst != NULL) { |
| 201 *dst = *src; | 242 *dst = *src; |
| 202 if (src->private_memory != NULL) { | 243 if (src->private_memory != NULL) { |
| 203 src->is_external_memory = 1; // src relinquishes ownership | 244 src->is_external_memory = 1; // src relinquishes ownership |
| 204 src->private_memory = NULL; | 245 src->private_memory = NULL; |
| 205 } | 246 } |
| 206 } | 247 } |
| 207 } | 248 } |
| 208 | 249 |
| 209 //------------------------------------------------------------------------------ | 250 //------------------------------------------------------------------------------ |
| 210 | 251 |
| OLD | NEW |