You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1222 lines
19 KiB
1222 lines
19 KiB
/*****************************************************************************/
|
|
// Copyright 2006-2007 Adobe Systems Incorporated
|
|
// All Rights Reserved.
|
|
//
|
|
// NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
// accordance with the terms of the Adobe license agreement accompanying it.
|
|
/*****************************************************************************/
|
|
|
|
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_stream.cpp#2 $ */
|
|
/* $DateTime: 2012/06/01 07:28:57 $ */
|
|
/* $Change: 832715 $ */
|
|
/* $Author: tknoll $ */
|
|
|
|
/*****************************************************************************/
|
|
|
|
#include "dng_stream.h"
|
|
|
|
#include "dng_abort_sniffer.h"
|
|
#include "dng_auto_ptr.h"
|
|
#include "dng_bottlenecks.h"
|
|
#include "dng_exceptions.h"
|
|
#include "dng_flags.h"
|
|
#include "dng_memory.h"
|
|
#include "dng_tag_types.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_stream::dng_stream (dng_abort_sniffer *sniffer,
|
|
uint32 bufferSize,
|
|
uint64 offsetInOriginalFile)
|
|
|
|
: fSwapBytes (false)
|
|
, fHaveLength (false)
|
|
, fLength (0)
|
|
, fOffsetInOriginalFile (offsetInOriginalFile)
|
|
, fPosition (0)
|
|
, fMemBlock (bufferSize)
|
|
, fBuffer (fMemBlock.Buffer_uint8 ())
|
|
, fBufferSize (bufferSize)
|
|
, fBufferStart (0)
|
|
, fBufferEnd (0)
|
|
, fBufferLimit (bufferSize)
|
|
, fBufferDirty (false)
|
|
, fSniffer (sniffer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_stream::dng_stream (const void *data,
|
|
uint32 count,
|
|
uint64 offsetInOriginalFile)
|
|
|
|
: fSwapBytes (false)
|
|
, fHaveLength (true)
|
|
, fLength (count)
|
|
, fOffsetInOriginalFile (offsetInOriginalFile)
|
|
, fPosition (0)
|
|
, fMemBlock ()
|
|
, fBuffer ((uint8 *) data)
|
|
, fBufferSize (count)
|
|
, fBufferStart (0)
|
|
, fBufferEnd (count)
|
|
, fBufferLimit (count)
|
|
, fBufferDirty (false)
|
|
, fSniffer (NULL)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_stream::~dng_stream ()
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint64 dng_stream::DoGetLength ()
|
|
{
|
|
|
|
ThrowProgramError ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::DoRead (void * /* data */,
|
|
uint32 /* count */,
|
|
uint64 /* offset */)
|
|
{
|
|
|
|
ThrowProgramError ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::DoSetLength (uint64 /* length */)
|
|
{
|
|
|
|
ThrowProgramError ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::DoWrite (const void * /* data */,
|
|
uint32 /* count */,
|
|
uint64 /* offset */)
|
|
{
|
|
|
|
ThrowProgramError ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
bool dng_stream::BigEndian () const
|
|
{
|
|
|
|
return fSwapBytes != (!!qDNGBigEndian);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::SetBigEndian (bool bigEndian)
|
|
{
|
|
|
|
fSwapBytes = (bigEndian != (!!qDNGBigEndian));
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
const void * dng_stream::Data () const
|
|
{
|
|
|
|
if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
|
|
{
|
|
|
|
return fBuffer;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
|
|
{
|
|
|
|
Flush ();
|
|
|
|
uint64 len64 = Length ();
|
|
|
|
if (len64 > 0xFFFFFFFF)
|
|
{
|
|
ThrowProgramError ();
|
|
}
|
|
|
|
uint32 len = (uint32) len64;
|
|
|
|
AutoPtr<dng_memory_block> block (allocator.Allocate (len));
|
|
|
|
if (len)
|
|
{
|
|
|
|
SetReadPosition (0);
|
|
|
|
Get (block->Buffer (), len);
|
|
|
|
}
|
|
|
|
return block.Release ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::SetReadPosition (uint64 offset)
|
|
{
|
|
|
|
fPosition = offset;
|
|
|
|
if (fPosition > Length ())
|
|
{
|
|
|
|
ThrowEndOfFile ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint64 dng_stream::OffsetInOriginalFile () const
|
|
{
|
|
|
|
return fOffsetInOriginalFile;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint64 dng_stream::PositionInOriginalFile () const
|
|
{
|
|
|
|
if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
|
|
return kDNGStreamInvalidOffset;
|
|
|
|
return fOffsetInOriginalFile + Position ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Get (void *data, uint32 count)
|
|
{
|
|
|
|
while (count)
|
|
{
|
|
|
|
// See if the request is totally inside buffer.
|
|
|
|
if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
|
|
{
|
|
|
|
DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart),
|
|
data,
|
|
count);
|
|
|
|
fPosition += count;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// See if first part of request is inside buffer.
|
|
|
|
if (fPosition >= fBufferStart && fPosition < fBufferEnd)
|
|
{
|
|
|
|
uint32 block = (uint32) (fBufferEnd - fPosition);
|
|
|
|
DoCopyBytes (fBuffer + (fPosition - fBufferStart),
|
|
data,
|
|
block);
|
|
|
|
count -= block;
|
|
|
|
data = (void *) (((char *) data) + block);
|
|
|
|
fPosition += block;
|
|
|
|
}
|
|
|
|
// Flush buffer if dirty.
|
|
|
|
Flush ();
|
|
|
|
// Do large reads unbuffered.
|
|
|
|
if (count > fBufferSize)
|
|
{
|
|
|
|
if (fPosition + count > Length ())
|
|
{
|
|
|
|
ThrowEndOfFile ();
|
|
|
|
}
|
|
|
|
DoRead (data,
|
|
count,
|
|
fPosition);
|
|
|
|
fPosition += count;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Figure out new buffer range.
|
|
|
|
fBufferStart = fPosition;
|
|
|
|
if (fBufferSize >= 4096)
|
|
{
|
|
|
|
// Align to a 4K file block.
|
|
|
|
fBufferStart &= (uint64) ~((int64) 4095);
|
|
|
|
}
|
|
|
|
fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
|
|
|
|
if (fBufferEnd <= fPosition)
|
|
{
|
|
|
|
ThrowEndOfFile ();
|
|
|
|
}
|
|
|
|
// Read data into buffer.
|
|
|
|
dng_abort_sniffer::SniffForAbort (fSniffer);
|
|
|
|
DoRead (fBuffer,
|
|
(uint32) (fBufferEnd - fBufferStart),
|
|
fBufferStart);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::SetWritePosition (uint64 offset)
|
|
{
|
|
|
|
fPosition = offset;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Flush ()
|
|
{
|
|
|
|
if (fBufferDirty)
|
|
{
|
|
|
|
dng_abort_sniffer::SniffForAbort (fSniffer);
|
|
|
|
DoWrite (fBuffer,
|
|
(uint32) (fBufferEnd - fBufferStart),
|
|
fBufferStart);
|
|
|
|
fBufferStart = 0;
|
|
fBufferEnd = 0;
|
|
fBufferLimit = fBufferSize;
|
|
|
|
fBufferDirty = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::SetLength (uint64 length)
|
|
{
|
|
|
|
Flush ();
|
|
|
|
if (Length () != length)
|
|
{
|
|
|
|
DoSetLength (length);
|
|
|
|
fLength = length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Put (const void *data,
|
|
uint32 count)
|
|
{
|
|
|
|
// See if we can replace or append to the existing buffer.
|
|
|
|
uint64 endPosition = fPosition + count;
|
|
|
|
if (fBufferDirty &&
|
|
fPosition >= fBufferStart &&
|
|
fPosition <= fBufferEnd &&
|
|
endPosition <= fBufferLimit)
|
|
{
|
|
|
|
DoCopyBytes (data,
|
|
fBuffer + (uint32) (fPosition - fBufferStart),
|
|
count);
|
|
|
|
if (fBufferEnd < endPosition)
|
|
fBufferEnd = endPosition;
|
|
|
|
}
|
|
|
|
// Else we need to write to the file.
|
|
|
|
else
|
|
{
|
|
|
|
// Write existing buffer.
|
|
|
|
Flush ();
|
|
|
|
// Write large blocks unbuffered.
|
|
|
|
if (count >= fBufferSize)
|
|
{
|
|
|
|
dng_abort_sniffer::SniffForAbort (fSniffer);
|
|
|
|
DoWrite (data, count, fPosition);
|
|
|
|
}
|
|
|
|
// Start a new buffer with small blocks.
|
|
|
|
else
|
|
{
|
|
|
|
fBufferDirty = true;
|
|
|
|
fBufferStart = fPosition;
|
|
fBufferEnd = endPosition;
|
|
fBufferLimit = fBufferStart + fBufferSize;
|
|
|
|
DoCopyBytes (data,
|
|
fBuffer,
|
|
count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fPosition = endPosition;
|
|
|
|
fLength = Max_uint64 (Length (), fPosition);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint16 dng_stream::Get_uint16 ()
|
|
{
|
|
|
|
uint16 x;
|
|
|
|
Get (&x, 2);
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
x = SwapBytes16 (x);
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Put_uint16 (uint16 x)
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
x = SwapBytes16 (x);
|
|
|
|
}
|
|
|
|
Put (&x, 2);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_stream::Get_uint32 ()
|
|
{
|
|
|
|
uint32 x;
|
|
|
|
Get (&x, 4);
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
x = SwapBytes32 (x);
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Put_uint32 (uint32 x)
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
x = SwapBytes32 (x);
|
|
|
|
}
|
|
|
|
Put (&x, 4);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint64 dng_stream::Get_uint64 ()
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
union
|
|
{
|
|
uint32 u32 [2];
|
|
uint64 u64;
|
|
} u;
|
|
|
|
u.u32 [1] = Get_uint32 ();
|
|
u.u32 [0] = Get_uint32 ();
|
|
|
|
return u.u64;
|
|
|
|
}
|
|
|
|
uint64 x;
|
|
|
|
Get (&x, 8);
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Put_uint64 (uint64 x)
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
union
|
|
{
|
|
uint32 u32 [2];
|
|
uint64 u64;
|
|
} u;
|
|
|
|
u.u64 = x;
|
|
|
|
Put_uint32 (u.u32 [1]);
|
|
Put_uint32 (u.u32 [0]);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
Put (&x, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
real32 dng_stream::Get_real32 ()
|
|
{
|
|
|
|
union
|
|
{
|
|
uint32 i;
|
|
real32 r;
|
|
} u;
|
|
|
|
u.i = Get_uint32 ();
|
|
|
|
return u.r;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Put_real32 (real32 x)
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
union
|
|
{
|
|
uint32 i;
|
|
real32 r;
|
|
} u;
|
|
|
|
u.r = x;
|
|
|
|
Put_uint32 (u.i);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
Put (&x, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
real64 dng_stream::Get_real64 ()
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
union
|
|
{
|
|
uint32 i [2];
|
|
real64 r;
|
|
} u;
|
|
|
|
u.i [1] = Get_uint32 ();
|
|
u.i [0] = Get_uint32 ();
|
|
|
|
return u.r;
|
|
|
|
}
|
|
|
|
real64 x;
|
|
|
|
Get (&x, 8);
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Put_real64 (real64 x)
|
|
{
|
|
|
|
if (fSwapBytes)
|
|
{
|
|
|
|
union
|
|
{
|
|
uint32 i [2];
|
|
real64 r;
|
|
} u;
|
|
|
|
u.r = x;
|
|
|
|
Put_uint32 (u.i [1]);
|
|
Put_uint32 (u.i [0]);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
Put (&x, 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Get_CString (char *data, uint32 maxLength)
|
|
{
|
|
|
|
memset (data, 0, maxLength);
|
|
|
|
uint32 index = 0;
|
|
|
|
while (true)
|
|
{
|
|
|
|
char c = (char) Get_uint8 ();
|
|
|
|
if (index + 1 < maxLength)
|
|
data [index++] = c;
|
|
|
|
if (c == 0)
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::Get_UString (char *data, uint32 maxLength)
|
|
{
|
|
|
|
memset (data, 0, maxLength);
|
|
|
|
uint32 index = 0;
|
|
|
|
while (true)
|
|
{
|
|
|
|
char c = (char) Get_uint16 ();
|
|
|
|
if (index + 1 < maxLength)
|
|
data [index++] = (char) c;
|
|
|
|
if (c == 0)
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::PutZeros (uint64 count)
|
|
{
|
|
|
|
const uint32 kZeroBufferSize = 4096;
|
|
|
|
if (count >= kZeroBufferSize)
|
|
{
|
|
|
|
dng_memory_data zeroBuffer (kZeroBufferSize);
|
|
|
|
DoZeroBytes (zeroBuffer.Buffer (),
|
|
kZeroBufferSize);
|
|
|
|
while (count)
|
|
{
|
|
|
|
uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
|
|
|
|
Put (zeroBuffer.Buffer (), (uint32) blockSize);
|
|
|
|
count -= blockSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
uint32 count32 = (uint32) count;
|
|
|
|
for (uint32 j = 0; j < count32; j++)
|
|
{
|
|
|
|
Put_uint8 (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::PadAlign2 ()
|
|
{
|
|
|
|
PutZeros (Position () & 1);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::PadAlign4 ()
|
|
{
|
|
|
|
PutZeros ((4 - (Position () & 3)) & 3);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_stream::TagValue_uint32 (uint32 tagType)
|
|
{
|
|
|
|
switch (tagType)
|
|
{
|
|
|
|
case ttByte:
|
|
return (uint32) Get_uint8 ();
|
|
|
|
case ttShort:
|
|
return (uint32) Get_uint16 ();
|
|
|
|
case ttLong:
|
|
case ttIFD:
|
|
return Get_uint32 ();
|
|
|
|
}
|
|
|
|
real64 x = TagValue_real64 (tagType);
|
|
|
|
if (x < 0.0)
|
|
x = 0.0;
|
|
|
|
if (x > (real64) 0xFFFFFFFF)
|
|
x = (real64) 0xFFFFFFFF;
|
|
|
|
return ConvertDoubleToUint32(x + 0.5);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int32 dng_stream::TagValue_int32 (uint32 tagType)
|
|
{
|
|
|
|
switch (tagType)
|
|
{
|
|
|
|
case ttSByte:
|
|
return (int32) Get_int8 ();
|
|
|
|
case ttSShort:
|
|
return (int32) Get_int16 ();
|
|
|
|
case ttSLong:
|
|
return Get_int32 ();
|
|
|
|
}
|
|
|
|
real64 x = TagValue_real64 (tagType);
|
|
|
|
if (x < 0.0)
|
|
{
|
|
|
|
if (x < -2147483648.0)
|
|
x = -2147483648.0;
|
|
|
|
return ConvertDoubleToInt32(x - 0.5);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
if (x > 2147483647.0)
|
|
x = 2147483647.0;
|
|
|
|
return ConvertDoubleToInt32(x + 0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_urational dng_stream::TagValue_urational (uint32 tagType)
|
|
{
|
|
|
|
dng_urational result;
|
|
|
|
result.n = 0;
|
|
result.d = 1;
|
|
|
|
switch (tagType)
|
|
{
|
|
|
|
case ttRational:
|
|
{
|
|
|
|
result.n = Get_uint32 ();
|
|
result.d = Get_uint32 ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttSRational:
|
|
{
|
|
|
|
int32 n = Get_int32 ();
|
|
int32 d = Get_int32 ();
|
|
|
|
if ((n < 0) == (d < 0))
|
|
{
|
|
|
|
if (d < 0)
|
|
{
|
|
result.n = (uint32) ((int64) n * -1);
|
|
result.d = (uint32) ((int64) d * -1);
|
|
}
|
|
else
|
|
{
|
|
result.n = (uint32) n;
|
|
result.d = (uint32) d;
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttByte:
|
|
case ttShort:
|
|
case ttLong:
|
|
case ttIFD:
|
|
{
|
|
|
|
result.n = TagValue_uint32 (tagType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttSByte:
|
|
case ttSShort:
|
|
case ttSLong:
|
|
{
|
|
|
|
int32 n = TagValue_int32 (tagType);
|
|
|
|
if (n > 0)
|
|
{
|
|
result.n = (uint32) n;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
real64 x = TagValue_real64 (tagType);
|
|
|
|
if (x > 0.0)
|
|
{
|
|
|
|
while (result.d < 10000 && x < 1000000)
|
|
{
|
|
|
|
result.d *= 10;
|
|
|
|
x *= 10.0;
|
|
|
|
}
|
|
|
|
result.n = ConvertDoubleToUint32(x + 0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_srational dng_stream::TagValue_srational (uint32 tagType)
|
|
{
|
|
|
|
dng_srational result;
|
|
|
|
result.n = 0;
|
|
result.d = 1;
|
|
|
|
switch (tagType)
|
|
{
|
|
|
|
case ttSRational:
|
|
{
|
|
|
|
result.n = Get_int32 ();
|
|
result.d = Get_int32 ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
real64 x = TagValue_real64 (tagType);
|
|
|
|
if (x > 0.0)
|
|
{
|
|
|
|
while (result.d < 10000 && x < 1000000.0)
|
|
{
|
|
|
|
result.d *= 10;
|
|
|
|
x *= 10.0;
|
|
|
|
}
|
|
|
|
result.n = ConvertDoubleToInt32(x + 0.5);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
while (result.d < 10000 && x > -1000000.0)
|
|
{
|
|
|
|
result.d *= 10;
|
|
|
|
x *= 10.0;
|
|
|
|
}
|
|
|
|
result.n = ConvertDoubleToInt32(x - 0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
real64 dng_stream::TagValue_real64 (uint32 tagType)
|
|
{
|
|
|
|
switch (tagType)
|
|
{
|
|
|
|
case ttByte:
|
|
case ttShort:
|
|
case ttLong:
|
|
case ttIFD:
|
|
return (real64) TagValue_uint32 (tagType);
|
|
|
|
case ttSByte:
|
|
case ttSShort:
|
|
case ttSLong:
|
|
return (real64) TagValue_int32 (tagType);
|
|
|
|
case ttRational:
|
|
{
|
|
|
|
uint32 n = Get_uint32 ();
|
|
uint32 d = Get_uint32 ();
|
|
|
|
if (d == 0)
|
|
return 0.0;
|
|
else
|
|
return (real64) n / (real64) d;
|
|
|
|
}
|
|
|
|
case ttSRational:
|
|
{
|
|
|
|
int32 n = Get_int32 ();
|
|
int32 d = Get_int32 ();
|
|
|
|
if (d == 0)
|
|
return 0.0;
|
|
else
|
|
return (real64) n / (real64) d;
|
|
|
|
}
|
|
|
|
case ttFloat:
|
|
return (real64) Get_real32 ();
|
|
|
|
case ttDouble:
|
|
return Get_real64 ();
|
|
|
|
}
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::CopyToStream (dng_stream &dstStream,
|
|
uint64 count)
|
|
{
|
|
|
|
uint8 smallBuffer [1024];
|
|
|
|
if (count <= sizeof (smallBuffer))
|
|
{
|
|
|
|
Get (smallBuffer, (uint32) count);
|
|
|
|
dstStream.Put (smallBuffer, (uint32) count);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
|
|
count);
|
|
|
|
dng_memory_data bigBuffer (bigBufferSize);
|
|
|
|
while (count)
|
|
{
|
|
|
|
uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
|
|
count);
|
|
|
|
Get (bigBuffer.Buffer (),
|
|
blockCount);
|
|
|
|
dstStream.Put (bigBuffer.Buffer (),
|
|
blockCount);
|
|
|
|
count -= blockCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_stream::DuplicateStream (dng_stream &dstStream)
|
|
{
|
|
|
|
// Turn off sniffers for this operation.
|
|
|
|
TempStreamSniffer noSniffer1 (*this , NULL);
|
|
TempStreamSniffer noSniffer2 (dstStream, NULL);
|
|
|
|
// First grow the destination stream if required, in an attempt to
|
|
// reserve any needed space before overwriting the existing data.
|
|
|
|
if (dstStream.Length () < Length ())
|
|
{
|
|
dstStream.SetLength (Length ());
|
|
}
|
|
|
|
SetReadPosition (0);
|
|
|
|
dstStream.SetWritePosition (0);
|
|
|
|
CopyToStream (dstStream, Length ());
|
|
|
|
dstStream.Flush ();
|
|
|
|
dstStream.SetLength (Length ());
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
TempBigEndian::TempBigEndian (dng_stream &stream,
|
|
bool bigEndian)
|
|
|
|
: fStream (stream)
|
|
, fOldSwap (stream.SwapBytes ())
|
|
|
|
{
|
|
|
|
fStream.SetBigEndian (bigEndian);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
TempBigEndian::~TempBigEndian ()
|
|
{
|
|
|
|
fStream.SetSwapBytes (fOldSwap);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
|
|
dng_abort_sniffer *sniffer)
|
|
|
|
: fStream (stream)
|
|
, fOldSniffer (stream.Sniffer ())
|
|
|
|
{
|
|
|
|
fStream.SetSniffer (sniffer);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
TempStreamSniffer::~TempStreamSniffer ()
|
|
{
|
|
|
|
fStream.SetSniffer (fOldSniffer);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|