| OLD | NEW |
| 1 // Copyright 2014 Google Inc. All Rights Reserved. | 1 // Copyright 2014 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 // WebPPicture tools: copy, crop, rescaling and view. | 10 // WebPPicture tools: copy, crop, rescaling and view. |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 return 1; | 168 return 1; |
| 169 } | 169 } |
| 170 | 170 |
| 171 //------------------------------------------------------------------------------ | 171 //------------------------------------------------------------------------------ |
| 172 // Simple picture rescaler | 172 // Simple picture rescaler |
| 173 | 173 |
| 174 static void RescalePlane(const uint8_t* src, | 174 static void RescalePlane(const uint8_t* src, |
| 175 int src_width, int src_height, int src_stride, | 175 int src_width, int src_height, int src_stride, |
| 176 uint8_t* dst, | 176 uint8_t* dst, |
| 177 int dst_width, int dst_height, int dst_stride, | 177 int dst_width, int dst_height, int dst_stride, |
| 178 int32_t* const work, | 178 rescaler_t* const work, |
| 179 int num_channels) { | 179 int num_channels) { |
| 180 WebPRescaler rescaler; | 180 WebPRescaler rescaler; |
| 181 int y = 0; | 181 int y = 0; |
| 182 WebPRescalerInit(&rescaler, src_width, src_height, | 182 WebPRescalerInit(&rescaler, src_width, src_height, |
| 183 dst, dst_width, dst_height, dst_stride, | 183 dst, dst_width, dst_height, dst_stride, |
| 184 num_channels, | 184 num_channels, work); |
| 185 src_width, dst_width, | |
| 186 src_height, dst_height, | |
| 187 work); | |
| 188 memset(work, 0, 2 * dst_width * num_channels * sizeof(*work)); | |
| 189 while (y < src_height) { | 185 while (y < src_height) { |
| 190 y += WebPRescalerImport(&rescaler, src_height - y, | 186 y += WebPRescalerImport(&rescaler, src_height - y, |
| 191 src + y * src_stride, src_stride); | 187 src + y * src_stride, src_stride); |
| 192 WebPRescalerExport(&rescaler); | 188 WebPRescalerExport(&rescaler); |
| 193 } | 189 } |
| 194 } | 190 } |
| 195 | 191 |
| 196 static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { | 192 static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) { |
| 197 assert(pic->argb != NULL); | 193 assert(pic->argb != NULL); |
| 198 WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), | 194 WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb), |
| 199 pic->width, pic->height, inverse); | 195 pic->width, pic->height, inverse); |
| 200 } | 196 } |
| 201 | 197 |
| 202 static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { | 198 static void AlphaMultiplyY(WebPPicture* const pic, int inverse) { |
| 203 if (pic->a != NULL) { | 199 if (pic->a != NULL) { |
| 204 WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, | 200 WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride, |
| 205 pic->width, pic->height, inverse); | 201 pic->width, pic->height, inverse); |
| 206 } | 202 } |
| 207 } | 203 } |
| 208 | 204 |
| 209 int WebPPictureRescale(WebPPicture* pic, int width, int height) { | 205 int WebPPictureRescale(WebPPicture* pic, int width, int height) { |
| 210 WebPPicture tmp; | 206 WebPPicture tmp; |
| 211 int prev_width, prev_height; | 207 int prev_width, prev_height; |
| 212 int32_t* work; | 208 rescaler_t* work; |
| 213 | 209 |
| 214 if (pic == NULL) return 0; | 210 if (pic == NULL) return 0; |
| 215 prev_width = pic->width; | 211 prev_width = pic->width; |
| 216 prev_height = pic->height; | 212 prev_height = pic->height; |
| 217 // if width is unspecified, scale original proportionally to height ratio. | 213 // if width is unspecified, scale original proportionally to height ratio. |
| 218 if (width == 0) { | 214 if (width == 0) { |
| 219 width = (prev_width * height + prev_height / 2) / prev_height; | 215 width = (prev_width * height + prev_height / 2) / prev_height; |
| 220 } | 216 } |
| 221 // if height is unspecified, scale original proportionally to width ratio. | 217 // if height is unspecified, scale original proportionally to width ratio. |
| 222 if (height == 0) { | 218 if (height == 0) { |
| 223 height = (prev_height * width + prev_width / 2) / prev_width; | 219 height = (prev_height * width + prev_width / 2) / prev_width; |
| 224 } | 220 } |
| 225 // Check if the overall dimensions still make sense. | 221 // Check if the overall dimensions still make sense. |
| 226 if (width <= 0 || height <= 0) return 0; | 222 if (width <= 0 || height <= 0) return 0; |
| 227 | 223 |
| 228 PictureGrabSpecs(pic, &tmp); | 224 PictureGrabSpecs(pic, &tmp); |
| 229 tmp.width = width; | 225 tmp.width = width; |
| 230 tmp.height = height; | 226 tmp.height = height; |
| 231 if (!WebPPictureAlloc(&tmp)) return 0; | 227 if (!WebPPictureAlloc(&tmp)) return 0; |
| 232 | 228 |
| 233 if (!pic->use_argb) { | 229 if (!pic->use_argb) { |
| 234 work = (int32_t*)WebPSafeMalloc(2ULL * width, sizeof(*work)); | 230 work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work)); |
| 235 if (work == NULL) { | 231 if (work == NULL) { |
| 236 WebPPictureFree(&tmp); | 232 WebPPictureFree(&tmp); |
| 237 return 0; | 233 return 0; |
| 238 } | 234 } |
| 239 // If present, we need to rescale alpha first (for AlphaMultiplyY). | 235 // If present, we need to rescale alpha first (for AlphaMultiplyY). |
| 240 if (pic->a != NULL) { | 236 if (pic->a != NULL) { |
| 241 WebPInitAlphaProcessing(); | 237 WebPInitAlphaProcessing(); |
| 242 RescalePlane(pic->a, prev_width, prev_height, pic->a_stride, | 238 RescalePlane(pic->a, prev_width, prev_height, pic->a_stride, |
| 243 tmp.a, width, height, tmp.a_stride, work, 1); | 239 tmp.a, width, height, tmp.a_stride, work, 1); |
| 244 } | 240 } |
| 245 | 241 |
| 246 // We take transparency into account on the luma plane only. That's not | 242 // We take transparency into account on the luma plane only. That's not |
| 247 // totally exact blending, but still is a good approximation. | 243 // totally exact blending, but still is a good approximation. |
| 248 AlphaMultiplyY(pic, 0); | 244 AlphaMultiplyY(pic, 0); |
| 249 RescalePlane(pic->y, prev_width, prev_height, pic->y_stride, | 245 RescalePlane(pic->y, prev_width, prev_height, pic->y_stride, |
| 250 tmp.y, width, height, tmp.y_stride, work, 1); | 246 tmp.y, width, height, tmp.y_stride, work, 1); |
| 251 AlphaMultiplyY(&tmp, 1); | 247 AlphaMultiplyY(&tmp, 1); |
| 252 | 248 |
| 253 RescalePlane(pic->u, | 249 RescalePlane(pic->u, |
| 254 HALVE(prev_width), HALVE(prev_height), pic->uv_stride, | 250 HALVE(prev_width), HALVE(prev_height), pic->uv_stride, |
| 255 tmp.u, | 251 tmp.u, |
| 256 HALVE(width), HALVE(height), tmp.uv_stride, work, 1); | 252 HALVE(width), HALVE(height), tmp.uv_stride, work, 1); |
| 257 RescalePlane(pic->v, | 253 RescalePlane(pic->v, |
| 258 HALVE(prev_width), HALVE(prev_height), pic->uv_stride, | 254 HALVE(prev_width), HALVE(prev_height), pic->uv_stride, |
| 259 tmp.v, | 255 tmp.v, |
| 260 HALVE(width), HALVE(height), tmp.uv_stride, work, 1); | 256 HALVE(width), HALVE(height), tmp.uv_stride, work, 1); |
| 261 } else { | 257 } else { |
| 262 work = (int32_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work)); | 258 work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work)); |
| 263 if (work == NULL) { | 259 if (work == NULL) { |
| 264 WebPPictureFree(&tmp); | 260 WebPPictureFree(&tmp); |
| 265 return 0; | 261 return 0; |
| 266 } | 262 } |
| 267 // In order to correctly interpolate colors, we need to apply the alpha | 263 // In order to correctly interpolate colors, we need to apply the alpha |
| 268 // weighting first (black-matting), scale the RGB values, and remove | 264 // weighting first (black-matting), scale the RGB values, and remove |
| 269 // the premultiplication afterward (while preserving the alpha channel). | 265 // the premultiplication afterward (while preserving the alpha channel). |
| 270 WebPInitAlphaProcessing(); | 266 WebPInitAlphaProcessing(); |
| 271 AlphaMultiplyARGB(pic, 0); | 267 AlphaMultiplyARGB(pic, 0); |
| 272 RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height, | 268 RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height, |
| 273 pic->argb_stride * 4, | 269 pic->argb_stride * 4, |
| 274 (uint8_t*)tmp.argb, width, height, | 270 (uint8_t*)tmp.argb, width, height, |
| 275 tmp.argb_stride * 4, | 271 tmp.argb_stride * 4, |
| 276 work, 4); | 272 work, 4); |
| 277 AlphaMultiplyARGB(&tmp, 1); | 273 AlphaMultiplyARGB(&tmp, 1); |
| 278 } | 274 } |
| 279 WebPPictureFree(pic); | 275 WebPPictureFree(pic); |
| 280 WebPSafeFree(work); | 276 WebPSafeFree(work); |
| 281 *pic = tmp; | 277 *pic = tmp; |
| 282 return 1; | 278 return 1; |
| 283 } | 279 } |
| 284 | 280 |
| 285 //------------------------------------------------------------------------------ | 281 //------------------------------------------------------------------------------ |
| OLD | NEW |