1 | /*****************************************************************************/ |
2 | // Copyright 2006-2007 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_stream.cpp#2 $ */ |
10 | /* $DateTime: 2012/06/01 07:28:57 $ */ |
11 | /* $Change: 832715 $ */ |
12 | /* $Author: tknoll $ */ |
13 | |
14 | /*****************************************************************************/ |
15 | |
16 | #include "dng_stream.h" |
17 | |
18 | #include "dng_abort_sniffer.h" |
19 | #include "dng_auto_ptr.h" |
20 | #include "dng_bottlenecks.h" |
21 | #include "dng_exceptions.h" |
22 | #include "dng_flags.h" |
23 | #include "dng_memory.h" |
24 | #include "dng_tag_types.h" |
25 | |
26 | /*****************************************************************************/ |
27 | |
28 | dng_stream::dng_stream (dng_abort_sniffer *sniffer, |
29 | uint32 bufferSize, |
30 | uint64 offsetInOriginalFile) |
31 | |
32 | : fSwapBytes (false) |
33 | , fHaveLength (false) |
34 | , fLength (0) |
35 | , fOffsetInOriginalFile (offsetInOriginalFile) |
36 | , fPosition (0) |
37 | , fMemBlock (bufferSize) |
38 | , fBuffer (fMemBlock.Buffer_uint8 ()) |
39 | , fBufferSize (bufferSize) |
40 | , fBufferStart (0) |
41 | , fBufferEnd (0) |
42 | , fBufferLimit (bufferSize) |
43 | , fBufferDirty (false) |
44 | , fSniffer (sniffer) |
45 | |
46 | { |
47 | |
48 | } |
49 | |
50 | /*****************************************************************************/ |
51 | |
52 | dng_stream::dng_stream (const void *data, |
53 | uint32 count, |
54 | uint64 offsetInOriginalFile) |
55 | |
56 | : fSwapBytes (false) |
57 | , fHaveLength (true) |
58 | , fLength (count) |
59 | , fOffsetInOriginalFile (offsetInOriginalFile) |
60 | , fPosition (0) |
61 | , fMemBlock () |
62 | , fBuffer ((uint8 *) data) |
63 | , fBufferSize (count) |
64 | , fBufferStart (0) |
65 | , fBufferEnd (count) |
66 | , fBufferLimit (count) |
67 | , fBufferDirty (false) |
68 | , fSniffer (NULL) |
69 | |
70 | { |
71 | |
72 | } |
73 | |
74 | /*****************************************************************************/ |
75 | |
76 | dng_stream::~dng_stream () |
77 | { |
78 | |
79 | } |
80 | |
81 | /*****************************************************************************/ |
82 | |
83 | uint64 dng_stream::DoGetLength () |
84 | { |
85 | |
86 | ThrowProgramError (); |
87 | |
88 | return 0; |
89 | |
90 | } |
91 | |
92 | /*****************************************************************************/ |
93 | |
94 | void dng_stream::DoRead (void * /* data */, |
95 | uint32 /* count */, |
96 | uint64 /* offset */) |
97 | { |
98 | |
99 | ThrowProgramError (); |
100 | |
101 | } |
102 | |
103 | /*****************************************************************************/ |
104 | |
105 | void dng_stream::DoSetLength (uint64 /* length */) |
106 | { |
107 | |
108 | ThrowProgramError (); |
109 | |
110 | } |
111 | |
112 | /*****************************************************************************/ |
113 | |
114 | void dng_stream::DoWrite (const void * /* data */, |
115 | uint32 /* count */, |
116 | uint64 /* offset */) |
117 | { |
118 | |
119 | ThrowProgramError (); |
120 | |
121 | } |
122 | |
123 | /*****************************************************************************/ |
124 | |
125 | bool dng_stream::BigEndian () const |
126 | { |
127 | |
128 | return fSwapBytes != (!!qDNGBigEndian); |
129 | |
130 | } |
131 | |
132 | /*****************************************************************************/ |
133 | |
134 | void dng_stream::SetBigEndian (bool bigEndian) |
135 | { |
136 | |
137 | fSwapBytes = (bigEndian != (!!qDNGBigEndian)); |
138 | |
139 | } |
140 | |
141 | /*****************************************************************************/ |
142 | |
143 | const void * dng_stream::Data () const |
144 | { |
145 | |
146 | if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength) |
147 | { |
148 | |
149 | return fBuffer; |
150 | |
151 | } |
152 | |
153 | return NULL; |
154 | |
155 | } |
156 | |
157 | /*****************************************************************************/ |
158 | |
159 | dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator) |
160 | { |
161 | |
162 | Flush (); |
163 | |
164 | uint64 len64 = Length (); |
165 | |
166 | if (len64 > 0xFFFFFFFF) |
167 | { |
168 | ThrowProgramError (); |
169 | } |
170 | |
171 | uint32 len = (uint32) len64; |
172 | |
173 | AutoPtr<dng_memory_block> block (allocator.Allocate (len)); |
174 | |
175 | if (len) |
176 | { |
177 | |
178 | SetReadPosition (0); |
179 | |
180 | Get (block->Buffer (), len); |
181 | |
182 | } |
183 | |
184 | return block.Release (); |
185 | |
186 | } |
187 | |
188 | /*****************************************************************************/ |
189 | |
190 | void dng_stream::SetReadPosition (uint64 offset) |
191 | { |
192 | |
193 | fPosition = offset; |
194 | |
195 | if (fPosition > Length ()) |
196 | { |
197 | |
198 | ThrowEndOfFile (); |
199 | |
200 | } |
201 | |
202 | } |
203 | |
204 | /*****************************************************************************/ |
205 | |
206 | uint64 dng_stream::OffsetInOriginalFile () const |
207 | { |
208 | |
209 | return fOffsetInOriginalFile; |
210 | |
211 | } |
212 | |
213 | /*****************************************************************************/ |
214 | |
215 | uint64 dng_stream::PositionInOriginalFile () const |
216 | { |
217 | |
218 | if (fOffsetInOriginalFile == kDNGStreamInvalidOffset) |
219 | return kDNGStreamInvalidOffset; |
220 | |
221 | return fOffsetInOriginalFile + Position (); |
222 | |
223 | } |
224 | |
225 | /*****************************************************************************/ |
226 | |
227 | void dng_stream::Get (void *data, uint32 count) |
228 | { |
229 | |
230 | while (count) |
231 | { |
232 | |
233 | // See if the request is totally inside buffer. |
234 | |
235 | if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd) |
236 | { |
237 | |
238 | DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart), |
239 | data, |
240 | count); |
241 | |
242 | fPosition += count; |
243 | |
244 | return; |
245 | |
246 | } |
247 | |
248 | // See if first part of request is inside buffer. |
249 | |
250 | if (fPosition >= fBufferStart && fPosition < fBufferEnd) |
251 | { |
252 | |
253 | uint32 block = (uint32) (fBufferEnd - fPosition); |
254 | |
255 | DoCopyBytes (fBuffer + (fPosition - fBufferStart), |
256 | data, |
257 | block); |
258 | |
259 | count -= block; |
260 | |
261 | data = (void *) (((char *) data) + block); |
262 | |
263 | fPosition += block; |
264 | |
265 | } |
266 | |
267 | // Flush buffer if dirty. |
268 | |
269 | Flush (); |
270 | |
271 | // Do large reads unbuffered. |
272 | |
273 | if (count > fBufferSize) |
274 | { |
275 | |
276 | if (fPosition + count > Length ()) |
277 | { |
278 | |
279 | ThrowEndOfFile (); |
280 | |
281 | } |
282 | |
283 | DoRead (data, |
284 | count, |
285 | fPosition); |
286 | |
287 | fPosition += count; |
288 | |
289 | return; |
290 | |
291 | } |
292 | |
293 | // Figure out new buffer range. |
294 | |
295 | fBufferStart = fPosition; |
296 | |
297 | if (fBufferSize >= 4096) |
298 | { |
299 | |
300 | // Align to a 4K file block. |
301 | |
302 | fBufferStart &= (uint64) ~((int64) 4095); |
303 | |
304 | } |
305 | |
306 | fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ()); |
307 | |
308 | if (fBufferEnd <= fPosition) |
309 | { |
310 | |
311 | ThrowEndOfFile (); |
312 | |
313 | } |
314 | |
315 | // Read data into buffer. |
316 | |
317 | dng_abort_sniffer::SniffForAbort (fSniffer); |
318 | |
319 | DoRead (fBuffer, |
320 | (uint32) (fBufferEnd - fBufferStart), |
321 | fBufferStart); |
322 | |
323 | } |
324 | |
325 | } |
326 | |
327 | /*****************************************************************************/ |
328 | |
329 | void dng_stream::SetWritePosition (uint64 offset) |
330 | { |
331 | |
332 | fPosition = offset; |
333 | |
334 | } |
335 | |
336 | /*****************************************************************************/ |
337 | |
338 | void dng_stream::Flush () |
339 | { |
340 | |
341 | if (fBufferDirty) |
342 | { |
343 | |
344 | dng_abort_sniffer::SniffForAbort (fSniffer); |
345 | |
346 | DoWrite (fBuffer, |
347 | (uint32) (fBufferEnd - fBufferStart), |
348 | fBufferStart); |
349 | |
350 | fBufferStart = 0; |
351 | fBufferEnd = 0; |
352 | fBufferLimit = fBufferSize; |
353 | |
354 | fBufferDirty = false; |
355 | |
356 | } |
357 | |
358 | } |
359 | |
360 | /*****************************************************************************/ |
361 | |
362 | void dng_stream::SetLength (uint64 length) |
363 | { |
364 | |
365 | Flush (); |
366 | |
367 | if (Length () != length) |
368 | { |
369 | |
370 | DoSetLength (length); |
371 | |
372 | fLength = length; |
373 | |
374 | } |
375 | |
376 | } |
377 | |
378 | /*****************************************************************************/ |
379 | |
380 | void dng_stream::Put (const void *data, |
381 | uint32 count) |
382 | { |
383 | |
384 | // See if we can replace or append to the existing buffer. |
385 | |
386 | uint64 endPosition = fPosition + count; |
387 | |
388 | if (fBufferDirty && |
389 | fPosition >= fBufferStart && |
390 | fPosition <= fBufferEnd && |
391 | endPosition <= fBufferLimit) |
392 | { |
393 | |
394 | DoCopyBytes (data, |
395 | fBuffer + (uint32) (fPosition - fBufferStart), |
396 | count); |
397 | |
398 | if (fBufferEnd < endPosition) |
399 | fBufferEnd = endPosition; |
400 | |
401 | } |
402 | |
403 | // Else we need to write to the file. |
404 | |
405 | else |
406 | { |
407 | |
408 | // Write existing buffer. |
409 | |
410 | Flush (); |
411 | |
412 | // Write large blocks unbuffered. |
413 | |
414 | if (count >= fBufferSize) |
415 | { |
416 | |
417 | dng_abort_sniffer::SniffForAbort (fSniffer); |
418 | |
419 | DoWrite (data, count, fPosition); |
420 | |
421 | } |
422 | |
423 | // Start a new buffer with small blocks. |
424 | |
425 | else |
426 | { |
427 | |
428 | fBufferDirty = true; |
429 | |
430 | fBufferStart = fPosition; |
431 | fBufferEnd = endPosition; |
432 | fBufferLimit = fBufferStart + fBufferSize; |
433 | |
434 | DoCopyBytes (data, |
435 | fBuffer, |
436 | count); |
437 | |
438 | } |
439 | |
440 | } |
441 | |
442 | fPosition = endPosition; |
443 | |
444 | fLength = Max_uint64 (Length (), fPosition); |
445 | |
446 | } |
447 | |
448 | /*****************************************************************************/ |
449 | |
450 | uint16 dng_stream::Get_uint16 () |
451 | { |
452 | |
453 | uint16 x; |
454 | |
455 | Get (&x, 2); |
456 | |
457 | if (fSwapBytes) |
458 | { |
459 | |
460 | x = SwapBytes16 (x); |
461 | |
462 | } |
463 | |
464 | return x; |
465 | |
466 | } |
467 | |
468 | /*****************************************************************************/ |
469 | |
470 | void dng_stream::Put_uint16 (uint16 x) |
471 | { |
472 | |
473 | if (fSwapBytes) |
474 | { |
475 | |
476 | x = SwapBytes16 (x); |
477 | |
478 | } |
479 | |
480 | Put (&x, 2); |
481 | |
482 | } |
483 | |
484 | /*****************************************************************************/ |
485 | |
486 | uint32 dng_stream::Get_uint32 () |
487 | { |
488 | |
489 | uint32 x; |
490 | |
491 | Get (&x, 4); |
492 | |
493 | if (fSwapBytes) |
494 | { |
495 | |
496 | x = SwapBytes32 (x); |
497 | |
498 | } |
499 | |
500 | return x; |
501 | |
502 | } |
503 | |
504 | /*****************************************************************************/ |
505 | |
506 | void dng_stream::Put_uint32 (uint32 x) |
507 | { |
508 | |
509 | if (fSwapBytes) |
510 | { |
511 | |
512 | x = SwapBytes32 (x); |
513 | |
514 | } |
515 | |
516 | Put (&x, 4); |
517 | |
518 | } |
519 | |
520 | /*****************************************************************************/ |
521 | |
522 | uint64 dng_stream::Get_uint64 () |
523 | { |
524 | |
525 | if (fSwapBytes) |
526 | { |
527 | |
528 | union |
529 | { |
530 | uint32 u32 [2]; |
531 | uint64 u64; |
532 | } u; |
533 | |
534 | u.u32 [1] = Get_uint32 (); |
535 | u.u32 [0] = Get_uint32 (); |
536 | |
537 | return u.u64; |
538 | |
539 | } |
540 | |
541 | uint64 x; |
542 | |
543 | Get (&x, 8); |
544 | |
545 | return x; |
546 | |
547 | } |
548 | |
549 | /*****************************************************************************/ |
550 | |
551 | void dng_stream::Put_uint64 (uint64 x) |
552 | { |
553 | |
554 | if (fSwapBytes) |
555 | { |
556 | |
557 | union |
558 | { |
559 | uint32 u32 [2]; |
560 | uint64 u64; |
561 | } u; |
562 | |
563 | u.u64 = x; |
564 | |
565 | Put_uint32 (u.u32 [1]); |
566 | Put_uint32 (u.u32 [0]); |
567 | |
568 | } |
569 | |
570 | else |
571 | { |
572 | |
573 | Put (&x, 8); |
574 | |
575 | } |
576 | |
577 | } |
578 | |
579 | /*****************************************************************************/ |
580 | |
581 | real32 dng_stream::Get_real32 () |
582 | { |
583 | |
584 | union |
585 | { |
586 | uint32 i; |
587 | real32 r; |
588 | } u; |
589 | |
590 | u.i = Get_uint32 (); |
591 | |
592 | return u.r; |
593 | |
594 | } |
595 | |
596 | /*****************************************************************************/ |
597 | |
598 | void dng_stream::Put_real32 (real32 x) |
599 | { |
600 | |
601 | if (fSwapBytes) |
602 | { |
603 | |
604 | union |
605 | { |
606 | uint32 i; |
607 | real32 r; |
608 | } u; |
609 | |
610 | u.r = x; |
611 | |
612 | Put_uint32 (u.i); |
613 | |
614 | } |
615 | |
616 | else |
617 | { |
618 | |
619 | Put (&x, 4); |
620 | |
621 | } |
622 | |
623 | } |
624 | |
625 | /*****************************************************************************/ |
626 | |
627 | real64 dng_stream::Get_real64 () |
628 | { |
629 | |
630 | if (fSwapBytes) |
631 | { |
632 | |
633 | union |
634 | { |
635 | uint32 i [2]; |
636 | real64 r; |
637 | } u; |
638 | |
639 | u.i [1] = Get_uint32 (); |
640 | u.i [0] = Get_uint32 (); |
641 | |
642 | return u.r; |
643 | |
644 | } |
645 | |
646 | real64 x; |
647 | |
648 | Get (&x, 8); |
649 | |
650 | return x; |
651 | |
652 | } |
653 | |
654 | /*****************************************************************************/ |
655 | |
656 | void dng_stream::Put_real64 (real64 x) |
657 | { |
658 | |
659 | if (fSwapBytes) |
660 | { |
661 | |
662 | union |
663 | { |
664 | uint32 i [2]; |
665 | real64 r; |
666 | } u; |
667 | |
668 | u.r = x; |
669 | |
670 | Put_uint32 (u.i [1]); |
671 | Put_uint32 (u.i [0]); |
672 | |
673 | } |
674 | |
675 | else |
676 | { |
677 | |
678 | Put (&x, 8); |
679 | |
680 | } |
681 | |
682 | } |
683 | |
684 | /*****************************************************************************/ |
685 | |
686 | void dng_stream::Get_CString (char *data, uint32 maxLength) |
687 | { |
688 | |
689 | memset (data, 0, maxLength); |
690 | |
691 | uint32 index = 0; |
692 | |
693 | while (true) |
694 | { |
695 | |
696 | char c = (char) Get_uint8 (); |
697 | |
698 | if (index + 1 < maxLength) |
699 | data [index++] = c; |
700 | |
701 | if (c == 0) |
702 | break; |
703 | |
704 | } |
705 | |
706 | } |
707 | |
708 | /*****************************************************************************/ |
709 | |
710 | void dng_stream::Get_UString (char *data, uint32 maxLength) |
711 | { |
712 | |
713 | memset (data, 0, maxLength); |
714 | |
715 | uint32 index = 0; |
716 | |
717 | while (true) |
718 | { |
719 | |
720 | char c = (char) Get_uint16 (); |
721 | |
722 | if (index + 1 < maxLength) |
723 | data [index++] = (char) c; |
724 | |
725 | if (c == 0) |
726 | break; |
727 | |
728 | } |
729 | |
730 | } |
731 | |
732 | /*****************************************************************************/ |
733 | |
734 | void dng_stream::PutZeros (uint64 count) |
735 | { |
736 | |
737 | const uint32 kZeroBufferSize = 4096; |
738 | |
739 | if (count >= kZeroBufferSize) |
740 | { |
741 | |
742 | dng_memory_data zeroBuffer (kZeroBufferSize); |
743 | |
744 | DoZeroBytes (zeroBuffer.Buffer (), |
745 | kZeroBufferSize); |
746 | |
747 | while (count) |
748 | { |
749 | |
750 | uint64 blockSize = Min_uint64 (count, kZeroBufferSize); |
751 | |
752 | Put (zeroBuffer.Buffer (), (uint32) blockSize); |
753 | |
754 | count -= blockSize; |
755 | |
756 | } |
757 | |
758 | } |
759 | |
760 | else |
761 | { |
762 | |
763 | uint32 count32 = (uint32) count; |
764 | |
765 | for (uint32 j = 0; j < count32; j++) |
766 | { |
767 | |
768 | Put_uint8 (0); |
769 | |
770 | } |
771 | |
772 | } |
773 | |
774 | } |
775 | |
776 | /*****************************************************************************/ |
777 | |
778 | void dng_stream::PadAlign2 () |
779 | { |
780 | |
781 | PutZeros (Position () & 1); |
782 | |
783 | } |
784 | |
785 | /*****************************************************************************/ |
786 | |
787 | void dng_stream::PadAlign4 () |
788 | { |
789 | |
790 | PutZeros ((4 - (Position () & 3)) & 3); |
791 | |
792 | } |
793 | |
794 | /*****************************************************************************/ |
795 | |
796 | uint32 dng_stream::TagValue_uint32 (uint32 tagType) |
797 | { |
798 | |
799 | switch (tagType) |
800 | { |
801 | |
802 | case ttByte: |
803 | return (uint32) Get_uint8 (); |
804 | |
805 | case ttShort: |
806 | return (uint32) Get_uint16 (); |
807 | |
808 | case ttLong: |
809 | case ttIFD: |
810 | return Get_uint32 (); |
811 | |
812 | } |
813 | |
814 | real64 x = TagValue_real64 (tagType); |
815 | |
816 | if (x < 0.0) |
817 | x = 0.0; |
818 | |
819 | if (x > (real64) 0xFFFFFFFF) |
820 | x = (real64) 0xFFFFFFFF; |
821 | |
822 | return ConvertDoubleToUint32(x + 0.5); |
823 | |
824 | } |
825 | |
826 | /*****************************************************************************/ |
827 | |
828 | int32 dng_stream::TagValue_int32 (uint32 tagType) |
829 | { |
830 | |
831 | switch (tagType) |
832 | { |
833 | |
834 | case ttSByte: |
835 | return (int32) Get_int8 (); |
836 | |
837 | case ttSShort: |
838 | return (int32) Get_int16 (); |
839 | |
840 | case ttSLong: |
841 | return Get_int32 (); |
842 | |
843 | } |
844 | |
845 | real64 x = TagValue_real64 (tagType); |
846 | |
847 | if (x < 0.0) |
848 | { |
849 | |
850 | if (x < -2147483648.0) |
851 | x = -2147483648.0; |
852 | |
853 | return ConvertDoubleToInt32(x - 0.5); |
854 | |
855 | } |
856 | |
857 | else |
858 | { |
859 | |
860 | if (x > 2147483647.0) |
861 | x = 2147483647.0; |
862 | |
863 | return ConvertDoubleToInt32(x + 0.5); |
864 | |
865 | } |
866 | |
867 | } |
868 | |
869 | /*****************************************************************************/ |
870 | |
871 | dng_urational dng_stream::TagValue_urational (uint32 tagType) |
872 | { |
873 | |
874 | dng_urational result; |
875 | |
876 | result.n = 0; |
877 | result.d = 1; |
878 | |
879 | switch (tagType) |
880 | { |
881 | |
882 | case ttRational: |
883 | { |
884 | |
885 | result.n = Get_uint32 (); |
886 | result.d = Get_uint32 (); |
887 | |
888 | break; |
889 | |
890 | } |
891 | |
892 | case ttSRational: |
893 | { |
894 | |
895 | int32 n = Get_int32 (); |
896 | int32 d = Get_int32 (); |
897 | |
898 | if ((n < 0) == (d < 0)) |
899 | { |
900 | |
901 | if (d < 0) |
902 | { |
903 | result.n = (uint32) ((int64) n * -1); |
904 | result.d = (uint32) ((int64) d * -1); |
905 | } |
906 | else |
907 | { |
908 | result.n = (uint32) n; |
909 | result.d = (uint32) d; |
910 | } |
911 | |
912 | } |
913 | |
914 | break; |
915 | |
916 | } |
917 | |
918 | case ttByte: |
919 | case ttShort: |
920 | case ttLong: |
921 | case ttIFD: |
922 | { |
923 | |
924 | result.n = TagValue_uint32 (tagType); |
925 | |
926 | break; |
927 | |
928 | } |
929 | |
930 | case ttSByte: |
931 | case ttSShort: |
932 | case ttSLong: |
933 | { |
934 | |
935 | int32 n = TagValue_int32 (tagType); |
936 | |
937 | if (n > 0) |
938 | { |
939 | result.n = (uint32) n; |
940 | } |
941 | |
942 | break; |
943 | |
944 | } |
945 | |
946 | default: |
947 | { |
948 | |
949 | real64 x = TagValue_real64 (tagType); |
950 | |
951 | if (x > 0.0) |
952 | { |
953 | |
954 | while (result.d < 10000 && x < 1000000) |
955 | { |
956 | |
957 | result.d *= 10; |
958 | |
959 | x *= 10.0; |
960 | |
961 | } |
962 | |
963 | result.n = ConvertDoubleToUint32(x + 0.5); |
964 | |
965 | } |
966 | |
967 | } |
968 | |
969 | } |
970 | |
971 | return result; |
972 | |
973 | } |
974 | |
975 | /*****************************************************************************/ |
976 | |
977 | dng_srational dng_stream::TagValue_srational (uint32 tagType) |
978 | { |
979 | |
980 | dng_srational result; |
981 | |
982 | result.n = 0; |
983 | result.d = 1; |
984 | |
985 | switch (tagType) |
986 | { |
987 | |
988 | case ttSRational: |
989 | { |
990 | |
991 | result.n = Get_int32 (); |
992 | result.d = Get_int32 (); |
993 | |
994 | break; |
995 | |
996 | } |
997 | |
998 | default: |
999 | { |
1000 | |
1001 | real64 x = TagValue_real64 (tagType); |
1002 | |
1003 | if (x > 0.0) |
1004 | { |
1005 | |
1006 | while (result.d < 10000 && x < 1000000.0) |
1007 | { |
1008 | |
1009 | result.d *= 10; |
1010 | |
1011 | x *= 10.0; |
1012 | |
1013 | } |
1014 | |
1015 | result.n = ConvertDoubleToInt32(x + 0.5); |
1016 | |
1017 | } |
1018 | |
1019 | else |
1020 | { |
1021 | |
1022 | while (result.d < 10000 && x > -1000000.0) |
1023 | { |
1024 | |
1025 | result.d *= 10; |
1026 | |
1027 | x *= 10.0; |
1028 | |
1029 | } |
1030 | |
1031 | result.n = ConvertDoubleToInt32(x - 0.5); |
1032 | |
1033 | } |
1034 | |
1035 | } |
1036 | |
1037 | } |
1038 | |
1039 | return result; |
1040 | |
1041 | } |
1042 | |
1043 | /*****************************************************************************/ |
1044 | |
1045 | real64 dng_stream::TagValue_real64 (uint32 tagType) |
1046 | { |
1047 | |
1048 | switch (tagType) |
1049 | { |
1050 | |
1051 | case ttByte: |
1052 | case ttShort: |
1053 | case ttLong: |
1054 | case ttIFD: |
1055 | return (real64) TagValue_uint32 (tagType); |
1056 | |
1057 | case ttSByte: |
1058 | case ttSShort: |
1059 | case ttSLong: |
1060 | return (real64) TagValue_int32 (tagType); |
1061 | |
1062 | case ttRational: |
1063 | { |
1064 | |
1065 | uint32 n = Get_uint32 (); |
1066 | uint32 d = Get_uint32 (); |
1067 | |
1068 | if (d == 0) |
1069 | return 0.0; |
1070 | else |
1071 | return (real64) n / (real64) d; |
1072 | |
1073 | } |
1074 | |
1075 | case ttSRational: |
1076 | { |
1077 | |
1078 | int32 n = Get_int32 (); |
1079 | int32 d = Get_int32 (); |
1080 | |
1081 | if (d == 0) |
1082 | return 0.0; |
1083 | else |
1084 | return (real64) n / (real64) d; |
1085 | |
1086 | } |
1087 | |
1088 | case ttFloat: |
1089 | return (real64) Get_real32 (); |
1090 | |
1091 | case ttDouble: |
1092 | return Get_real64 (); |
1093 | |
1094 | } |
1095 | |
1096 | return 0.0; |
1097 | |
1098 | } |
1099 | |
1100 | /*****************************************************************************/ |
1101 | |
1102 | void dng_stream::CopyToStream (dng_stream &dstStream, |
1103 | uint64 count) |
1104 | { |
1105 | |
1106 | uint8 smallBuffer [1024]; |
1107 | |
1108 | if (count <= sizeof (smallBuffer)) |
1109 | { |
1110 | |
1111 | Get (smallBuffer, (uint32) count); |
1112 | |
1113 | dstStream.Put (smallBuffer, (uint32) count); |
1114 | |
1115 | } |
1116 | |
1117 | else |
1118 | { |
1119 | |
1120 | const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize, |
1121 | count); |
1122 | |
1123 | dng_memory_data bigBuffer (bigBufferSize); |
1124 | |
1125 | while (count) |
1126 | { |
1127 | |
1128 | uint32 blockCount = (uint32) Min_uint64 (bigBufferSize, |
1129 | count); |
1130 | |
1131 | Get (bigBuffer.Buffer (), |
1132 | blockCount); |
1133 | |
1134 | dstStream.Put (bigBuffer.Buffer (), |
1135 | blockCount); |
1136 | |
1137 | count -= blockCount; |
1138 | |
1139 | } |
1140 | |
1141 | } |
1142 | |
1143 | } |
1144 | |
1145 | /*****************************************************************************/ |
1146 | |
1147 | void dng_stream::DuplicateStream (dng_stream &dstStream) |
1148 | { |
1149 | |
1150 | // Turn off sniffers for this operation. |
1151 | |
1152 | TempStreamSniffer noSniffer1 (*this , NULL); |
1153 | TempStreamSniffer noSniffer2 (dstStream, NULL); |
1154 | |
1155 | // First grow the destination stream if required, in an attempt to |
1156 | // reserve any needed space before overwriting the existing data. |
1157 | |
1158 | if (dstStream.Length () < Length ()) |
1159 | { |
1160 | dstStream.SetLength (Length ()); |
1161 | } |
1162 | |
1163 | SetReadPosition (0); |
1164 | |
1165 | dstStream.SetWritePosition (0); |
1166 | |
1167 | CopyToStream (dstStream, Length ()); |
1168 | |
1169 | dstStream.Flush (); |
1170 | |
1171 | dstStream.SetLength (Length ()); |
1172 | |
1173 | } |
1174 | |
1175 | /*****************************************************************************/ |
1176 | |
1177 | TempBigEndian::TempBigEndian (dng_stream &stream, |
1178 | bool bigEndian) |
1179 | |
1180 | : fStream (stream) |
1181 | , fOldSwap (stream.SwapBytes ()) |
1182 | |
1183 | { |
1184 | |
1185 | fStream.SetBigEndian (bigEndian); |
1186 | |
1187 | } |
1188 | |
1189 | /*****************************************************************************/ |
1190 | |
1191 | TempBigEndian::~TempBigEndian () |
1192 | { |
1193 | |
1194 | fStream.SetSwapBytes (fOldSwap); |
1195 | |
1196 | } |
1197 | |
1198 | /*****************************************************************************/ |
1199 | |
1200 | TempStreamSniffer::TempStreamSniffer (dng_stream &stream, |
1201 | dng_abort_sniffer *sniffer) |
1202 | |
1203 | : fStream (stream) |
1204 | , fOldSniffer (stream.Sniffer ()) |
1205 | |
1206 | { |
1207 | |
1208 | fStream.SetSniffer (sniffer); |
1209 | |
1210 | } |
1211 | |
1212 | /*****************************************************************************/ |
1213 | |
1214 | TempStreamSniffer::~TempStreamSniffer () |
1215 | { |
1216 | |
1217 | fStream.SetSniffer (fOldSniffer); |
1218 | |
1219 | } |
1220 | |
1221 | /*****************************************************************************/ |
1222 | |