1 /*****************************************************************************/ 2 // Copyright 2006-2008 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_image.cpp#1 $ */ 10 /* $DateTime: 2012/05/30 13:28:51 $ */ 11 /* $Change: 832332 $ */ 12 /* $Author: tknoll $ */ 13 14 /*****************************************************************************/ 15 16 #include "dng_image.h" 17 18 #include "dng_assertions.h" 19 #include "dng_exceptions.h" 20 #include "dng_orientation.h" 21 #include "dng_pixel_buffer.h" 22 #include "dng_tag_types.h" 23 #include "dng_tile_iterator.h" 24 #include "dng_utils.h" 25 26 /*****************************************************************************/ 27 28 dng_tile_buffer::dng_tile_buffer (const dng_image &image, 29 const dng_rect &tile, 30 bool dirty) 31 32 : fImage (image) 33 , fRefData (NULL) 34 35 { 36 37 fImage.AcquireTileBuffer (*this, 38 tile, 39 dirty); 40 41 } 42 43 /*****************************************************************************/ 44 45 dng_tile_buffer::~dng_tile_buffer () 46 { 47 48 fImage.ReleaseTileBuffer (*this); 49 50 } 51 52 /*****************************************************************************/ 53 54 dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image, 55 const dng_rect &tile) 56 57 : dng_tile_buffer (image, tile, false) 58 59 { 60 61 } 62 63 /*****************************************************************************/ 64 65 dng_const_tile_buffer::~dng_const_tile_buffer () 66 { 67 68 } 69 70 /*****************************************************************************/ 71 72 dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image, 73 const dng_rect &tile) 74 75 : dng_tile_buffer (image, tile, true) 76 77 { 78 79 } 80 81 /*****************************************************************************/ 82 83 dng_dirty_tile_buffer::~dng_dirty_tile_buffer () 84 { 85 86 } 87 88 /*****************************************************************************/ 89 90 dng_image::dng_image (const dng_rect &bounds, 91 uint32 planes, 92 uint32 pixelType) 93 94 : fBounds (bounds) 95 , fPlanes (planes) 96 , fPixelType (pixelType) 97 98 { 99 100 if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0) 101 { 102 103 #if qDNGValidate 104 105 ReportError ("Fuzz: Attempt to create zero size image"); 106 107 #endif 108 109 ThrowBadFormat (); 110 111 } 112 113 } 114 115 /*****************************************************************************/ 116 117 dng_image::~dng_image () 118 { 119 120 } 121 122 /*****************************************************************************/ 123 124 dng_image * dng_image::Clone () const 125 { 126 127 ThrowProgramError ("Clone is not supported by this dng_image subclass"); 128 129 return NULL; 130 131 } 132 133 /*****************************************************************************/ 134 135 void dng_image::SetPixelType (uint32 pixelType) 136 { 137 138 if (TagTypeSize (pixelType) != PixelSize ()) 139 { 140 141 ThrowProgramError ("Cannot change pixel size for existing image"); 142 143 } 144 145 fPixelType = pixelType; 146 147 } 148 149 /*****************************************************************************/ 150 151 uint32 dng_image::PixelSize () const 152 { 153 154 return TagTypeSize (PixelType ()); 155 156 } 157 158 /*****************************************************************************/ 159 160 uint32 dng_image::PixelRange () const 161 { 162 163 switch (fPixelType) 164 { 165 166 case ttByte: 167 case ttSByte: 168 { 169 return 0x0FF; 170 } 171 172 case ttShort: 173 case ttSShort: 174 { 175 return 0x0FFFF; 176 } 177 178 case ttLong: 179 case ttSLong: 180 { 181 return 0xFFFFFFFF; 182 } 183 184 default: 185 break; 186 187 } 188 189 return 0; 190 191 } 192 193 /*****************************************************************************/ 194 195 dng_rect dng_image::RepeatingTile () const 196 { 197 198 return fBounds; 199 200 } 201 202 /*****************************************************************************/ 203 204 void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */, 205 const dng_rect & /* area */, 206 bool /* dirty */) const 207 { 208 209 ThrowProgramError (); 210 211 } 212 213 /*****************************************************************************/ 214 215 void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const 216 { 217 218 } 219 220 /*****************************************************************************/ 221 222 void dng_image::DoGet (dng_pixel_buffer &buffer) const 223 { 224 225 dng_rect tile; 226 227 dng_tile_iterator iter (*this, buffer.fArea); 228 229 while (iter.GetOneTile (tile)) 230 { 231 232 dng_const_tile_buffer tileBuffer (*this, tile); 233 234 buffer.CopyArea (tileBuffer, 235 tile, 236 buffer.fPlane, 237 buffer.fPlanes); 238 239 } 240 241 } 242 243 /*****************************************************************************/ 244 245 void dng_image::DoPut (const dng_pixel_buffer &buffer) 246 { 247 248 dng_rect tile; 249 250 dng_tile_iterator iter (*this, buffer.fArea); 251 252 while (iter.GetOneTile (tile)) 253 { 254 255 dng_dirty_tile_buffer tileBuffer (*this, tile); 256 257 tileBuffer.CopyArea (buffer, 258 tile, 259 buffer.fPlane, 260 buffer.fPlanes); 261 262 } 263 264 } 265 266 /*****************************************************************************/ 267 268 void dng_image::GetRepeat (dng_pixel_buffer &buffer, 269 const dng_rect &srcArea, 270 const dng_rect &dstArea) const 271 { 272 273 // If we already have the entire srcArea in the 274 // buffer, we can just repeat that. 275 276 if ((srcArea & buffer.fArea) == srcArea) 277 { 278 279 buffer.RepeatArea (srcArea, 280 dstArea); 281 282 } 283 284 // Else we first need to get the srcArea into the buffer area. 285 286 else 287 { 288 289 // Find repeating pattern size. 290 291 dng_point repeat = srcArea.Size (); 292 293 // Find pattern phase at top-left corner of destination area. 294 295 dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea, 296 dstArea); 297 298 // Find new source area at top-left of dstArea. 299 300 dng_rect newArea = srcArea + (dstArea.TL () - 301 srcArea.TL ()); 302 303 // Find quadrant split coordinates. 304 305 int32 splitV = newArea.t + repeat.v - phase.v; 306 int32 splitH = newArea.l + repeat.h - phase.h; 307 308 // Top-left quadrant. 309 310 dng_rect dst1 (dng_rect (newArea.t, 311 newArea.l, 312 splitV, 313 splitH) & dstArea); 314 315 if (dst1.NotEmpty ()) 316 { 317 318 dng_pixel_buffer temp (buffer); 319 320 temp.fArea = dst1 + (srcArea.TL () - 321 dstArea.TL () + 322 dng_point (phase.v, phase.h)); 323 324 temp.fData = buffer.DirtyPixel (dst1.t, 325 dst1.l, 326 buffer.fPlane); 327 328 DoGet (temp); 329 330 } 331 332 // Top-right quadrant. 333 334 dng_rect dst2 (dng_rect (newArea.t, 335 splitH, 336 splitV, 337 newArea.r) & dstArea); 338 339 if (dst2.NotEmpty ()) 340 { 341 342 dng_pixel_buffer temp (buffer); 343 344 temp.fArea = dst2 + (srcArea.TL () - 345 dstArea.TL () + 346 dng_point (phase.v, -phase.h)); 347 348 temp.fData = buffer.DirtyPixel (dst2.t, 349 dst2.l, 350 buffer.fPlane); 351 352 DoGet (temp); 353 354 } 355 356 // Bottom-left quadrant. 357 358 dng_rect dst3 (dng_rect (splitV, 359 newArea.l, 360 newArea.b, 361 splitH) & dstArea); 362 363 if (dst3.NotEmpty ()) 364 { 365 366 dng_pixel_buffer temp (buffer); 367 368 temp.fArea = dst3 + (srcArea.TL () - 369 dstArea.TL () + 370 dng_point (-phase.v, phase.h)); 371 372 temp.fData = buffer.DirtyPixel (dst3.t, 373 dst3.l, 374 buffer.fPlane); 375 376 DoGet (temp); 377 378 } 379 380 // Bottom-right quadrant. 381 382 dng_rect dst4 (dng_rect (splitV, 383 splitH, 384 newArea.b, 385 newArea.r) & dstArea); 386 387 if (dst4.NotEmpty ()) 388 { 389 390 dng_pixel_buffer temp (buffer); 391 392 temp.fArea = dst4 + (srcArea.TL () - 393 dstArea.TL () + 394 dng_point (-phase.v, -phase.h)); 395 396 temp.fData = buffer.DirtyPixel (dst4.t, 397 dst4.l, 398 buffer.fPlane); 399 400 DoGet (temp); 401 402 } 403 404 // Replicate this new source area. 405 406 buffer.RepeatArea (newArea, 407 dstArea); 408 409 } 410 411 } 412 413 /*****************************************************************************/ 414 415 void dng_image::GetEdge (dng_pixel_buffer &buffer, 416 edge_option edgeOption, 417 const dng_rect &srcArea, 418 const dng_rect &dstArea) const 419 { 420 421 switch (edgeOption) 422 { 423 424 case edge_zero: 425 { 426 427 buffer.SetZero (dstArea, 428 buffer.fPlane, 429 buffer.fPlanes); 430 431 break; 432 433 } 434 435 case edge_repeat: 436 { 437 438 GetRepeat (buffer, 439 srcArea, 440 dstArea); 441 442 break; 443 444 } 445 446 case edge_repeat_zero_last: 447 { 448 449 if (buffer.fPlanes > 1) 450 { 451 452 dng_pixel_buffer buffer1 (buffer); 453 454 buffer1.fPlanes--; 455 456 GetEdge (buffer1, 457 edge_repeat, 458 srcArea, 459 dstArea); 460 461 } 462 463 dng_pixel_buffer buffer2 (buffer); 464 465 buffer2.fPlane = buffer.fPlanes - 1; 466 buffer2.fPlanes = 1; 467 468 buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t, 469 buffer2.fArea.l, 470 buffer2.fPlane); 471 472 GetEdge (buffer2, 473 edge_zero, 474 srcArea, 475 dstArea); 476 477 break; 478 479 } 480 481 default: 482 { 483 484 ThrowProgramError (); 485 486 } 487 488 } 489 490 } 491 492 /*****************************************************************************/ 493 494 void dng_image::Get (dng_pixel_buffer &buffer, 495 edge_option edgeOption, 496 uint32 repeatV, 497 uint32 repeatH) const 498 { 499 500 // Find the overlap with the image bounds. 501 502 dng_rect overlap = buffer.fArea & fBounds; 503 504 // Move the overlapping pixels. 505 506 if (overlap.NotEmpty ()) 507 { 508 509 dng_pixel_buffer temp (buffer); 510 511 temp.fArea = overlap; 512 513 temp.fData = buffer.DirtyPixel (overlap.t, 514 overlap.l, 515 buffer.fPlane); 516 517 DoGet (temp); 518 519 } 520 521 // See if we need to pad the edge values. 522 523 if ((edgeOption != edge_none) && (overlap != buffer.fArea)) 524 { 525 526 dng_rect areaT (buffer.fArea); 527 dng_rect areaL (buffer.fArea); 528 dng_rect areaB (buffer.fArea); 529 dng_rect areaR (buffer.fArea); 530 531 areaT.b = Min_int32 (areaT.b, fBounds.t); 532 areaL.r = Min_int32 (areaL.r, fBounds.l); 533 areaB.t = Max_int32 (areaB.t, fBounds.b); 534 areaR.l = Max_int32 (areaR.l, fBounds.r); 535 536 dng_rect areaH (buffer.fArea); 537 dng_rect areaV (buffer.fArea); 538 539 areaH.l = Max_int32 (areaH.l, fBounds.l); 540 areaH.r = Min_int32 (areaH.r, fBounds.r); 541 542 areaV.t = Max_int32 (areaV.t, fBounds.t); 543 areaV.b = Min_int32 (areaV.b, fBounds.b); 544 545 // Top left. 546 547 dng_rect areaTL = areaT & areaL; 548 549 if (areaTL.NotEmpty ()) 550 { 551 552 GetEdge (buffer, 553 edgeOption, 554 dng_rect (fBounds.t, 555 fBounds.l, 556 fBounds.t + repeatV, 557 fBounds.l + repeatH), 558 areaTL); 559 560 } 561 562 // Top middle. 563 564 dng_rect areaTM = areaT & areaH; 565 566 if (areaTM.NotEmpty ()) 567 { 568 569 GetEdge (buffer, 570 edgeOption, 571 dng_rect (fBounds.t, 572 areaTM.l, 573 fBounds.t + repeatV, 574 areaTM.r), 575 areaTM); 576 577 } 578 579 // Top right. 580 581 dng_rect areaTR = areaT & areaR; 582 583 if (areaTR.NotEmpty ()) 584 { 585 586 GetEdge (buffer, 587 edgeOption, 588 dng_rect (fBounds.t, 589 fBounds.r - repeatH, 590 fBounds.t + repeatV, 591 fBounds.r), 592 areaTR); 593 594 } 595 596 // Left middle. 597 598 dng_rect areaLM = areaL & areaV; 599 600 if (areaLM.NotEmpty ()) 601 { 602 603 GetEdge (buffer, 604 edgeOption, 605 dng_rect (areaLM.t, 606 fBounds.l, 607 areaLM.b, 608 fBounds.l + repeatH), 609 areaLM); 610 611 } 612 613 // Right middle. 614 615 dng_rect areaRM = areaR & areaV; 616 617 if (areaRM.NotEmpty ()) 618 { 619 620 GetEdge (buffer, 621 edgeOption, 622 dng_rect (areaRM.t, 623 fBounds.r - repeatH, 624 areaRM.b, 625 fBounds.r), 626 areaRM); 627 628 } 629 630 // Bottom left. 631 632 dng_rect areaBL = areaB & areaL; 633 634 if (areaBL.NotEmpty ()) 635 { 636 637 GetEdge (buffer, 638 edgeOption, 639 dng_rect (fBounds.b - repeatV, 640 fBounds.l, 641 fBounds.b, 642 fBounds.l + repeatH), 643 areaBL); 644 645 } 646 647 // Bottom middle. 648 649 dng_rect areaBM = areaB & areaH; 650 651 if (areaBM.NotEmpty ()) 652 { 653 654 GetEdge (buffer, 655 edgeOption, 656 dng_rect (fBounds.b - repeatV, 657 areaBM.l, 658 fBounds.b, 659 areaBM.r), 660 areaBM); 661 662 } 663 664 // Bottom right. 665 666 dng_rect areaBR = areaB & areaR; 667 668 if (areaBR.NotEmpty ()) 669 { 670 671 GetEdge (buffer, 672 edgeOption, 673 dng_rect (fBounds.b - repeatV, 674 fBounds.r - repeatH, 675 fBounds.b, 676 fBounds.r), 677 areaBR); 678 679 } 680 681 } 682 683 } 684 685 /*****************************************************************************/ 686 687 void dng_image::Put (const dng_pixel_buffer &buffer) 688 { 689 690 // Move the overlapping pixels. 691 692 dng_rect overlap = buffer.fArea & fBounds; 693 694 if (overlap.NotEmpty ()) 695 { 696 697 dng_pixel_buffer temp (buffer); 698 699 temp.fArea = overlap; 700 701 temp.fData = (void *) buffer.ConstPixel (overlap.t, 702 overlap.l, 703 buffer.fPlane); 704 705 // Move the overlapping planes. 706 707 if (temp.fPlane < Planes ()) 708 { 709 710 temp.fPlanes = Min_uint32 (temp.fPlanes, 711 Planes () - temp.fPlane); 712 713 DoPut (temp); 714 715 } 716 717 } 718 719 } 720 721 /*****************************************************************************/ 722 723 void dng_image::Trim (const dng_rect &r) 724 { 725 726 if (r != Bounds ()) 727 { 728 729 ThrowProgramError ("Trim is not support by this dng_image subclass"); 730 731 } 732 733 } 734 735 /*****************************************************************************/ 736 737 void dng_image::Rotate (const dng_orientation &orientation) 738 { 739 740 if (orientation != dng_orientation::Normal ()) 741 { 742 743 ThrowProgramError ("Rotate is not support by this dng_image subclass"); 744 745 } 746 747 } 748 749 /*****************************************************************************/ 750 751 void dng_image::CopyArea (const dng_image &src, 752 const dng_rect &area, 753 uint32 srcPlane, 754 uint32 dstPlane, 755 uint32 planes) 756 { 757 758 if (&src == this) 759 return; 760 761 dng_tile_iterator destIter(*this, area); 762 dng_rect destTileArea; 763 764 while (destIter.GetOneTile(destTileArea)) 765 { 766 dng_tile_iterator srcIter(src, destTileArea); 767 dng_rect srcTileArea; 768 769 while (srcIter.GetOneTile(srcTileArea)) 770 { 771 772 dng_dirty_tile_buffer destTile(*this, srcTileArea); 773 dng_const_tile_buffer srcTile(src, srcTileArea); 774 775 destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes); 776 777 } 778 779 } 780 781 } 782 783 /*****************************************************************************/ 784 785 bool dng_image::EqualArea (const dng_image &src, 786 const dng_rect &area, 787 uint32 plane, 788 uint32 planes) const 789 { 790 791 if (&src == this) 792 return true; 793 794 dng_tile_iterator destIter (*this, area); 795 796 dng_rect destTileArea; 797 798 while (destIter.GetOneTile (destTileArea)) 799 { 800 801 dng_tile_iterator srcIter (src, destTileArea); 802 803 dng_rect srcTileArea; 804 805 while (srcIter.GetOneTile (srcTileArea)) 806 { 807 808 dng_const_tile_buffer destTile (*this, srcTileArea); 809 dng_const_tile_buffer srcTile (src , srcTileArea); 810 811 if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes)) 812 { 813 return false; 814 } 815 816 } 817 818 } 819 820 return true; 821 822 } 823 824 /*****************************************************************************/ 825 826 void dng_image::SetConstant (uint32 value, 827 const dng_rect &area) 828 { 829 830 dng_tile_iterator iter (*this, area); 831 832 dng_rect tileArea; 833 834 while (iter.GetOneTile (tileArea)) 835 { 836 837 dng_dirty_tile_buffer buffer (*this, tileArea); 838 839 buffer.SetConstant (tileArea, 840 0, 841 fPlanes, 842 value); 843 844 } 845 846 } 847 848 /*****************************************************************************/ 849