| 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 |