File indexing completed on 2025-01-19 03:55:16
0001 /*****************************************************************************/ 0002 // Copyright 2006-2019 Adobe Systems Incorporated 0003 // All Rights Reserved. 0004 // 0005 // NOTICE: Adobe permits you to use, modify, and distribute this file in 0006 // accordance with the terms of the Adobe license agreement accompanying it. 0007 /*****************************************************************************/ 0008 0009 #include "dng_stream.h" 0010 0011 #include "dng_abort_sniffer.h" 0012 #include "dng_auto_ptr.h" 0013 #include "dng_bottlenecks.h" 0014 #include "dng_exceptions.h" 0015 #include "dng_globals.h" 0016 #include "dng_flags.h" 0017 #include "dng_memory.h" 0018 #include "dng_tag_types.h" 0019 #include "dng_assertions.h" 0020 0021 /*****************************************************************************/ 0022 0023 dng_stream::dng_stream (dng_abort_sniffer *sniffer, 0024 uint32 bufferSize, 0025 uint64 offsetInOriginalFile) 0026 0027 : fSwapBytes (false) 0028 , fHaveLength (false) 0029 , fLength (0) 0030 , fOffsetInOriginalFile (offsetInOriginalFile) 0031 , fPosition (0) 0032 , fMemBlock () 0033 , fBuffer (NULL) 0034 , fBufferSize (Max_uint32 (bufferSize, gDNGStreamBlockSize * 2)) 0035 , fBufferStart (0) 0036 , fBufferEnd (0) 0037 , fBufferLimit (bufferSize) 0038 , fBufferDirty (false) 0039 , fSniffer (sniffer) 0040 0041 { 0042 0043 fMemBlock.Reset (gDefaultDNGMemoryAllocator.Allocate (fBufferSize)); 0044 0045 fBuffer = fMemBlock->Buffer_uint8 (); 0046 0047 } 0048 0049 /*****************************************************************************/ 0050 0051 dng_stream::dng_stream (const void *data, 0052 uint32 count, 0053 uint64 offsetInOriginalFile) 0054 0055 : fSwapBytes (false) 0056 , fHaveLength (true) 0057 , fLength (count) 0058 , fOffsetInOriginalFile (offsetInOriginalFile) 0059 , fPosition (0) 0060 , fMemBlock () 0061 , fBuffer ((uint8 *) data) 0062 , fBufferSize (count) 0063 , fBufferStart (0) 0064 , fBufferEnd (count) 0065 , fBufferLimit (count) 0066 , fBufferDirty (false) 0067 , fSniffer (NULL) 0068 0069 { 0070 0071 } 0072 0073 /*****************************************************************************/ 0074 0075 dng_stream::~dng_stream () 0076 { 0077 0078 } 0079 0080 /*****************************************************************************/ 0081 0082 uint64 dng_stream::DoGetLength () 0083 { 0084 0085 ThrowProgramError (); 0086 0087 return 0; 0088 0089 } 0090 0091 /*****************************************************************************/ 0092 0093 void dng_stream::DoRead (void * /* data */, 0094 uint32 /* count */, 0095 uint64 /* offset */) 0096 { 0097 0098 ThrowProgramError (); 0099 0100 } 0101 0102 /*****************************************************************************/ 0103 0104 void dng_stream::DoSetLength (uint64 /* length */) 0105 { 0106 0107 ThrowProgramError (); 0108 0109 } 0110 0111 /*****************************************************************************/ 0112 0113 void dng_stream::DoWrite (const void * /* data */, 0114 uint32 /* count */, 0115 uint64 /* offset */) 0116 { 0117 0118 ThrowProgramError (); 0119 0120 } 0121 0122 /*****************************************************************************/ 0123 0124 bool dng_stream::BigEndian () const 0125 { 0126 0127 return fSwapBytes != (!!qDNGBigEndian); 0128 0129 } 0130 0131 /*****************************************************************************/ 0132 0133 void dng_stream::SetBigEndian (bool bigEndian) 0134 { 0135 0136 fSwapBytes = (bigEndian != (!!qDNGBigEndian)); 0137 0138 } 0139 0140 /*****************************************************************************/ 0141 0142 void dng_stream::SetBufferSize (dng_memory_allocator &allocator, 0143 uint32 newBufferSize) 0144 { 0145 0146 if (newBufferSize != fBufferSize && 0147 newBufferSize >= gDNGStreamBlockSize * 2 && 0148 !Data () && 0149 !fBufferDirty) 0150 { 0151 0152 try 0153 { 0154 0155 fMemBlock.Reset (allocator.Allocate (newBufferSize)); 0156 0157 fBuffer = fMemBlock->Buffer_uint8 (); 0158 0159 fBufferSize = newBufferSize; 0160 0161 fBufferStart = 0; 0162 fBufferEnd = 0; 0163 fBufferLimit = newBufferSize; 0164 0165 } 0166 0167 catch (...) 0168 { 0169 0170 } 0171 0172 } 0173 0174 } 0175 0176 /*****************************************************************************/ 0177 0178 const void * dng_stream::Data () const 0179 { 0180 0181 if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength) 0182 { 0183 0184 return fBuffer; 0185 0186 } 0187 0188 return NULL; 0189 0190 } 0191 0192 /*****************************************************************************/ 0193 0194 dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator) 0195 { 0196 0197 Flush (); 0198 0199 uint64 len64 = Length (); 0200 0201 if (len64 > 0xFFFFFFFF) 0202 { 0203 ThrowProgramError (); 0204 } 0205 0206 uint32 len = (uint32) len64; 0207 0208 AutoPtr<dng_memory_block> block (allocator.Allocate (len)); 0209 0210 if (len) 0211 { 0212 0213 SetReadPosition (0); 0214 0215 Get (block->Buffer (), len); 0216 0217 } 0218 0219 return block.Release (); 0220 0221 } 0222 0223 /*****************************************************************************/ 0224 0225 void dng_stream::SetReadPosition (uint64 offset) 0226 { 0227 0228 fPosition = offset; 0229 0230 if (fPosition > Length ()) 0231 { 0232 0233 ThrowEndOfFile (); 0234 0235 } 0236 0237 } 0238 0239 /*****************************************************************************/ 0240 0241 uint64 dng_stream::OffsetInOriginalFile () const 0242 { 0243 0244 return fOffsetInOriginalFile; 0245 0246 } 0247 0248 /*****************************************************************************/ 0249 0250 uint64 dng_stream::PositionInOriginalFile () const 0251 { 0252 0253 if (fOffsetInOriginalFile == kDNGStreamInvalidOffset) 0254 return kDNGStreamInvalidOffset; 0255 0256 return fOffsetInOriginalFile + Position (); 0257 0258 } 0259 0260 /*****************************************************************************/ 0261 0262 void dng_stream::Get (void *data, uint32 count, uint32 maxOverRead) 0263 { 0264 0265 while (count) 0266 { 0267 0268 // See if the request is totally inside buffer. 0269 0270 if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd) 0271 { 0272 0273 memcpy (data, 0274 fBuffer + (uint32) (fPosition - fBufferStart), 0275 count); 0276 0277 fPosition += count; 0278 0279 return; 0280 0281 } 0282 0283 // See if first part of request is inside buffer. 0284 0285 if (fPosition >= fBufferStart && fPosition < fBufferEnd) 0286 { 0287 0288 uint32 block = (uint32) (fBufferEnd - fPosition); 0289 0290 memcpy (data, 0291 fBuffer + (fPosition - fBufferStart), 0292 block); 0293 0294 count -= block; 0295 0296 data = (void *) (((char *) data) + block); 0297 0298 fPosition += block; 0299 0300 } 0301 0302 // Flush buffer if dirty. 0303 0304 Flush (); 0305 0306 // Do large reads unbuffered. 0307 0308 if (count > fBufferSize) 0309 { 0310 DNG_ASSERT(maxOverRead == 0, "Over-read of large size unexpected"); 0311 if (fPosition + count > Length ()) 0312 { 0313 0314 ThrowEndOfFile (); 0315 0316 } 0317 0318 DoRead (data, 0319 count, 0320 fPosition); 0321 0322 fPosition += count; 0323 0324 return; 0325 0326 } 0327 0328 // Figure out new buffer range. 0329 0330 fBufferStart = fPosition; 0331 0332 if (fBufferSize >= gDNGStreamBlockSize) 0333 { 0334 0335 // Align to a file block. 0336 0337 fBufferStart &= (uint64) ~((int64) (gDNGStreamBlockSize - 1)); 0338 0339 } 0340 0341 fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ()); 0342 0343 if ((fBufferEnd - fPosition) < maxOverRead) 0344 return; // ep, allow over-read requests 0345 else 0346 if (fBufferEnd <= fPosition) 0347 { 0348 0349 ThrowEndOfFile (); 0350 0351 } 0352 0353 // Read data into buffer. 0354 0355 dng_abort_sniffer::SniffForAbort (fSniffer); 0356 0357 DoRead (fBuffer, 0358 (uint32) (fBufferEnd - fBufferStart), 0359 fBufferStart); 0360 0361 } 0362 0363 } 0364 0365 /*****************************************************************************/ 0366 0367 void dng_stream::SetWritePosition (uint64 offset) 0368 { 0369 0370 fPosition = offset; 0371 0372 } 0373 0374 /*****************************************************************************/ 0375 0376 void dng_stream::Flush () 0377 { 0378 0379 if (fBufferDirty) 0380 { 0381 0382 dng_abort_sniffer::SniffForAbort (fSniffer); 0383 0384 DoWrite (fBuffer, 0385 (uint32) (fBufferEnd - fBufferStart), 0386 fBufferStart); 0387 0388 fBufferStart = 0; 0389 fBufferEnd = 0; 0390 fBufferLimit = fBufferSize; 0391 0392 fBufferDirty = false; 0393 0394 } 0395 0396 } 0397 0398 /*****************************************************************************/ 0399 0400 void dng_stream::SetLength (uint64 length) 0401 { 0402 0403 Flush (); 0404 0405 if (Length () != length) 0406 { 0407 0408 DoSetLength (length); 0409 0410 fLength = length; 0411 0412 } 0413 0414 } 0415 0416 /*****************************************************************************/ 0417 0418 void dng_stream::Put (const void *data, 0419 uint32 count) 0420 { 0421 0422 // See if we can replace or append to the existing buffer. 0423 0424 uint64 endPosition = fPosition + count; 0425 0426 if (fBufferDirty && 0427 fPosition >= fBufferStart && 0428 fPosition <= fBufferEnd && 0429 endPosition <= fBufferLimit) 0430 { 0431 0432 memcpy (fBuffer + (uint32) (fPosition - fBufferStart), 0433 data, 0434 count); 0435 0436 if (fBufferEnd < endPosition) 0437 fBufferEnd = endPosition; 0438 0439 } 0440 0441 // Else we need to write to the file. 0442 0443 else 0444 { 0445 0446 // Write initial part of the data to buffer, if possible. 0447 0448 if (fBufferDirty && 0449 fPosition >= fBufferStart && 0450 fPosition <= fBufferEnd && 0451 fPosition < fBufferLimit) 0452 { 0453 0454 uint32 subCount = (uint32) (fBufferLimit - fPosition); 0455 0456 memcpy (fBuffer + (uint32) (fPosition - fBufferStart), 0457 data, 0458 subCount); 0459 0460 count -= subCount; 0461 data = (const void *) (((const uint8 *) data) + subCount); 0462 0463 fPosition = fBufferLimit; 0464 fBufferEnd = fBufferLimit; 0465 0466 } 0467 0468 // Write existing buffer. 0469 0470 Flush (); 0471 0472 // Figure out how much space we have in buffer from 0473 // current position to end of file block. 0474 0475 uint64 blockRound = gDNGStreamBlockSize - 1; 0476 0477 uint64 blockMask = ~((int64) blockRound); 0478 0479 uint32 alignedSize = (uint32) 0480 (((fPosition + fBufferSize) & blockMask) - fPosition); 0481 0482 // If write request will not fit in buffer, then write everything except 0483 // for the final unaligned part of the data. 0484 0485 if (count > alignedSize) 0486 { 0487 0488 uint32 alignedCount = (uint32) 0489 (((fPosition + count) & blockMask) - fPosition); 0490 0491 dng_abort_sniffer::SniffForAbort (fSniffer); 0492 0493 DoWrite (data, alignedCount, fPosition); 0494 0495 count -= alignedCount; 0496 data = (const void *) (((const uint8 *) data) + alignedCount); 0497 0498 fPosition += alignedCount; 0499 0500 } 0501 0502 // Start a new buffer with small blocks. 0503 0504 if (count > 0) 0505 { 0506 0507 fBufferDirty = true; 0508 0509 fBufferStart = fPosition; 0510 fBufferEnd = endPosition; 0511 fBufferLimit = (fBufferStart + fBufferSize) & blockMask; 0512 0513 memcpy (fBuffer, 0514 data, 0515 count); 0516 0517 } 0518 0519 } 0520 0521 fPosition = endPosition; 0522 0523 fLength = Max_uint64 (Length (), fPosition); 0524 0525 } 0526 0527 /*****************************************************************************/ 0528 0529 uint16 dng_stream::Get_uint16 () 0530 { 0531 0532 uint16 x; 0533 0534 Get (&x, 2); 0535 0536 if (fSwapBytes) 0537 { 0538 0539 x = SwapBytes16 (x); 0540 0541 } 0542 0543 return x; 0544 0545 } 0546 0547 /*****************************************************************************/ 0548 0549 void dng_stream::Put_uint16 (uint16 x) 0550 { 0551 0552 if (fSwapBytes) 0553 { 0554 0555 x = SwapBytes16 (x); 0556 0557 } 0558 0559 Put (&x, 2); 0560 0561 } 0562 0563 /*****************************************************************************/ 0564 uint32 dng_stream::Get_uint32 () 0565 { 0566 0567 uint32 x; 0568 0569 Get (&x, 4); 0570 0571 if (fSwapBytes) 0572 { 0573 0574 x = SwapBytes32 (x); 0575 0576 } 0577 0578 return x; 0579 0580 } 0581 0582 /*****************************************************************************/ 0583 0584 void dng_stream::Put_uint32 (uint32 x) 0585 { 0586 0587 if (fSwapBytes) 0588 { 0589 0590 x = SwapBytes32 (x); 0591 0592 } 0593 0594 Put (&x, 4); 0595 0596 } 0597 0598 /*****************************************************************************/ 0599 0600 uint64 dng_stream::Get_uint64 () 0601 { 0602 0603 if (fSwapBytes) 0604 { 0605 0606 union 0607 { 0608 uint32 u32 [2]; 0609 uint64 u64; 0610 } u; 0611 0612 u.u32 [1] = Get_uint32 (); 0613 u.u32 [0] = Get_uint32 (); 0614 0615 return u.u64; 0616 0617 } 0618 0619 uint64 x; 0620 0621 Get (&x, 8); 0622 0623 return x; 0624 0625 } 0626 0627 /*****************************************************************************/ 0628 0629 void dng_stream::Put_uint64 (uint64 x) 0630 { 0631 0632 if (fSwapBytes) 0633 { 0634 0635 union 0636 { 0637 uint32 u32 [2]; 0638 uint64 u64; 0639 } u; 0640 0641 u.u64 = x; 0642 0643 Put_uint32 (u.u32 [1]); 0644 Put_uint32 (u.u32 [0]); 0645 0646 } 0647 0648 else 0649 { 0650 0651 Put (&x, 8); 0652 0653 } 0654 0655 } 0656 0657 /*****************************************************************************/ 0658 0659 real32 dng_stream::Get_real32 () 0660 { 0661 0662 union 0663 { 0664 uint32 i; 0665 real32 r; 0666 } u; 0667 0668 u.i = Get_uint32 (); 0669 0670 return u.r; 0671 0672 } 0673 0674 /*****************************************************************************/ 0675 0676 void dng_stream::Put_real32 (real32 x) 0677 { 0678 0679 if (fSwapBytes) 0680 { 0681 0682 union 0683 { 0684 uint32 i; 0685 real32 r; 0686 } u; 0687 0688 u.r = x; 0689 0690 Put_uint32 (u.i); 0691 0692 } 0693 0694 else 0695 { 0696 0697 Put (&x, 4); 0698 0699 } 0700 0701 } 0702 0703 /*****************************************************************************/ 0704 0705 real64 dng_stream::Get_real64 () 0706 { 0707 0708 if (fSwapBytes) 0709 { 0710 0711 union 0712 { 0713 uint32 i [2]; 0714 real64 r; 0715 } u; 0716 0717 u.i [1] = Get_uint32 (); 0718 u.i [0] = Get_uint32 (); 0719 0720 return u.r; 0721 0722 } 0723 0724 real64 x; 0725 0726 Get (&x, 8); 0727 0728 return x; 0729 0730 } 0731 0732 /*****************************************************************************/ 0733 0734 void dng_stream::Put_real64 (real64 x) 0735 { 0736 0737 if (fSwapBytes) 0738 { 0739 0740 union 0741 { 0742 uint32 i [2]; 0743 real64 r; 0744 } u; 0745 0746 u.r = x; 0747 0748 Put_uint32 (u.i [1]); 0749 Put_uint32 (u.i [0]); 0750 0751 } 0752 0753 else 0754 { 0755 0756 Put (&x, 8); 0757 0758 } 0759 0760 } 0761 0762 /*****************************************************************************/ 0763 0764 void dng_stream::Get_CString (char *data, uint32 maxLength) 0765 { 0766 0767 memset (data, 0, maxLength); 0768 0769 uint32 index = 0; 0770 0771 while (true) 0772 { 0773 0774 char c = (char) Get_uint8 (); 0775 0776 if (index + 1 < maxLength) 0777 data [index++] = c; 0778 0779 if (c == 0) 0780 break; 0781 0782 } 0783 0784 } 0785 0786 /*****************************************************************************/ 0787 0788 void dng_stream::Get_UString (char *data, uint32 maxLength) 0789 { 0790 0791 memset (data, 0, maxLength); 0792 0793 uint32 index = 0; 0794 0795 while (true) 0796 { 0797 0798 char c = (char) Get_uint16 (); 0799 0800 if (index + 1 < maxLength) 0801 data [index++] = (char) c; 0802 0803 if (c == 0) 0804 break; 0805 0806 } 0807 0808 } 0809 0810 /*****************************************************************************/ 0811 0812 void dng_stream::PutZeros (uint64 count) 0813 { 0814 0815 const uint32 kZeroBufferSize = 4096; 0816 0817 if (count >= kZeroBufferSize) 0818 { 0819 0820 dng_memory_data zeroBuffer (kZeroBufferSize); 0821 0822 DoZeroBytes (zeroBuffer.Buffer (), 0823 kZeroBufferSize); 0824 0825 while (count) 0826 { 0827 0828 uint64 blockSize = Min_uint64 (count, kZeroBufferSize); 0829 0830 Put (zeroBuffer.Buffer (), (uint32) blockSize); 0831 0832 count -= blockSize; 0833 0834 } 0835 0836 } 0837 0838 else 0839 { 0840 0841 uint32 count32 = (uint32) count; 0842 0843 for (uint32 j = 0; j < count32; j++) 0844 { 0845 0846 Put_uint8 (0); 0847 0848 } 0849 0850 } 0851 0852 } 0853 0854 /*****************************************************************************/ 0855 0856 void dng_stream::PadAlign2 () 0857 { 0858 0859 PutZeros (Position () & 1); 0860 0861 } 0862 0863 /*****************************************************************************/ 0864 0865 void dng_stream::PadAlign4 () 0866 { 0867 0868 PutZeros ((4 - (Position () & 3)) & 3); 0869 0870 } 0871 0872 /*****************************************************************************/ 0873 0874 uint32 dng_stream::TagValue_uint32 (uint32 tagType) 0875 { 0876 0877 switch (tagType) 0878 { 0879 0880 case ttByte: 0881 return (uint32) Get_uint8 (); 0882 0883 case ttShort: 0884 return (uint32) Get_uint16 (); 0885 0886 case ttLong: 0887 case ttIFD: 0888 return Get_uint32 (); 0889 0890 } 0891 0892 real64 x = TagValue_real64 (tagType); 0893 0894 if (x < 0.0) 0895 x = 0.0; 0896 0897 if (x > (real64) 0xFFFFFFFF) 0898 x = (real64) 0xFFFFFFFF; 0899 0900 return (uint32) (x + 0.5); 0901 0902 } 0903 0904 /*****************************************************************************/ 0905 0906 int32 dng_stream::TagValue_int32 (uint32 tagType) 0907 { 0908 0909 switch (tagType) 0910 { 0911 0912 case ttSByte: 0913 return (int32) Get_int8 (); 0914 0915 case ttSShort: 0916 return (int32) Get_int16 (); 0917 0918 case ttSLong: 0919 return Get_int32 (); 0920 0921 } 0922 0923 real64 x = TagValue_real64 (tagType); 0924 0925 if (x < 0.0) 0926 { 0927 0928 if (x < -2147483648.0) 0929 x = -2147483648.0; 0930 0931 return (int32) (x - 0.5); 0932 0933 } 0934 0935 else 0936 { 0937 0938 if (x > 2147483647.0) 0939 x = 2147483647.0; 0940 0941 return (int32) (x + 0.5); 0942 0943 } 0944 0945 } 0946 0947 /*****************************************************************************/ 0948 0949 dng_urational dng_stream::TagValue_urational (uint32 tagType) 0950 { 0951 0952 dng_urational result; 0953 0954 result.n = 0; 0955 result.d = 1; 0956 0957 switch (tagType) 0958 { 0959 0960 case ttRational: 0961 { 0962 0963 result.n = Get_uint32 (); 0964 result.d = Get_uint32 (); 0965 0966 break; 0967 0968 } 0969 0970 case ttSRational: 0971 { 0972 0973 int32 n = Get_int32 (); 0974 int32 d = Get_int32 (); 0975 0976 if ((n < 0) == (d < 0)) 0977 { 0978 0979 if (d < 0) 0980 { 0981 n = -n; 0982 d = -d; 0983 } 0984 0985 result.n = (uint32) n; 0986 result.d = (uint32) d; 0987 0988 } 0989 0990 break; 0991 0992 } 0993 0994 case ttByte: 0995 case ttShort: 0996 case ttLong: 0997 case ttIFD: 0998 { 0999 1000 result.n = TagValue_uint32 (tagType); 1001 1002 break; 1003 1004 } 1005 1006 case ttSByte: 1007 case ttSShort: 1008 case ttSLong: 1009 { 1010 1011 int32 n = TagValue_int32 (tagType); 1012 1013 if (n > 0) 1014 { 1015 result.n = (uint32) n; 1016 } 1017 1018 break; 1019 1020 } 1021 1022 default: 1023 { 1024 1025 real64 x = TagValue_real64 (tagType); 1026 1027 if (x > 0.0) 1028 { 1029 1030 while (result.d < 10000 && x < 1000000) 1031 { 1032 1033 result.d *= 10; 1034 1035 x *= 10.0; 1036 1037 } 1038 1039 result.n = (uint32) (x + 0.5); 1040 1041 } 1042 1043 } 1044 1045 } 1046 1047 return result; 1048 1049 } 1050 1051 /*****************************************************************************/ 1052 1053 dng_srational dng_stream::TagValue_srational (uint32 tagType) 1054 { 1055 1056 dng_srational result; 1057 1058 result.n = 0; 1059 result.d = 1; 1060 1061 switch (tagType) 1062 { 1063 1064 case ttSRational: 1065 { 1066 1067 result.n = Get_int32 (); 1068 result.d = Get_int32 (); 1069 1070 break; 1071 1072 } 1073 1074 default: 1075 { 1076 1077 real64 x = TagValue_real64 (tagType); 1078 1079 if (x > 0.0) 1080 { 1081 1082 while (result.d < 10000 && x < 1000000.0) 1083 { 1084 1085 result.d *= 10; 1086 1087 x *= 10.0; 1088 1089 } 1090 1091 result.n = (int32) (x + 0.5); 1092 1093 } 1094 1095 else 1096 { 1097 1098 while (result.d < 10000 && x > -1000000.0) 1099 { 1100 1101 result.d *= 10; 1102 1103 x *= 10.0; 1104 1105 } 1106 1107 result.n = (int32) (x - 0.5); 1108 1109 } 1110 1111 } 1112 1113 } 1114 1115 return result; 1116 1117 } 1118 1119 /*****************************************************************************/ 1120 1121 real64 dng_stream::TagValue_real64 (uint32 tagType) 1122 { 1123 1124 switch (tagType) 1125 { 1126 1127 case ttByte: 1128 case ttShort: 1129 case ttLong: 1130 case ttIFD: 1131 return (real64) TagValue_uint32 (tagType); 1132 1133 case ttSByte: 1134 case ttSShort: 1135 case ttSLong: 1136 return (real64) TagValue_int32 (tagType); 1137 1138 case ttRational: 1139 { 1140 1141 uint32 n = Get_uint32 (); 1142 uint32 d = Get_uint32 (); 1143 1144 if (d == 0) 1145 return 0.0; 1146 else 1147 return (real64) n / (real64) d; 1148 1149 } 1150 1151 case ttSRational: 1152 { 1153 1154 int32 n = Get_int32 (); 1155 int32 d = Get_int32 (); 1156 1157 if (d == 0) 1158 return 0.0; 1159 else 1160 return (real64) n / (real64) d; 1161 1162 } 1163 1164 case ttFloat: 1165 return (real64) Get_real32 (); 1166 1167 case ttDouble: 1168 return Get_real64 (); 1169 1170 } 1171 1172 return 0.0; 1173 1174 } 1175 1176 /*****************************************************************************/ 1177 1178 void dng_stream::CopyToStream (dng_stream &dstStream, 1179 uint64 count) 1180 { 1181 1182 uint8 smallBuffer [1024]; 1183 1184 if (count <= sizeof (smallBuffer)) 1185 { 1186 1187 Get (smallBuffer, (uint32) count); 1188 1189 dstStream.Put (smallBuffer, (uint32) count); 1190 1191 } 1192 1193 else 1194 { 1195 1196 const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize, 1197 count); 1198 1199 dng_memory_data bigBuffer (bigBufferSize); 1200 1201 while (count) 1202 { 1203 1204 uint32 blockCount = (uint32) Min_uint64 (bigBufferSize, 1205 count); 1206 1207 Get (bigBuffer.Buffer (), 1208 blockCount); 1209 1210 dstStream.Put (bigBuffer.Buffer (), 1211 blockCount); 1212 1213 count -= blockCount; 1214 1215 } 1216 1217 } 1218 1219 } 1220 1221 /*****************************************************************************/ 1222 1223 void dng_stream::DuplicateStream (dng_stream &dstStream) 1224 { 1225 1226 // Turn off sniffers for this operation. 1227 1228 TempStreamSniffer noSniffer1 (*this , NULL); 1229 TempStreamSniffer noSniffer2 (dstStream, NULL); 1230 1231 // First grow the destination stream if required, in an attempt to 1232 // reserve any needed space before overwriting the existing data. 1233 1234 if (dstStream.Length () < Length ()) 1235 { 1236 dstStream.SetLength (Length ()); 1237 } 1238 1239 SetReadPosition (0); 1240 1241 dstStream.SetWritePosition (0); 1242 1243 CopyToStream (dstStream, Length ()); 1244 1245 dstStream.Flush (); 1246 1247 dstStream.SetLength (Length ()); 1248 1249 } 1250 1251 /*****************************************************************************/ 1252 1253 dng_stream_contiguous_read_hint::dng_stream_contiguous_read_hint 1254 (dng_stream &stream, 1255 dng_memory_allocator &allocator, 1256 uint64 offset, 1257 uint64 count) 1258 1259 : fStream (stream) 1260 , fAllocator (allocator) 1261 , fOldBufferSize (stream.BufferSize ()) 1262 1263 { 1264 1265 fStream.Flush (); // Cannot change buffer size with dirty buffer 1266 1267 // Don't bother changing buffer size if only a small change. 1268 1269 if (count > fOldBufferSize * 4) 1270 { 1271 1272 // Round contiguous size up and down to stream blocks. 1273 1274 uint64 blockRound = gDNGStreamBlockSize - 1; 1275 1276 uint64 blockMask = ~((int64) blockRound); 1277 1278 count = (count + (offset & blockRound) + blockRound) & blockMask; 1279 1280 // Limit to maximum buffer size. 1281 1282 uint64 newBufferSize = Min_uint64 (gDNGMaxStreamBufferSize, count); 1283 1284 // To avoid reading too many bytes with the final read, adjust buffer 1285 // size the to make an exact number of buffers fit. 1286 1287 uint64 numBuffers = (count + newBufferSize - 1) / newBufferSize; 1288 1289 newBufferSize = (count + numBuffers - 1) / numBuffers; 1290 1291 // Finally round up to a block size. 1292 1293 newBufferSize = (newBufferSize + blockRound) & blockMask; 1294 1295 // Change the buffer size. 1296 1297 fStream.SetBufferSize (fAllocator, (uint32) newBufferSize); 1298 1299 } 1300 1301 } 1302 1303 /*****************************************************************************/ 1304 1305 dng_stream_contiguous_read_hint::~dng_stream_contiguous_read_hint () 1306 { 1307 1308 fStream.SetBufferSize (fAllocator, fOldBufferSize); 1309 1310 } 1311 1312 /*****************************************************************************/ 1313 1314 TempBigEndian::TempBigEndian (dng_stream &stream, 1315 bool bigEndian) 1316 1317 : fStream (stream) 1318 , fOldSwap (stream.SwapBytes ()) 1319 1320 { 1321 1322 fStream.SetBigEndian (bigEndian); 1323 1324 } 1325 1326 /*****************************************************************************/ 1327 1328 TempBigEndian::~TempBigEndian () 1329 { 1330 1331 fStream.SetSwapBytes (fOldSwap); 1332 1333 } 1334 1335 /*****************************************************************************/ 1336 1337 TempStreamSniffer::TempStreamSniffer (dng_stream &stream, 1338 dng_abort_sniffer *sniffer) 1339 1340 : fStream (stream) 1341 , fOldSniffer (stream.Sniffer ()) 1342 1343 { 1344 1345 fStream.SetSniffer (sniffer); 1346 1347 } 1348 1349 /*****************************************************************************/ 1350 1351 TempStreamSniffer::~TempStreamSniffer () 1352 { 1353 1354 fStream.SetSniffer (fOldSniffer); 1355 1356 } 1357 1358 /*****************************************************************************/