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 |