Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: third_party/libwebp/dec/io_dec.c

Issue 2651883004: libwebp-0.6.0-rc1 (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/libwebp/dec/io.c ('k') | third_party/libwebp/dec/quant.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // functions for sample output. 10 // functions for sample output.
11 // 11 //
12 // Author: Skal (pascal.massimino@gmail.com) 12 // Author: Skal (pascal.massimino@gmail.com)
13 13
14 #include <assert.h> 14 #include <assert.h>
15 #include <stdlib.h> 15 #include <stdlib.h>
16 #include "../dec/vp8i.h" 16 #include "../dec/vp8i_dec.h"
17 #include "./webpi.h" 17 #include "./webpi_dec.h"
18 #include "../dsp/dsp.h" 18 #include "../dsp/dsp.h"
19 #include "../dsp/yuv.h" 19 #include "../dsp/yuv.h"
20 #include "../utils/utils.h" 20 #include "../utils/utils.h"
21 21
22 //------------------------------------------------------------------------------ 22 //------------------------------------------------------------------------------
23 // Main YUV<->RGB conversion functions 23 // Main YUV<->RGB conversion functions
24 24
25 static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { 25 static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
26 WebPDecBuffer* output = p->output; 26 WebPDecBuffer* output = p->output;
27 const WebPYUVABuffer* const buf = &output->u.YUVA; 27 const WebPYUVABuffer* const buf = &output->u.YUVA;
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 src += lines_in * src_stride; 249 src += lines_in * src_stride;
250 new_lines -= lines_in; 250 new_lines -= lines_in;
251 num_lines_out += WebPRescalerExport(wrk); // emit output row(s) 251 num_lines_out += WebPRescalerExport(wrk); // emit output row(s)
252 } 252 }
253 return num_lines_out; 253 return num_lines_out;
254 } 254 }
255 255
256 static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { 256 static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
257 const int mb_h = io->mb_h; 257 const int mb_h = io->mb_h;
258 const int uv_mb_h = (mb_h + 1) >> 1; 258 const int uv_mb_h = (mb_h + 1) >> 1;
259 WebPRescaler* const scaler = &p->scaler_y; 259 WebPRescaler* const scaler = p->scaler_y;
260 int num_lines_out = 0; 260 int num_lines_out = 0;
261 if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { 261 if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) {
262 // Before rescaling, we premultiply the luma directly into the io->y 262 // Before rescaling, we premultiply the luma directly into the io->y
263 // internal buffer. This is OK since these samples are not used for 263 // internal buffer. This is OK since these samples are not used for
264 // intra-prediction (the top samples are saved in cache_y_/u_/v_). 264 // intra-prediction (the top samples are saved in cache_y_/u_/v_).
265 // But we need to cast the const away, though. 265 // But we need to cast the const away, though.
266 WebPMultRows((uint8_t*)io->y, io->y_stride, 266 WebPMultRows((uint8_t*)io->y, io->y_stride,
267 io->a, io->width, io->mb_w, mb_h, 0); 267 io->a, io->width, io->mb_w, mb_h, 0);
268 } 268 }
269 num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); 269 num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
270 Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u); 270 Rescale(io->u, io->uv_stride, uv_mb_h, p->scaler_u);
271 Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v); 271 Rescale(io->v, io->uv_stride, uv_mb_h, p->scaler_v);
272 return num_lines_out; 272 return num_lines_out;
273 } 273 }
274 274
275 static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p, 275 static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p,
276 int expected_num_lines_out) { 276 int expected_num_lines_out) {
277 const WebPYUVABuffer* const buf = &p->output->u.YUVA; 277 const WebPYUVABuffer* const buf = &p->output->u.YUVA;
278 uint8_t* const dst_a = buf->a + p->last_y * buf->a_stride;
278 if (io->a != NULL) { 279 if (io->a != NULL) {
279 uint8_t* dst_y = buf->y + p->last_y * buf->y_stride; 280 uint8_t* const dst_y = buf->y + p->last_y * buf->y_stride;
280 const uint8_t* src_a = buf->a + p->last_y * buf->a_stride; 281 const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a);
281 const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
282 (void)expected_num_lines_out;
283 assert(expected_num_lines_out == num_lines_out); 282 assert(expected_num_lines_out == num_lines_out);
284 if (num_lines_out > 0) { // unmultiply the Y 283 if (num_lines_out > 0) { // unmultiply the Y
285 WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride, 284 WebPMultRows(dst_y, buf->y_stride, dst_a, buf->a_stride,
286 p->scaler_a.dst_width, num_lines_out, 1); 285 p->scaler_a->dst_width, num_lines_out, 1);
287 } 286 }
288 } else if (buf->a != NULL) { 287 } else if (buf->a != NULL) {
289 // the user requested alpha, but there is none, set it to opaque. 288 // the user requested alpha, but there is none, set it to opaque.
290 assert(p->last_y + expected_num_lines_out <= io->scaled_height); 289 assert(p->last_y + expected_num_lines_out <= io->scaled_height);
291 FillAlphaPlane(buf->a + p->last_y * buf->a_stride, 290 FillAlphaPlane(dst_a, io->scaled_width, expected_num_lines_out,
292 io->scaled_width, expected_num_lines_out, buf->a_stride); 291 buf->a_stride);
293 } 292 }
294 return 0; 293 return 0;
295 } 294 }
296 295
297 static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { 296 static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
298 const int has_alpha = WebPIsAlphaMode(p->output->colorspace); 297 const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
299 const WebPYUVABuffer* const buf = &p->output->u.YUVA; 298 const WebPYUVABuffer* const buf = &p->output->u.YUVA;
300 const int out_width = io->scaled_width; 299 const int out_width = io->scaled_width;
301 const int out_height = io->scaled_height; 300 const int out_height = io->scaled_height;
302 const int uv_out_width = (out_width + 1) >> 1; 301 const int uv_out_width = (out_width + 1) >> 1;
303 const int uv_out_height = (out_height + 1) >> 1; 302 const int uv_out_height = (out_height + 1) >> 1;
304 const int uv_in_width = (io->mb_w + 1) >> 1; 303 const int uv_in_width = (io->mb_w + 1) >> 1;
305 const int uv_in_height = (io->mb_h + 1) >> 1; 304 const int uv_in_height = (io->mb_h + 1) >> 1;
306 const size_t work_size = 2 * out_width; // scratch memory for luma rescaler 305 const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
307 const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones 306 const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
308 size_t tmp_size; 307 size_t tmp_size, rescaler_size;
309 rescaler_t* work; 308 rescaler_t* work;
309 WebPRescaler* scalers;
310 const int num_rescalers = has_alpha ? 4 : 3;
310 311
311 tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); 312 tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
312 if (has_alpha) { 313 if (has_alpha) {
313 tmp_size += work_size * sizeof(*work); 314 tmp_size += work_size * sizeof(*work);
314 } 315 }
315 p->memory = WebPSafeMalloc(1ULL, tmp_size); 316 rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
317
318 p->memory = WebPSafeMalloc(1ULL, tmp_size + rescaler_size);
316 if (p->memory == NULL) { 319 if (p->memory == NULL) {
317 return 0; // memory error 320 return 0; // memory error
318 } 321 }
319 work = (rescaler_t*)p->memory; 322 work = (rescaler_t*)p->memory;
320 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, 323
324 scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + tmp_size);
325 p->scaler_y = &scalers[0];
326 p->scaler_u = &scalers[1];
327 p->scaler_v = &scalers[2];
328 p->scaler_a = has_alpha ? &scalers[3] : NULL;
329
330 WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
321 buf->y, out_width, out_height, buf->y_stride, 1, 331 buf->y, out_width, out_height, buf->y_stride, 1,
322 work); 332 work);
323 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, 333 WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
324 buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, 334 buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
325 work + work_size); 335 work + work_size);
326 WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, 336 WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
327 buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, 337 buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
328 work + work_size + uv_work_size); 338 work + work_size + uv_work_size);
329 p->emit = EmitRescaledYUV; 339 p->emit = EmitRescaledYUV;
330 340
331 if (has_alpha) { 341 if (has_alpha) {
332 WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, 342 WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
333 buf->a, out_width, out_height, buf->a_stride, 1, 343 buf->a, out_width, out_height, buf->a_stride, 1,
334 work + work_size + 2 * uv_work_size); 344 work + work_size + 2 * uv_work_size);
335 p->emit_alpha = EmitRescaledAlphaYUV; 345 p->emit_alpha = EmitRescaledAlphaYUV;
336 WebPInitAlphaProcessing(); 346 WebPInitAlphaProcessing();
337 } 347 }
338 return 1; 348 return 1;
339 } 349 }
340 350
341 //------------------------------------------------------------------------------ 351 //------------------------------------------------------------------------------
342 // RGBA rescaling 352 // RGBA rescaling
343 353
344 static int ExportRGB(WebPDecParams* const p, int y_pos) { 354 static int ExportRGB(WebPDecParams* const p, int y_pos) {
345 const WebPYUV444Converter convert = 355 const WebPYUV444Converter convert =
346 WebPYUV444Converters[p->output->colorspace]; 356 WebPYUV444Converters[p->output->colorspace];
347 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 357 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
348 uint8_t* dst = buf->rgba + y_pos * buf->stride; 358 uint8_t* dst = buf->rgba + y_pos * buf->stride;
349 int num_lines_out = 0; 359 int num_lines_out = 0;
350 // For RGB rescaling, because of the YUV420, current scan position 360 // For RGB rescaling, because of the YUV420, current scan position
351 // U/V can be +1/-1 line from the Y one. Hence the double test. 361 // U/V can be +1/-1 line from the Y one. Hence the double test.
352 while (WebPRescalerHasPendingOutput(&p->scaler_y) && 362 while (WebPRescalerHasPendingOutput(p->scaler_y) &&
353 WebPRescalerHasPendingOutput(&p->scaler_u)) { 363 WebPRescalerHasPendingOutput(p->scaler_u)) {
354 assert(y_pos + num_lines_out < p->output->height); 364 assert(y_pos + num_lines_out < p->output->height);
355 assert(p->scaler_u.y_accum == p->scaler_v.y_accum); 365 assert(p->scaler_u->y_accum == p->scaler_v->y_accum);
356 WebPRescalerExportRow(&p->scaler_y); 366 WebPRescalerExportRow(p->scaler_y);
357 WebPRescalerExportRow(&p->scaler_u); 367 WebPRescalerExportRow(p->scaler_u);
358 WebPRescalerExportRow(&p->scaler_v); 368 WebPRescalerExportRow(p->scaler_v);
359 convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst, 369 convert(p->scaler_y->dst, p->scaler_u->dst, p->scaler_v->dst,
360 dst, p->scaler_y.dst_width); 370 dst, p->scaler_y->dst_width);
361 dst += buf->stride; 371 dst += buf->stride;
362 ++num_lines_out; 372 ++num_lines_out;
363 } 373 }
364 return num_lines_out; 374 return num_lines_out;
365 } 375 }
366 376
367 static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { 377 static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
368 const int mb_h = io->mb_h; 378 const int mb_h = io->mb_h;
369 const int uv_mb_h = (mb_h + 1) >> 1; 379 const int uv_mb_h = (mb_h + 1) >> 1;
370 int j = 0, uv_j = 0; 380 int j = 0, uv_j = 0;
371 int num_lines_out = 0; 381 int num_lines_out = 0;
372 while (j < mb_h) { 382 while (j < mb_h) {
373 const int y_lines_in = 383 const int y_lines_in =
374 WebPRescalerImport(&p->scaler_y, mb_h - j, 384 WebPRescalerImport(p->scaler_y, mb_h - j,
375 io->y + j * io->y_stride, io->y_stride); 385 io->y + j * io->y_stride, io->y_stride);
376 j += y_lines_in; 386 j += y_lines_in;
377 if (WebPRescaleNeededLines(&p->scaler_u, uv_mb_h - uv_j)) { 387 if (WebPRescaleNeededLines(p->scaler_u, uv_mb_h - uv_j)) {
378 const int u_lines_in = 388 const int u_lines_in =
379 WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j, 389 WebPRescalerImport(p->scaler_u, uv_mb_h - uv_j,
380 io->u + uv_j * io->uv_stride, io->uv_stride); 390 io->u + uv_j * io->uv_stride, io->uv_stride);
381 const int v_lines_in = 391 const int v_lines_in =
382 WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j, 392 WebPRescalerImport(p->scaler_v, uv_mb_h - uv_j,
383 io->v + uv_j * io->uv_stride, io->uv_stride); 393 io->v + uv_j * io->uv_stride, io->uv_stride);
384 (void)v_lines_in; // remove a gcc warning 394 (void)v_lines_in; // remove a gcc warning
385 assert(u_lines_in == v_lines_in); 395 assert(u_lines_in == v_lines_in);
386 uv_j += u_lines_in; 396 uv_j += u_lines_in;
387 } 397 }
388 num_lines_out += ExportRGB(p, p->last_y + num_lines_out); 398 num_lines_out += ExportRGB(p, p->last_y + num_lines_out);
389 } 399 }
390 return num_lines_out; 400 return num_lines_out;
391 } 401 }
392 402
393 static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) { 403 static int ExportAlpha(WebPDecParams* const p, int y_pos, int max_lines_out) {
394 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 404 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
395 uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; 405 uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
396 const WEBP_CSP_MODE colorspace = p->output->colorspace; 406 const WEBP_CSP_MODE colorspace = p->output->colorspace;
397 const int alpha_first = 407 const int alpha_first =
398 (colorspace == MODE_ARGB || colorspace == MODE_Argb); 408 (colorspace == MODE_ARGB || colorspace == MODE_Argb);
399 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); 409 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
400 int num_lines_out = 0; 410 int num_lines_out = 0;
401 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); 411 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
402 uint32_t non_opaque = 0; 412 uint32_t non_opaque = 0;
403 const int width = p->scaler_a.dst_width; 413 const int width = p->scaler_a->dst_width;
404 414
405 while (WebPRescalerHasPendingOutput(&p->scaler_a) && 415 while (WebPRescalerHasPendingOutput(p->scaler_a) &&
406 num_lines_out < max_lines_out) { 416 num_lines_out < max_lines_out) {
407 assert(y_pos + num_lines_out < p->output->height); 417 assert(y_pos + num_lines_out < p->output->height);
408 WebPRescalerExportRow(&p->scaler_a); 418 WebPRescalerExportRow(p->scaler_a);
409 non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0); 419 non_opaque |= WebPDispatchAlpha(p->scaler_a->dst, 0, width, 1, dst, 0);
410 dst += buf->stride; 420 dst += buf->stride;
411 ++num_lines_out; 421 ++num_lines_out;
412 } 422 }
413 if (is_premult_alpha && non_opaque) { 423 if (is_premult_alpha && non_opaque) {
414 WebPApplyAlphaMultiply(base_rgba, alpha_first, 424 WebPApplyAlphaMultiply(base_rgba, alpha_first,
415 width, num_lines_out, buf->stride); 425 width, num_lines_out, buf->stride);
416 } 426 }
417 return num_lines_out; 427 return num_lines_out;
418 } 428 }
419 429
420 static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, 430 static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos,
421 int max_lines_out) { 431 int max_lines_out) {
422 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 432 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
423 uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; 433 uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride;
424 #ifdef WEBP_SWAP_16BIT_CSP 434 #ifdef WEBP_SWAP_16BIT_CSP
425 uint8_t* alpha_dst = base_rgba; 435 uint8_t* alpha_dst = base_rgba;
426 #else 436 #else
427 uint8_t* alpha_dst = base_rgba + 1; 437 uint8_t* alpha_dst = base_rgba + 1;
428 #endif 438 #endif
429 int num_lines_out = 0; 439 int num_lines_out = 0;
430 const WEBP_CSP_MODE colorspace = p->output->colorspace; 440 const WEBP_CSP_MODE colorspace = p->output->colorspace;
431 const int width = p->scaler_a.dst_width; 441 const int width = p->scaler_a->dst_width;
432 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); 442 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
433 uint32_t alpha_mask = 0x0f; 443 uint32_t alpha_mask = 0x0f;
434 444
435 while (WebPRescalerHasPendingOutput(&p->scaler_a) && 445 while (WebPRescalerHasPendingOutput(p->scaler_a) &&
436 num_lines_out < max_lines_out) { 446 num_lines_out < max_lines_out) {
437 int i; 447 int i;
438 assert(y_pos + num_lines_out < p->output->height); 448 assert(y_pos + num_lines_out < p->output->height);
439 WebPRescalerExportRow(&p->scaler_a); 449 WebPRescalerExportRow(p->scaler_a);
440 for (i = 0; i < width; ++i) { 450 for (i = 0; i < width; ++i) {
441 // Fill in the alpha value (converted to 4 bits). 451 // Fill in the alpha value (converted to 4 bits).
442 const uint32_t alpha_value = p->scaler_a.dst[i] >> 4; 452 const uint32_t alpha_value = p->scaler_a->dst[i] >> 4;
443 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; 453 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
444 alpha_mask &= alpha_value; 454 alpha_mask &= alpha_value;
445 } 455 }
446 alpha_dst += buf->stride; 456 alpha_dst += buf->stride;
447 ++num_lines_out; 457 ++num_lines_out;
448 } 458 }
449 if (is_premult_alpha && alpha_mask != 0x0f) { 459 if (is_premult_alpha && alpha_mask != 0x0f) {
450 WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); 460 WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
451 } 461 }
452 return num_lines_out; 462 return num_lines_out;
453 } 463 }
454 464
455 static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p, 465 static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p,
456 int expected_num_out_lines) { 466 int expected_num_out_lines) {
457 if (io->a != NULL) { 467 if (io->a != NULL) {
458 WebPRescaler* const scaler = &p->scaler_a; 468 WebPRescaler* const scaler = p->scaler_a;
459 int lines_left = expected_num_out_lines; 469 int lines_left = expected_num_out_lines;
460 const int y_end = p->last_y + lines_left; 470 const int y_end = p->last_y + lines_left;
461 while (lines_left > 0) { 471 while (lines_left > 0) {
462 const int row_offset = scaler->src_y - io->mb_y; 472 const int row_offset = scaler->src_y - io->mb_y;
463 WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y, 473 WebPRescalerImport(scaler, io->mb_h + io->mb_y - scaler->src_y,
464 io->a + row_offset * io->width, io->width); 474 io->a + row_offset * io->width, io->width);
465 lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left); 475 lines_left -= p->emit_alpha_row(p, y_end - lines_left, lines_left);
466 } 476 }
467 } 477 }
468 return 0; 478 return 0;
469 } 479 }
470 480
471 static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { 481 static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
472 const int has_alpha = WebPIsAlphaMode(p->output->colorspace); 482 const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
473 const int out_width = io->scaled_width; 483 const int out_width = io->scaled_width;
474 const int out_height = io->scaled_height; 484 const int out_height = io->scaled_height;
475 const int uv_in_width = (io->mb_w + 1) >> 1; 485 const int uv_in_width = (io->mb_w + 1) >> 1;
476 const int uv_in_height = (io->mb_h + 1) >> 1; 486 const int uv_in_height = (io->mb_h + 1) >> 1;
477 const size_t work_size = 2 * out_width; // scratch memory for one rescaler 487 const size_t work_size = 2 * out_width; // scratch memory for one rescaler
478 rescaler_t* work; // rescalers work area 488 rescaler_t* work; // rescalers work area
479 uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion 489 uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
480 size_t tmp_size1, tmp_size2, total_size; 490 size_t tmp_size1, tmp_size2, total_size, rescaler_size;
491 WebPRescaler* scalers;
492 const int num_rescalers = has_alpha ? 4 : 3;
481 493
482 tmp_size1 = 3 * work_size; 494 tmp_size1 = 3 * work_size;
483 tmp_size2 = 3 * out_width; 495 tmp_size2 = 3 * out_width;
484 if (has_alpha) { 496 if (has_alpha) {
485 tmp_size1 += work_size; 497 tmp_size1 += work_size;
486 tmp_size2 += out_width; 498 tmp_size2 += out_width;
487 } 499 }
488 total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); 500 total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
489 p->memory = WebPSafeMalloc(1ULL, total_size); 501 rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
502
503 p->memory = WebPSafeMalloc(1ULL, total_size + rescaler_size);
490 if (p->memory == NULL) { 504 if (p->memory == NULL) {
491 return 0; // memory error 505 return 0; // memory error
492 } 506 }
493 work = (rescaler_t*)p->memory; 507 work = (rescaler_t*)p->memory;
494 tmp = (uint8_t*)(work + tmp_size1); 508 tmp = (uint8_t*)(work + tmp_size1);
495 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, 509
510 scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + total_size);
511 p->scaler_y = &scalers[0];
512 p->scaler_u = &scalers[1];
513 p->scaler_v = &scalers[2];
514 p->scaler_a = has_alpha ? &scalers[3] : NULL;
515
516 WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
496 tmp + 0 * out_width, out_width, out_height, 0, 1, 517 tmp + 0 * out_width, out_width, out_height, 0, 1,
497 work + 0 * work_size); 518 work + 0 * work_size);
498 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, 519 WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
499 tmp + 1 * out_width, out_width, out_height, 0, 1, 520 tmp + 1 * out_width, out_width, out_height, 0, 1,
500 work + 1 * work_size); 521 work + 1 * work_size);
501 WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, 522 WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
502 tmp + 2 * out_width, out_width, out_height, 0, 1, 523 tmp + 2 * out_width, out_width, out_height, 0, 1,
503 work + 2 * work_size); 524 work + 2 * work_size);
504 p->emit = EmitRescaledRGB; 525 p->emit = EmitRescaledRGB;
505 WebPInitYUV444Converters(); 526 WebPInitYUV444Converters();
506 527
507 if (has_alpha) { 528 if (has_alpha) {
508 WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, 529 WebPRescalerInit(p->scaler_a, io->mb_w, io->mb_h,
509 tmp + 3 * out_width, out_width, out_height, 0, 1, 530 tmp + 3 * out_width, out_width, out_height, 0, 1,
510 work + 3 * work_size); 531 work + 3 * work_size);
511 p->emit_alpha = EmitRescaledAlphaRGB; 532 p->emit_alpha = EmitRescaledAlphaRGB;
512 if (p->output->colorspace == MODE_RGBA_4444 || 533 if (p->output->colorspace == MODE_RGBA_4444 ||
513 p->output->colorspace == MODE_rgbA_4444) { 534 p->output->colorspace == MODE_rgbA_4444) {
514 p->emit_alpha_row = ExportAlphaRGBA4444; 535 p->emit_alpha_row = ExportAlphaRGBA4444;
515 } else { 536 } else {
516 p->emit_alpha_row = ExportAlpha; 537 p->emit_alpha_row = ExportAlpha;
517 } 538 }
518 WebPInitAlphaProcessing(); 539 WebPInitAlphaProcessing();
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 // Main entry point 636 // Main entry point
616 637
617 void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { 638 void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
618 io->put = CustomPut; 639 io->put = CustomPut;
619 io->setup = CustomSetup; 640 io->setup = CustomSetup;
620 io->teardown = CustomTeardown; 641 io->teardown = CustomTeardown;
621 io->opaque = params; 642 io->opaque = params;
622 } 643 }
623 644
624 //------------------------------------------------------------------------------ 645 //------------------------------------------------------------------------------
OLDNEW
« no previous file with comments | « third_party/libwebp/dec/io.c ('k') | third_party/libwebp/dec/quant.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698