OLD | NEW |
1 /* | 1 /* |
2 * jdmerge.c | 2 * jdmerge.c |
3 * | 3 * |
4 * This file was part of the Independent JPEG Group's software: | 4 * This file was part of the Independent JPEG Group's software: |
5 * Copyright (C) 1994-1996, Thomas G. Lane. | 5 * Copyright (C) 1994-1996, Thomas G. Lane. |
6 * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB | 6 * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB |
7 * libjpeg-turbo Modifications: | 7 * libjpeg-turbo Modifications: |
8 * Copyright (C) 2009, 2011, D. R. Commander. | 8 * Copyright (C) 2009, 2011, 2014 D. R. Commander. |
| 9 * Copyright (C) 2013, Linaro Limited. |
9 * For conditions of distribution and use, see the accompanying README file. | 10 * For conditions of distribution and use, see the accompanying README file. |
10 * | 11 * |
11 * This file contains code for merged upsampling/color conversion. | 12 * This file contains code for merged upsampling/color conversion. |
12 * | 13 * |
13 * This file combines functions from jdsample.c and jdcolor.c; | 14 * This file combines functions from jdsample.c and jdcolor.c; |
14 * read those files first to understand what's going on. | 15 * read those files first to understand what's going on. |
15 * | 16 * |
16 * When the chroma components are to be upsampled by simple replication | 17 * When the chroma components are to be upsampled by simple replication |
17 * (ie, box filtering), we can save some work in color conversion by | 18 * (ie, box filtering), we can save some work in color conversion by |
18 * calculating all the output pixels corresponding to a pair of chroma | 19 * calculating all the output pixels corresponding to a pair of chroma |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, | 254 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, |
254 JDIMENSION out_rows_avail) | 255 JDIMENSION out_rows_avail) |
255 /* 2:1 vertical sampling case: may need a spare row. */ | 256 /* 2:1 vertical sampling case: may need a spare row. */ |
256 { | 257 { |
257 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; | 258 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; |
258 JSAMPROW work_ptrs[2]; | 259 JSAMPROW work_ptrs[2]; |
259 JDIMENSION num_rows; /* number of rows returned to caller */ | 260 JDIMENSION num_rows; /* number of rows returned to caller */ |
260 | 261 |
261 if (upsample->spare_full) { | 262 if (upsample->spare_full) { |
262 /* If we have a spare row saved from a previous cycle, just return it. */ | 263 /* If we have a spare row saved from a previous cycle, just return it. */ |
| 264 JDIMENSION size = upsample->out_row_width; |
| 265 if (cinfo->out_color_space == JCS_RGB565) |
| 266 size = cinfo->output_width * 2; |
263 jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, | 267 jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, |
264 » » 1, upsample->out_row_width); | 268 » » 1, size); |
265 num_rows = 1; | 269 num_rows = 1; |
266 upsample->spare_full = FALSE; | 270 upsample->spare_full = FALSE; |
267 } else { | 271 } else { |
268 /* Figure number of rows to return to caller. */ | 272 /* Figure number of rows to return to caller. */ |
269 num_rows = 2; | 273 num_rows = 2; |
270 /* Not more than the distance to the end of the image. */ | 274 /* Not more than the distance to the end of the image. */ |
271 if (num_rows > upsample->rows_to_go) | 275 if (num_rows > upsample->rows_to_go) |
272 num_rows = upsample->rows_to_go; | 276 num_rows = upsample->rows_to_go; |
273 /* And not more than what the client can accept: */ | 277 /* And not more than what the client can accept: */ |
274 out_rows_avail -= *out_row_ctr; | 278 out_rows_avail -= *out_row_ctr; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 break; | 414 break; |
411 default: | 415 default: |
412 h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, | 416 h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, |
413 output_buf); | 417 output_buf); |
414 break; | 418 break; |
415 } | 419 } |
416 } | 420 } |
417 | 421 |
418 | 422 |
419 /* | 423 /* |
| 424 * RGB565 conversion |
| 425 */ |
| 426 |
| 427 #define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \ |
| 428 (((g) << 3) & 0x7E0) | ((b) >> 3)) |
| 429 #define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \ |
| 430 (((g) << 11) & 0xE000) | \ |
| 431 (((b) << 5) & 0x1F00)) |
| 432 |
| 433 #define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l) |
| 434 #define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r) |
| 435 |
| 436 #define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3) |
| 437 |
| 438 #define WRITE_TWO_PIXELS_LE(addr, pixels) { \ |
| 439 ((INT16*)(addr))[0] = (pixels); \ |
| 440 ((INT16*)(addr))[1] = (pixels) >> 16; \ |
| 441 } |
| 442 #define WRITE_TWO_PIXELS_BE(addr, pixels) { \ |
| 443 ((INT16*)(addr))[1] = (pixels); \ |
| 444 ((INT16*)(addr))[0] = (pixels) >> 16; \ |
| 445 } |
| 446 |
| 447 #define DITHER_565_R(r, dither) ((r) + ((dither) & 0xFF)) |
| 448 #define DITHER_565_G(g, dither) ((g) + (((dither) & 0xFF) >> 1)) |
| 449 #define DITHER_565_B(b, dither) ((b) + ((dither) & 0xFF)) |
| 450 |
| 451 |
| 452 /* Declarations for ordered dithering |
| 453 * |
| 454 * We use a 4x4 ordered dither array packed into 32 bits. This array is |
| 455 * sufficent for dithering RGB888 to RGB565. |
| 456 */ |
| 457 |
| 458 #define DITHER_MASK 0x3 |
| 459 #define DITHER_ROTATE(x) (((x) << 24) | (((x) >> 8) & 0x00FFFFFF)) |
| 460 static const INT32 dither_matrix[4] = { |
| 461 0x0008020A, |
| 462 0x0C040E06, |
| 463 0x030B0109, |
| 464 0x0F070D05 |
| 465 }; |
| 466 |
| 467 |
| 468 /* Include inline routines for RGB565 conversion */ |
| 469 |
| 470 #define PACK_SHORT_565 PACK_SHORT_565_LE |
| 471 #define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE |
| 472 #define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_LE |
| 473 #define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_le |
| 474 #define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_le |
| 475 #define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_le |
| 476 #define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_le |
| 477 #include "jdmrg565.c" |
| 478 #undef PACK_SHORT_565 |
| 479 #undef PACK_TWO_PIXELS |
| 480 #undef WRITE_TWO_PIXELS |
| 481 #undef h2v1_merged_upsample_565_internal |
| 482 #undef h2v1_merged_upsample_565D_internal |
| 483 #undef h2v2_merged_upsample_565_internal |
| 484 #undef h2v2_merged_upsample_565D_internal |
| 485 |
| 486 #define PACK_SHORT_565 PACK_SHORT_565_BE |
| 487 #define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE |
| 488 #define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_BE |
| 489 #define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_be |
| 490 #define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_be |
| 491 #define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_be |
| 492 #define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_be |
| 493 #include "jdmrg565.c" |
| 494 #undef PACK_SHORT_565 |
| 495 #undef PACK_TWO_PIXELS |
| 496 #undef WRITE_TWO_PIXELS |
| 497 #undef h2v1_merged_upsample_565_internal |
| 498 #undef h2v1_merged_upsample_565D_internal |
| 499 #undef h2v2_merged_upsample_565_internal |
| 500 #undef h2v2_merged_upsample_565D_internal |
| 501 |
| 502 |
| 503 static INLINE boolean is_big_endian(void) |
| 504 { |
| 505 int test_value = 1; |
| 506 if(*(char *)&test_value != 1) |
| 507 return TRUE; |
| 508 return FALSE; |
| 509 } |
| 510 |
| 511 |
| 512 METHODDEF(void) |
| 513 h2v1_merged_upsample_565 (j_decompress_ptr cinfo, |
| 514 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, |
| 515 JSAMPARRAY output_buf) |
| 516 { |
| 517 if (is_big_endian()) |
| 518 h2v1_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr, |
| 519 output_buf); |
| 520 else |
| 521 h2v1_merged_upsample_565_le(cinfo, input_buf, in_row_group_ctr, |
| 522 output_buf); |
| 523 } |
| 524 |
| 525 |
| 526 METHODDEF(void) |
| 527 h2v1_merged_upsample_565D (j_decompress_ptr cinfo, |
| 528 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, |
| 529 JSAMPARRAY output_buf) |
| 530 { |
| 531 if (is_big_endian()) |
| 532 h2v1_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr, |
| 533 output_buf); |
| 534 else |
| 535 h2v1_merged_upsample_565D_le(cinfo, input_buf, in_row_group_ctr, |
| 536 output_buf); |
| 537 } |
| 538 |
| 539 |
| 540 METHODDEF(void) |
| 541 h2v2_merged_upsample_565 (j_decompress_ptr cinfo, |
| 542 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, |
| 543 JSAMPARRAY output_buf) |
| 544 { |
| 545 if (is_big_endian()) |
| 546 h2v2_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr, |
| 547 output_buf); |
| 548 else |
| 549 h2v2_merged_upsample_565_le(cinfo, input_buf, in_row_group_ctr, |
| 550 output_buf); |
| 551 } |
| 552 |
| 553 |
| 554 METHODDEF(void) |
| 555 h2v2_merged_upsample_565D (j_decompress_ptr cinfo, |
| 556 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, |
| 557 JSAMPARRAY output_buf) |
| 558 { |
| 559 if (is_big_endian()) |
| 560 h2v2_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr, |
| 561 output_buf); |
| 562 else |
| 563 h2v2_merged_upsample_565D_le(cinfo, input_buf, in_row_group_ctr, |
| 564 output_buf); |
| 565 } |
| 566 |
| 567 |
| 568 /* |
420 * Module initialization routine for merged upsampling/color conversion. | 569 * Module initialization routine for merged upsampling/color conversion. |
421 * | 570 * |
422 * NB: this is called under the conditions determined by use_merged_upsample() | 571 * NB: this is called under the conditions determined by use_merged_upsample() |
423 * in jdmaster.c. That routine MUST correspond to the actual capabilities | 572 * in jdmaster.c. That routine MUST correspond to the actual capabilities |
424 * of this module; no safety checks are made here. | 573 * of this module; no safety checks are made here. |
425 */ | 574 */ |
426 | 575 |
427 GLOBAL(void) | 576 GLOBAL(void) |
428 jinit_merged_upsampler (j_decompress_ptr cinfo) | 577 jinit_merged_upsampler (j_decompress_ptr cinfo) |
429 { | 578 { |
430 my_upsample_ptr upsample; | 579 my_upsample_ptr upsample; |
431 | 580 |
432 upsample = (my_upsample_ptr) | 581 upsample = (my_upsample_ptr) |
433 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | 582 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
434 SIZEOF(my_upsampler)); | 583 SIZEOF(my_upsampler)); |
435 cinfo->upsample = (struct jpeg_upsampler *) upsample; | 584 cinfo->upsample = (struct jpeg_upsampler *) upsample; |
436 upsample->pub.start_pass = start_pass_merged_upsample; | 585 upsample->pub.start_pass = start_pass_merged_upsample; |
437 upsample->pub.need_context_rows = FALSE; | 586 upsample->pub.need_context_rows = FALSE; |
438 | 587 |
439 upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; | 588 upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; |
440 | 589 |
441 if (cinfo->max_v_samp_factor == 2) { | 590 if (cinfo->max_v_samp_factor == 2) { |
442 upsample->pub.upsample = merged_2v_upsample; | 591 upsample->pub.upsample = merged_2v_upsample; |
443 if (jsimd_can_h2v2_merged_upsample()) | 592 if (jsimd_can_h2v2_merged_upsample()) |
444 upsample->upmethod = jsimd_h2v2_merged_upsample; | 593 upsample->upmethod = jsimd_h2v2_merged_upsample; |
445 else | 594 else |
446 upsample->upmethod = h2v2_merged_upsample; | 595 upsample->upmethod = h2v2_merged_upsample; |
| 596 if (cinfo->out_color_space == JCS_RGB565) { |
| 597 if (cinfo->dither_mode != JDITHER_NONE) { |
| 598 upsample->upmethod = h2v2_merged_upsample_565D; |
| 599 } else { |
| 600 upsample->upmethod = h2v2_merged_upsample_565; |
| 601 } |
| 602 } |
447 /* Allocate a spare row buffer */ | 603 /* Allocate a spare row buffer */ |
448 upsample->spare_row = (JSAMPROW) | 604 upsample->spare_row = (JSAMPROW) |
449 (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, | 605 (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
450 (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); | 606 (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); |
451 } else { | 607 } else { |
452 upsample->pub.upsample = merged_1v_upsample; | 608 upsample->pub.upsample = merged_1v_upsample; |
453 if (jsimd_can_h2v1_merged_upsample()) | 609 if (jsimd_can_h2v1_merged_upsample()) |
454 upsample->upmethod = jsimd_h2v1_merged_upsample; | 610 upsample->upmethod = jsimd_h2v1_merged_upsample; |
455 else | 611 else |
456 upsample->upmethod = h2v1_merged_upsample; | 612 upsample->upmethod = h2v1_merged_upsample; |
| 613 if (cinfo->out_color_space == JCS_RGB565) { |
| 614 if (cinfo->dither_mode != JDITHER_NONE) { |
| 615 upsample->upmethod = h2v1_merged_upsample_565D; |
| 616 } else { |
| 617 upsample->upmethod = h2v1_merged_upsample_565; |
| 618 } |
| 619 } |
457 /* No spare row needed */ | 620 /* No spare row needed */ |
458 upsample->spare_row = NULL; | 621 upsample->spare_row = NULL; |
459 } | 622 } |
460 | 623 |
461 build_ycc_rgb_table(cinfo); | 624 build_ycc_rgb_table(cinfo); |
462 } | 625 } |
463 | 626 |
464 #endif /* UPSAMPLE_MERGING_SUPPORTED */ | 627 #endif /* UPSAMPLE_MERGING_SUPPORTED */ |
OLD | NEW |