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 // functions for sample output. | 10 // functions for sample output. |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 const WebPYUVABuffer* const buf = &p->output->u.YUVA; | 315 const WebPYUVABuffer* const buf = &p->output->u.YUVA; |
316 const int out_width = io->scaled_width; | 316 const int out_width = io->scaled_width; |
317 const int out_height = io->scaled_height; | 317 const int out_height = io->scaled_height; |
318 const int uv_out_width = (out_width + 1) >> 1; | 318 const int uv_out_width = (out_width + 1) >> 1; |
319 const int uv_out_height = (out_height + 1) >> 1; | 319 const int uv_out_height = (out_height + 1) >> 1; |
320 const int uv_in_width = (io->mb_w + 1) >> 1; | 320 const int uv_in_width = (io->mb_w + 1) >> 1; |
321 const int uv_in_height = (io->mb_h + 1) >> 1; | 321 const int uv_in_height = (io->mb_h + 1) >> 1; |
322 const size_t work_size = 2 * out_width; // scratch memory for luma rescaler | 322 const size_t work_size = 2 * out_width; // scratch memory for luma rescaler |
323 const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones | 323 const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones |
324 size_t tmp_size; | 324 size_t tmp_size; |
325 int32_t* work; | 325 rescaler_t* work; |
326 | 326 |
327 tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); | 327 tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); |
328 if (has_alpha) { | 328 if (has_alpha) { |
329 tmp_size += work_size * sizeof(*work); | 329 tmp_size += work_size * sizeof(*work); |
330 } | 330 } |
331 p->memory = WebPSafeCalloc(1ULL, tmp_size); | 331 p->memory = WebPSafeMalloc(1ULL, tmp_size); |
332 if (p->memory == NULL) { | 332 if (p->memory == NULL) { |
333 return 0; // memory error | 333 return 0; // memory error |
334 } | 334 } |
335 work = (int32_t*)p->memory; | 335 work = (rescaler_t*)p->memory; |
336 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, | 336 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, |
337 buf->y, out_width, out_height, buf->y_stride, 1, | 337 buf->y, out_width, out_height, buf->y_stride, 1, |
338 io->mb_w, out_width, io->mb_h, out_height, | |
339 work); | 338 work); |
340 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, | 339 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, |
341 buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, | 340 buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, |
342 uv_in_width, uv_out_width, | |
343 uv_in_height, uv_out_height, | |
344 work + work_size); | 341 work + work_size); |
345 WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, | 342 WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, |
346 buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, | 343 buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, |
347 uv_in_width, uv_out_width, | |
348 uv_in_height, uv_out_height, | |
349 work + work_size + uv_work_size); | 344 work + work_size + uv_work_size); |
350 p->emit = EmitRescaledYUV; | 345 p->emit = EmitRescaledYUV; |
351 | 346 |
352 if (has_alpha) { | 347 if (has_alpha) { |
353 WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, | 348 WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, |
354 buf->a, out_width, out_height, buf->a_stride, 1, | 349 buf->a, out_width, out_height, buf->a_stride, 1, |
355 io->mb_w, out_width, io->mb_h, out_height, | |
356 work + work_size + 2 * uv_work_size); | 350 work + work_size + 2 * uv_work_size); |
357 p->emit_alpha = EmitRescaledAlphaYUV; | 351 p->emit_alpha = EmitRescaledAlphaYUV; |
358 WebPInitAlphaProcessing(); | 352 WebPInitAlphaProcessing(); |
359 } | 353 } |
360 return 1; | 354 return 1; |
361 } | 355 } |
362 | 356 |
363 //------------------------------------------------------------------------------ | 357 //------------------------------------------------------------------------------ |
364 // RGBA rescaling | 358 // RGBA rescaling |
365 | 359 |
366 static int ExportRGB(WebPDecParams* const p, int y_pos) { | 360 static int ExportRGB(WebPDecParams* const p, int y_pos) { |
367 const WebPYUV444Converter convert = | 361 const WebPYUV444Converter convert = |
368 WebPYUV444Converters[p->output->colorspace]; | 362 WebPYUV444Converters[p->output->colorspace]; |
369 const WebPRGBABuffer* const buf = &p->output->u.RGBA; | 363 const WebPRGBABuffer* const buf = &p->output->u.RGBA; |
370 uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride; | 364 uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride; |
371 int num_lines_out = 0; | 365 int num_lines_out = 0; |
372 // For RGB rescaling, because of the YUV420, current scan position | 366 // For RGB rescaling, because of the YUV420, current scan position |
373 // U/V can be +1/-1 line from the Y one. Hence the double test. | 367 // U/V can be +1/-1 line from the Y one. Hence the double test. |
374 while (WebPRescalerHasPendingOutput(&p->scaler_y) && | 368 while (WebPRescalerHasPendingOutput(&p->scaler_y) && |
375 WebPRescalerHasPendingOutput(&p->scaler_u)) { | 369 WebPRescalerHasPendingOutput(&p->scaler_u)) { |
376 assert(p->last_y + y_pos + num_lines_out < p->output->height); | 370 assert(p->last_y + y_pos + num_lines_out < p->output->height); |
377 assert(p->scaler_u.y_accum == p->scaler_v.y_accum); | 371 assert(p->scaler_u.y_accum == p->scaler_v.y_accum); |
378 WebPRescalerExportRow(&p->scaler_y, 0); | 372 WebPRescalerExportRow(&p->scaler_y); |
379 WebPRescalerExportRow(&p->scaler_u, 0); | 373 WebPRescalerExportRow(&p->scaler_u); |
380 WebPRescalerExportRow(&p->scaler_v, 0); | 374 WebPRescalerExportRow(&p->scaler_v); |
381 convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst, | 375 convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst, |
382 dst, p->scaler_y.dst_width); | 376 dst, p->scaler_y.dst_width); |
383 dst += buf->stride; | 377 dst += buf->stride; |
384 ++num_lines_out; | 378 ++num_lines_out; |
385 } | 379 } |
386 return num_lines_out; | 380 return num_lines_out; |
387 } | 381 } |
388 | 382 |
389 static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { | 383 static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { |
390 const int mb_h = io->mb_h; | 384 const int mb_h = io->mb_h; |
(...skipping 27 matching lines...) Expand all Loading... |
418 (colorspace == MODE_ARGB || colorspace == MODE_Argb); | 412 (colorspace == MODE_ARGB || colorspace == MODE_Argb); |
419 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); | 413 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); |
420 int num_lines_out = 0; | 414 int num_lines_out = 0; |
421 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); | 415 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); |
422 uint32_t alpha_mask = 0xff; | 416 uint32_t alpha_mask = 0xff; |
423 const int width = p->scaler_a.dst_width; | 417 const int width = p->scaler_a.dst_width; |
424 | 418 |
425 while (WebPRescalerHasPendingOutput(&p->scaler_a)) { | 419 while (WebPRescalerHasPendingOutput(&p->scaler_a)) { |
426 int i; | 420 int i; |
427 assert(p->last_y + y_pos + num_lines_out < p->output->height); | 421 assert(p->last_y + y_pos + num_lines_out < p->output->height); |
428 WebPRescalerExportRow(&p->scaler_a, 0); | 422 WebPRescalerExportRow(&p->scaler_a); |
429 for (i = 0; i < width; ++i) { | 423 for (i = 0; i < width; ++i) { |
430 const uint32_t alpha_value = p->scaler_a.dst[i]; | 424 const uint32_t alpha_value = p->scaler_a.dst[i]; |
431 dst[4 * i] = alpha_value; | 425 dst[4 * i] = alpha_value; |
432 alpha_mask &= alpha_value; | 426 alpha_mask &= alpha_value; |
433 } | 427 } |
434 dst += buf->stride; | 428 dst += buf->stride; |
435 ++num_lines_out; | 429 ++num_lines_out; |
436 } | 430 } |
437 if (is_premult_alpha && alpha_mask != 0xff) { | 431 if (is_premult_alpha && alpha_mask != 0xff) { |
438 WebPApplyAlphaMultiply(base_rgba, alpha_first, | 432 WebPApplyAlphaMultiply(base_rgba, alpha_first, |
(...skipping 12 matching lines...) Expand all Loading... |
451 #endif | 445 #endif |
452 int num_lines_out = 0; | 446 int num_lines_out = 0; |
453 const WEBP_CSP_MODE colorspace = p->output->colorspace; | 447 const WEBP_CSP_MODE colorspace = p->output->colorspace; |
454 const int width = p->scaler_a.dst_width; | 448 const int width = p->scaler_a.dst_width; |
455 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); | 449 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); |
456 uint32_t alpha_mask = 0x0f; | 450 uint32_t alpha_mask = 0x0f; |
457 | 451 |
458 while (WebPRescalerHasPendingOutput(&p->scaler_a)) { | 452 while (WebPRescalerHasPendingOutput(&p->scaler_a)) { |
459 int i; | 453 int i; |
460 assert(p->last_y + y_pos + num_lines_out < p->output->height); | 454 assert(p->last_y + y_pos + num_lines_out < p->output->height); |
461 WebPRescalerExportRow(&p->scaler_a, 0); | 455 WebPRescalerExportRow(&p->scaler_a); |
462 for (i = 0; i < width; ++i) { | 456 for (i = 0; i < width; ++i) { |
463 // Fill in the alpha value (converted to 4 bits). | 457 // Fill in the alpha value (converted to 4 bits). |
464 const uint32_t alpha_value = p->scaler_a.dst[i] >> 4; | 458 const uint32_t alpha_value = p->scaler_a.dst[i] >> 4; |
465 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; | 459 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; |
466 alpha_mask &= alpha_value; | 460 alpha_mask &= alpha_value; |
467 } | 461 } |
468 alpha_dst += buf->stride; | 462 alpha_dst += buf->stride; |
469 ++num_lines_out; | 463 ++num_lines_out; |
470 } | 464 } |
471 if (is_premult_alpha && alpha_mask != 0x0f) { | 465 if (is_premult_alpha && alpha_mask != 0x0f) { |
(...skipping 16 matching lines...) Expand all Loading... |
488 return 0; | 482 return 0; |
489 } | 483 } |
490 | 484 |
491 static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { | 485 static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { |
492 const int has_alpha = WebPIsAlphaMode(p->output->colorspace); | 486 const int has_alpha = WebPIsAlphaMode(p->output->colorspace); |
493 const int out_width = io->scaled_width; | 487 const int out_width = io->scaled_width; |
494 const int out_height = io->scaled_height; | 488 const int out_height = io->scaled_height; |
495 const int uv_in_width = (io->mb_w + 1) >> 1; | 489 const int uv_in_width = (io->mb_w + 1) >> 1; |
496 const int uv_in_height = (io->mb_h + 1) >> 1; | 490 const int uv_in_height = (io->mb_h + 1) >> 1; |
497 const size_t work_size = 2 * out_width; // scratch memory for one rescaler | 491 const size_t work_size = 2 * out_width; // scratch memory for one rescaler |
498 int32_t* work; // rescalers work area | 492 rescaler_t* work; // rescalers work area |
499 uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion | 493 uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion |
500 size_t tmp_size1, tmp_size2, total_size; | 494 size_t tmp_size1, tmp_size2, total_size; |
501 | 495 |
502 tmp_size1 = 3 * work_size; | 496 tmp_size1 = 3 * work_size; |
503 tmp_size2 = 3 * out_width; | 497 tmp_size2 = 3 * out_width; |
504 if (has_alpha) { | 498 if (has_alpha) { |
505 tmp_size1 += work_size; | 499 tmp_size1 += work_size; |
506 tmp_size2 += out_width; | 500 tmp_size2 += out_width; |
507 } | 501 } |
508 total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); | 502 total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); |
509 p->memory = WebPSafeCalloc(1ULL, total_size); | 503 p->memory = WebPSafeMalloc(1ULL, total_size); |
510 if (p->memory == NULL) { | 504 if (p->memory == NULL) { |
511 return 0; // memory error | 505 return 0; // memory error |
512 } | 506 } |
513 work = (int32_t*)p->memory; | 507 work = (rescaler_t*)p->memory; |
514 tmp = (uint8_t*)(work + tmp_size1); | 508 tmp = (uint8_t*)(work + tmp_size1); |
515 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, | 509 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, |
516 tmp + 0 * out_width, out_width, out_height, 0, 1, | 510 tmp + 0 * out_width, out_width, out_height, 0, 1, |
517 io->mb_w, out_width, io->mb_h, out_height, | |
518 work + 0 * work_size); | 511 work + 0 * work_size); |
519 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, | 512 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, |
520 tmp + 1 * out_width, out_width, out_height, 0, 1, | 513 tmp + 1 * out_width, out_width, out_height, 0, 1, |
521 io->mb_w, 2 * out_width, io->mb_h, 2 * out_height, | |
522 work + 1 * work_size); | 514 work + 1 * work_size); |
523 WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, | 515 WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, |
524 tmp + 2 * out_width, out_width, out_height, 0, 1, | 516 tmp + 2 * out_width, out_width, out_height, 0, 1, |
525 io->mb_w, 2 * out_width, io->mb_h, 2 * out_height, | |
526 work + 2 * work_size); | 517 work + 2 * work_size); |
527 p->emit = EmitRescaledRGB; | 518 p->emit = EmitRescaledRGB; |
528 | 519 |
529 if (has_alpha) { | 520 if (has_alpha) { |
530 WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, | 521 WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, |
531 tmp + 3 * out_width, out_width, out_height, 0, 1, | 522 tmp + 3 * out_width, out_width, out_height, 0, 1, |
532 io->mb_w, out_width, io->mb_h, out_height, | |
533 work + 3 * work_size); | 523 work + 3 * work_size); |
534 p->emit_alpha = EmitRescaledAlphaRGB; | 524 p->emit_alpha = EmitRescaledAlphaRGB; |
535 if (p->output->colorspace == MODE_RGBA_4444 || | 525 if (p->output->colorspace == MODE_RGBA_4444 || |
536 p->output->colorspace == MODE_rgbA_4444) { | 526 p->output->colorspace == MODE_rgbA_4444) { |
537 p->emit_alpha_row = ExportAlphaRGBA4444; | 527 p->emit_alpha_row = ExportAlphaRGBA4444; |
538 } else { | 528 } else { |
539 p->emit_alpha_row = ExportAlpha; | 529 p->emit_alpha_row = ExportAlpha; |
540 } | 530 } |
541 WebPInitAlphaProcessing(); | 531 WebPInitAlphaProcessing(); |
542 } | 532 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 // Main entry point | 629 // Main entry point |
640 | 630 |
641 void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { | 631 void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { |
642 io->put = CustomPut; | 632 io->put = CustomPut; |
643 io->setup = CustomSetup; | 633 io->setup = CustomSetup; |
644 io->teardown = CustomTeardown; | 634 io->teardown = CustomTeardown; |
645 io->opaque = params; | 635 io->opaque = params; |
646 } | 636 } |
647 | 637 |
648 //------------------------------------------------------------------------------ | 638 //------------------------------------------------------------------------------ |
OLD | NEW |