added DNG
parent
cf3639fbff
commit
4ddadbb600
@ -0,0 +1,12 @@
|
||||
#include "cdcp.h"
|
||||
|
||||
|
||||
cDCP::cDCP(QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void cDCPList::load(const QString& fileName)
|
||||
{
|
||||
m_fileName = fileName;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
#ifndef CDCP_H
|
||||
#define CDCP_H
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QMetaObject>
|
||||
#include <QList>
|
||||
|
||||
|
||||
class cDCP : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit cDCP(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(cDCP*)
|
||||
|
||||
class cDCPList : public QList<cDCP*>
|
||||
{
|
||||
public:
|
||||
void load(const QString& fileName);
|
||||
|
||||
private:
|
||||
QString m_fileName;
|
||||
};
|
||||
|
||||
#endif // CDCP_H
|
||||
@ -0,0 +1,19 @@
|
||||
#ifndef __dng_RawEnvironment__
|
||||
#define __dng_RawEnvironment__
|
||||
// Define preprocessor constants that control platform-specific conditional
|
||||
// compilation. The constants qMacOS and qWinOS must be defined on all
|
||||
// platforms. Other constants, such as qLinux, only need to be defined if we're
|
||||
// actually compiling for that platform.
|
||||
#if defined(__linux__)
|
||||
#define qMacOS 0
|
||||
#define qWinOS 0
|
||||
#define qLinux 1
|
||||
#elif defined(__APPLE__)
|
||||
#define qMacOS 1
|
||||
#define qWinOS 0
|
||||
#elif defined(_WIN32)
|
||||
#define qMacOS 0
|
||||
#define qWinOS 1
|
||||
#endif
|
||||
#define qDNGXMPDocOps 0
|
||||
#endif // __dng_RawEnvironment__
|
||||
@ -0,0 +1,188 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_1d_function.h"
|
||||
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_1d_function::~dng_1d_function ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_1d_function::IsIdentity () const
|
||||
{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_function::EvaluateInverse (real64 y) const
|
||||
{
|
||||
|
||||
const uint32 kMaxIterations = 30;
|
||||
const real64 kNearZero = 1.0e-10;
|
||||
|
||||
real64 x0 = 0.0;
|
||||
real64 y0 = Evaluate (x0);
|
||||
|
||||
real64 x1 = 1.0;
|
||||
real64 y1 = Evaluate (x1);
|
||||
|
||||
for (uint32 iteration = 0; iteration < kMaxIterations; iteration++)
|
||||
{
|
||||
|
||||
if (Abs_real64 (y1 - y0) < kNearZero)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
real64 x2 = Pin_real64 (0.0,
|
||||
x1 + (y - y1) * (x1 - x0) / (y1 - y0),
|
||||
1.0);
|
||||
|
||||
real64 y2 = Evaluate (x2);
|
||||
|
||||
x0 = x1;
|
||||
y0 = y1;
|
||||
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
|
||||
}
|
||||
|
||||
return x1;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_1d_identity::IsIdentity () const
|
||||
{
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_identity::Evaluate (real64 x) const
|
||||
{
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_identity::EvaluateInverse (real64 x) const
|
||||
{
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const dng_1d_function & dng_1d_identity::Get ()
|
||||
{
|
||||
|
||||
static dng_1d_identity static_function;
|
||||
|
||||
return static_function;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_1d_concatenate::dng_1d_concatenate (const dng_1d_function &function1,
|
||||
const dng_1d_function &function2)
|
||||
|
||||
: fFunction1 (function1)
|
||||
, fFunction2 (function2)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_1d_concatenate::IsIdentity () const
|
||||
{
|
||||
|
||||
return fFunction1.IsIdentity () &&
|
||||
fFunction2.IsIdentity ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_concatenate::Evaluate (real64 x) const
|
||||
{
|
||||
|
||||
real64 y = Pin_real64 (0.0, fFunction1.Evaluate (x), 1.0);
|
||||
|
||||
return fFunction2.Evaluate (y);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_concatenate::EvaluateInverse (real64 x) const
|
||||
{
|
||||
|
||||
real64 y = fFunction2.EvaluateInverse (x);
|
||||
|
||||
return fFunction1.EvaluateInverse (y);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_1d_inverse::dng_1d_inverse (const dng_1d_function &f)
|
||||
|
||||
: fFunction (f)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_1d_inverse::IsIdentity () const
|
||||
{
|
||||
|
||||
return fFunction.IsIdentity ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_inverse::Evaluate (real64 x) const
|
||||
{
|
||||
|
||||
return fFunction.EvaluateInverse (x);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 dng_1d_inverse::EvaluateInverse (real64 y) const
|
||||
{
|
||||
|
||||
return fFunction.Evaluate (y);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,154 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Classes for a 1D floating-point to floating-point function abstraction.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_1d_function__
|
||||
#define __dng_1d_function__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 1D floating-point function.
|
||||
///
|
||||
/// The domain (input) is always from 0.0 to 1.0, while the range (output) can be an arbitrary interval.
|
||||
|
||||
class dng_1d_function
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_1d_function ();
|
||||
|
||||
/// Returns true if this function is the map x -> y such that x == y for all x . That is if Evaluate(x) == x for all x.
|
||||
|
||||
virtual bool IsIdentity () const;
|
||||
|
||||
/// Return the mapping for value x.
|
||||
/// This method must be implemented by a derived class of dng_1d_function and the derived class determines the
|
||||
/// lookup method and function used.
|
||||
/// \param x A value between 0.0 and 1.0 (inclusive).
|
||||
/// \retval Mapped value for x
|
||||
|
||||
virtual real64 Evaluate (real64 x) const = 0;
|
||||
|
||||
/// Return the reverse mapped value for y.
|
||||
/// This method can be implemented by derived classes. The default implementation uses Newton's method to solve
|
||||
/// for x such that Evaluate(x) == y.
|
||||
/// \param y A value to reverse map. Should be within the range of the function implemented by this dng_1d_function .
|
||||
/// \retval A value x such that Evaluate(x) == y (to very close approximation).
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// An identity (x -> y such that x == y for all x) mapping function.
|
||||
|
||||
class dng_1d_identity: public dng_1d_function
|
||||
{
|
||||
|
||||
public:
|
||||
/// Always returns true for this class.
|
||||
|
||||
virtual bool IsIdentity () const;
|
||||
|
||||
/// Always returns x for this class.
|
||||
|
||||
virtual real64 Evaluate (real64 x) const;
|
||||
|
||||
/// Always returns y for this class.
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
/// This class is a singleton, and is entirely threadsafe. Use this method to get an instance of the class.
|
||||
|
||||
static const dng_1d_function & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// A dng_1d_function that represents the composition (curry) of two other dng_1d_functions.
|
||||
|
||||
class dng_1d_concatenate: public dng_1d_function
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
const dng_1d_function &fFunction1;
|
||||
|
||||
const dng_1d_function &fFunction2;
|
||||
|
||||
public:
|
||||
|
||||
/// Create a dng_1d_function which computes y = function2.Evaluate(function1.Evaluate(x)).
|
||||
/// Compose function1 and function2 to compute y = function2.Evaluate(function1.Evaluate(x)). The range of function1.Evaluate must be a subset of 0.0 to 1.0 inclusive,
|
||||
/// otherwise the result of function1(x) will be pinned (clipped) to 0.0 if <0.0 and to 1.0 if > 1.0 .
|
||||
/// \param function1 Inner function of composition.
|
||||
/// \param function2 Outer function of composition.
|
||||
|
||||
dng_1d_concatenate (const dng_1d_function &function1,
|
||||
const dng_1d_function &function2);
|
||||
|
||||
/// Only true if both function1 and function2 have IsIdentity equal to true.
|
||||
|
||||
virtual bool IsIdentity () const;
|
||||
|
||||
/// Return the composed mapping for value x.
|
||||
/// \param x A value between 0.0 and 1.0 (inclusive).
|
||||
/// \retval function2.Evaluate(function1.Evaluate(x)).
|
||||
|
||||
virtual real64 Evaluate (real64 x) const;
|
||||
|
||||
/// Return the reverse mapped value for y.
|
||||
/// Be careful using this method with compositions where the inner function does not have a range 0.0 to 1.0 . (Or better yet, do not use such functions.)
|
||||
/// \param y A value to reverse map. Should be within the range of function2.Evaluate.
|
||||
/// \retval A value x such that function2.Evaluate(function1.Evaluate(x)) == y (to very close approximation).
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// A dng_1d_function that represents the inverse of another dng_1d_function.
|
||||
|
||||
class dng_1d_inverse: public dng_1d_function
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
const dng_1d_function &fFunction;
|
||||
|
||||
public:
|
||||
|
||||
dng_1d_inverse (const dng_1d_function &f);
|
||||
|
||||
virtual bool IsIdentity () const;
|
||||
|
||||
virtual real64 Evaluate (real64 x) const;
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,196 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_1d_table.h"
|
||||
|
||||
#include "dng_1d_function.h"
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_1d_table::dng_1d_table (uint32 count)
|
||||
|
||||
: fBuffer ()
|
||||
, fTable (NULL)
|
||||
, fTableCount (count)
|
||||
|
||||
{
|
||||
|
||||
DNG_REQUIRE (count >= kMinTableSize,
|
||||
"count must be at least kMinTableSize");
|
||||
|
||||
DNG_REQUIRE ((count & (count - 1)) == 0,
|
||||
"count must be power of 2");
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_1d_table::~dng_1d_table ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_1d_table::SubDivide (const dng_1d_function &function,
|
||||
uint32 lower,
|
||||
uint32 upper,
|
||||
real32 maxDelta)
|
||||
{
|
||||
|
||||
uint32 range = upper - lower;
|
||||
|
||||
bool subDivide = (range > (fTableCount >> 8));
|
||||
|
||||
if (!subDivide)
|
||||
{
|
||||
|
||||
real32 delta = Abs_real32 (fTable [upper] -
|
||||
fTable [lower]);
|
||||
|
||||
if (delta > maxDelta)
|
||||
{
|
||||
|
||||
subDivide = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (subDivide)
|
||||
{
|
||||
|
||||
uint32 middle = (lower + upper) >> 1;
|
||||
|
||||
fTable [middle] = (real32) function.Evaluate (middle * (1.0 / (real64) fTableCount));
|
||||
|
||||
if (range > 2)
|
||||
{
|
||||
|
||||
SubDivide (function, lower, middle, maxDelta);
|
||||
|
||||
SubDivide (function, middle, upper, maxDelta);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
real64 y0 = fTable [lower];
|
||||
real64 y1 = fTable [upper];
|
||||
|
||||
real64 delta = (y1 - y0) / (real64) range;
|
||||
|
||||
for (uint32 j = lower + 1; j < upper; j++)
|
||||
{
|
||||
|
||||
y0 += delta;
|
||||
|
||||
fTable [j] = (real32) y0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_1d_table::Initialize (dng_memory_allocator &allocator,
|
||||
const dng_1d_function &function,
|
||||
bool subSample)
|
||||
{
|
||||
|
||||
fBuffer.Reset (allocator.Allocate ((fTableCount + 2) * sizeof (real32)));
|
||||
|
||||
fTable = fBuffer->Buffer_real32 ();
|
||||
|
||||
if (subSample)
|
||||
{
|
||||
|
||||
fTable [0 ] = (real32) function.Evaluate (0.0);
|
||||
fTable [fTableCount] = (real32) function.Evaluate (1.0);
|
||||
|
||||
real32 maxDelta = Max_real32 (Abs_real32 (fTable [fTableCount] -
|
||||
fTable [0 ]), 1.0f) *
|
||||
(1.0f / 256.0f);
|
||||
|
||||
SubDivide (function,
|
||||
0,
|
||||
fTableCount,
|
||||
maxDelta);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
for (uint32 j = 0; j <= fTableCount; j++)
|
||||
{
|
||||
|
||||
real64 x = j * (1.0 / (real64) fTableCount);
|
||||
|
||||
real64 y = function.Evaluate (x);
|
||||
|
||||
fTable [j] = (real32) y;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fTable [fTableCount + 1] = fTable [fTableCount];
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_1d_table::Expand16 (uint16 *table16) const
|
||||
{
|
||||
|
||||
real64 step = (real64) fTableCount / 65535.0;
|
||||
|
||||
real64 y0 = fTable [0];
|
||||
real64 y1 = fTable [1];
|
||||
|
||||
real64 base = y0 * 65535.0 + 0.5;
|
||||
real64 slope = (y1 - y0) * 65535.0;
|
||||
|
||||
uint32 index = 1;
|
||||
real64 fract = 0.0;
|
||||
|
||||
for (uint32 j = 0; j < 0x10000; j++)
|
||||
{
|
||||
|
||||
table16 [j] = (uint16) (base + slope * fract);
|
||||
|
||||
fract += step;
|
||||
|
||||
if (fract > 1.0)
|
||||
{
|
||||
|
||||
index += 1;
|
||||
fract -= 1.0;
|
||||
|
||||
y0 = y1;
|
||||
y1 = fTable [index];
|
||||
|
||||
base = y0 * 65535.0 + 0.5;
|
||||
slope = (y1 - y0) * 65535.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,126 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Definition of a lookup table based 1D floating-point to floating-point function abstraction using linear interpolation.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_1d_table__
|
||||
#define __dng_1d_table__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 1D floating-point lookup table using linear interpolation.
|
||||
|
||||
class dng_1d_table: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// Constant denoting minimum size of table.
|
||||
|
||||
static const uint32 kMinTableSize = 512;
|
||||
|
||||
private:
|
||||
|
||||
/// Constant denoting default size of table.
|
||||
|
||||
static const uint32 kDefaultTableSize = 4096;
|
||||
|
||||
protected:
|
||||
|
||||
AutoPtr<dng_memory_block> fBuffer;
|
||||
|
||||
real32 *fTable;
|
||||
|
||||
const uint32 fTableCount;
|
||||
|
||||
public:
|
||||
|
||||
/// Table constructor. count must be a power of two
|
||||
/// and at least kMinTableSize.
|
||||
|
||||
explicit dng_1d_table (uint32 count = kDefaultTableSize);
|
||||
|
||||
virtual ~dng_1d_table ();
|
||||
|
||||
/// Number of table entries.
|
||||
|
||||
uint32 Count () const
|
||||
{
|
||||
return fTableCount;
|
||||
}
|
||||
|
||||
/// Set up table, initialize entries using functiion.
|
||||
/// This method can throw an exception, e.g. if there is not enough memory.
|
||||
/// \param allocator Memory allocator from which table memory is allocated.
|
||||
/// \param function Table is initialized with values of finction.Evalluate(0.0) to function.Evaluate(1.0).
|
||||
/// \param subSample If true, only sample the function a limited number of times and interpolate.
|
||||
|
||||
void Initialize (dng_memory_allocator &allocator,
|
||||
const dng_1d_function &function,
|
||||
bool subSample = false);
|
||||
|
||||
/// Lookup and interpolate mapping for an input.
|
||||
/// \param x value from 0.0 to 1.0 used as input for mapping
|
||||
/// \retval Approximation of function.Evaluate(x)
|
||||
|
||||
real32 Interpolate (real32 x) const
|
||||
{
|
||||
|
||||
real32 y = x * (real32) fTableCount;
|
||||
|
||||
int32 index = (int32) y;
|
||||
|
||||
// Enable vectorization by using DNG_ASSERT instead of DNG_REQUIRE
|
||||
DNG_ASSERT(!(index < 0 || index >(int32) fTableCount), "dng_1d_table::Interpolate parameter out of range");
|
||||
|
||||
real32 z = (real32) index;
|
||||
|
||||
real32 fract = y - z;
|
||||
|
||||
return fTable [index ] * (1.0f - fract) +
|
||||
fTable [index + 1] * ( fract);
|
||||
|
||||
}
|
||||
|
||||
/// Direct access function for table data.
|
||||
|
||||
const real32 * Table () const
|
||||
{
|
||||
return fTable;
|
||||
}
|
||||
|
||||
/// Expand the table to a 16-bit to 16-bit table.
|
||||
|
||||
void Expand16 (uint16 *table16) const;
|
||||
|
||||
private:
|
||||
|
||||
void SubDivide (const dng_1d_function &function,
|
||||
uint32 lower,
|
||||
uint32 upper,
|
||||
real32 maxDelta);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,316 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_abort_sniffer.h"
|
||||
#include "dng_assertions.h"
|
||||
|
||||
#include "dng_mutex.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// TO DO: This priority-based wait mechanism is not compatible with thread
|
||||
// pools. Putting worker threads to sleep may result in deadlock because
|
||||
// higher priority work may not make progress (the pool may not be able to
|
||||
// spin up any new threads).
|
||||
|
||||
class dng_priority_manager
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
// Use lower-level mutex and condition_variable for priority manager
|
||||
// since we don't want to include these in our priority tracking.
|
||||
|
||||
dng_mutex fMutex;
|
||||
|
||||
dng_condition fCondition;
|
||||
|
||||
uint32 fCounter [dng_priority_count];
|
||||
|
||||
public:
|
||||
|
||||
dng_priority_manager ();
|
||||
|
||||
void Increment (dng_priority priority,
|
||||
const char *name);
|
||||
|
||||
void Decrement (dng_priority priority,
|
||||
const char *name);
|
||||
|
||||
void Wait (dng_abort_sniffer *sniffer);
|
||||
|
||||
private:
|
||||
|
||||
dng_priority MinPriority ()
|
||||
{
|
||||
|
||||
// Assumes mutex is locked.
|
||||
|
||||
for (uint32 level = dng_priority_maximum;
|
||||
level > dng_priority_minimum;
|
||||
level--)
|
||||
{
|
||||
|
||||
if (fCounter [level])
|
||||
{
|
||||
return (dng_priority) level;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return dng_priority_minimum;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_priority_manager::dng_priority_manager ()
|
||||
|
||||
: fMutex ("dng_priority_manager::fMutex")
|
||||
, fCondition ()
|
||||
|
||||
{
|
||||
|
||||
for (uint32 level = dng_priority_minimum;
|
||||
level <= dng_priority_maximum;
|
||||
level++)
|
||||
{
|
||||
|
||||
fCounter [level] = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_priority_manager::Increment (dng_priority priority,
|
||||
const char *name)
|
||||
{
|
||||
|
||||
dng_lock_mutex lock (&fMutex);
|
||||
|
||||
fCounter [priority] += 1;
|
||||
|
||||
#if 0
|
||||
|
||||
printf ("increment priority %d (%s) (%d, %d, %d)\n",
|
||||
(int) priority,
|
||||
name,
|
||||
fCounter [dng_priority_low],
|
||||
fCounter [dng_priority_medium],
|
||||
fCounter [dng_priority_high]);
|
||||
|
||||
#else
|
||||
|
||||
(void) name;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_priority_manager::Decrement (dng_priority priority,
|
||||
const char *name)
|
||||
{
|
||||
|
||||
dng_priority oldMin = dng_priority_minimum;
|
||||
dng_priority newMin = dng_priority_minimum;
|
||||
|
||||
{
|
||||
|
||||
dng_lock_mutex lock (&fMutex);
|
||||
|
||||
oldMin = MinPriority ();
|
||||
|
||||
fCounter [priority] -= 1;
|
||||
|
||||
newMin = MinPriority ();
|
||||
|
||||
#if 0
|
||||
|
||||
printf ("decrement priority %d (%s) (%d, %d, %d)\n",
|
||||
(int) priority,
|
||||
name,
|
||||
fCounter [dng_priority_low],
|
||||
fCounter [dng_priority_medium],
|
||||
fCounter [dng_priority_high]);
|
||||
|
||||
#else
|
||||
|
||||
(void) name;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (newMin < oldMin)
|
||||
{
|
||||
|
||||
fCondition.Broadcast ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_priority_manager::Wait (dng_abort_sniffer *sniffer)
|
||||
{
|
||||
|
||||
if (!sniffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const dng_priority priority = sniffer->Priority ();
|
||||
|
||||
if (priority < dng_priority_maximum)
|
||||
{
|
||||
|
||||
dng_lock_mutex lock (&fMutex);
|
||||
|
||||
while (priority < MinPriority ())
|
||||
{
|
||||
|
||||
fCondition.Wait (fMutex);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static dng_priority_manager gPriorityManager;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif // qDNGThreadSafe
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_set_minimum_priority::dng_set_minimum_priority (dng_priority priority,
|
||||
const char *name)
|
||||
|
||||
: fPriority (priority)
|
||||
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
gPriorityManager.Increment (fPriority, name);
|
||||
|
||||
#endif
|
||||
|
||||
fName.Set (name);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_set_minimum_priority::~dng_set_minimum_priority ()
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
gPriorityManager.Decrement (fPriority, fName.Get ());
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_abort_sniffer::dng_abort_sniffer ()
|
||||
|
||||
: fPriority (dng_priority_maximum)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_abort_sniffer::~dng_abort_sniffer ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_abort_sniffer::SetPriority (dng_priority priority)
|
||||
{
|
||||
|
||||
fPriority = priority;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_abort_sniffer::SupportsPriorityWait () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_abort_sniffer::SniffForAbort (dng_abort_sniffer *sniffer)
|
||||
{
|
||||
|
||||
if (sniffer)
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
if (sniffer->SupportsPriorityWait ())
|
||||
{
|
||||
|
||||
gPriorityManager.Wait (sniffer);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
sniffer->Sniff ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_abort_sniffer::StartTask (const char * /* name */,
|
||||
real64 /* fract */)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_abort_sniffer::EndTask ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_abort_sniffer::UpdateProgress (real64 /* fract */)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,241 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Classes supporting user cancellation and progress tracking.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_abort_sniffer__
|
||||
#define __dng_abort_sniffer__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_flags.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Thread priority level.
|
||||
|
||||
enum dng_priority
|
||||
{
|
||||
|
||||
dng_priority_low,
|
||||
dng_priority_medium,
|
||||
dng_priority_high,
|
||||
|
||||
dng_priority_count,
|
||||
|
||||
dng_priority_minimum = dng_priority_low,
|
||||
dng_priority_maximum = dng_priority_high
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience class for setting thread priority level to minimum.
|
||||
|
||||
class dng_set_minimum_priority
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_priority fPriority;
|
||||
|
||||
dng_string fName;
|
||||
|
||||
public:
|
||||
|
||||
dng_set_minimum_priority (dng_priority priority,
|
||||
const char *name);
|
||||
|
||||
~dng_set_minimum_priority ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \brief Class for signaling user cancellation and receiving progress updates.
|
||||
*
|
||||
* DNG SDK clients should derive a host application specific implementation
|
||||
* from this class.
|
||||
*/
|
||||
|
||||
class dng_abort_sniffer
|
||||
{
|
||||
|
||||
friend class dng_sniffer_task;
|
||||
|
||||
private:
|
||||
|
||||
dng_priority fPriority;
|
||||
|
||||
public:
|
||||
|
||||
dng_abort_sniffer ();
|
||||
|
||||
virtual ~dng_abort_sniffer ();
|
||||
|
||||
/// Getter for priority level.
|
||||
|
||||
dng_priority Priority () const
|
||||
{
|
||||
return fPriority;
|
||||
}
|
||||
|
||||
/// Setter for priority level.
|
||||
|
||||
void SetPriority (dng_priority priority);
|
||||
|
||||
/// Check for pending user cancellation or other abort. ThrowUserCanceled
|
||||
/// will be called if one is pending. This static method is provided as a
|
||||
/// convenience for quickly testing for an abort and throwing an exception
|
||||
/// if one is pending.
|
||||
/// \param sniffer The dng_sniffer to test for a pending abort. Can be NULL,
|
||||
/// in which case there an abort is never signalled.
|
||||
|
||||
static void SniffForAbort (dng_abort_sniffer *sniffer);
|
||||
|
||||
// A way to call Sniff while bypassing the priority wait.
|
||||
|
||||
void SniffNoPriorityWait ()
|
||||
{
|
||||
Sniff ();
|
||||
}
|
||||
|
||||
// Specifies whether or not the sniffer may be called by multiple threads
|
||||
// in parallel. Default result is false. Subclass must override to return
|
||||
// true.
|
||||
|
||||
virtual bool ThreadSafe () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Specifies whether or not this sniffer may participate in
|
||||
// priority-based waiting (sleep the current thread on which
|
||||
// SniffForAbort is called, if another thread has higher priority).
|
||||
// Default result is false. Subclass must override to return true.
|
||||
|
||||
virtual bool SupportsPriorityWait () const;
|
||||
|
||||
protected:
|
||||
|
||||
/// Should be implemented by derived classes to check for an user
|
||||
/// cancellation.
|
||||
|
||||
virtual void Sniff () = 0;
|
||||
|
||||
/// Signals the start of a named task withn processing in the DNG SDK.
|
||||
/// Tasks may be nested.
|
||||
/// \param name of the task
|
||||
/// \param fract Percentage of total processing this task is expected to
|
||||
/// take. From 0.0 to 1.0 .
|
||||
|
||||
virtual void StartTask (const char *name,
|
||||
real64 fract);
|
||||
|
||||
/// Signals the end of the innermost task that has been started.
|
||||
|
||||
virtual void EndTask ();
|
||||
|
||||
/// Signals progress made on current task.
|
||||
/// \param fract percentage of processing completed on current task.
|
||||
/// From 0.0 to 1.0 .
|
||||
|
||||
virtual void UpdateProgress (real64 fract);
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/// \brief Class to establish scope of a named subtask in DNG processing.
|
||||
///
|
||||
/// Instances of this class are intended to be stack allocated.
|
||||
|
||||
class dng_sniffer_task: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_abort_sniffer *fSniffer;
|
||||
|
||||
public:
|
||||
|
||||
/// Inform a sniffer of a subtask in DNG processing.
|
||||
/// \param sniffer The sniffer associated with the host on which this
|
||||
/// processing is occurring.
|
||||
/// \param name The name of this subtask as a NUL terminated string.
|
||||
/// \param fract Percentage of total processing this task is expected
|
||||
/// to take, from 0.0 to 1.0 .
|
||||
|
||||
dng_sniffer_task (dng_abort_sniffer *sniffer,
|
||||
const char *name = NULL,
|
||||
real64 fract = 0.0)
|
||||
|
||||
: fSniffer (sniffer)
|
||||
|
||||
{
|
||||
if (fSniffer)
|
||||
fSniffer->StartTask (name, fract);
|
||||
}
|
||||
|
||||
~dng_sniffer_task ()
|
||||
{
|
||||
if (fSniffer)
|
||||
fSniffer->EndTask ();
|
||||
}
|
||||
|
||||
/// Check for pending user cancellation or other abort. ThrowUserCanceled
|
||||
/// will be called if one is pending.
|
||||
|
||||
void Sniff ()
|
||||
{
|
||||
dng_abort_sniffer::SniffForAbort (fSniffer);
|
||||
}
|
||||
|
||||
/// Update progress on this subtask.
|
||||
/// \param fract Percentage of processing completed on current task,
|
||||
/// from 0.0 to 1.0 .
|
||||
|
||||
void UpdateProgress (real64 fract)
|
||||
{
|
||||
if (fSniffer)
|
||||
fSniffer->UpdateProgress (fract);
|
||||
}
|
||||
|
||||
/// Update progress on this subtask.
|
||||
/// \param done Amount of task completed in arbitrary integer units.
|
||||
/// \param total Total size of task in same arbitrary integer units as done.
|
||||
|
||||
void UpdateProgress (uint32 done,
|
||||
uint32 total)
|
||||
{
|
||||
UpdateProgress ((real64) done /
|
||||
(real64) total);
|
||||
}
|
||||
|
||||
/// Signal task completed for progress purposes.
|
||||
|
||||
void Finish ()
|
||||
{
|
||||
UpdateProgress (1.0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,324 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_area_task.h"
|
||||
|
||||
#include "dng_abort_sniffer.h"
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_flags.h"
|
||||
#include "dng_globals.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
#include "dng_tile_iterator.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_area_task::dng_area_task (const char *name)
|
||||
|
||||
: fMaxThreads (kMaxMPThreads)
|
||||
|
||||
, fMinTaskArea (256 * 256)
|
||||
|
||||
, fUnitCell (1, 1)
|
||||
|
||||
, fMaxTileSize (256, 256)
|
||||
|
||||
, fName ()
|
||||
|
||||
{
|
||||
|
||||
if (!name)
|
||||
{
|
||||
name = "dng_area_task";
|
||||
}
|
||||
|
||||
fName.Set (name);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_area_task::~dng_area_task ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_rect dng_area_task::RepeatingTile1 () const
|
||||
{
|
||||
|
||||
return dng_rect ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_rect dng_area_task::RepeatingTile2 () const
|
||||
{
|
||||
|
||||
return dng_rect ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_rect dng_area_task::RepeatingTile3 () const
|
||||
{
|
||||
|
||||
return dng_rect ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_area_task::Start (uint32 /* threadCount */,
|
||||
const dng_rect & /* dstArea */,
|
||||
const dng_point & /* tileSize */,
|
||||
dng_memory_allocator * /* allocator */,
|
||||
dng_abort_sniffer * /* sniffer */)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_area_task::Finish (uint32 /* threadCount */)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_point dng_area_task::FindTileSize (const dng_rect &area) const
|
||||
{
|
||||
|
||||
dng_rect repeatingTile1 = RepeatingTile1 ();
|
||||
dng_rect repeatingTile2 = RepeatingTile2 ();
|
||||
dng_rect repeatingTile3 = RepeatingTile3 ();
|
||||
|
||||
if (repeatingTile1.IsEmpty ())
|
||||
{
|
||||
repeatingTile1 = area;
|
||||
}
|
||||
|
||||
if (repeatingTile2.IsEmpty ())
|
||||
{
|
||||
repeatingTile2 = area;
|
||||
}
|
||||
|
||||
if (repeatingTile3.IsEmpty ())
|
||||
{
|
||||
repeatingTile3 = area;
|
||||
}
|
||||
|
||||
uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (),
|
||||
repeatingTile2.H ()),
|
||||
repeatingTile3.H ());
|
||||
|
||||
uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (),
|
||||
repeatingTile2.W ()),
|
||||
repeatingTile3.W ());
|
||||
|
||||
dng_point maxTileSize = MaxTileSize ();
|
||||
|
||||
dng_point tileSize;
|
||||
|
||||
tileSize.v = Min_int32 (repeatV, maxTileSize.v);
|
||||
tileSize.h = Min_int32 (repeatH, maxTileSize.h);
|
||||
|
||||
// Make Xcode happy (div by zero).
|
||||
|
||||
tileSize.v = Max_int32 (tileSize.v, 1);
|
||||
tileSize.h = Max_int32 (tileSize.h, 1);
|
||||
|
||||
// What this is doing is, if the smallest repeating image tile is larger than the
|
||||
// maximum tile size, adjusting the tile size down so that the tiles are as small
|
||||
// as possible while still having the same number of tiles covering the
|
||||
// repeat area. This makes the areas more equal in size, making MP
|
||||
// algorithms work better.
|
||||
|
||||
// The image core team did not understand this code, and disabled it.
|
||||
// Really stupid idea to turn off code you don't understand!
|
||||
// I'm undoing this removal, because I think the code is correct and useful.
|
||||
|
||||
uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v;
|
||||
uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h;
|
||||
|
||||
// Make Xcode happy (div by zero).
|
||||
|
||||
countV = Max_uint32 (countV, 1);
|
||||
countH = Max_uint32 (countH, 1);
|
||||
|
||||
tileSize.v = (repeatV + countV - 1) / countV;
|
||||
tileSize.h = (repeatH + countH - 1) / countH;
|
||||
|
||||
// Round up to unit cell size.
|
||||
|
||||
dng_point unitCell = UnitCell ();
|
||||
|
||||
if (unitCell.h != 1 || unitCell.v != 1)
|
||||
{
|
||||
tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v;
|
||||
tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h;
|
||||
}
|
||||
|
||||
// But if that is larger than maximum tile size, round down to unit cell size.
|
||||
|
||||
if (tileSize.v > maxTileSize.v)
|
||||
{
|
||||
tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v;
|
||||
}
|
||||
|
||||
if (tileSize.h > maxTileSize.h)
|
||||
{
|
||||
tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h;
|
||||
}
|
||||
|
||||
if (gPrintTimings)
|
||||
{
|
||||
fprintf (stdout,
|
||||
"\nRender tile for below: %d x %d\n",
|
||||
(int32) tileSize.h,
|
||||
(int32) tileSize.v);
|
||||
}
|
||||
|
||||
return tileSize;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_area_task::ProcessOnThread (uint32 threadIndex,
|
||||
const dng_rect &area,
|
||||
const dng_point &tileSize,
|
||||
dng_abort_sniffer *sniffer,
|
||||
dng_area_task_progress *progress)
|
||||
{
|
||||
|
||||
dng_rect repeatingTile1 = RepeatingTile1 ();
|
||||
dng_rect repeatingTile2 = RepeatingTile2 ();
|
||||
dng_rect repeatingTile3 = RepeatingTile3 ();
|
||||
|
||||
if (repeatingTile1.IsEmpty ())
|
||||
{
|
||||
repeatingTile1 = area;
|
||||
}
|
||||
|
||||
if (repeatingTile2.IsEmpty ())
|
||||
{
|
||||
repeatingTile2 = area;
|
||||
}
|
||||
|
||||
if (repeatingTile3.IsEmpty ())
|
||||
{
|
||||
repeatingTile3 = area;
|
||||
}
|
||||
|
||||
dng_rect tile1;
|
||||
|
||||
// TODO_EP: Review & document case where these dynamic allocations appeared to have significant overhead
|
||||
AutoPtr<dng_base_tile_iterator> iter1
|
||||
(MakeTileIterator (threadIndex,
|
||||
repeatingTile3,
|
||||
area));
|
||||
|
||||
while (iter1->GetOneTile (tile1))
|
||||
{
|
||||
|
||||
dng_rect tile2;
|
||||
|
||||
AutoPtr<dng_base_tile_iterator> iter2
|
||||
(MakeTileIterator (threadIndex,
|
||||
repeatingTile2,
|
||||
tile1));
|
||||
|
||||
while (iter2->GetOneTile (tile2))
|
||||
{
|
||||
|
||||
dng_rect tile3;
|
||||
|
||||
AutoPtr<dng_base_tile_iterator> iter3
|
||||
(MakeTileIterator (threadIndex,
|
||||
repeatingTile1,
|
||||
tile2));
|
||||
|
||||
while (iter3->GetOneTile (tile3))
|
||||
{
|
||||
|
||||
dng_rect tile4;
|
||||
|
||||
AutoPtr<dng_base_tile_iterator> iter4
|
||||
(MakeTileIterator (threadIndex,
|
||||
tileSize,
|
||||
tile3));
|
||||
|
||||
while (iter4->GetOneTile (tile4))
|
||||
{
|
||||
|
||||
dng_abort_sniffer::SniffForAbort (sniffer);
|
||||
|
||||
Process (threadIndex, tile4, sniffer);
|
||||
|
||||
if (progress)
|
||||
{
|
||||
progress->FinishedTile (tile4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_base_tile_iterator * dng_area_task::MakeTileIterator (uint32 /* threadIndex */,
|
||||
const dng_rect &tile,
|
||||
const dng_rect &area) const
|
||||
{
|
||||
|
||||
return new dng_tile_forward_iterator (tile, area);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_base_tile_iterator * dng_area_task::MakeTileIterator (uint32 /* threadIndex */,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &area) const
|
||||
{
|
||||
|
||||
return new dng_tile_forward_iterator (tileSize, area);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_area_task::Perform (dng_area_task &task,
|
||||
const dng_rect &area,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer *sniffer,
|
||||
dng_area_task_progress *progress)
|
||||
{
|
||||
|
||||
dng_point tileSize (task.FindTileSize (area));
|
||||
|
||||
task.Start (1, area, tileSize, allocator, sniffer);
|
||||
|
||||
task.ProcessOnThread (0, area, tileSize, sniffer, progress);
|
||||
|
||||
task.Finish (1);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,286 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Class to handle partitioning a rectangular image processing operation taking
|
||||
* into account multiple processing resources and memory constraints.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_area_task__
|
||||
#define __dng_area_task__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_point.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_area_task_progress: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_area_task_progress ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void FinishedTile (const dng_rect & /* tile */) = 0;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Abstract class for rectangular processing operations with support
|
||||
/// for partitioning across multiple processing resources and observing memory
|
||||
/// constraints.
|
||||
|
||||
class dng_area_task
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
uint32 fMaxThreads;
|
||||
|
||||
uint32 fMinTaskArea;
|
||||
|
||||
dng_point fUnitCell;
|
||||
|
||||
dng_point fMaxTileSize;
|
||||
|
||||
dng_string fName;
|
||||
|
||||
public:
|
||||
|
||||
explicit dng_area_task (const char *name = "unnamed dng_area_task");
|
||||
|
||||
virtual ~dng_area_task ();
|
||||
|
||||
const char * Name () const
|
||||
{
|
||||
return fName.Get ();
|
||||
}
|
||||
|
||||
/// Getter for the maximum number of threads (resources) that can be
|
||||
/// used for processing
|
||||
///
|
||||
/// \retval Number of threads, minimum of 1, that can be used for this task.
|
||||
|
||||
virtual uint32 MaxThreads () const
|
||||
{
|
||||
return fMaxThreads;
|
||||
}
|
||||
|
||||
/// Getter for minimum area of a partitioned rectangle.
|
||||
/// Often it is not profitable to use more resources if it requires
|
||||
/// partitioning the input into chunks that are too small, as the
|
||||
/// overhead increases more than the speedup. This method can be
|
||||
/// ovreridden for a specific task to indicate the smallest area for
|
||||
/// partitioning. Default is 256x256 pixels.
|
||||
///
|
||||
/// \retval Minimum area for a partitoned tile in order to give performant
|
||||
/// operation. (Partitions can be smaller due to small inputs and edge cases.)
|
||||
|
||||
virtual uint32 MinTaskArea () const
|
||||
{
|
||||
return fMinTaskArea;
|
||||
}
|
||||
|
||||
/// Getter for dimensions of which partitioned tiles should be a multiple.
|
||||
/// Various methods of processing prefer certain alignments. The
|
||||
/// partitioning attempts to construct tiles such that the sizes are a
|
||||
/// multiple of the dimensions of this point.
|
||||
///
|
||||
/// \retval a point giving preferred alignment in x and y
|
||||
|
||||
virtual dng_point UnitCell () const
|
||||
{
|
||||
return fUnitCell;
|
||||
}
|
||||
|
||||
/// Getter for maximum size of a tile for processing.
|
||||
/// Often processing will need to allocate temporary buffers or use
|
||||
/// other resources that are either fixed or in limited supply. The
|
||||
/// maximum tile size forces further partitioning if the tile is bigger
|
||||
/// than this size.
|
||||
///
|
||||
/// \retval Maximum tile size allowed for this area task.
|
||||
|
||||
virtual dng_point MaxTileSize () const
|
||||
{
|
||||
return fMaxTileSize;
|
||||
}
|
||||
|
||||
/// Getter for RepeatingTile1.
|
||||
/// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to
|
||||
/// establish a set of 0 to 3 tile patterns for which the resulting
|
||||
/// partitions that the final Process method is called on will not cross
|
||||
/// tile boundaries in any of the tile patterns. This can be used for a
|
||||
/// processing routine that needs to read from two tiles and write to a
|
||||
/// third such that all the tiles are aligned and sized in a certain
|
||||
/// way. A RepeatingTile value is valid if it is non-empty. Higher
|
||||
/// numbered RepeatingTile patterns are only used if all lower ones are
|
||||
/// non-empty. A RepeatingTile pattern must be a multiple of UnitCell in
|
||||
/// size for all constraints of the partitionerr to be met.
|
||||
|
||||
virtual dng_rect RepeatingTile1 () const;
|
||||
|
||||
/// Getter for RepeatingTile2.
|
||||
/// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to
|
||||
/// establish a set of 0 to 3 tile patterns for which the resulting
|
||||
/// partitions that the final Process method is called on will not cross
|
||||
/// tile boundaries in any of the tile patterns. This can be used for a
|
||||
/// processing routine that needs to read from two tiles and write to a
|
||||
/// third such that all the tiles are aligned and sized in a certain
|
||||
/// way. A RepeatingTile value is valid if it is non-empty. Higher
|
||||
/// numbered RepeatingTile patterns are only used if all lower ones are
|
||||
/// non-empty. A RepeatingTile pattern must be a multiple of UnitCell in
|
||||
/// size for all constraints of the partitionerr to be met.
|
||||
|
||||
virtual dng_rect RepeatingTile2 () const;
|
||||
|
||||
/// Getter for RepeatingTile3.
|
||||
/// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to
|
||||
/// establish a set of 0 to 3 tile patterns for which the resulting
|
||||
/// partitions that the final Process method is called on will not cross
|
||||
/// tile boundaries in any of the tile patterns. This can be used for a
|
||||
/// processing routine that needs to read from two tiles and write to a
|
||||
/// third such that all the tiles are aligned and sized in a certain
|
||||
/// way. A RepeatingTile value is valid if it is non-empty. Higher
|
||||
/// numbered RepeatingTile patterns are only used if all lower ones are
|
||||
/// non-empty. A RepeatingTile pattern must be a multiple of UnitCell in
|
||||
/// size for all constraints of the partitionerr to be met.
|
||||
|
||||
virtual dng_rect RepeatingTile3 () const;
|
||||
|
||||
/// Task startup method called before any processing is done on partitions.
|
||||
/// The Start method is called before any processing is done and can be
|
||||
/// overridden to allocate temporary buffers, etc.
|
||||
///
|
||||
/// \param threadCount Total number of threads that will be used for processing.
|
||||
/// Less than or equal to MaxThreads.
|
||||
/// \param dstArea Area to be processed in the current run of the task.
|
||||
/// \param tileSize Size of source tiles which will be processed.
|
||||
/// (Not all tiles will be this size due to edge conditions.)
|
||||
/// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc.
|
||||
/// \param sniffer Sniffer to test for user cancellation and to set up progress.
|
||||
|
||||
virtual void Start (uint32 threadCount,
|
||||
const dng_rect &dstArea,
|
||||
const dng_point &tileSize,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer *sniffer);
|
||||
|
||||
/// Process one tile or fully partitioned area. This method is
|
||||
/// overridden by derived classes to implement the actual image
|
||||
/// processing. Note that the sniffer can be ignored if it is certain
|
||||
/// that a processing task will complete very quickly. This method
|
||||
/// should never be called directly but rather accessed via Process.
|
||||
/// There is no allocator parameter as all allocation should be done in
|
||||
/// Start.
|
||||
///
|
||||
/// \param threadIndex 0 to threadCount - 1 index indicating which thread this is.
|
||||
/// (Can be used to get a thread-specific buffer allocated in the Start method.)
|
||||
/// \param tile Area to process.
|
||||
/// \param sniffer dng_abort_sniffer to use to check for user cancellation
|
||||
/// and progress updates.
|
||||
|
||||
virtual void Process (uint32 threadIndex,
|
||||
const dng_rect &tile,
|
||||
dng_abort_sniffer *sniffer) = 0;
|
||||
|
||||
/// Task computation finalization and teardown method. Called after all
|
||||
/// resources have completed processing. Can be overridden to accumulate
|
||||
/// results and free resources allocated in Start.
|
||||
///
|
||||
/// \param threadCount Number of threads used for processing. Same as value passed to Start.
|
||||
|
||||
virtual void Finish (uint32 threadCount);
|
||||
|
||||
/// Find tile size taking into account repeating tiles, unit cell, and maximum tile size.
|
||||
/// \param area Computation area for which to find tile size.
|
||||
/// \retval Tile size as height and width in point.
|
||||
|
||||
dng_point FindTileSize (const dng_rect &area) const;
|
||||
|
||||
/// Handle one resource's worth of partitioned tiles. Called after
|
||||
/// thread partitioning has already been done. Area may be further
|
||||
/// subdivided to handle maximum tile size, etc. It will be rare to
|
||||
/// override this method.
|
||||
///
|
||||
/// \param threadIndex 0 to threadCount - 1 index indicating which thread this is.
|
||||
/// \param area Tile area partitioned to this resource.
|
||||
/// \param tileSize size of tiles to use for processing.
|
||||
/// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
|
||||
/// \param progress optional pointer to progress reporting object.
|
||||
|
||||
void ProcessOnThread (uint32 threadIndex,
|
||||
const dng_rect &area,
|
||||
const dng_point &tileSize,
|
||||
dng_abort_sniffer *sniffer,
|
||||
dng_area_task_progress *progress);
|
||||
|
||||
/// Factory method to make a tile iterator. This iterator will be used
|
||||
/// by a thread to process tiles in an area in a specific order. The
|
||||
/// default implementation uses a forward iterator that visits tiles
|
||||
/// from left to right (inner), top down (outer). Subclasses can
|
||||
/// override this method to produce tile iterators that visit tiles in
|
||||
/// different orders.
|
||||
///
|
||||
/// \param threadIndex 0 to threadCount - 1 index indicating which thread this is.
|
||||
/// \param tile The tile to be traversed within the tile area.
|
||||
/// \param area Tile area partitioned to this resource.
|
||||
|
||||
virtual dng_base_tile_iterator * MakeTileIterator (uint32 threadIndex,
|
||||
const dng_rect &tile,
|
||||
const dng_rect &area) const;
|
||||
|
||||
/// Factory method to make a tile iterator. This iterator will be used
|
||||
/// by a thread to process tiles in an area in a specific order. The
|
||||
/// default implementation uses a forward iterator that visits tiles
|
||||
/// from left to right (inner), top down (outer). Subclasses can
|
||||
/// override this method to produce tile iterators that visit tiles in
|
||||
/// different orders.
|
||||
///
|
||||
/// \param threadIndex 0 to threadCount - 1 index indicating which thread this is.
|
||||
/// \param tileSize The tile size to be traversed within the tile area.
|
||||
/// \param area Tile area partitioned to this resource.
|
||||
|
||||
virtual dng_base_tile_iterator * MakeTileIterator (uint32 threadIndex,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &area) const;
|
||||
|
||||
/// Default resource partitioner that assumes a single resource to be
|
||||
/// used for processing. Implementations that are aware of multiple
|
||||
/// processing resources should override (replace) this method. This is
|
||||
/// usually done in dng_host::PerformAreaTask.
|
||||
///
|
||||
/// \param task The task to perform.
|
||||
/// \param area The area on which mage processing should be performed.
|
||||
/// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc.
|
||||
/// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
|
||||
/// \param progress optional pointer to progress reporting object.
|
||||
|
||||
static void Perform (dng_area_task &task,
|
||||
const dng_rect &area,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer *sniffer,
|
||||
dng_area_task_progress *progress);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,128 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Conditionally compiled assertion check support.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_assertions__
|
||||
#define __dng_assertions__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_flags.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGDebug
|
||||
|
||||
/// Platform-specific function to display an assert.
|
||||
|
||||
void dng_show_message (const char *s);
|
||||
|
||||
/// Show a formatted error message.
|
||||
|
||||
void dng_show_message_f (const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_ASSERT
|
||||
|
||||
#if qDNGDebug
|
||||
|
||||
/// Conditionally compiled macro to check an assertion and display a message if
|
||||
/// it fails and assertions are compiled in via qDNGDebug
|
||||
/// \param x Predicate which must be true.
|
||||
/// \param y String to display if x is not true.
|
||||
|
||||
#define DNG_ASSERT(x,y) { if (!(x)) dng_show_message (y); }
|
||||
|
||||
#else
|
||||
|
||||
/// Conditionally compiled macro to check an assertion and display a message if
|
||||
/// it fails and assertions are compiled in via qDNGDebug
|
||||
/// \param x Predicate which must be true.
|
||||
/// \param y String to display if x is not true.
|
||||
|
||||
#define DNG_ASSERT(x,y)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_REQUIRE
|
||||
|
||||
#if qDNGDebug
|
||||
|
||||
/// Conditionally compiled macro to check an assertion, display a message, and throw
|
||||
/// an exception if it fails and assertions are compiled in via qDNGDebug
|
||||
/// \param condition Predicate which must be true.
|
||||
/// \param msg String to display if condition is not true.
|
||||
|
||||
#define DNG_REQUIRE(condition,msg) \
|
||||
do \
|
||||
{ \
|
||||
\
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
\
|
||||
DNG_ASSERT(condition, msg); \
|
||||
\
|
||||
ThrowProgramError (msg); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#else
|
||||
|
||||
/// Conditionally compiled macro to check an assertion, display a message, and throw
|
||||
/// an exception if it fails and assertions are compiled in via qDNGDebug
|
||||
/// \param condition Predicate which must be true.
|
||||
/// \param msg String to display if condition is not true.
|
||||
|
||||
#define DNG_REQUIRE(condition,msg) \
|
||||
do \
|
||||
{ \
|
||||
\
|
||||
if (!(condition)) \
|
||||
{ \
|
||||
\
|
||||
ThrowProgramError (msg); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_REPORT
|
||||
|
||||
/// Macro to display an informational message
|
||||
/// \param x String to display.
|
||||
|
||||
#define DNG_REPORT(x) DNG_ASSERT (false, x)
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,239 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Class to implement std::auto_ptr like functionality even on platforms which do not
|
||||
* have a full Standard C++ library.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_auto_ptr__
|
||||
#define __dng_auto_ptr__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// The following template has similar functionality to the STL auto_ptr, without
|
||||
// requiring all the weight of STL.
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A class intended to be used in stack scope to hold a pointer from new. The
|
||||
/// held pointer will be deleted automatically if the scope is left without calling
|
||||
/// Release on the AutoPtr first.
|
||||
|
||||
template<class T>
|
||||
class AutoPtr: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
T *p_;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an AutoPtr with no referent.
|
||||
|
||||
AutoPtr () : p_ (0) { }
|
||||
|
||||
/// Construct an AutoPtr which owns the argument pointer.
|
||||
/// \param p pointer which constructed AutoPtr takes ownership of. p will be
|
||||
/// deleted on destruction or Reset unless Release is called first.
|
||||
|
||||
explicit AutoPtr (T *p) : p_( p ) { }
|
||||
|
||||
/// Reset is called on destruction.
|
||||
|
||||
~AutoPtr ();
|
||||
|
||||
/// Call Reset with a pointer from new. Uses T's default constructor.
|
||||
|
||||
void Alloc ();
|
||||
|
||||
/// Return the owned pointer of this AutoPtr, NULL if none. No change in
|
||||
/// ownership or other effects occur.
|
||||
|
||||
T *Get () const { return p_; }
|
||||
|
||||
/// Return the owned pointer of this AutoPtr, NULL if none. The AutoPtr gives
|
||||
/// up ownership and takes NULL as its value.
|
||||
|
||||
T *Release ();
|
||||
|
||||
/// If a pointer is owned, it is deleted. Ownership is taken of passed in
|
||||
/// pointer.
|
||||
/// \param p pointer which constructed AutoPtr takes ownership of. p will be
|
||||
/// deleted on destruction or Reset unless Release is called first.
|
||||
|
||||
void Reset (T *p);
|
||||
|
||||
/// If a pointer is owned, it is deleted and the AutoPtr takes NULL as its
|
||||
/// value.
|
||||
|
||||
void Reset ();
|
||||
|
||||
/// Allows members of the owned pointer to be accessed directly. It is an
|
||||
/// error to call this if the AutoPtr has NULL as its value.
|
||||
|
||||
T *operator-> () const { return p_; }
|
||||
|
||||
/// Returns a reference to the object that the owned pointer points to. It is
|
||||
/// an error to call this if the AutoPtr has NULL as its value.
|
||||
|
||||
T &operator* () const { return *p_; }
|
||||
|
||||
/// Swap with another auto ptr.
|
||||
|
||||
friend inline void Swap (AutoPtr< T > &x, AutoPtr< T > &y)
|
||||
{
|
||||
T* temp = x.p_;
|
||||
x.p_ = y.p_;
|
||||
y.p_ = temp;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
template<class T>
|
||||
AutoPtr<T>::~AutoPtr ()
|
||||
{
|
||||
|
||||
delete p_;
|
||||
p_ = 0;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
template<class T>
|
||||
T *AutoPtr<T>::Release ()
|
||||
{
|
||||
T *result = p_;
|
||||
p_ = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
template<class T>
|
||||
void AutoPtr<T>::Reset (T *p)
|
||||
{
|
||||
|
||||
if (p_ != p)
|
||||
{
|
||||
if (p_ != 0)
|
||||
delete p_;
|
||||
p_ = p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
template<class T>
|
||||
void AutoPtr<T>::Reset ()
|
||||
{
|
||||
|
||||
if (p_ != 0)
|
||||
{
|
||||
delete p_;
|
||||
p_ = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
template<class T>
|
||||
void AutoPtr<T>::Alloc ()
|
||||
{
|
||||
this->Reset (new T);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A class intended to be used similarly to AutoPtr but for arrays.
|
||||
|
||||
template<typename T>
|
||||
class AutoArray: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an AutoArray which owns the argument pointer.
|
||||
/// \param p_ array pointer which constructed AutoArray takes ownership of. p_
|
||||
/// will be deleted on destruction or Reset unless Release is called first.
|
||||
|
||||
explicit AutoArray (T *p_ = 0) : p (p_) { }
|
||||
|
||||
/// Reset is called on destruction.
|
||||
|
||||
~AutoArray ()
|
||||
{
|
||||
delete [] p;
|
||||
p = 0;
|
||||
}
|
||||
|
||||
/// Return the owned array pointer of this AutoArray, NULL if none. The
|
||||
/// AutoArray gives up ownership and takes NULL as its value.
|
||||
|
||||
T *Release ()
|
||||
{
|
||||
T *p_ = p;
|
||||
p = 0;
|
||||
return p_;
|
||||
}
|
||||
|
||||
/// If an array pointer is owned, it is deleted. Ownership is
|
||||
/// taken of the passed in pointer p_.
|
||||
/// \param p_ array pointer which constructed AutoArray takes ownership of. p_
|
||||
/// will be deleted on destruction or Reset unless Release is called first.
|
||||
|
||||
void Reset (T *p_ = 0)
|
||||
{
|
||||
if (p != p_)
|
||||
{
|
||||
delete [] p;
|
||||
p = p_;
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows indexing into the AutoArray. It is an error to call this if the
|
||||
/// AutoArray has NULL as its value.
|
||||
|
||||
T &operator[] (ptrdiff_t i) const
|
||||
{
|
||||
return p [i];
|
||||
}
|
||||
|
||||
/// Return the owned pointer of this AutoArray, NULL if none. No change in
|
||||
/// ownership or other effects occur.
|
||||
|
||||
T *Get () const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Owned pointer or NULL.
|
||||
|
||||
T *p;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,303 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Opcodes to fix defective pixels, including individual pixels and regions (such as
|
||||
* defective rows and columns).
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_bad_pixels__
|
||||
#define __dng_bad_pixels__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_memory.h"
|
||||
#include "dng_opcodes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to fix individual bad pixels that are marked with a constant
|
||||
/// value (e.g., 0) in a Bayer image.
|
||||
|
||||
class dng_opcode_FixBadPixelsConstant: public dng_filter_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
uint32 fConstant;
|
||||
|
||||
uint32 fBayerPhase;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an opcode to fix an individual bad pixels that are marked with
|
||||
/// a constant value in a Bayer image.
|
||||
/// \param constant The constant value that indicates a bad pixel.
|
||||
/// \param bayerPhase The phase of the Bayer mosaic pattern (0, 1, 2, 3).
|
||||
|
||||
dng_opcode_FixBadPixelsConstant (uint32 constant,
|
||||
uint32 bayerPhase);
|
||||
|
||||
dng_opcode_FixBadPixelsConstant (dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual dng_point SrcRepeat ();
|
||||
|
||||
virtual dng_rect SrcArea (const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
virtual void Prepare (dng_negative &negative,
|
||||
uint32 threadCount,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes,
|
||||
uint32 bufferPixelType,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &srcBuffer,
|
||||
dng_pixel_buffer &dstBuffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
protected:
|
||||
|
||||
bool IsGreen (int32 row, int32 col) const
|
||||
{
|
||||
return (((uint32) row + (uint32) col + fBayerPhase + (fBayerPhase >> 1)) & 1) == 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A list of bad pixels and rectangles (usually single rows or columns).
|
||||
|
||||
class dng_bad_pixel_list
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kNoIndex = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// List of bad single pixels.
|
||||
|
||||
dng_std_vector<dng_point> fBadPoints;
|
||||
|
||||
// List of bad rectangles (usually single rows or columns).
|
||||
|
||||
dng_std_vector<dng_rect> fBadRects;
|
||||
|
||||
public:
|
||||
|
||||
/// Create an empty bad pixel list.
|
||||
|
||||
dng_bad_pixel_list ();
|
||||
|
||||
/// Returns the number of bad single pixels.
|
||||
|
||||
uint32 PointCount () const
|
||||
{
|
||||
return (uint32) fBadPoints.size ();
|
||||
}
|
||||
|
||||
/// Retrieves the bad single pixel coordinate via the specified list index.
|
||||
///
|
||||
/// \param index The list index from which to retrieve the bad single pixel
|
||||
/// coordinate.
|
||||
|
||||
const dng_point & Point (uint32 index) const
|
||||
{
|
||||
return fBadPoints [index];
|
||||
}
|
||||
|
||||
/// Returns the number of bad rectangles.
|
||||
|
||||
uint32 RectCount () const
|
||||
{
|
||||
return (uint32) fBadRects.size ();
|
||||
}
|
||||
|
||||
/// Retrieves the bad rectangle via the specified list index.
|
||||
///
|
||||
/// \param index The list index from which to retrieve the bad rectangle
|
||||
/// coordinates.
|
||||
|
||||
const dng_rect & Rect (uint32 index) const
|
||||
{
|
||||
return fBadRects [index];
|
||||
}
|
||||
|
||||
/// Returns true iff there are zero bad single pixels and zero bad
|
||||
/// rectangles.
|
||||
|
||||
bool IsEmpty () const
|
||||
{
|
||||
return PointCount () == 0 &&
|
||||
RectCount () == 0;
|
||||
}
|
||||
|
||||
/// Returns true iff there is at least one bad single pixel or at least one
|
||||
/// bad rectangle.
|
||||
|
||||
bool NotEmpty () const
|
||||
{
|
||||
return !IsEmpty ();
|
||||
}
|
||||
|
||||
/// Add the specified coordinate to the list of bad single pixels.
|
||||
///
|
||||
/// \param pt The bad single pixel to add.
|
||||
|
||||
void AddPoint (const dng_point &pt);
|
||||
|
||||
/// Add the specified rectangle to the list of bad rectangles.
|
||||
///
|
||||
/// \param r The bad rectangle to add.
|
||||
|
||||
void AddRect (const dng_rect &r);
|
||||
|
||||
/// Sort the bad single pixels and bad rectangles by coordinates (top to
|
||||
/// bottom, then left to right).
|
||||
|
||||
void Sort ();
|
||||
|
||||
/// Returns true iff the specified bad single pixel is isolated, i.e., there
|
||||
/// is no other bad single pixel or bad rectangle that lies within radius
|
||||
/// pixels of this bad single pixel.
|
||||
///
|
||||
/// \param index The index of the bad single pixel to test.
|
||||
/// \param radius The pixel radius to test for isolation.
|
||||
|
||||
bool IsPointIsolated (uint32 index,
|
||||
uint32 radius) const;
|
||||
|
||||
/// Returns true iff the specified bad rectangle is isolated, i.e., there
|
||||
/// is no other bad single pixel or bad rectangle that lies within radius
|
||||
/// pixels of this bad rectangle.
|
||||
///
|
||||
/// \param index The index of the bad rectangle to test.
|
||||
/// \param radius The pixel radius to test for isolation.
|
||||
|
||||
bool IsRectIsolated (uint32 index,
|
||||
uint32 radius) const;
|
||||
|
||||
/// Returns true iff the specified point is valid, i.e., lies within the
|
||||
/// specified image bounds, is different from all other bad single pixels,
|
||||
/// and is not contained in any bad rectangle. The second and third
|
||||
/// conditions are only checked if provided with a starting search index.
|
||||
///
|
||||
/// \param pt The point to test for validity.
|
||||
/// \param imageBounds The pt must lie within imageBounds to be valid.
|
||||
/// \index The search index to use (or kNoIndex, to avoid a search) for
|
||||
/// checking for validity.
|
||||
|
||||
bool IsPointValid (const dng_point &pt,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 index = kNoIndex) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to fix lists of bad pixels (indicated by position) in a Bayer
|
||||
/// image.
|
||||
|
||||
class dng_opcode_FixBadPixelsList: public dng_filter_opcode
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kBadPointPadding = 2,
|
||||
kBadRectPadding = 4
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
AutoPtr<dng_bad_pixel_list> fList;
|
||||
|
||||
uint32 fBayerPhase;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an opcode to fix lists of bad pixels (indicated by position) in
|
||||
/// a Bayer image.
|
||||
/// \param list The list of bad pixels to fix.
|
||||
/// \param bayerPhase The phase of the Bayer mosaic pattern (0, 1, 2, 3).
|
||||
|
||||
dng_opcode_FixBadPixelsList (AutoPtr<dng_bad_pixel_list> &list,
|
||||
uint32 bayerPhase);
|
||||
|
||||
dng_opcode_FixBadPixelsList (dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual dng_point SrcRepeat ();
|
||||
|
||||
virtual dng_rect SrcArea (const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
virtual void Prepare (dng_negative &negative,
|
||||
uint32 threadCount,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes,
|
||||
uint32 bufferPixelType,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &srcBuffer,
|
||||
dng_pixel_buffer &dstBuffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
protected:
|
||||
|
||||
bool IsGreen (int32 row, int32 col) const
|
||||
{
|
||||
return ((row + col + fBayerPhase + (fBayerPhase >> 1)) & 1) == 0;
|
||||
}
|
||||
|
||||
virtual void FixIsolatedPixel (dng_pixel_buffer &buffer,
|
||||
dng_point &badPoint);
|
||||
|
||||
virtual void FixClusteredPixel (dng_pixel_buffer &buffer,
|
||||
uint32 pointIndex,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
virtual void FixSingleColumn (dng_pixel_buffer &buffer,
|
||||
const dng_rect &badRect);
|
||||
|
||||
virtual void FixSingleRow (dng_pixel_buffer &buffer,
|
||||
const dng_rect &badRect);
|
||||
|
||||
virtual void FixClusteredRect (dng_pixel_buffer &buffer,
|
||||
const dng_rect &badRect,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,670 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2015-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_big_table__
|
||||
#define __dng_big_table__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_camera_profile.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_big_table_cache;
|
||||
class dng_big_table_storage;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_big_table_cache_flush ();
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_big_table
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
enum BigTableTypeEnum
|
||||
{
|
||||
btt_LookTable = 0,
|
||||
btt_RGBTable = 1
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
dng_fingerprint fFingerprint;
|
||||
|
||||
dng_big_table_cache * fCache;
|
||||
|
||||
bool fIsMissing;
|
||||
|
||||
protected:
|
||||
|
||||
dng_big_table (dng_big_table_cache *cache);
|
||||
|
||||
dng_big_table (const dng_big_table &table);
|
||||
|
||||
dng_big_table & operator= (const dng_big_table &table);
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_big_table ();
|
||||
|
||||
bool IsMissing () const
|
||||
{
|
||||
return fIsMissing;
|
||||
}
|
||||
|
||||
void SetMissing ()
|
||||
{
|
||||
fIsMissing = true;
|
||||
}
|
||||
|
||||
virtual bool IsValid () const = 0;
|
||||
|
||||
const dng_fingerprint & Fingerprint () const;
|
||||
|
||||
bool DecodeFromBinary (const uint8 * compressedData,
|
||||
uint32 compressedSize,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
bool DecodeFromString (const dng_string &block1,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
dng_memory_block * EncodeAsBinary (dng_memory_allocator &allocator,
|
||||
uint32 &compressedSize) const;
|
||||
|
||||
dng_memory_block * EncodeAsString (dng_memory_allocator &allocator) const;
|
||||
|
||||
bool ExtractFromCache (const dng_fingerprint &fingerprint);
|
||||
|
||||
bool ReadTableFromXMP (const dng_xmp &xmp,
|
||||
const char *ns,
|
||||
const dng_fingerprint &fingerprint);
|
||||
|
||||
bool ReadFromXMP (const dng_xmp &xmp,
|
||||
const char *ns,
|
||||
const char *path,
|
||||
dng_big_table_storage &storage);
|
||||
|
||||
void WriteToXMP (dng_xmp &xmp,
|
||||
const char *ns,
|
||||
const char *path,
|
||||
dng_big_table_storage &storage) const;
|
||||
|
||||
protected:
|
||||
|
||||
void RecomputeFingerprint ();
|
||||
|
||||
virtual void GetStream (dng_stream &stream) = 0;
|
||||
|
||||
virtual void PutStream (dng_stream &stream,
|
||||
bool forFingerprint) const = 0;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_big_table_storage
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_big_table_storage ();
|
||||
|
||||
virtual ~dng_big_table_storage ();
|
||||
|
||||
virtual bool ReadTable (dng_big_table &table,
|
||||
const dng_fingerprint &fingerprint,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
virtual bool WriteTable (const dng_big_table &table,
|
||||
const dng_fingerprint &fingerprint,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
virtual void MissingTable (const dng_fingerprint &fingerprint);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_look_table : public dng_big_table
|
||||
{
|
||||
|
||||
friend class dng_look_table_cache;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
// Tables are are allowed to trade off resolution
|
||||
// between dimensions, but need to keep total
|
||||
// samples below this limit. This results in
|
||||
// 216K memory footprint (12 byte per sample)
|
||||
// which is similar in size to the RGB table
|
||||
// size limit.
|
||||
|
||||
kMaxTotalSamples = 36 * 32 * 16,
|
||||
|
||||
// Also each must be within their own limits.
|
||||
|
||||
kMaxHueSamples = 360,
|
||||
kMaxSatSamples = 256,
|
||||
kMaxValSamples = 256
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
kLookTableVersion1 = 1,
|
||||
kLookTableVersion2 = 2
|
||||
};
|
||||
|
||||
// Table data affecting fingerprint and caching.
|
||||
|
||||
struct table_data
|
||||
{
|
||||
|
||||
// 3-D hue/sat table to apply a "look".
|
||||
|
||||
dng_hue_sat_map fMap;
|
||||
|
||||
// Value (V of HSV) encoding for look table.
|
||||
|
||||
uint32 fEncoding;
|
||||
|
||||
// Minimum and maximum scale amounts supported by table.
|
||||
|
||||
real64 fMinAmount;
|
||||
real64 fMaxAmount;
|
||||
|
||||
// Does this table have only monochrome output (when amount is 1.0)?
|
||||
|
||||
bool fMonochrome;
|
||||
|
||||
// Constructor to set defaults.
|
||||
|
||||
table_data ()
|
||||
|
||||
: fMap ()
|
||||
, fEncoding (encoding_Linear)
|
||||
, fMinAmount (1.0)
|
||||
, fMaxAmount (1.0)
|
||||
, fMonochrome (false)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
// Compute monchrome flag.
|
||||
|
||||
void ComputeMonochrome ()
|
||||
{
|
||||
|
||||
fMonochrome = true;
|
||||
|
||||
uint32 count = fMap.DeltasCount ();
|
||||
|
||||
dng_hue_sat_map::HSBModify * deltas = fMap.GetDeltas ();
|
||||
|
||||
for (uint32 index = 0; index < count; index++)
|
||||
{
|
||||
|
||||
if (deltas [index] . fSatScale != 0.0f)
|
||||
{
|
||||
|
||||
fMonochrome = false;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
table_data fData;
|
||||
|
||||
// Amount to apply at runtime (does not affect fingerprint).
|
||||
|
||||
real64 fAmount;
|
||||
|
||||
public:
|
||||
|
||||
dng_look_table ();
|
||||
|
||||
dng_look_table (const dng_look_table &table);
|
||||
|
||||
dng_look_table & operator= (const dng_look_table &table);
|
||||
|
||||
virtual ~dng_look_table ();
|
||||
|
||||
bool operator== (const dng_look_table &table) const
|
||||
{
|
||||
return Fingerprint () == table.Fingerprint () &&
|
||||
Amount () == table.Amount () &&
|
||||
IsMissing () == table.IsMissing ();
|
||||
}
|
||||
|
||||
bool operator!= (const dng_look_table &table) const
|
||||
{
|
||||
return !(*this == table);
|
||||
}
|
||||
|
||||
void Set (const dng_hue_sat_map &map,
|
||||
uint32 encoding);
|
||||
|
||||
virtual bool IsValid () const;
|
||||
|
||||
void SetInvalid ();
|
||||
|
||||
real64 MinAmount () const
|
||||
{
|
||||
return fData.fMinAmount;
|
||||
}
|
||||
|
||||
real64 MaxAmount () const
|
||||
{
|
||||
return fData.fMaxAmount;
|
||||
}
|
||||
|
||||
void SetAmountRange (real64 minAmount,
|
||||
real64 maxAmount)
|
||||
{
|
||||
|
||||
fData.fMinAmount = Pin_real64 (0.0,
|
||||
Round_int32 (minAmount * 100.0) * 0.01,
|
||||
1.0);
|
||||
|
||||
fData.fMaxAmount = Pin_real64 (1.0,
|
||||
Round_int32 (maxAmount * 100.0) * 0.01,
|
||||
2.0);
|
||||
|
||||
fAmount = Pin_real64 (fData.fMinAmount, fAmount, fData.fMaxAmount);
|
||||
|
||||
RecomputeFingerprint ();
|
||||
|
||||
}
|
||||
|
||||
real64 Amount () const
|
||||
{
|
||||
return fAmount;
|
||||
}
|
||||
|
||||
void SetAmount (real64 amount)
|
||||
{
|
||||
|
||||
fAmount = Pin_real64 (fData.fMinAmount,
|
||||
Round_int32 (amount * 100.0) * 0.01,
|
||||
fData.fMaxAmount);
|
||||
|
||||
// Not part of fingerprint.
|
||||
|
||||
}
|
||||
|
||||
const dng_hue_sat_map & Map () const
|
||||
{
|
||||
return fData.fMap;
|
||||
}
|
||||
|
||||
uint32 Encoding () const
|
||||
{
|
||||
return fData.fEncoding;
|
||||
}
|
||||
|
||||
bool Monochrome () const
|
||||
{
|
||||
return IsValid () && fAmount == 1.0 && fData.fMonochrome;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void GetStream (dng_stream &stream);
|
||||
|
||||
virtual void PutStream (dng_stream &stream,
|
||||
bool forFingerprint) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_rgb_table : public dng_big_table
|
||||
{
|
||||
|
||||
friend class dng_rgb_table_cache;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
kMinDivisions1D = 2,
|
||||
kMaxDivisions1D = 4096,
|
||||
|
||||
kMinDivisions3D = 2,
|
||||
kMaxDivisions3D = 32,
|
||||
|
||||
kMaxDivisions3D_InMemory = 128
|
||||
|
||||
};
|
||||
|
||||
enum primaries_enum
|
||||
{
|
||||
|
||||
primaries_sRGB = 0,
|
||||
primaries_Adobe,
|
||||
primaries_ProPhoto,
|
||||
primaries_P3,
|
||||
primaries_Rec2020,
|
||||
|
||||
primaries_count
|
||||
|
||||
};
|
||||
|
||||
enum gamma_enum
|
||||
{
|
||||
|
||||
gamma_Linear = 0,
|
||||
gamma_sRGB,
|
||||
gamma_1_8,
|
||||
gamma_2_2,
|
||||
gamma_Rec2020,
|
||||
|
||||
gamma_count
|
||||
|
||||
};
|
||||
|
||||
enum gamut_enum
|
||||
{
|
||||
|
||||
gamut_clip = 0,
|
||||
gamut_extend,
|
||||
|
||||
gamut_count
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
kRGBTableVersion = 1
|
||||
};
|
||||
|
||||
// Table data affecting fingerprint and caching.
|
||||
|
||||
struct table_data
|
||||
{
|
||||
|
||||
// Number of dimensions of the table (1 or 3).
|
||||
|
||||
uint32 fDimensions;
|
||||
|
||||
// Number of samples per side of table.
|
||||
|
||||
uint32 fDivisions;
|
||||
|
||||
// Sample data. 16-bit unsigned encoding.
|
||||
// Right zero padded to 64 bits per sample (i.e. RGB0).
|
||||
|
||||
dng_ref_counted_block fSamples;
|
||||
|
||||
// Color primaries for table.
|
||||
|
||||
primaries_enum fPrimaries;
|
||||
|
||||
// Gamma encoding for table.
|
||||
|
||||
gamma_enum fGamma;
|
||||
|
||||
// Gamut processing option for table.
|
||||
|
||||
gamut_enum fGamut;
|
||||
|
||||
// Minimum and maximum scale amounts supported by table.
|
||||
|
||||
real64 fMinAmount;
|
||||
real64 fMaxAmount;
|
||||
|
||||
// Does this table have only monochrome output (when amount is 1.0)?
|
||||
|
||||
bool fMonochrome;
|
||||
|
||||
// Constructor to set defaults.
|
||||
|
||||
table_data ()
|
||||
|
||||
: fDimensions (0)
|
||||
, fDivisions (0)
|
||||
, fSamples ()
|
||||
, fPrimaries (primaries_sRGB)
|
||||
, fGamma (gamma_sRGB)
|
||||
, fGamut (gamut_clip)
|
||||
, fMinAmount (0.0)
|
||||
, fMaxAmount (2.0)
|
||||
, fMonochrome (false)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
// Compute monchrome flag.
|
||||
|
||||
void ComputeMonochrome ()
|
||||
{
|
||||
|
||||
if (fPrimaries != primaries_ProPhoto &&
|
||||
fGamut != gamut_clip)
|
||||
{
|
||||
|
||||
fMonochrome = false;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (fDimensions != 3)
|
||||
{
|
||||
|
||||
fMonochrome = false;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
fMonochrome = true;
|
||||
|
||||
uint32 count = fDivisions * fDivisions * fDivisions;
|
||||
|
||||
const uint16 * sample = fSamples.Buffer_uint16 ();
|
||||
|
||||
for (uint32 index = 0; index < count; index++)
|
||||
{
|
||||
|
||||
if (sample [0] != sample [1] ||
|
||||
sample [0] != sample [2])
|
||||
{
|
||||
|
||||
fMonochrome = false;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
sample += 4;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
table_data fData;
|
||||
|
||||
// Amount to apply at runtime (does not affect fingerprint).
|
||||
|
||||
real64 fAmount;
|
||||
|
||||
public:
|
||||
|
||||
dng_rgb_table ();
|
||||
|
||||
dng_rgb_table (const dng_rgb_table &table);
|
||||
|
||||
dng_rgb_table & operator= (const dng_rgb_table &table);
|
||||
|
||||
virtual ~dng_rgb_table ();
|
||||
|
||||
bool operator== (const dng_rgb_table &table) const
|
||||
{
|
||||
return Fingerprint () == table.Fingerprint () &&
|
||||
Amount () == table.Amount () &&
|
||||
IsMissing () == table.IsMissing ();
|
||||
}
|
||||
|
||||
bool operator!= (const dng_rgb_table &table) const
|
||||
{
|
||||
return !(*this == table);
|
||||
}
|
||||
|
||||
virtual bool IsValid () const;
|
||||
|
||||
void SetInvalid ();
|
||||
|
||||
primaries_enum Primaries () const
|
||||
{
|
||||
return fData.fPrimaries;
|
||||
}
|
||||
|
||||
void SetPrimaries (primaries_enum primaries)
|
||||
{
|
||||
|
||||
fData.fPrimaries = primaries;
|
||||
|
||||
fData.ComputeMonochrome ();
|
||||
|
||||
RecomputeFingerprint ();
|
||||
|
||||
}
|
||||
|
||||
gamma_enum Gamma () const
|
||||
{
|
||||
return fData.fGamma;
|
||||
}
|
||||
|
||||
void SetGamma (gamma_enum gamma)
|
||||
{
|
||||
|
||||
fData.fGamma = gamma;
|
||||
|
||||
RecomputeFingerprint ();
|
||||
|
||||
}
|
||||
|
||||
gamut_enum Gamut () const
|
||||
{
|
||||
return fData.fGamut;
|
||||
}
|
||||
|
||||
void SetGamut (gamut_enum gamut)
|
||||
{
|
||||
|
||||
fData.fGamut = gamut;
|
||||
|
||||
fData.ComputeMonochrome ();
|
||||
|
||||
RecomputeFingerprint ();
|
||||
|
||||
}
|
||||
|
||||
real64 MinAmount () const
|
||||
{
|
||||
return fData.fMinAmount;
|
||||
}
|
||||
|
||||
real64 MaxAmount () const
|
||||
{
|
||||
return fData.fMaxAmount;
|
||||
}
|
||||
|
||||
void SetAmountRange (real64 minAmount,
|
||||
real64 maxAmount)
|
||||
{
|
||||
|
||||
fData.fMinAmount = Pin_real64 (0.0,
|
||||
Round_int32 (minAmount * 100.0) * 0.01,
|
||||
1.0);
|
||||
|
||||
fData.fMaxAmount = Pin_real64 (1.0,
|
||||
Round_int32 (maxAmount * 100.0) * 0.01,
|
||||
2.0);
|
||||
|
||||
fAmount = Pin_real64 (fData.fMinAmount, fAmount, fData.fMaxAmount);
|
||||
|
||||
RecomputeFingerprint ();
|
||||
|
||||
}
|
||||
|
||||
real64 Amount () const
|
||||
{
|
||||
return fAmount;
|
||||
}
|
||||
|
||||
void SetAmount (real64 amount)
|
||||
{
|
||||
|
||||
fAmount = Pin_real64 (fData.fMinAmount,
|
||||
Round_int32 (amount * 100.0) * 0.01,
|
||||
fData.fMaxAmount);
|
||||
|
||||
// Not part of fingerprint.
|
||||
|
||||
}
|
||||
|
||||
uint32 Dimensions () const
|
||||
{
|
||||
return fData.fDimensions;
|
||||
}
|
||||
|
||||
uint32 Divisions () const
|
||||
{
|
||||
return fData.fDivisions;
|
||||
}
|
||||
|
||||
const uint16 * Samples () const
|
||||
{
|
||||
return fData.fSamples.Buffer_uint16 ();
|
||||
}
|
||||
|
||||
bool Monochrome () const
|
||||
{
|
||||
return IsValid () && fAmount == 1.0 && fData.fMonochrome;
|
||||
}
|
||||
|
||||
void Set (uint32 dimensions,
|
||||
uint32 divisions,
|
||||
dng_ref_counted_block samples);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void GetStream (dng_stream &stream);
|
||||
|
||||
virtual void PutStream (dng_stream &stream,
|
||||
bool forFingerprint) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,66 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_bottlenecks.h"
|
||||
|
||||
#include "dng_reference.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_suite gDNGSuite =
|
||||
{
|
||||
RefZeroBytes,
|
||||
RefCopyBytes,
|
||||
RefSwapBytes16,
|
||||
RefSwapBytes32,
|
||||
RefSetArea8,
|
||||
RefSetArea<Scalar, uint16>,
|
||||
RefSetArea<Scalar, uint32>,
|
||||
RefCopyArea8,
|
||||
RefCopyArea16,
|
||||
RefCopyArea32,
|
||||
RefCopyArea8_16,
|
||||
RefCopyArea8_S16,
|
||||
RefCopyArea8_32,
|
||||
RefCopyArea16_S16<Scalar>,
|
||||
RefCopyArea16_32,
|
||||
RefCopyArea8_R32,
|
||||
RefCopyArea16_R32,
|
||||
RefCopyAreaS16_R32,
|
||||
RefCopyAreaR32_8,
|
||||
RefCopyAreaR32_16,
|
||||
RefCopyAreaR32_S16,
|
||||
RefRepeatArea8,
|
||||
RefRepeatArea16,
|
||||
RefRepeatArea32,
|
||||
RefShiftRight16,
|
||||
RefBilinearRow16,
|
||||
RefBilinearRow32,
|
||||
RefBaselineABCtoRGB,
|
||||
RefBaselineABCDtoRGB,
|
||||
RefBaselineHueSatMap,
|
||||
RefBaselineRGBtoGray,
|
||||
RefBaselineRGBtoRGB,
|
||||
RefBaseline1DTable,
|
||||
RefBaselineRGBTone,
|
||||
RefResampleDown16,
|
||||
RefResampleDown32,
|
||||
RefResampleAcross16,
|
||||
RefResampleAcross32,
|
||||
RefEqualBytes,
|
||||
RefEqualArea8,
|
||||
RefEqualArea16,
|
||||
RefEqualArea32,
|
||||
RefVignetteMask16,
|
||||
RefVignette16,
|
||||
RefVignette32,
|
||||
RefMapArea16,
|
||||
RefBaselineMapPoly32
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,879 @@
|
||||
/******************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/******************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Support for DNG camera color profile information.
|
||||
* Per the \ref spec_dng "DNG 1.1.0 specification", a DNG file can store up to
|
||||
* two sets of color profile information for a camera in the DNG file from that
|
||||
* camera. The second set is optional and when there are two sets, they represent
|
||||
* profiles made under different illumination.
|
||||
*
|
||||
* Profiling information is optionally separated into two parts. One part represents
|
||||
* a profile for a reference camera. (ColorMatrix1 and ColorMatrix2 here.) The
|
||||
* second is a per-camera calibration that takes into account unit-to-unit variation.
|
||||
* This is designed to allow replacing the reference color matrix with one of one's
|
||||
* own construction while maintaining any unit-specific calibration the camera
|
||||
* manufacturer may have provided.
|
||||
*
|
||||
* See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification" for more information.
|
||||
*/
|
||||
|
||||
#ifndef __dng_camera_profile__
|
||||
#define __dng_camera_profile__
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_fingerprint.h"
|
||||
#include "dng_hue_sat_map.h"
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_tag_values.h"
|
||||
#include "dng_tone_curve.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
extern const char * kProfileName_Embedded;
|
||||
|
||||
extern const char * kAdobeCalibrationSignature;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/// \brief An ID for a camera profile consisting of a name and optional fingerprint.
|
||||
|
||||
class dng_camera_profile_id
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_string fName;
|
||||
|
||||
dng_fingerprint fFingerprint;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an invalid camera profile ID (empty name and fingerprint).
|
||||
|
||||
dng_camera_profile_id ()
|
||||
|
||||
: fName ()
|
||||
, fFingerprint ()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a camera profile ID with the specified name and no fingerprint.
|
||||
/// \param name The name of the camera profile ID.
|
||||
|
||||
dng_camera_profile_id (const char *name)
|
||||
|
||||
: fName ()
|
||||
, fFingerprint ()
|
||||
|
||||
{
|
||||
fName.Set (name);
|
||||
}
|
||||
|
||||
/// Construct a camera profile ID with the specified name and no fingerprint.
|
||||
/// \param name The name of the camera profile ID.
|
||||
|
||||
dng_camera_profile_id (const dng_string &name)
|
||||
|
||||
: fName (name)
|
||||
, fFingerprint ()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a camera profile ID with the specified name and fingerprint.
|
||||
/// \param name The name of the camera profile ID.
|
||||
/// \param fingerprint The fingerprint of the camera profile ID.
|
||||
|
||||
dng_camera_profile_id (const char *name,
|
||||
const dng_fingerprint &fingerprint)
|
||||
|
||||
: fName ()
|
||||
, fFingerprint (fingerprint)
|
||||
|
||||
{
|
||||
fName.Set (name);
|
||||
DNG_ASSERT (!fFingerprint.IsValid () || fName.NotEmpty (),
|
||||
"Cannot have profile fingerprint without name");
|
||||
}
|
||||
|
||||
/// Construct a camera profile ID with the specified name and fingerprint.
|
||||
/// \param name The name of the camera profile ID.
|
||||
/// \param fingerprint The fingerprint of the camera profile ID.
|
||||
|
||||
dng_camera_profile_id (const dng_string &name,
|
||||
const dng_fingerprint &fingerprint)
|
||||
|
||||
: fName (name)
|
||||
, fFingerprint (fingerprint)
|
||||
|
||||
{
|
||||
DNG_ASSERT (!fFingerprint.IsValid () || fName.NotEmpty (),
|
||||
"Cannot have profile fingerprint without name");
|
||||
}
|
||||
|
||||
/// Getter for the name of the camera profile ID.
|
||||
/// \retval The name of the camera profile ID.
|
||||
|
||||
const dng_string & Name () const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
/// Getter for the fingerprint of the camera profile ID.
|
||||
/// \retval The fingerprint of the camera profile ID.
|
||||
|
||||
const dng_fingerprint & Fingerprint () const
|
||||
{
|
||||
return fFingerprint;
|
||||
}
|
||||
|
||||
/// Test for equality of two camera profile IDs.
|
||||
/// \param id The id of the camera profile ID to compare.
|
||||
|
||||
bool operator== (const dng_camera_profile_id &id) const
|
||||
{
|
||||
return fName == id.fName &&
|
||||
fFingerprint == id.fFingerprint;
|
||||
}
|
||||
|
||||
/// Test for inequality of two camera profile IDs.
|
||||
/// \param id The id of the camera profile ID to compare.
|
||||
|
||||
bool operator!= (const dng_camera_profile_id &id) const
|
||||
{
|
||||
return !(*this == id);
|
||||
}
|
||||
|
||||
/// Returns true iff the camera profile ID is valid.
|
||||
|
||||
bool IsValid () const
|
||||
{
|
||||
return fName.NotEmpty (); // Fingerprint is optional.
|
||||
}
|
||||
|
||||
/// Resets the name and fingerprint, thereby making this camera profile ID
|
||||
/// invalid.
|
||||
|
||||
void Clear ()
|
||||
{
|
||||
*this = dng_camera_profile_id ();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/// \brief Container for DNG camera color profile and calibration data.
|
||||
|
||||
class dng_camera_profile
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Name of this camera profile.
|
||||
|
||||
dng_string fName;
|
||||
|
||||
// Light sources for up to two calibrations. These use the EXIF
|
||||
// encodings for illuminant and are used to distinguish which
|
||||
// matrix to use.
|
||||
|
||||
uint32 fCalibrationIlluminant1;
|
||||
uint32 fCalibrationIlluminant2;
|
||||
|
||||
// Color matrices for up to two calibrations.
|
||||
|
||||
// These matrices map XYZ values to non-white balanced camera values.
|
||||
// Adobe needs to go that direction in order to determine the clipping
|
||||
// points for highlight recovery logic based on the white point. If
|
||||
// cameras were all 3-color, the matrix could be stored as a forward matrix,
|
||||
// but we need the backwards matrix to deal with 4-color cameras.
|
||||
|
||||
dng_matrix fColorMatrix1;
|
||||
dng_matrix fColorMatrix2;
|
||||
|
||||
// These matrices map white balanced camera values to XYZ chromatically
|
||||
// adapted to D50 (the ICC profile PCS white point). If the matrices
|
||||
// exist, then this implies that white balancing should be done by scaling
|
||||
// camera values with a diagonal matrix.
|
||||
|
||||
dng_matrix fForwardMatrix1;
|
||||
dng_matrix fForwardMatrix2;
|
||||
|
||||
// Dimensionality reduction hints for more than three color cameras.
|
||||
// This is an optional matrix that maps the camera's color components
|
||||
// to 3 components. These are only used if the forward matrices don't
|
||||
// exist, and are used invert the color matrices.
|
||||
|
||||
dng_matrix fReductionMatrix1;
|
||||
dng_matrix fReductionMatrix2;
|
||||
|
||||
// MD5 hash for all data bits of the profile.
|
||||
|
||||
mutable dng_fingerprint fFingerprint;
|
||||
|
||||
// Copyright notice from creator of profile.
|
||||
|
||||
dng_string fCopyright;
|
||||
|
||||
// Rules for how this profile can be embedded and/or copied.
|
||||
|
||||
uint32 fEmbedPolicy;
|
||||
|
||||
// 2-D (or 3-D) hue/sat tables to modify colors.
|
||||
|
||||
dng_hue_sat_map fHueSatDeltas1;
|
||||
dng_hue_sat_map fHueSatDeltas2;
|
||||
|
||||
// Value (V of HSV) encoding for hue/sat tables.
|
||||
|
||||
uint32 fHueSatMapEncoding;
|
||||
|
||||
// 3-D hue/sat table to apply a "look".
|
||||
|
||||
dng_hue_sat_map fLookTable;
|
||||
|
||||
// Value (V of HSV) encoding for look table.
|
||||
|
||||
uint32 fLookTableEncoding;
|
||||
|
||||
// Baseline exposure offset. When using this profile, this offset value is
|
||||
// added to the BaselineExposure value for the negative to determine the
|
||||
// overall baseline exposure to apply.
|
||||
|
||||
dng_srational fBaselineExposureOffset;
|
||||
|
||||
// Default black rendering.
|
||||
|
||||
uint32 fDefaultBlackRender;
|
||||
|
||||
// The "as shot" tone curve for this profile. Check IsValid method
|
||||
// to tell if one exists in profile.
|
||||
|
||||
dng_tone_curve fToneCurve;
|
||||
|
||||
// If this string matches the fCameraCalibrationSignature of the
|
||||
// negative, then use the calibration matrix values from the negative.
|
||||
|
||||
dng_string fProfileCalibrationSignature;
|
||||
|
||||
// If non-empty, only allow use of this profile with camera having
|
||||
// same unique model name.
|
||||
|
||||
dng_string fUniqueCameraModelRestriction;
|
||||
|
||||
// Was this profile read from inside a DNG file? (If so, we wnat
|
||||
// to be sure to include it again when writing out an updated
|
||||
// DNG file)
|
||||
|
||||
bool fWasReadFromDNG;
|
||||
|
||||
// Was this profile read from disk (i.e., an external profile)? (If so, we
|
||||
// may need to refresh when changes are made externally to the profile
|
||||
// directory.)
|
||||
|
||||
bool fWasReadFromDisk;
|
||||
|
||||
// Was this profile a built-in "Matrix" profile? (If so, we may need to
|
||||
// refresh -- i.e., remove it from the list of available profiles -- when
|
||||
// changes are made externally to the profile directory.)
|
||||
|
||||
bool fWasBuiltinMatrix;
|
||||
|
||||
// Was this profile stubbed to save memory (and no longer valid
|
||||
// for building color conversion tables)?
|
||||
|
||||
bool fWasStubbed;
|
||||
|
||||
public:
|
||||
|
||||
dng_camera_profile ();
|
||||
|
||||
virtual ~dng_camera_profile ();
|
||||
|
||||
// API for profile name:
|
||||
|
||||
/// Setter for camera profile name.
|
||||
/// \param name Name to use for this camera profile.
|
||||
|
||||
void SetName (const char *name)
|
||||
{
|
||||
fName.Set (name);
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Getter for camera profile name.
|
||||
/// \retval Name of profile.
|
||||
|
||||
const dng_string & Name () const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
/// Test if this name is embedded.
|
||||
/// \retval true if the name matches the name of the embedded camera profile.
|
||||
|
||||
bool NameIsEmbedded () const
|
||||
{
|
||||
return fName.Matches (kProfileName_Embedded, true);
|
||||
}
|
||||
|
||||
// API for calibration illuminants:
|
||||
|
||||
/// Setter for first of up to two light sources used for calibration.
|
||||
/// Uses the EXIF encodings for illuminant and is used to distinguish which
|
||||
/// matrix to use.
|
||||
/// Corresponds to the DNG CalibrationIlluminant1 tag.
|
||||
|
||||
void SetCalibrationIlluminant1 (uint32 light)
|
||||
{
|
||||
fCalibrationIlluminant1 = light;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Setter for second of up to two light sources used for calibration.
|
||||
/// Uses the EXIF encodings for illuminant and is used to distinguish which
|
||||
/// matrix to use.
|
||||
/// Corresponds to the DNG CalibrationIlluminant2 tag.
|
||||
|
||||
void SetCalibrationIlluminant2 (uint32 light)
|
||||
{
|
||||
fCalibrationIlluminant2 = light;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Getter for first of up to two light sources used for calibration.
|
||||
/// Uses the EXIF encodings for illuminant and is used to distinguish which
|
||||
/// matrix to use.
|
||||
/// Corresponds to the DNG CalibrationIlluminant1 tag.
|
||||
|
||||
uint32 CalibrationIlluminant1 () const
|
||||
{
|
||||
return fCalibrationIlluminant1;
|
||||
}
|
||||
|
||||
/// Getter for second of up to two light sources used for calibration.
|
||||
/// Uses the EXIF encodings for illuminant and is used to distinguish which
|
||||
/// matrix to use.
|
||||
/// Corresponds to the DNG CalibrationIlluminant2 tag.
|
||||
|
||||
uint32 CalibrationIlluminant2 () const
|
||||
{
|
||||
return fCalibrationIlluminant2;
|
||||
}
|
||||
|
||||
/// Getter for first of up to two light sources used for calibration, returning
|
||||
/// result as color temperature.
|
||||
|
||||
real64 CalibrationTemperature1 () const
|
||||
{
|
||||
return IlluminantToTemperature (CalibrationIlluminant1 ());
|
||||
}
|
||||
|
||||
/// Getter for second of up to two light sources used for calibration, returning
|
||||
/// result as color temperature.
|
||||
|
||||
real64 CalibrationTemperature2 () const
|
||||
{
|
||||
return IlluminantToTemperature (CalibrationIlluminant2 ());
|
||||
}
|
||||
|
||||
// API for color matrices:
|
||||
|
||||
/// Utility function to normalize the scale of the color matrix.
|
||||
|
||||
static void NormalizeColorMatrix (dng_matrix &m);
|
||||
|
||||
/// Setter for first of up to two color matrices used for reference camera calibrations.
|
||||
/// These matrices map XYZ values to camera values. The DNG SDK needs to map colors
|
||||
/// that direction in order to determine the clipping points for
|
||||
/// highlight recovery logic based on the white point. If cameras
|
||||
/// were all three-color, the matrix could be stored as a forward matrix.
|
||||
/// The inverse matrix is requried to support four-color cameras.
|
||||
|
||||
void SetColorMatrix1 (const dng_matrix &m);
|
||||
|
||||
/// Setter for second of up to two color matrices used for reference camera calibrations.
|
||||
/// These matrices map XYZ values to camera values. The DNG SDK needs to map colors
|
||||
/// that direction in order to determine the clipping points for
|
||||
/// highlight recovery logic based on the white point. If cameras
|
||||
/// were all three-color, the matrix could be stored as a forward matrix.
|
||||
/// The inverse matrix is requried to support four-color cameras.
|
||||
|
||||
void SetColorMatrix2 (const dng_matrix &m);
|
||||
|
||||
/// Predicate to test if first camera matrix is set
|
||||
|
||||
bool HasColorMatrix1 () const;
|
||||
|
||||
/// Predicate to test if second camera matrix is set
|
||||
|
||||
bool HasColorMatrix2 () const;
|
||||
|
||||
/// Getter for first of up to two color matrices used for calibrations.
|
||||
|
||||
const dng_matrix & ColorMatrix1 () const
|
||||
{
|
||||
return fColorMatrix1;
|
||||
}
|
||||
|
||||
/// Getter for second of up to two color matrices used for calibrations.
|
||||
|
||||
const dng_matrix & ColorMatrix2 () const
|
||||
{
|
||||
return fColorMatrix2;
|
||||
}
|
||||
|
||||
// API for forward matrices:
|
||||
|
||||
/// Utility function to normalize the scale of the forward matrix.
|
||||
|
||||
static void NormalizeForwardMatrix (dng_matrix &m);
|
||||
|
||||
/// Setter for first of up to two forward matrices used for calibrations.
|
||||
|
||||
void SetForwardMatrix1 (const dng_matrix &m);
|
||||
|
||||
/// Setter for second of up to two forward matrices used for calibrations.
|
||||
|
||||
void SetForwardMatrix2 (const dng_matrix &m);
|
||||
|
||||
/// Getter for first of up to two forward matrices used for calibrations.
|
||||
|
||||
const dng_matrix & ForwardMatrix1 () const
|
||||
{
|
||||
return fForwardMatrix1;
|
||||
}
|
||||
|
||||
/// Getter for second of up to two forward matrices used for calibrations.
|
||||
|
||||
const dng_matrix & ForwardMatrix2 () const
|
||||
{
|
||||
return fForwardMatrix2;
|
||||
}
|
||||
|
||||
// API for reduction matrices:
|
||||
|
||||
/// Setter for first of up to two dimensionality reduction hints for four-color cameras.
|
||||
/// This is an optional matrix that maps four components to three.
|
||||
/// See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification."
|
||||
|
||||
void SetReductionMatrix1 (const dng_matrix &m);
|
||||
|
||||
/// Setter for second of up to two dimensionality reduction hints for four-color cameras.
|
||||
/// This is an optional matrix that maps four components to three.
|
||||
/// See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification."
|
||||
|
||||
void SetReductionMatrix2 (const dng_matrix &m);
|
||||
|
||||
/// Getter for first of up to two dimensionality reduction hints for four color cameras.
|
||||
|
||||
const dng_matrix & ReductionMatrix1 () const
|
||||
{
|
||||
return fReductionMatrix1;
|
||||
}
|
||||
|
||||
/// Getter for second of up to two dimensionality reduction hints for four color cameras.
|
||||
|
||||
const dng_matrix & ReductionMatrix2 () const
|
||||
{
|
||||
return fReductionMatrix2;
|
||||
}
|
||||
|
||||
/// Getter function from profile fingerprint.
|
||||
|
||||
const dng_fingerprint &Fingerprint () const
|
||||
{
|
||||
|
||||
if (!fFingerprint.IsValid ())
|
||||
CalculateFingerprint ();
|
||||
|
||||
return fFingerprint;
|
||||
|
||||
}
|
||||
|
||||
/// Getter for camera profile unique ID. Use this ID for uniquely
|
||||
/// identifying profiles (e.g., for syncing purposes).
|
||||
|
||||
dng_fingerprint UniqueID () const;
|
||||
|
||||
/// Getter for camera profile id.
|
||||
/// \retval ID of profile.
|
||||
|
||||
dng_camera_profile_id ProfileID () const
|
||||
{
|
||||
return dng_camera_profile_id (Name (), Fingerprint ());
|
||||
}
|
||||
|
||||
/// Setter for camera profile copyright.
|
||||
/// \param copyright Copyright string to use for this camera profile.
|
||||
|
||||
void SetCopyright (const char *copyright)
|
||||
{
|
||||
fCopyright.Set (copyright);
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Getter for camera profile copyright.
|
||||
/// \retval Copyright string for profile.
|
||||
|
||||
const dng_string & Copyright () const
|
||||
{
|
||||
return fCopyright;
|
||||
}
|
||||
|
||||
// Accessors for embed policy.
|
||||
|
||||
/// Setter for camera profile embed policy.
|
||||
/// \param policy Policy to use for this camera profile.
|
||||
|
||||
void SetEmbedPolicy (uint32 policy)
|
||||
{
|
||||
fEmbedPolicy = policy;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Getter for camera profile embed policy.
|
||||
/// \retval Policy for profile.
|
||||
|
||||
uint32 EmbedPolicy () const
|
||||
{
|
||||
return fEmbedPolicy;
|
||||
}
|
||||
|
||||
/// Returns true iff the profile is legal to embed in a DNG, per the
|
||||
/// profile's embed policy.
|
||||
|
||||
bool IsLegalToEmbed () const
|
||||
{
|
||||
return WasReadFromDNG () ||
|
||||
EmbedPolicy () == pepAllowCopying ||
|
||||
EmbedPolicy () == pepEmbedIfUsed ||
|
||||
EmbedPolicy () == pepNoRestrictions;
|
||||
}
|
||||
|
||||
// Accessors for hue sat maps.
|
||||
|
||||
/// Returns true iff the profile has a valid HueSatMap color table.
|
||||
|
||||
bool HasHueSatDeltas () const
|
||||
{
|
||||
return fHueSatDeltas1.IsValid ();
|
||||
}
|
||||
|
||||
/// Getter for first HueSatMap color table (for calibration illuminant 1).
|
||||
|
||||
const dng_hue_sat_map & HueSatDeltas1 () const
|
||||
{
|
||||
return fHueSatDeltas1;
|
||||
}
|
||||
|
||||
/// Setter for first HueSatMap color table (for calibration illuminant 1).
|
||||
|
||||
void SetHueSatDeltas1 (const dng_hue_sat_map &deltas1);
|
||||
|
||||
/// Getter for second HueSatMap color table (for calibration illuminant 2).
|
||||
|
||||
const dng_hue_sat_map & HueSatDeltas2 () const
|
||||
{
|
||||
return fHueSatDeltas2;
|
||||
}
|
||||
|
||||
/// Setter for second HueSatMap color table (for calibration illuminant 2).
|
||||
|
||||
void SetHueSatDeltas2 (const dng_hue_sat_map &deltas2);
|
||||
|
||||
// Accessors for hue sat map encoding.
|
||||
|
||||
/// Returns the hue sat map encoding (see ProfileHueSatMapEncoding tag).
|
||||
|
||||
uint32 HueSatMapEncoding () const
|
||||
{
|
||||
return fHueSatMapEncoding;
|
||||
}
|
||||
|
||||
/// Sets the hue sat map encoding (see ProfileHueSatMapEncoding tag) to the
|
||||
/// specified encoding.
|
||||
|
||||
void SetHueSatMapEncoding (uint32 encoding)
|
||||
{
|
||||
fHueSatMapEncoding = encoding;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
// Accessors for look table.
|
||||
|
||||
/// Returns true if the profile has a LookTable.
|
||||
|
||||
bool HasLookTable () const
|
||||
{
|
||||
return fLookTable.IsValid ();
|
||||
}
|
||||
|
||||
/// Getter for LookTable.
|
||||
|
||||
const dng_hue_sat_map & LookTable () const
|
||||
{
|
||||
return fLookTable;
|
||||
}
|
||||
|
||||
/// Setter for LookTable.
|
||||
|
||||
void SetLookTable (const dng_hue_sat_map &table);
|
||||
|
||||
// Accessors for look table encoding.
|
||||
|
||||
/// Returns the LookTable encoding (see ProfileLookTableEncoding tag).
|
||||
|
||||
uint32 LookTableEncoding () const
|
||||
{
|
||||
return fLookTableEncoding;
|
||||
}
|
||||
|
||||
/// Sets the LookTable encoding (see ProfileLookTableEncoding tag) to the
|
||||
/// specified encoding.
|
||||
|
||||
void SetLookTableEncoding (uint32 encoding)
|
||||
{
|
||||
fLookTableEncoding = encoding;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
// Accessors for baseline exposure offset.
|
||||
|
||||
/// Sets the baseline exposure offset of the profile (see
|
||||
/// BaselineExposureOffset tag) to the specified value.
|
||||
|
||||
void SetBaselineExposureOffset (real64 exposureOffset)
|
||||
{
|
||||
fBaselineExposureOffset.Set_real64 (exposureOffset, 100);
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Returns the baseline exposure offset of the profile (see
|
||||
/// BaselineExposureOffset tag).
|
||||
|
||||
const dng_srational & BaselineExposureOffset () const
|
||||
{
|
||||
return fBaselineExposureOffset;
|
||||
}
|
||||
|
||||
// Accessors for default black render.
|
||||
|
||||
/// Sets the default black render of the profile (see DefaultBlackRender tag)
|
||||
/// to the specified option.
|
||||
|
||||
void SetDefaultBlackRender (uint32 defaultBlackRender)
|
||||
{
|
||||
fDefaultBlackRender = defaultBlackRender;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Returns the default black render of the profile (see DefaultBlackRender
|
||||
/// tag).
|
||||
|
||||
uint32 DefaultBlackRender () const
|
||||
{
|
||||
return fDefaultBlackRender;
|
||||
}
|
||||
|
||||
// Accessors for tone curve.
|
||||
|
||||
/// Returns the tone curve of the profile.
|
||||
|
||||
const dng_tone_curve & ToneCurve () const
|
||||
{
|
||||
return fToneCurve;
|
||||
}
|
||||
|
||||
/// Sets the tone curve of the profile to the specified curve.
|
||||
|
||||
void SetToneCurve (const dng_tone_curve &curve)
|
||||
{
|
||||
fToneCurve = curve;
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
// Accessors for profile calibration signature.
|
||||
|
||||
/// Sets the profile calibration signature (see ProfileCalibrationSignature
|
||||
/// tag) to the specified string.
|
||||
|
||||
void SetProfileCalibrationSignature (const char *signature)
|
||||
{
|
||||
fProfileCalibrationSignature.Set (signature);
|
||||
ClearFingerprint ();
|
||||
}
|
||||
|
||||
/// Returns the profile calibration signature (see ProfileCalibrationSignature
|
||||
/// tag) of the profile.
|
||||
|
||||
const dng_string & ProfileCalibrationSignature () const
|
||||
{
|
||||
return fProfileCalibrationSignature;
|
||||
}
|
||||
|
||||
/// Setter for camera unique model name to restrict use of this profile.
|
||||
/// \param camera Camera unique model name designating only camera this
|
||||
/// profile can be used with. (Empty string for no restriction.)
|
||||
|
||||
void SetUniqueCameraModelRestriction (const char *camera)
|
||||
{
|
||||
fUniqueCameraModelRestriction.Set (camera);
|
||||
// Not included in fingerprint, so don't need ClearFingerprint ().
|
||||
}
|
||||
|
||||
/// Getter for camera unique model name to restrict use of this profile.
|
||||
/// \retval Unique model name of only camera this profile can be used with
|
||||
/// or empty if no restriction.
|
||||
|
||||
const dng_string & UniqueCameraModelRestriction () const
|
||||
{
|
||||
return fUniqueCameraModelRestriction;
|
||||
}
|
||||
|
||||
// Accessors for was read from DNG flag.
|
||||
|
||||
/// Sets internal flag to indicate this profile was originally read from a
|
||||
/// DNG file.
|
||||
|
||||
void SetWasReadFromDNG (bool state = true)
|
||||
{
|
||||
fWasReadFromDNG = state;
|
||||
}
|
||||
|
||||
/// Was this profile read from a DNG?
|
||||
|
||||
bool WasReadFromDNG () const
|
||||
{
|
||||
return fWasReadFromDNG;
|
||||
}
|
||||
|
||||
// Accessors for was read from disk flag.
|
||||
|
||||
/// Sets internal flag to indicate this profile was originally read from
|
||||
/// disk.
|
||||
|
||||
void SetWasReadFromDisk (bool state = true)
|
||||
{
|
||||
fWasReadFromDisk = state;
|
||||
}
|
||||
|
||||
/// Was this profile read from disk?
|
||||
|
||||
bool WasReadFromDisk () const
|
||||
{
|
||||
return fWasReadFromDisk;
|
||||
}
|
||||
|
||||
// Accessors for was built-in matrix flag.
|
||||
|
||||
/// Sets internal flag to indicate this profile was originally a built-in
|
||||
/// matrix profile.
|
||||
|
||||
void SetWasBuiltinMatrix (bool state = true)
|
||||
{
|
||||
fWasBuiltinMatrix = state;
|
||||
}
|
||||
|
||||
/// Was this profile a built-in matrix profile?
|
||||
|
||||
bool WasBuiltinMatrix () const
|
||||
{
|
||||
return fWasBuiltinMatrix;
|
||||
}
|
||||
|
||||
/// Determines if this a valid profile for this number of color channels?
|
||||
/// \retval true if the profile is valid.
|
||||
|
||||
bool IsValid (uint32 channels) const;
|
||||
|
||||
/// Predicate to check if two camera profiles are colorwise equal, thus ignores
|
||||
/// the profile name.
|
||||
/// \param profile Camera profile to compare to.
|
||||
|
||||
bool EqualData (const dng_camera_profile &profile) const;
|
||||
|
||||
/// Parse profile from dng_camera_profile_info data.
|
||||
|
||||
void Parse (dng_stream &stream,
|
||||
dng_camera_profile_info &profileInfo);
|
||||
|
||||
/// Parse from an extended profile stream, which is similar to stand alone
|
||||
/// TIFF file.
|
||||
|
||||
bool ParseExtended (dng_stream &stream);
|
||||
|
||||
/// Convert from a three-color to a four-color Bayer profile.
|
||||
|
||||
virtual void SetFourColorBayer ();
|
||||
|
||||
/// Find the hue/sat table to use for a given white point, if any.
|
||||
/// The calling routine owns the resulting table.
|
||||
|
||||
dng_hue_sat_map * HueSatMapForWhite (const dng_xy_coord &white) const;
|
||||
|
||||
/// Stub out the profile (free memory used by large tables).
|
||||
|
||||
void Stub ();
|
||||
|
||||
/// Was this profile stubbed?
|
||||
|
||||
bool WasStubbed () const
|
||||
{
|
||||
return fWasStubbed;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static real64 IlluminantToTemperature (uint32 light);
|
||||
|
||||
void ClearFingerprint ()
|
||||
{
|
||||
fFingerprint.Clear ();
|
||||
}
|
||||
|
||||
void CalculateFingerprint () const;
|
||||
|
||||
static bool ValidForwardMatrix (const dng_matrix &m);
|
||||
|
||||
static void ReadHueSatMap (dng_stream &stream,
|
||||
dng_hue_sat_map &hueSatMap,
|
||||
uint32 hues,
|
||||
uint32 sats,
|
||||
uint32 vals,
|
||||
bool skipSat0);
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void SplitCameraProfileName (const dng_string &name,
|
||||
dng_string &baseName,
|
||||
int32 &version);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void BuildHueSatMapEncodingTable (dng_memory_allocator &allocator,
|
||||
uint32 encoding,
|
||||
AutoPtr<dng_1d_table> &encodeTable,
|
||||
AutoPtr<dng_1d_table> &decodeTable,
|
||||
bool subSample);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
@ -0,0 +1,108 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/*** \file
|
||||
* Forward class declarations to avoid having to include many .h files in most places.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_classes__
|
||||
#define __dng_classes__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_1d_function;
|
||||
class dng_1d_table;
|
||||
class dng_abort_sniffer;
|
||||
class dng_area_task;
|
||||
class dng_area_task_progress;
|
||||
class dng_base_tile_iterator;
|
||||
class dng_basic_tag_set;
|
||||
class dng_big_table;
|
||||
class dng_camera_profile;
|
||||
class dng_camera_profile_id;
|
||||
class dng_camera_profile_info;
|
||||
class dng_color_space;
|
||||
class dng_color_spec;
|
||||
class dng_date_time;
|
||||
class dng_date_time_info;
|
||||
class dng_exif;
|
||||
class dng_fingerprint;
|
||||
class dng_host;
|
||||
class dng_hue_sat_map;
|
||||
class dng_ifd;
|
||||
class dng_image;
|
||||
class dng_image_preview;
|
||||
class dng_image_writer;
|
||||
class dng_info;
|
||||
class dng_iptc;
|
||||
class dng_jpeg_image;
|
||||
class dng_jpeg_preview;
|
||||
class dng_linearization_info;
|
||||
class dng_local_string;
|
||||
class dng_look_table;
|
||||
class dng_matrix;
|
||||
class dng_matrix_3by3;
|
||||
class dng_matrix_4by3;
|
||||
class dng_md5_printer;
|
||||
class dng_memory_allocator;
|
||||
class dng_memory_block;
|
||||
class dng_memory_data;
|
||||
class dng_memory_stream;
|
||||
class dng_metadata;
|
||||
class dng_mosaic_info;
|
||||
class dng_mutex;
|
||||
class dng_noise_function;
|
||||
class dng_noise_profile;
|
||||
class dng_opcode;
|
||||
class dng_opcode_list;
|
||||
class dng_orientation;
|
||||
class dng_negative;
|
||||
class dng_pixel_buffer;
|
||||
class dng_point;
|
||||
class dng_point_real64;
|
||||
class dng_preview;
|
||||
class dng_preview_info;
|
||||
class dng_preview_list;
|
||||
class dng_raw_preview;
|
||||
class dng_read_image;
|
||||
class dng_rect;
|
||||
class dng_rect_real64;
|
||||
class dng_ref_counted_block;
|
||||
class dng_render;
|
||||
class dng_resample_function;
|
||||
class dng_resolution;
|
||||
class dng_rgb_table;
|
||||
class dng_set_minimum_priority;
|
||||
class dng_shared;
|
||||
class dng_spline_solver;
|
||||
class dng_srational;
|
||||
class dng_stream;
|
||||
class dng_string;
|
||||
class dng_string_list;
|
||||
class dng_tiff_directory;
|
||||
class dng_tile_buffer;
|
||||
class dng_time_zone;
|
||||
class dng_tone_curve;
|
||||
class dng_urational;
|
||||
class dng_vector;
|
||||
class dng_vector_3;
|
||||
class dng_xmp;
|
||||
class dng_xmp_sdk;
|
||||
class dng_xy_coord;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct dng_xmp_namespace;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,346 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Standard gamma functions and color spaces used within the DNG SDK.
|
||||
*/
|
||||
|
||||
#ifndef __dng_color_space__
|
||||
#define __dng_color_space__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_1d_function.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A dng_1d_function for gamma encoding in sRGB color space
|
||||
|
||||
class dng_function_GammaEncode_sRGB: public dng_1d_function
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual real64 Evaluate (real64 x) const;
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
static const dng_1d_function & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A dng_1d_function for gamma encoding with 1.8 gamma.
|
||||
|
||||
class dng_function_GammaEncode_1_8: public dng_1d_function
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual real64 Evaluate (real64 x) const;
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
static const dng_1d_function & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A dng_1d_function for gamma encoding with 2.2 gamma.
|
||||
|
||||
class dng_function_GammaEncode_2_2: public dng_1d_function
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual real64 Evaluate (real64 x) const;
|
||||
|
||||
virtual real64 EvaluateInverse (real64 y) const;
|
||||
|
||||
static const dng_1d_function & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An abstract color space
|
||||
|
||||
class dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_matrix fMatrixToPCS;
|
||||
|
||||
dng_matrix fMatrixFromPCS;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_color_space ();
|
||||
|
||||
/// Return a matrix which transforms source data in this color space into the
|
||||
/// Profile Connection Space.
|
||||
|
||||
const dng_matrix & MatrixToPCS () const
|
||||
{
|
||||
return fMatrixToPCS;
|
||||
}
|
||||
|
||||
/// Return a matrix which transforms Profile Connection Space data into this
|
||||
/// color space.
|
||||
|
||||
const dng_matrix & MatrixFromPCS () const
|
||||
{
|
||||
return fMatrixFromPCS;
|
||||
}
|
||||
|
||||
/// Predicate which is true if this color space is monochrome (has only a
|
||||
/// single column).
|
||||
|
||||
bool IsMonochrome () const
|
||||
{
|
||||
return fMatrixToPCS.Cols () == 1;
|
||||
}
|
||||
|
||||
/// Getter for the gamma function for this color space.
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns true if this color space is linear. (I.e. has gamma 1.0.)
|
||||
|
||||
bool IsLinear () const
|
||||
{
|
||||
return GammaFunction ().IsIdentity ();
|
||||
}
|
||||
|
||||
/// Map an input value through this color space's encoding gamma.
|
||||
|
||||
real64 GammaEncode (real64 x) const
|
||||
{
|
||||
return GammaFunction ().Evaluate (x);
|
||||
}
|
||||
|
||||
/// Map an input value through this color space's decoding gamma (inverse of
|
||||
/// the encoding gamma).
|
||||
|
||||
real64 GammaDecode (real64 y) const
|
||||
{
|
||||
return GammaFunction ().EvaluateInverse (y);
|
||||
}
|
||||
|
||||
/// Getter for ICC profile, if this color space has one.
|
||||
/// \param size Out parameter which receives size on return.
|
||||
/// \param data Receives bytes of profile.
|
||||
/// \retval Returns true if this color space has an ICC profile, false otherwise.
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
protected:
|
||||
|
||||
dng_color_space ();
|
||||
|
||||
void SetMonochrome ();
|
||||
|
||||
void SetMatrixToPCS (const dng_matrix_3by3 &M);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Singleton class for sRGB color space.
|
||||
|
||||
class dng_space_sRGB: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_sRGB ();
|
||||
|
||||
public:
|
||||
|
||||
/// Returns dng_function_GammaEncode_sRGB
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns sRGB IEC61966-2.1 ICC profile
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
/// Static method for getting single global instance of this color space.
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Singleton class for AdobeRGB color space.
|
||||
|
||||
class dng_space_AdobeRGB: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_AdobeRGB ();
|
||||
|
||||
public:
|
||||
|
||||
/// Returns dng_function_GammaEncode_2_2
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns AdobeRGB (1998) ICC profile
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
/// Static method for getting single global instance of this color space.
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Singleton class for ColorMatch color space.
|
||||
|
||||
class dng_space_ColorMatch: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_ColorMatch ();
|
||||
|
||||
public:
|
||||
|
||||
/// Returns dng_function_GammaEncode_1_8
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns ColorMatch RGB ICC profile
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
/// Static method for getting single global instance of this color space.
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Singleton class for ProPhoto RGB color space.
|
||||
|
||||
class dng_space_ProPhoto: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_ProPhoto ();
|
||||
|
||||
public:
|
||||
|
||||
/// Returns dng_function_GammaEncode_1_8
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns ProPhoto RGB ICC profile
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
/// Static method for getting single global instance of this color space.
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Singleton class for gamma 1.8 grayscale color space.
|
||||
|
||||
class dng_space_GrayGamma18: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_GrayGamma18 ();
|
||||
|
||||
public:
|
||||
|
||||
/// Returns dng_function_GammaEncode_1_8
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns simple grayscale gamma 1.8 ICC profile
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
/// Static method for getting single global instance of this color space.
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Singleton class for gamma 2.2 grayscale color space.
|
||||
|
||||
class dng_space_GrayGamma22: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_GrayGamma22 ();
|
||||
|
||||
public:
|
||||
|
||||
/// Returns dng_function_GammaEncode_2_2
|
||||
|
||||
virtual const dng_1d_function & GammaFunction () const;
|
||||
|
||||
/// Returns simple grayscale gamma 2.2 ICC profile
|
||||
|
||||
virtual bool ICCProfile (uint32 &size,
|
||||
const uint8 *&data) const;
|
||||
|
||||
/// Static method for getting single global instance of this color space.
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_space_fakeRGB: public dng_color_space
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_space_fakeRGB ();
|
||||
|
||||
public:
|
||||
|
||||
static const dng_color_space & Get ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,554 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_color_spec.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_camera_profile.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_temperature.h"
|
||||
#include "dng_utils.h"
|
||||
#include "dng_xy_coord.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1,
|
||||
const dng_xy_coord &white2)
|
||||
{
|
||||
|
||||
// Use the linearized Bradford adaptation matrix.
|
||||
|
||||
dng_matrix_3by3 Mb ( 0.8951, 0.2664, -0.1614,
|
||||
-0.7502, 1.7135, 0.0367,
|
||||
0.0389, -0.0685, 1.0296);
|
||||
|
||||
dng_vector_3 w1 = Mb * XYtoXYZ (white1);
|
||||
dng_vector_3 w2 = Mb * XYtoXYZ (white2);
|
||||
|
||||
// Negative white coordinates are kind of meaningless.
|
||||
|
||||
w1 [0] = Max_real64 (w1 [0], 0.0);
|
||||
w1 [1] = Max_real64 (w1 [1], 0.0);
|
||||
w1 [2] = Max_real64 (w1 [2], 0.0);
|
||||
|
||||
w2 [0] = Max_real64 (w2 [0], 0.0);
|
||||
w2 [1] = Max_real64 (w2 [1], 0.0);
|
||||
w2 [2] = Max_real64 (w2 [2], 0.0);
|
||||
|
||||
// Limit scaling to something reasonable.
|
||||
|
||||
dng_matrix_3by3 A;
|
||||
|
||||
A [0] [0] = Pin_real64 (0.1, w1 [0] > 0.0 ? w2 [0] / w1 [0] : 10.0, 10.0);
|
||||
A [1] [1] = Pin_real64 (0.1, w1 [1] > 0.0 ? w2 [1] / w1 [1] : 10.0, 10.0);
|
||||
A [2] [2] = Pin_real64 (0.1, w1 [2] > 0.0 ? w2 [2] / w1 [2] : 10.0, 10.0);
|
||||
|
||||
dng_matrix_3by3 B = Invert (Mb) * A * Mb;
|
||||
|
||||
return B;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
dng_color_spec::dng_color_spec (const dng_negative &negative,
|
||||
const dng_camera_profile *profile)
|
||||
|
||||
: fChannels (negative.ColorChannels ())
|
||||
|
||||
, fTemperature1 (0.0)
|
||||
, fTemperature2 (0.0)
|
||||
|
||||
, fColorMatrix1 ()
|
||||
, fColorMatrix2 ()
|
||||
|
||||
, fForwardMatrix1 ()
|
||||
, fForwardMatrix2 ()
|
||||
|
||||
, fReductionMatrix1 ()
|
||||
, fReductionMatrix2 ()
|
||||
|
||||
, fCameraCalibration1 ()
|
||||
, fCameraCalibration2 ()
|
||||
|
||||
, fAnalogBalance ()
|
||||
|
||||
, fWhiteXY ()
|
||||
|
||||
, fCameraWhite ()
|
||||
, fCameraToPCS ()
|
||||
|
||||
, fPCStoCamera ()
|
||||
|
||||
{
|
||||
|
||||
if (fChannels > 1)
|
||||
{
|
||||
|
||||
if (!profile || !profile->IsValid (fChannels))
|
||||
{
|
||||
ThrowBadFormat ();
|
||||
}
|
||||
|
||||
if (profile->WasStubbed ())
|
||||
{
|
||||
ThrowProgramError ("Using stubbed profile");
|
||||
}
|
||||
|
||||
fTemperature1 = profile->CalibrationTemperature1 ();
|
||||
fTemperature2 = profile->CalibrationTemperature2 ();
|
||||
|
||||
fColorMatrix1 = profile->ColorMatrix1 ();
|
||||
fColorMatrix2 = profile->ColorMatrix2 ();
|
||||
|
||||
fForwardMatrix1 = profile->ForwardMatrix1 ();
|
||||
fForwardMatrix2 = profile->ForwardMatrix2 ();
|
||||
|
||||
fReductionMatrix1 = profile->ReductionMatrix1 ();
|
||||
fReductionMatrix2 = profile->ReductionMatrix2 ();
|
||||
|
||||
fCameraCalibration1.SetIdentity (fChannels);
|
||||
fCameraCalibration2.SetIdentity (fChannels);
|
||||
|
||||
if (negative. CameraCalibrationSignature () ==
|
||||
profile->ProfileCalibrationSignature ())
|
||||
{
|
||||
|
||||
if (negative.CameraCalibration1 ().Rows () == fChannels &&
|
||||
negative.CameraCalibration1 ().Cols () == fChannels)
|
||||
{
|
||||
|
||||
fCameraCalibration1 = negative.CameraCalibration1 ();
|
||||
|
||||
}
|
||||
|
||||
if (negative.CameraCalibration2 ().Rows () == fChannels &&
|
||||
negative.CameraCalibration2 ().Cols () == fChannels)
|
||||
{
|
||||
|
||||
fCameraCalibration2 = negative.CameraCalibration2 ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fAnalogBalance = dng_matrix (fChannels, fChannels);
|
||||
|
||||
for (uint32 j = 0; j < fChannels; j++)
|
||||
{
|
||||
|
||||
fAnalogBalance [j] [j] = negative.AnalogBalance (j);
|
||||
|
||||
}
|
||||
|
||||
dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix1);
|
||||
|
||||
fColorMatrix1 = fAnalogBalance * fCameraCalibration1 * fColorMatrix1;
|
||||
|
||||
if (!profile->HasColorMatrix2 () ||
|
||||
fTemperature1 <= 0.0 ||
|
||||
fTemperature2 <= 0.0 ||
|
||||
fTemperature1 == fTemperature2)
|
||||
{
|
||||
|
||||
fTemperature1 = 5000.0;
|
||||
fTemperature2 = 5000.0;
|
||||
|
||||
fColorMatrix2 = fColorMatrix1;
|
||||
fForwardMatrix2 = fForwardMatrix1;
|
||||
fReductionMatrix2 = fReductionMatrix1;
|
||||
fCameraCalibration2 = fCameraCalibration1;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix2);
|
||||
|
||||
fColorMatrix2 = fAnalogBalance * fCameraCalibration2 * fColorMatrix2;
|
||||
|
||||
// Swap values if temperatures are out of order.
|
||||
|
||||
if (fTemperature1 > fTemperature2)
|
||||
{
|
||||
|
||||
real64 temp = fTemperature1;
|
||||
fTemperature1 = fTemperature2;
|
||||
fTemperature2 = temp;
|
||||
|
||||
dng_matrix T = fColorMatrix1;
|
||||
fColorMatrix1 = fColorMatrix2;
|
||||
fColorMatrix2 = T;
|
||||
|
||||
T = fForwardMatrix1;
|
||||
fForwardMatrix1 = fForwardMatrix2;
|
||||
fForwardMatrix2 = T;
|
||||
|
||||
T = fReductionMatrix1;
|
||||
fReductionMatrix1 = fReductionMatrix2;
|
||||
fReductionMatrix2 = T;
|
||||
|
||||
T = fCameraCalibration1;
|
||||
fCameraCalibration1 = fCameraCalibration2;
|
||||
fCameraCalibration2 = T;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_matrix dng_color_spec::FindXYZtoCamera (const dng_xy_coord &white,
|
||||
dng_matrix *forwardMatrix,
|
||||
dng_matrix *reductionMatrix,
|
||||
dng_matrix *cameraCalibration)
|
||||
{
|
||||
|
||||
// Convert to temperature/offset space.
|
||||
|
||||
dng_temperature td (white);
|
||||
|
||||
// Find fraction to weight the first calibration.
|
||||
|
||||
real64 g;
|
||||
|
||||
if (td.Temperature () <= fTemperature1)
|
||||
g = 1.0;
|
||||
|
||||
else if (td.Temperature () >= fTemperature2)
|
||||
g = 0.0;
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
real64 invT = 1.0 / td.Temperature ();
|
||||
|
||||
g = (invT - (1.0 / fTemperature2)) /
|
||||
((1.0 / fTemperature1) - (1.0 / fTemperature2));
|
||||
|
||||
}
|
||||
|
||||
// Interpolate the color matrix.
|
||||
|
||||
dng_matrix colorMatrix;
|
||||
|
||||
if (g >= 1.0)
|
||||
colorMatrix = fColorMatrix1;
|
||||
|
||||
else if (g <= 0.0)
|
||||
colorMatrix = fColorMatrix2;
|
||||
|
||||
else
|
||||
colorMatrix = (g ) * fColorMatrix1 +
|
||||
(1.0 - g) * fColorMatrix2;
|
||||
|
||||
// Interpolate forward matrix, if any.
|
||||
|
||||
if (forwardMatrix)
|
||||
{
|
||||
|
||||
bool has1 = fForwardMatrix1.NotEmpty ();
|
||||
bool has2 = fForwardMatrix2.NotEmpty ();
|
||||
|
||||
if (has1 && has2)
|
||||
{
|
||||
|
||||
if (g >= 1.0)
|
||||
*forwardMatrix = fForwardMatrix1;
|
||||
|
||||
else if (g <= 0.0)
|
||||
*forwardMatrix = fForwardMatrix2;
|
||||
|
||||
else
|
||||
*forwardMatrix = (g ) * fForwardMatrix1 +
|
||||
(1.0 - g) * fForwardMatrix2;
|
||||
|
||||
}
|
||||
|
||||
else if (has1)
|
||||
{
|
||||
|
||||
*forwardMatrix = fForwardMatrix1;
|
||||
|
||||
}
|
||||
|
||||
else if (has2)
|
||||
{
|
||||
|
||||
*forwardMatrix = fForwardMatrix2;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
forwardMatrix->Clear ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Interpolate reduction matrix, if any.
|
||||
|
||||
if (reductionMatrix)
|
||||
{
|
||||
|
||||
bool has1 = fReductionMatrix1.NotEmpty ();
|
||||
bool has2 = fReductionMatrix2.NotEmpty ();
|
||||
|
||||
if (has1 && has2)
|
||||
{
|
||||
|
||||
if (g >= 1.0)
|
||||
*reductionMatrix = fReductionMatrix1;
|
||||
|
||||
else if (g <= 0.0)
|
||||
*reductionMatrix = fReductionMatrix2;
|
||||
|
||||
else
|
||||
*reductionMatrix = (g ) * fReductionMatrix1 +
|
||||
(1.0 - g) * fReductionMatrix2;
|
||||
|
||||
}
|
||||
|
||||
else if (has1)
|
||||
{
|
||||
|
||||
*reductionMatrix = fReductionMatrix1;
|
||||
|
||||
}
|
||||
|
||||
else if (has2)
|
||||
{
|
||||
|
||||
*reductionMatrix = fReductionMatrix2;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
reductionMatrix->Clear ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Interpolate camera calibration matrix.
|
||||
|
||||
if (cameraCalibration)
|
||||
{
|
||||
|
||||
if (g >= 1.0)
|
||||
*cameraCalibration = fCameraCalibration1;
|
||||
|
||||
else if (g <= 0.0)
|
||||
*cameraCalibration = fCameraCalibration2;
|
||||
|
||||
else
|
||||
*cameraCalibration = (g ) * fCameraCalibration1 +
|
||||
(1.0 - g) * fCameraCalibration2;
|
||||
|
||||
}
|
||||
|
||||
// Return the interpolated color matrix.
|
||||
|
||||
return colorMatrix;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_color_spec::SetWhiteXY (const dng_xy_coord &white)
|
||||
{
|
||||
|
||||
fWhiteXY = white;
|
||||
|
||||
// Deal with monochrome cameras.
|
||||
|
||||
if (fChannels == 1)
|
||||
{
|
||||
|
||||
fCameraWhite.SetIdentity (1);
|
||||
|
||||
fCameraToPCS = PCStoXYZ ().AsColumn ();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Interpolate an matric values for this white point.
|
||||
|
||||
dng_matrix colorMatrix;
|
||||
dng_matrix forwardMatrix;
|
||||
dng_matrix reductionMatrix;
|
||||
dng_matrix cameraCalibration;
|
||||
|
||||
colorMatrix = FindXYZtoCamera (fWhiteXY,
|
||||
&forwardMatrix,
|
||||
&reductionMatrix,
|
||||
&cameraCalibration);
|
||||
|
||||
// Find the camera white values.
|
||||
|
||||
fCameraWhite = colorMatrix * XYtoXYZ (fWhiteXY);
|
||||
|
||||
real64 whiteScale = 1.0 / MaxEntry (fCameraWhite);
|
||||
|
||||
for (uint32 j = 0; j < fChannels; j++)
|
||||
{
|
||||
|
||||
// We don't support non-positive values for camera neutral values.
|
||||
|
||||
fCameraWhite [j] = Pin_real64 (0.001,
|
||||
whiteScale * fCameraWhite [j],
|
||||
1.0);
|
||||
|
||||
}
|
||||
|
||||
// Find PCS to Camera transform. Scale matrix so PCS white can just be
|
||||
// reached when the first camera channel saturates
|
||||
|
||||
fPCStoCamera = colorMatrix * MapWhiteMatrix (PCStoXY (), fWhiteXY);
|
||||
|
||||
real64 scale = MaxEntry (fPCStoCamera * PCStoXYZ ());
|
||||
|
||||
fPCStoCamera = (1.0 / scale) * fPCStoCamera;
|
||||
|
||||
// If we have a forward matrix, then just use that.
|
||||
|
||||
if (forwardMatrix.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_matrix individualToReference = Invert (fAnalogBalance * cameraCalibration);
|
||||
|
||||
dng_vector refCameraWhite = individualToReference * fCameraWhite;
|
||||
|
||||
fCameraToPCS = forwardMatrix *
|
||||
Invert (refCameraWhite.AsDiagonal ()) *
|
||||
individualToReference;
|
||||
|
||||
}
|
||||
|
||||
// Else we need to use the adapt in XYZ method.
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
// Invert this PCS to camera matrix. Note that if there are more than three
|
||||
// camera channels, this inversion is non-unique.
|
||||
|
||||
fCameraToPCS = Invert (fPCStoCamera, reductionMatrix);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const dng_xy_coord & dng_color_spec::WhiteXY () const
|
||||
{
|
||||
|
||||
DNG_ASSERT (fWhiteXY.IsValid (), "Using invalid WhiteXY");
|
||||
|
||||
return fWhiteXY;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const dng_vector & dng_color_spec::CameraWhite () const
|
||||
{
|
||||
|
||||
DNG_ASSERT (fCameraWhite.NotEmpty (), "Using invalid CameraWhite");
|
||||
|
||||
return fCameraWhite;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const dng_matrix & dng_color_spec::CameraToPCS () const
|
||||
{
|
||||
|
||||
DNG_ASSERT (fCameraToPCS.NotEmpty (), "Using invalid CameraToPCS");
|
||||
|
||||
return fCameraToPCS;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const dng_matrix & dng_color_spec::PCStoCamera () const
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPCStoCamera.NotEmpty (), "Using invalid PCStoCamera");
|
||||
|
||||
return fPCStoCamera;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_xy_coord dng_color_spec::NeutralToXY (const dng_vector &neutral)
|
||||
{
|
||||
|
||||
const uint32 kMaxPasses = 30;
|
||||
|
||||
if (fChannels == 1)
|
||||
{
|
||||
|
||||
return PCStoXY ();
|
||||
|
||||
}
|
||||
|
||||
dng_xy_coord last = D50_xy_coord ();
|
||||
|
||||
for (uint32 pass = 0; pass < kMaxPasses; pass++)
|
||||
{
|
||||
|
||||
dng_matrix xyzToCamera = FindXYZtoCamera (last);
|
||||
|
||||
dng_xy_coord next = XYZtoXY (Invert (xyzToCamera) * neutral);
|
||||
|
||||
if (Abs_real64 (next.x - last.x) +
|
||||
Abs_real64 (next.y - last.y) < 0.0000001)
|
||||
{
|
||||
|
||||
return next;
|
||||
|
||||
}
|
||||
|
||||
// If we reach the limit without converging, we are most likely
|
||||
// in a two value oscillation. So take the average of the last
|
||||
// two estimates and give up.
|
||||
|
||||
if (pass == kMaxPasses - 1)
|
||||
{
|
||||
|
||||
next.x = (last.x + next.x) * 0.5;
|
||||
next.y = (last.y + next.y) * 0.5;
|
||||
|
||||
}
|
||||
|
||||
last = next;
|
||||
|
||||
}
|
||||
|
||||
return last;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,141 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Class for holding a specific color transform.
|
||||
*/
|
||||
|
||||
#ifndef __dng_color_spec__
|
||||
#define __dng_color_spec__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_xy_coord.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Compute a 3x3 matrix which maps colors from white point white1 to
|
||||
/// white point white2
|
||||
///
|
||||
/// Uses linearized Bradford adaptation matrix to compute a mapping from
|
||||
/// colors measured with one white point (white1) to another (white2).
|
||||
|
||||
dng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1,
|
||||
const dng_xy_coord &white2);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Color transform taking into account white point and camera calibration and
|
||||
/// individual calibration from DNG negative.
|
||||
|
||||
class dng_color_spec
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
uint32 fChannels;
|
||||
|
||||
real64 fTemperature1;
|
||||
real64 fTemperature2;
|
||||
|
||||
dng_matrix fColorMatrix1;
|
||||
dng_matrix fColorMatrix2;
|
||||
|
||||
dng_matrix fForwardMatrix1;
|
||||
dng_matrix fForwardMatrix2;
|
||||
|
||||
dng_matrix fReductionMatrix1;
|
||||
dng_matrix fReductionMatrix2;
|
||||
|
||||
dng_matrix fCameraCalibration1;
|
||||
dng_matrix fCameraCalibration2;
|
||||
|
||||
dng_matrix fAnalogBalance;
|
||||
|
||||
dng_xy_coord fWhiteXY;
|
||||
|
||||
dng_vector fCameraWhite;
|
||||
dng_matrix fCameraToPCS;
|
||||
|
||||
dng_matrix fPCStoCamera;
|
||||
|
||||
public:
|
||||
|
||||
/// Read calibration info from DNG negative and construct a
|
||||
/// dng_color_spec.
|
||||
|
||||
dng_color_spec (const dng_negative &negative,
|
||||
const dng_camera_profile *profile);
|
||||
|
||||
virtual ~dng_color_spec ()
|
||||
{
|
||||
}
|
||||
|
||||
/// Number of channels used for this color transform. Three
|
||||
/// for most cameras.
|
||||
|
||||
uint32 Channels () const
|
||||
{
|
||||
return fChannels;
|
||||
}
|
||||
|
||||
/// Setter for white point. Value is as XY colorspace coordinate.
|
||||
/// \param white White point to set as an XY value.
|
||||
|
||||
void SetWhiteXY (const dng_xy_coord &white);
|
||||
|
||||
/// Getter for white point. Value is as XY colorspace coordinate.
|
||||
/// \retval XY value of white point.
|
||||
|
||||
const dng_xy_coord & WhiteXY () const;
|
||||
|
||||
/// Return white point in camera native color coordinates.
|
||||
/// \retval A dng_vector with components ranging from 0.0 to 1.0
|
||||
/// that is normalized such that one component is equal to 1.0 .
|
||||
|
||||
const dng_vector & CameraWhite () const;
|
||||
|
||||
/// Getter for camera to Profile Connection Space color transform.
|
||||
/// \retval A transform that takes into account all camera calibration
|
||||
/// transforms and white point.
|
||||
|
||||
const dng_matrix & CameraToPCS () const;
|
||||
|
||||
/// Getter for Profile Connection Space to camera color transform.
|
||||
/// \retval A transform that takes into account all camera calibration
|
||||
/// transforms and white point.
|
||||
|
||||
const dng_matrix & PCStoCamera () const;
|
||||
|
||||
/// Return the XY value to use for SetWhiteXY for a given camera color
|
||||
/// space coordinate as the white point.
|
||||
/// \param neutral A camera color space value to use for white point.
|
||||
/// Components range from 0.0 to 1.0 and should be normalized such that
|
||||
/// the largest value is 1.0 .
|
||||
/// \retval White point in XY space that makes neutral map to this
|
||||
/// XY value as closely as possible.
|
||||
|
||||
dng_xy_coord NeutralToXY (const dng_vector &neutral);
|
||||
|
||||
private:
|
||||
|
||||
dng_matrix FindXYZtoCamera (const dng_xy_coord &white,
|
||||
dng_matrix *forwardMatrix = NULL,
|
||||
dng_matrix *reductionMatrix = NULL,
|
||||
dng_matrix *cameraCalibration = NULL);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,388 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Functions and classes for working with dates and times in DNG files.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_date_time__
|
||||
#define __dng_date_time__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class for holding a date/time and converting to and from relevant
|
||||
/// date/time formats
|
||||
|
||||
class dng_date_time
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
uint32 fYear;
|
||||
uint32 fMonth;
|
||||
uint32 fDay;
|
||||
uint32 fHour;
|
||||
uint32 fMinute;
|
||||
uint32 fSecond;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an invalid date/time
|
||||
|
||||
dng_date_time ();
|
||||
|
||||
/// Construct a date/time with specific values.
|
||||
/// \param year Year to use as actual integer value, such as 2006.
|
||||
/// \param month Month to use from 1 - 12, where 1 is January.
|
||||
/// \param day Day of month to use from 1 -31, where 1 is the first.
|
||||
/// \param hour Hour of day to use from 0 - 23, where 0 is midnight.
|
||||
/// \param minute Minute of hour to use from 0 - 59.
|
||||
/// \param second Second of minute to use from 0 - 59.
|
||||
|
||||
dng_date_time (uint32 year,
|
||||
uint32 month,
|
||||
uint32 day,
|
||||
uint32 hour,
|
||||
uint32 minute,
|
||||
uint32 second);
|
||||
|
||||
/// Predicate to determine if a date is valid.
|
||||
/// \retval true if all fields are within range.
|
||||
|
||||
bool IsValid () const;
|
||||
|
||||
/// Predicate to determine if a date is invalid.
|
||||
/// \retval true if any field is out of range.
|
||||
|
||||
bool NotValid () const
|
||||
{
|
||||
return !IsValid ();
|
||||
}
|
||||
|
||||
/// Equal operator.
|
||||
|
||||
bool operator== (const dng_date_time &dt) const
|
||||
{
|
||||
return fYear == dt.fYear &&
|
||||
fMonth == dt.fMonth &&
|
||||
fDay == dt.fDay &&
|
||||
fHour == dt.fHour &&
|
||||
fMinute == dt.fMinute &&
|
||||
fSecond == dt.fSecond;
|
||||
}
|
||||
|
||||
// Not-equal operator.
|
||||
|
||||
bool operator!= (const dng_date_time &dt) const
|
||||
{
|
||||
return !(*this == dt);
|
||||
}
|
||||
|
||||
/// Set date to an invalid value.
|
||||
|
||||
void Clear ();
|
||||
|
||||
/// Parse an EXIF format date string.
|
||||
/// \param s Input date string to parse.
|
||||
/// \retval true if date was parsed successfully and date is valid.
|
||||
|
||||
bool Parse (const char *s);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class for holding a time zone.
|
||||
|
||||
class dng_time_zone
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
kMaxOffsetHours = 15,
|
||||
kMinOffsetHours = -kMaxOffsetHours,
|
||||
|
||||
kMaxOffsetMinutes = kMaxOffsetHours * 60,
|
||||
kMinOffsetMinutes = kMinOffsetHours * 60,
|
||||
|
||||
kInvalidOffset = kMinOffsetMinutes - 1
|
||||
|
||||
};
|
||||
|
||||
// Offset from GMT in minutes. Positive numbers are
|
||||
// ahead of GMT, negative number are behind GMT.
|
||||
|
||||
int32 fOffsetMinutes;
|
||||
|
||||
public:
|
||||
|
||||
dng_time_zone ()
|
||||
: fOffsetMinutes (kInvalidOffset)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear ()
|
||||
{
|
||||
fOffsetMinutes = kInvalidOffset;
|
||||
}
|
||||
|
||||
void SetOffsetHours (int32 offset)
|
||||
{
|
||||
fOffsetMinutes = offset * 60;
|
||||
}
|
||||
|
||||
void SetOffsetMinutes (int32 offset)
|
||||
{
|
||||
fOffsetMinutes = offset;
|
||||
}
|
||||
|
||||
void SetOffsetSeconds (int32 offset)
|
||||
{
|
||||
fOffsetMinutes = (offset > 0) ? ((offset + 30) / 60)
|
||||
: ((offset - 30) / 60);
|
||||
}
|
||||
|
||||
bool IsValid () const
|
||||
{
|
||||
return fOffsetMinutes >= kMinOffsetMinutes &&
|
||||
fOffsetMinutes <= kMaxOffsetMinutes;
|
||||
}
|
||||
|
||||
bool NotValid () const
|
||||
{
|
||||
return !IsValid ();
|
||||
}
|
||||
|
||||
int32 OffsetMinutes () const
|
||||
{
|
||||
return fOffsetMinutes;
|
||||
}
|
||||
|
||||
bool IsExactHourOffset () const
|
||||
{
|
||||
return IsValid () && ((fOffsetMinutes % 60) == 0);
|
||||
}
|
||||
|
||||
int32 ExactHourOffset () const
|
||||
{
|
||||
return fOffsetMinutes / 60;
|
||||
}
|
||||
|
||||
dng_string Encode_ISO_8601 () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class for holding complete data/time/zone information.
|
||||
|
||||
class dng_date_time_info
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
// Is only the date valid and not the time?
|
||||
|
||||
bool fDateOnly;
|
||||
|
||||
// Date and time.
|
||||
|
||||
dng_date_time fDateTime;
|
||||
|
||||
// Subseconds string (stored in a separate tag in EXIF).
|
||||
|
||||
dng_string fSubseconds;
|
||||
|
||||
// Time zone, if known.
|
||||
|
||||
dng_time_zone fTimeZone;
|
||||
|
||||
public:
|
||||
|
||||
dng_date_time_info ();
|
||||
|
||||
bool IsValid () const;
|
||||
|
||||
bool NotValid () const
|
||||
{
|
||||
return !IsValid ();
|
||||
}
|
||||
|
||||
void Clear ()
|
||||
{
|
||||
*this = dng_date_time_info ();
|
||||
}
|
||||
|
||||
bool IsDateOnly () const
|
||||
{
|
||||
return fDateOnly;
|
||||
}
|
||||
|
||||
const dng_date_time & DateTime () const
|
||||
{
|
||||
return fDateTime;
|
||||
}
|
||||
|
||||
void SetDateTime (const dng_date_time &dt)
|
||||
{
|
||||
fDateOnly = false;
|
||||
fDateTime = dt;
|
||||
}
|
||||
|
||||
const dng_string & Subseconds () const
|
||||
{
|
||||
return fSubseconds;
|
||||
}
|
||||
|
||||
void SetSubseconds (const dng_string &s)
|
||||
{
|
||||
fSubseconds = s;
|
||||
}
|
||||
|
||||
const dng_time_zone & TimeZone () const
|
||||
{
|
||||
return fTimeZone;
|
||||
}
|
||||
|
||||
void SetZone (const dng_time_zone &zone)
|
||||
{
|
||||
fTimeZone = zone;
|
||||
}
|
||||
|
||||
void ClearZone ()
|
||||
{
|
||||
fTimeZone.Clear ();
|
||||
}
|
||||
|
||||
void SetOffsetTime (const dng_string &s);
|
||||
|
||||
dng_string OffsetTime () const;
|
||||
|
||||
void Decode_ISO_8601 (const char *s);
|
||||
|
||||
dng_string Encode_ISO_8601 () const;
|
||||
|
||||
void Decode_IPTC_Date (const char *s);
|
||||
|
||||
dng_string Encode_IPTC_Date () const;
|
||||
|
||||
void Decode_IPTC_Time (const char *s);
|
||||
|
||||
dng_string Encode_IPTC_Time () const;
|
||||
|
||||
private:
|
||||
|
||||
void SetDate (uint32 year,
|
||||
uint32 month,
|
||||
uint32 day);
|
||||
|
||||
void SetTime (uint32 hour,
|
||||
uint32 minute,
|
||||
uint32 second);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Get the current date/time and timezone.
|
||||
/// \param info Receives current data/time/zone.
|
||||
|
||||
void CurrentDateTimeAndZone (dng_date_time_info &info);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Convert UNIX "seconds since Jan 1, 1970" time to a dng_date_time
|
||||
|
||||
void DecodeUnixTime (uint32 unixTime, dng_date_time &dt);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Return timezone of current location at a given date.
|
||||
/// \param dt Date at which to compute timezone difference. (For example, used
|
||||
/// to determine Daylight Savings, etc.)
|
||||
/// \retval Time zone for date/time dt.
|
||||
|
||||
dng_time_zone LocalTimeZone (const dng_date_time &dt);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Tag to encode date represenation format
|
||||
|
||||
enum dng_date_time_format
|
||||
{
|
||||
dng_date_time_format_unknown = 0, /// Date format not known
|
||||
dng_date_time_format_exif = 1, /// EXIF date string
|
||||
dng_date_time_format_unix_little_endian = 2, /// 32-bit UNIX time as 4-byte little endian
|
||||
dng_date_time_format_unix_big_endian = 3 /// 32-bit UNIX time as 4-byte big endian
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Store file offset from which date was read.
|
||||
///
|
||||
/// Used internally by Adobe to update date in original file.
|
||||
/// \warning Use at your own risk.
|
||||
|
||||
class dng_date_time_storage_info
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
uint64 fOffset;
|
||||
|
||||
dng_date_time_format fFormat;
|
||||
|
||||
public:
|
||||
|
||||
/// The default constructor initializes to an invalid state.
|
||||
|
||||
dng_date_time_storage_info ();
|
||||
|
||||
/// Construct with file offset and date format.
|
||||
|
||||
dng_date_time_storage_info (uint64 offset,
|
||||
dng_date_time_format format);
|
||||
|
||||
/// Predicate to determine if an offset is valid.
|
||||
/// \retval true if offset is valid.
|
||||
|
||||
bool IsValid () const;
|
||||
|
||||
// The accessors throw if the data is not valid.
|
||||
|
||||
/// Getter for offset in file.
|
||||
/// \exception dng_exception with fErrorCode equal to dng_error_unknown
|
||||
/// if offset is not valid.
|
||||
|
||||
uint64 Offset () const;
|
||||
|
||||
/// Get for format date was originally stored in file. Throws a
|
||||
/// dng_error_unknown exception if offset is invalid.
|
||||
/// \exception dng_exception with fErrorCode equal to dng_error_unknown
|
||||
/// if offset is not valid.
|
||||
|
||||
dng_date_time_format Format () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,54 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Error code values.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_errors__
|
||||
#define __dng_errors__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Type for all errors used in DNG SDK. Generally held inside a dng_exception.
|
||||
|
||||
typedef int32 dng_error_code;
|
||||
|
||||
enum
|
||||
{
|
||||
dng_error_none = 0, //!< No error. Success.
|
||||
dng_error_unknown = 100000, //!< Logic or program error or other unclassifiable error.
|
||||
dng_error_not_yet_implemented, //!< Functionality requested is not yet implemented.
|
||||
dng_error_silent, //!< An error which should not be signalled to user.
|
||||
dng_error_user_canceled, //!< Processing stopped by user (or host application) request
|
||||
dng_error_host_insufficient, //!< Necessary host functionality is not present.
|
||||
dng_error_memory, //!< Out of memory.
|
||||
dng_error_bad_format, //!< File format is not valid.
|
||||
dng_error_matrix_math, //!< Matrix has wrong shape, is badly conditioned, or similar problem.
|
||||
dng_error_open_file, //!< Could not open file.
|
||||
dng_error_read_file, //!< Error reading file.
|
||||
dng_error_write_file, //!< Error writing file.
|
||||
dng_error_end_of_file, //!< Unexpected end of file.
|
||||
dng_error_file_is_damaged, //!< File is damaged in some way.
|
||||
dng_error_image_too_big_dng, //!< Image is too big to save as DNG.
|
||||
dng_error_image_too_big_tiff, //!< Image is too big to save as TIFF.
|
||||
dng_error_unsupported_dng, //!< DNG version is unsupported.
|
||||
dng_error_overflow //!< Arithmetic overflow.
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,219 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_exceptions.h"
|
||||
|
||||
#include "dng_flags.h"
|
||||
#include "dng_globals.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef qDNGReportErrors
|
||||
// assuming this isn't enable on Win, because it's using printf, but an app can redirect that to console
|
||||
#define qDNGReportErrors ((qDNGDebug && qMacOS) || qDNGValidate)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ReportWarning (const char *message,
|
||||
const char *sub_message)
|
||||
{
|
||||
|
||||
#if qDNGReportErrors
|
||||
|
||||
#ifdef cr_logw
|
||||
|
||||
cr_logs("report", 2, NULL, 0, cr_logfunc(), "%s %s\n", message, sub_message ? sub_message : "");
|
||||
|
||||
#else
|
||||
|
||||
if (sub_message)
|
||||
fprintf (stderr, "*** Warning: %s (%s) ***\n", message, sub_message);
|
||||
else
|
||||
fprintf (stderr, "*** Warning: %s ***\n", message);
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
(void) message;
|
||||
(void) sub_message;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ReportError (const char *message,
|
||||
const char *sub_message)
|
||||
{
|
||||
|
||||
#if qDNGReportErrors
|
||||
|
||||
#ifdef cr_loge
|
||||
|
||||
cr_logs("report", 3, NULL, 0, cr_logfunc(), "%s %s\n", message, sub_message ? sub_message : "");
|
||||
|
||||
#else
|
||||
|
||||
if (sub_message)
|
||||
fprintf (stderr, "*** Error: %s (%s) ***\n", message, sub_message);
|
||||
else
|
||||
fprintf (stderr, "*** Error: %s ***\n", message);
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
(void) message;
|
||||
(void) sub_message;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void Throw_dng_error (dng_error_code err,
|
||||
const char *message,
|
||||
const char *sub_message,
|
||||
bool silent)
|
||||
{
|
||||
|
||||
#if qDNGReportErrors
|
||||
|
||||
{
|
||||
|
||||
if (!message)
|
||||
{
|
||||
|
||||
switch (err)
|
||||
{
|
||||
|
||||
case dng_error_none:
|
||||
case dng_error_silent:
|
||||
case dng_error_user_canceled:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_not_yet_implemented:
|
||||
{
|
||||
message = "Not yet implemented";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_host_insufficient:
|
||||
{
|
||||
message = "Host insufficient";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_memory:
|
||||
{
|
||||
message = "Unable to allocate memory";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_bad_format:
|
||||
{
|
||||
message = "File format is invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_matrix_math:
|
||||
{
|
||||
message = "Matrix math error";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_open_file:
|
||||
{
|
||||
message = "Unable to open file";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_read_file:
|
||||
{
|
||||
message = "File read error";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_write_file:
|
||||
{
|
||||
message = "File write error";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_end_of_file:
|
||||
{
|
||||
message = "Unexpected end-of-file";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_file_is_damaged:
|
||||
{
|
||||
message = "File is damaged";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_image_too_big_dng:
|
||||
{
|
||||
message = "Image is too big to save as DNG";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_image_too_big_tiff:
|
||||
{
|
||||
message = "Image is too big to save as TIFF";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_unsupported_dng:
|
||||
{
|
||||
message = "DNG version is unsupported";
|
||||
break;
|
||||
}
|
||||
|
||||
case dng_error_overflow:
|
||||
{
|
||||
message = "Arithmetic overflow/underflow";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
message = "Unknown error";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (message && !silent)
|
||||
{
|
||||
ReportError (message, sub_message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
(void) message;
|
||||
(void) sub_message;
|
||||
(void) silent;
|
||||
|
||||
#endif
|
||||
|
||||
throw dng_exception (err);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,319 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* C++ exception support for DNG SDK.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_exceptions__
|
||||
#define __dng_exceptions__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_errors.h"
|
||||
#include "dng_flags.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_NO_RETURN
|
||||
#ifdef __GNUC__
|
||||
#define DNG_NO_RETURN __attribute__((noreturn))
|
||||
#else
|
||||
#define DNG_NO_RETURN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Display a warning message. Note that this may just eat the message.
|
||||
|
||||
void ReportWarning (const char *message,
|
||||
const char *sub_message = NULL);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Display an error message. Note that this may just eat the message.
|
||||
|
||||
void ReportError (const char *message,
|
||||
const char *sub_message = NULL);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief All exceptions thrown by the DNG SDK use this exception class.
|
||||
|
||||
class dng_exception
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_error_code fErrorCode;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an exception representing the given error code.
|
||||
/// \param code Error code this exception is for.
|
||||
|
||||
dng_exception (dng_error_code code)
|
||||
|
||||
: fErrorCode (code)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dng_exception ()
|
||||
{
|
||||
}
|
||||
|
||||
/// Getter for error code of this exception
|
||||
/// \retval The error code of this exception.
|
||||
|
||||
dng_error_code ErrorCode () const
|
||||
{
|
||||
return fErrorCode;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/// \brief Throw an exception based on an arbitrary error code.
|
||||
|
||||
void Throw_dng_error (dng_error_code err,
|
||||
const char * message = NULL,
|
||||
const char * sub_message = NULL,
|
||||
bool silent = false) DNG_NO_RETURN;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code if
|
||||
/// error_code is not dng_error_none .
|
||||
|
||||
inline void Fail_dng_error (dng_error_code err)
|
||||
{
|
||||
|
||||
if (err != dng_error_none)
|
||||
{
|
||||
|
||||
Throw_dng_error (err);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_unknown .
|
||||
|
||||
inline void ThrowProgramError (const char * sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_unknown, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_overflow.
|
||||
|
||||
inline void ThrowOverflow (const char * sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_overflow, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_not_yet_implemented .
|
||||
|
||||
inline void ThrowNotYetImplemented (const char * sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_not_yet_implemented, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_silent .
|
||||
|
||||
inline void ThrowSilentError ()
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_silent);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_user_canceled .
|
||||
|
||||
inline void ThrowUserCanceled ()
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_user_canceled);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_host_insufficient .
|
||||
|
||||
inline void ThrowHostInsufficient (const char * sub_message = NULL,
|
||||
bool silent = false)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_host_insufficient, NULL, sub_message, silent);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_memory .
|
||||
|
||||
inline void ThrowMemoryFull (const char * sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_memory, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_bad_format .
|
||||
|
||||
inline void ThrowBadFormat (const char * sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_bad_format, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_matrix_math .
|
||||
|
||||
inline void ThrowMatrixMath (const char * sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_matrix_math, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_open_file .
|
||||
|
||||
inline void ThrowOpenFile (const char * sub_message = NULL, bool silent = false)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_open_file, NULL, sub_message, silent);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_read_file .
|
||||
|
||||
inline void ThrowReadFile (const char *sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_read_file, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_write_file .
|
||||
|
||||
inline void ThrowWriteFile (const char *sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_write_file, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_end_of_file .
|
||||
|
||||
inline void ThrowEndOfFile (const char *sub_message = NULL)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_end_of_file, NULL, sub_message);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_file_is_damaged .
|
||||
|
||||
inline void ThrowFileIsDamaged ()
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_file_is_damaged);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_image_too_big_dng .
|
||||
|
||||
inline void ThrowImageTooBigDNG ()
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_image_too_big_dng);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_image_too_big_tiff .
|
||||
|
||||
inline void ThrowImageTooBigTIFF ()
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_image_too_big_tiff);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Convenience function to throw dng_exception with error code
|
||||
/// dng_error_unsupported_dng .
|
||||
|
||||
inline void ThrowUnsupportedDNG ()
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_unsupported_dng);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,377 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* EXIF read access support. See the \ref spec_exif "EXIF specification" for full
|
||||
* description of tags.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_exif__
|
||||
#define __dng_exif__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_date_time.h"
|
||||
#include "dng_fingerprint.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_rational.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Container class for parsing and holding EXIF tags.
|
||||
///
|
||||
/// Public member fields are documented in \ref spec_exif "EXIF specification."
|
||||
|
||||
class dng_exif
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_string fImageDescription;
|
||||
dng_string fMake;
|
||||
dng_string fModel;
|
||||
dng_string fSoftware;
|
||||
dng_string fArtist;
|
||||
dng_string fCopyright;
|
||||
dng_string fCopyright2;
|
||||
dng_string fUserComment;
|
||||
|
||||
dng_date_time_info fDateTime;
|
||||
dng_date_time_storage_info fDateTimeStorageInfo;
|
||||
|
||||
dng_date_time_info fDateTimeOriginal;
|
||||
dng_date_time_storage_info fDateTimeOriginalStorageInfo;
|
||||
|
||||
dng_date_time_info fDateTimeDigitized;
|
||||
dng_date_time_storage_info fDateTimeDigitizedStorageInfo;
|
||||
|
||||
uint32 fTIFF_EP_StandardID;
|
||||
uint32 fExifVersion;
|
||||
uint32 fFlashPixVersion;
|
||||
|
||||
dng_urational fExposureTime;
|
||||
dng_urational fFNumber;
|
||||
dng_srational fShutterSpeedValue;
|
||||
dng_urational fApertureValue;
|
||||
dng_srational fBrightnessValue;
|
||||
dng_srational fExposureBiasValue;
|
||||
dng_urational fMaxApertureValue;
|
||||
dng_urational fFocalLength;
|
||||
dng_urational fDigitalZoomRatio;
|
||||
dng_urational fExposureIndex;
|
||||
dng_urational fSubjectDistance;
|
||||
dng_urational fGamma;
|
||||
|
||||
dng_urational fBatteryLevelR;
|
||||
dng_string fBatteryLevelA;
|
||||
|
||||
uint32 fExposureProgram;
|
||||
uint32 fMeteringMode;
|
||||
uint32 fLightSource;
|
||||
uint32 fFlash;
|
||||
uint32 fFlashMask;
|
||||
uint32 fSensingMethod;
|
||||
uint32 fColorSpace;
|
||||
uint32 fFileSource;
|
||||
uint32 fSceneType;
|
||||
uint32 fCustomRendered;
|
||||
uint32 fExposureMode;
|
||||
uint32 fWhiteBalance;
|
||||
uint32 fSceneCaptureType;
|
||||
uint32 fGainControl;
|
||||
uint32 fContrast;
|
||||
uint32 fSaturation;
|
||||
uint32 fSharpness;
|
||||
uint32 fSubjectDistanceRange;
|
||||
uint32 fSelfTimerMode;
|
||||
uint32 fImageNumber;
|
||||
|
||||
uint32 fFocalLengthIn35mmFilm;
|
||||
|
||||
uint32 fISOSpeedRatings [3]; // EXIF 2.3: PhotographicSensitivity.
|
||||
|
||||
// Sensitivity tags added in EXIF 2.3.
|
||||
|
||||
uint32 fSensitivityType;
|
||||
uint32 fStandardOutputSensitivity;
|
||||
uint32 fRecommendedExposureIndex;
|
||||
uint32 fISOSpeed;
|
||||
uint32 fISOSpeedLatitudeyyy;
|
||||
uint32 fISOSpeedLatitudezzz;
|
||||
|
||||
uint32 fSubjectAreaCount;
|
||||
uint32 fSubjectArea [4];
|
||||
|
||||
uint32 fComponentsConfiguration;
|
||||
|
||||
dng_urational fCompresssedBitsPerPixel;
|
||||
|
||||
uint32 fPixelXDimension;
|
||||
uint32 fPixelYDimension;
|
||||
|
||||
dng_urational fFocalPlaneXResolution;
|
||||
dng_urational fFocalPlaneYResolution;
|
||||
|
||||
uint32 fFocalPlaneResolutionUnit;
|
||||
|
||||
uint32 fCFARepeatPatternRows;
|
||||
uint32 fCFARepeatPatternCols;
|
||||
|
||||
uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
|
||||
|
||||
dng_fingerprint fImageUniqueID;
|
||||
|
||||
uint32 fGPSVersionID;
|
||||
dng_string fGPSLatitudeRef;
|
||||
dng_urational fGPSLatitude [3];
|
||||
dng_string fGPSLongitudeRef;
|
||||
dng_urational fGPSLongitude [3];
|
||||
uint32 fGPSAltitudeRef;
|
||||
dng_urational fGPSAltitude;
|
||||
dng_urational fGPSTimeStamp [3];
|
||||
dng_string fGPSSatellites;
|
||||
dng_string fGPSStatus;
|
||||
dng_string fGPSMeasureMode;
|
||||
dng_urational fGPSDOP;
|
||||
dng_string fGPSSpeedRef;
|
||||
dng_urational fGPSSpeed;
|
||||
dng_string fGPSTrackRef;
|
||||
dng_urational fGPSTrack;
|
||||
dng_string fGPSImgDirectionRef;
|
||||
dng_urational fGPSImgDirection;
|
||||
dng_string fGPSMapDatum;
|
||||
dng_string fGPSDestLatitudeRef;
|
||||
dng_urational fGPSDestLatitude [3];
|
||||
dng_string fGPSDestLongitudeRef;
|
||||
dng_urational fGPSDestLongitude [3];
|
||||
dng_string fGPSDestBearingRef;
|
||||
dng_urational fGPSDestBearing;
|
||||
dng_string fGPSDestDistanceRef;
|
||||
dng_urational fGPSDestDistance;
|
||||
dng_string fGPSProcessingMethod;
|
||||
dng_string fGPSAreaInformation;
|
||||
dng_string fGPSDateStamp;
|
||||
uint32 fGPSDifferential;
|
||||
dng_urational fGPSHPositioningError;
|
||||
|
||||
dng_string fInteroperabilityIndex;
|
||||
|
||||
uint32 fInteroperabilityVersion;
|
||||
|
||||
dng_string fRelatedImageFileFormat;
|
||||
|
||||
uint32 fRelatedImageWidth;
|
||||
uint32 fRelatedImageLength;
|
||||
|
||||
dng_string fCameraSerialNumber; // EXIF 2.3: BodySerialNumber.
|
||||
|
||||
dng_urational fLensInfo [4]; // EXIF 2.3: LensSpecification.
|
||||
|
||||
dng_string fLensID;
|
||||
dng_string fLensMake;
|
||||
dng_string fLensName; // EXIF 2.3: LensModel.
|
||||
dng_string fLensSerialNumber;
|
||||
|
||||
// Was the lens name field read from a LensModel tag?
|
||||
|
||||
bool fLensNameWasReadFromExif;
|
||||
|
||||
// Private field to hold the approximate focus distance of the lens, in
|
||||
// meters. This value is often coarsely measured/reported and hence should be
|
||||
// interpreted only as a rough estimate of the true distance from the plane
|
||||
// of focus (in object space) to the focal plane. It is still useful for the
|
||||
// purposes of applying lens corrections.
|
||||
|
||||
dng_urational fApproxFocusDistance;
|
||||
|
||||
dng_srational fFlashCompensation;
|
||||
|
||||
dng_string fOwnerName; // EXIF 2.3: CameraOwnerName.
|
||||
dng_string fFirmware;
|
||||
|
||||
// EXIF 2.3.1:
|
||||
|
||||
dng_srational fTemperature;
|
||||
dng_urational fHumidity;
|
||||
dng_urational fPressure;
|
||||
dng_srational fWaterDepth;
|
||||
dng_urational fAcceleration;
|
||||
dng_srational fCameraElevationAngle;
|
||||
|
||||
// Not really part of EXIF, but some formats may use.
|
||||
|
||||
dng_string fTitle;
|
||||
|
||||
// Image-specific radial distortion correction metadata that can be
|
||||
// used later during (UI-driven) lens profile corrections. Same model
|
||||
// as DNG opcode model.
|
||||
|
||||
dng_srational fLensDistortInfo [4];
|
||||
|
||||
public:
|
||||
|
||||
dng_exif ();
|
||||
|
||||
virtual ~dng_exif ();
|
||||
|
||||
/// Make clone.
|
||||
|
||||
virtual dng_exif * Clone () const;
|
||||
|
||||
/// Clear all EXIF fields.
|
||||
|
||||
void SetEmpty ();
|
||||
|
||||
/// Copy all GPS-related fields.
|
||||
/// \param exif Source object from which to copy GPS fields.
|
||||
|
||||
void CopyGPSFrom (const dng_exif &exif);
|
||||
|
||||
/// Utility to fix up common errors and rounding issues with EXIF exposure
|
||||
/// times.
|
||||
|
||||
static real64 SnapExposureTime (real64 et);
|
||||
|
||||
/// Set exposure time and shutter speed fields. Optionally fix up common
|
||||
/// errors and rounding issues with EXIF exposure times.
|
||||
/// \param et Exposure time in seconds.
|
||||
/// \param snap Set to true to fix up common errors and rounding issues with
|
||||
/// EXIF exposure times.
|
||||
|
||||
void SetExposureTime (real64 et,
|
||||
bool snap = true);
|
||||
|
||||
/// Set shutter speed value (APEX units) and exposure time.
|
||||
/// \param ss Shutter speed in APEX units.
|
||||
|
||||
void SetShutterSpeedValue (real64 ss);
|
||||
|
||||
/// Utility to encode f-number as a rational.
|
||||
/// \param fs The f-number to encode.
|
||||
|
||||
static dng_urational EncodeFNumber (real64 fs);
|
||||
|
||||
/// Set the FNumber and ApertureValue fields.
|
||||
/// \param fs The f-number to set.
|
||||
|
||||
void SetFNumber (real64 fs);
|
||||
|
||||
/// Set the FNumber and ApertureValue fields.
|
||||
/// \param av The aperture value (APEX units).
|
||||
|
||||
void SetApertureValue (real64 av);
|
||||
|
||||
/// Utility to convert aperture value (APEX units) to f-number.
|
||||
/// \param av The aperture value (APEX units) to convert.
|
||||
|
||||
static real64 ApertureValueToFNumber (real64 av);
|
||||
|
||||
/// Utility to convert aperture value (APEX units) to f-number.
|
||||
/// \param av The aperture value (APEX units) to convert.
|
||||
|
||||
static real64 ApertureValueToFNumber (const dng_urational &av);
|
||||
|
||||
/// Utility to convert f-number to aperture value (APEX units).
|
||||
/// \param fNumber The f-number to convert.
|
||||
|
||||
static real64 FNumberToApertureValue (real64 fNumber);
|
||||
|
||||
/// Utility to convert f-number to aperture value (APEX units).
|
||||
/// \param fNumber The f-number to convert.
|
||||
|
||||
static real64 FNumberToApertureValue (const dng_urational &fNumber);
|
||||
|
||||
/// Set the DateTime field.
|
||||
/// \param dt The DateTime value.
|
||||
|
||||
void UpdateDateTime (const dng_date_time_info &dt);
|
||||
|
||||
/// Returns true iff the EXIF version is at least 2.3.
|
||||
|
||||
bool AtLeastVersion0230 () const;
|
||||
|
||||
/// Returns true iff the EXIF version is at least 2.3.1.
|
||||
|
||||
bool AtLeastVersion0231 () const;
|
||||
|
||||
/// Sets the EXIF version to 2.3.1.
|
||||
|
||||
void SetVersion0231 ();
|
||||
|
||||
bool HasLensDistortInfo () const;
|
||||
|
||||
void SetLensDistortInfo (const dng_vector ¶ms);
|
||||
|
||||
virtual bool ParseTag (dng_stream &stream,
|
||||
dng_shared &shared,
|
||||
uint32 parentCode,
|
||||
bool isMainIFD,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
virtual void PostParse (dng_host &host,
|
||||
dng_shared &shared);
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool Parse_ifd0 (dng_stream &stream,
|
||||
dng_shared &shared,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
virtual bool Parse_ifd0_main (dng_stream &stream,
|
||||
dng_shared &shared,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
virtual bool Parse_ifd0_exif (dng_stream &stream,
|
||||
dng_shared &shared,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
virtual bool Parse_gps (dng_stream &stream,
|
||||
dng_shared &shared,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
virtual bool Parse_interoperability (dng_stream &stream,
|
||||
dng_shared &shared,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,26 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Include file to set optimization to highest level for performance-critical routines.
|
||||
* Normal files should have otpimization set to normal level to save code size as there is less
|
||||
* cache pollution this way.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Include this file in modules that contain routines that should be as fast
|
||||
// as possible, even at the expense of slight code size increases.
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma optimize ("t", on)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,182 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_file_stream.h"
|
||||
|
||||
#include "dng_exceptions.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_file_stream::dng_file_stream (const char *filename,
|
||||
bool output,
|
||||
uint32 bufferSize)
|
||||
|
||||
: dng_stream ((dng_abort_sniffer *) NULL,
|
||||
bufferSize,
|
||||
0)
|
||||
|
||||
, fFile (NULL)
|
||||
|
||||
{
|
||||
|
||||
fFile = fopen (filename, output ? "wb" : "rb");
|
||||
|
||||
if (!fFile)
|
||||
{
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
ReportError ("Unable to open file",
|
||||
filename);
|
||||
|
||||
ThrowSilentError ();
|
||||
|
||||
#else
|
||||
|
||||
ThrowOpenFile ();
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qWinOS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_file_stream::dng_file_stream (const wchar_t *filename,
|
||||
bool output,
|
||||
uint32 bufferSize)
|
||||
|
||||
: dng_stream ((dng_abort_sniffer *) NULL,
|
||||
bufferSize,
|
||||
0)
|
||||
|
||||
, fFile (NULL)
|
||||
|
||||
{
|
||||
|
||||
fFile = _wfopen (filename, output ? L"wb" : L"rb");
|
||||
|
||||
if (!fFile)
|
||||
{
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
char filenameCString[256];
|
||||
|
||||
size_t returnCount;
|
||||
|
||||
wcstombs_s (&returnCount,
|
||||
filenameCString,
|
||||
256,
|
||||
filename,
|
||||
_TRUNCATE);
|
||||
|
||||
ReportError ("Unable to open file",
|
||||
filenameCString);
|
||||
|
||||
ThrowSilentError ();
|
||||
|
||||
#else
|
||||
|
||||
ThrowOpenFile ();
|
||||
|
||||
#endif // qDNGValidate
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif // qWinOS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_file_stream::~dng_file_stream ()
|
||||
{
|
||||
|
||||
if (fFile)
|
||||
{
|
||||
fclose (fFile);
|
||||
fFile = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint64 dng_file_stream::DoGetLength ()
|
||||
{
|
||||
|
||||
if (fseek (fFile, 0, SEEK_END) != 0)
|
||||
{
|
||||
|
||||
ThrowReadFile ();
|
||||
|
||||
}
|
||||
|
||||
return (uint64) ftell (fFile);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_file_stream::DoRead (void *data,
|
||||
uint32 count,
|
||||
uint64 offset)
|
||||
{
|
||||
|
||||
if (fseek (fFile, (long) offset, SEEK_SET) != 0)
|
||||
{
|
||||
|
||||
ThrowReadFile ();
|
||||
|
||||
}
|
||||
|
||||
uint32 bytesRead = (uint32) fread (data, 1, count, fFile);
|
||||
|
||||
if (bytesRead != count)
|
||||
{
|
||||
|
||||
ThrowReadFile ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_file_stream::DoWrite (const void *data,
|
||||
uint32 count,
|
||||
uint64 offset)
|
||||
{
|
||||
|
||||
if (fseek (fFile, (uint32) offset, SEEK_SET) != 0)
|
||||
{
|
||||
|
||||
ThrowWriteFile ();
|
||||
|
||||
}
|
||||
|
||||
uint32 bytesWritten = (uint32) fwrite (data, 1, count, fFile);
|
||||
|
||||
if (bytesWritten != count)
|
||||
{
|
||||
|
||||
ThrowWriteFile ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,72 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Simple, portable, file read/write support.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_file_stream__
|
||||
#define __dng_file_stream__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_stream.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A stream to/from a disk file. See dng_stream for read/write interface
|
||||
|
||||
class dng_file_stream: public dng_stream
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
FILE *fFile;
|
||||
|
||||
public:
|
||||
|
||||
/// Open a stream on a file.
|
||||
/// \param filename Pathname in platform synax.
|
||||
/// \param output Set to true if writing, false otherwise.
|
||||
/// \param bufferSize size of internal buffer to use. Defaults to 4k.
|
||||
|
||||
dng_file_stream (const char *filename,
|
||||
bool output = false,
|
||||
uint32 bufferSize = kDefaultBufferSize);
|
||||
|
||||
#if qWinOS
|
||||
|
||||
dng_file_stream (const wchar_t *filename,
|
||||
bool output = false,
|
||||
uint32 bufferSize = kDefaultBufferSize);
|
||||
|
||||
#endif // qWinOS
|
||||
|
||||
virtual ~dng_file_stream ();
|
||||
|
||||
protected:
|
||||
|
||||
virtual uint64 DoGetLength ();
|
||||
|
||||
virtual void DoRead (void *data,
|
||||
uint32 count,
|
||||
uint64 offset);
|
||||
|
||||
virtual void DoWrite (const void *data,
|
||||
uint32 count,
|
||||
uint64 offset);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,157 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_filter_task.h"
|
||||
|
||||
#include "dng_bottlenecks.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_image.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_tag_types.h"
|
||||
#include "dng_tag_values.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_filter_task::dng_filter_task (const char *name,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage)
|
||||
|
||||
: dng_area_task (name)
|
||||
|
||||
, fSrcImage (srcImage)
|
||||
, fDstImage (dstImage)
|
||||
|
||||
, fSrcPlane (0 )
|
||||
, fSrcPlanes (srcImage.Planes ())
|
||||
, fSrcPixelType (srcImage.PixelType ())
|
||||
|
||||
, fDstPlane (0 )
|
||||
, fDstPlanes (dstImage.Planes ())
|
||||
, fDstPixelType (dstImage.PixelType ())
|
||||
|
||||
, fSrcRepeat (1, 1)
|
||||
, fSrcTileSize (0, 0)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_filter_task::~dng_filter_task ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_filter_task::Start (uint32 threadCount,
|
||||
const dng_rect & /* dstArea */,
|
||||
const dng_point &tileSize,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer * /* sniffer */)
|
||||
{
|
||||
|
||||
fSrcTileSize = SrcTileSize (tileSize);
|
||||
|
||||
uint32 srcBufferSize = ComputeBufferSize (fSrcPixelType,
|
||||
fSrcTileSize,
|
||||
fSrcPlanes,
|
||||
padSIMDBytes);
|
||||
|
||||
uint32 dstBufferSize = ComputeBufferSize (fDstPixelType,
|
||||
tileSize,
|
||||
fDstPlanes,
|
||||
padSIMDBytes);
|
||||
|
||||
for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
|
||||
{
|
||||
|
||||
fSrcBuffer [threadIndex] . Reset (allocator->Allocate (srcBufferSize));
|
||||
|
||||
fDstBuffer [threadIndex] . Reset (allocator->Allocate (dstBufferSize));
|
||||
|
||||
// Zero buffers so any pad bytes have defined values.
|
||||
|
||||
DoZeroBytes (fSrcBuffer [threadIndex]->Buffer (),
|
||||
fSrcBuffer [threadIndex]->LogicalSize ());
|
||||
|
||||
DoZeroBytes (fDstBuffer [threadIndex]->Buffer (),
|
||||
fDstBuffer [threadIndex]->LogicalSize ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_filter_task::Process (uint32 threadIndex,
|
||||
const dng_rect &area,
|
||||
dng_abort_sniffer * /* sniffer */)
|
||||
{
|
||||
|
||||
// Find source area for this destination area.
|
||||
|
||||
dng_rect srcArea = SrcArea (area);
|
||||
|
||||
// Safety check.
|
||||
|
||||
int32 src_area_w;
|
||||
int32 src_area_h;
|
||||
|
||||
if (!ConvertUint32ToInt32 (srcArea.W (),
|
||||
&src_area_w) ||
|
||||
!ConvertUint32ToInt32 (srcArea.H (),
|
||||
&src_area_h) ||
|
||||
src_area_w > fSrcTileSize.h ||
|
||||
src_area_h > fSrcTileSize.v)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ("Area exceeds tile size.");
|
||||
|
||||
}
|
||||
|
||||
// Setup srcBuffer.
|
||||
|
||||
dng_pixel_buffer srcBuffer (srcArea,
|
||||
fSrcPlane,
|
||||
fSrcPlanes,
|
||||
fSrcPixelType,
|
||||
pcRowInterleavedAlignSIMD,
|
||||
fSrcBuffer [threadIndex]->Buffer ());
|
||||
|
||||
// Setup dstBuffer.
|
||||
|
||||
dng_pixel_buffer dstBuffer (area,
|
||||
fDstPlane,
|
||||
fDstPlanes,
|
||||
fDstPixelType,
|
||||
pcRowInterleavedAlignSIMD,
|
||||
fDstBuffer [threadIndex]->Buffer ());
|
||||
|
||||
// Get source pixels.
|
||||
|
||||
fSrcImage.Get (srcBuffer,
|
||||
dng_image::edge_repeat,
|
||||
fSrcRepeat.v,
|
||||
fSrcRepeat.h);
|
||||
|
||||
// Process area.
|
||||
|
||||
ProcessArea (threadIndex,
|
||||
srcBuffer,
|
||||
dstBuffer);
|
||||
|
||||
// Save result pixels.
|
||||
|
||||
fDstImage.Put (dstBuffer);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,155 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Specialization of dng_area_task for processing an area from one dng_image to an
|
||||
* area of another.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_filter_task__
|
||||
#define __dng_filter_task__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_area_task.h"
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_point.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Represents a task which filters an area of a source dng_image to an area
|
||||
/// of a destination dng_image.
|
||||
|
||||
class dng_filter_task: public dng_area_task
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
const dng_image &fSrcImage;
|
||||
|
||||
dng_image &fDstImage;
|
||||
|
||||
uint32 fSrcPlane;
|
||||
uint32 fSrcPlanes;
|
||||
uint32 fSrcPixelType;
|
||||
|
||||
uint32 fDstPlane;
|
||||
uint32 fDstPlanes;
|
||||
uint32 fDstPixelType;
|
||||
|
||||
dng_point fSrcRepeat;
|
||||
dng_point fSrcTileSize;
|
||||
|
||||
AutoPtr<dng_memory_block> fSrcBuffer [kMaxMPThreads];
|
||||
AutoPtr<dng_memory_block> fDstBuffer [kMaxMPThreads];
|
||||
|
||||
public:
|
||||
|
||||
/// Construct a filter task given a source and destination images.
|
||||
/// \param srcImage Image from which source pixels are read.
|
||||
/// \param dstImage Image to which result pixels are written.
|
||||
|
||||
dng_filter_task (const char *name,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage);
|
||||
|
||||
virtual ~dng_filter_task ();
|
||||
|
||||
/// Compute the source area needed for a given destination area. Default
|
||||
/// implementation assumes destination area is equal to source area for all
|
||||
/// cases.
|
||||
///
|
||||
/// \param dstArea Area to for which pixels will be computed.
|
||||
///
|
||||
/// \retval The source area needed as input to calculate the requested
|
||||
/// destination area.
|
||||
|
||||
virtual dng_rect SrcArea (const dng_rect &dstArea)
|
||||
{
|
||||
return dstArea;
|
||||
}
|
||||
|
||||
/// Given a destination tile size, calculate input tile size. Simlar to
|
||||
/// SrcArea, and should seldom be overridden.
|
||||
///
|
||||
/// \param dstTileSize The destination tile size that is targeted for output.
|
||||
///
|
||||
/// \retval The source tile size needed to compute a tile of the destination
|
||||
/// size.
|
||||
|
||||
virtual dng_point SrcTileSize (const dng_point &dstTileSize)
|
||||
{
|
||||
return SrcArea (dng_rect (dstTileSize)).Size ();
|
||||
}
|
||||
|
||||
/// Implements filtering operation from one buffer to another. Source and
|
||||
/// destination pixels are set up in member fields of this class. Ideally, no
|
||||
/// allocation should be done in this routine.
|
||||
///
|
||||
/// \param threadIndex The thread on which this routine is being called,
|
||||
/// between 0 and threadCount - 1 for the threadCount passed to Start method.
|
||||
///
|
||||
/// \param srcBuffer Input area and source pixels.
|
||||
///
|
||||
/// \param dstBuffer Output area and destination pixels.
|
||||
|
||||
virtual void ProcessArea (uint32 threadIndex,
|
||||
dng_pixel_buffer &srcBuffer,
|
||||
dng_pixel_buffer &dstBuffer) = 0;
|
||||
|
||||
/// Called prior to processing on specific threads. Can be used to allocate
|
||||
/// per-thread memory buffers, etc.
|
||||
///
|
||||
/// \param threadCount Total number of threads that will be used for
|
||||
/// processing. Less than or equal to MaxThreads of dng_area_task.
|
||||
///
|
||||
/// \param tileSize Size of source tiles which will be processed. (Not all
|
||||
/// tiles will be this size due to edge conditions.)
|
||||
///
|
||||
/// \param allocator dng_memory_allocator to use for allocating temporary
|
||||
/// buffers, etc.
|
||||
///
|
||||
/// \param sniffer Sniffer to test for user cancellation and to set up
|
||||
/// progress.
|
||||
|
||||
virtual void Start (uint32 threadCount,
|
||||
const dng_rect &dstArea,
|
||||
const dng_point &tileSize,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer *sniffer);
|
||||
|
||||
/// Process one tile or partitioned area. Should not be overridden. Instead,
|
||||
/// override ProcessArea, which is where to implement filter processing for a
|
||||
/// specific type of dng_filter_task. There is no allocator parameter as all
|
||||
/// allocation should be done in Start.
|
||||
///
|
||||
/// \param threadIndex 0 to threadCount - 1 index indicating which thread
|
||||
/// this is. (Can be used to get a thread-specific buffer allocated in the
|
||||
/// Start method.)
|
||||
///
|
||||
/// \param area Size of tiles to be used for sizing buffers, etc. (Edges of
|
||||
/// processing can be smaller.)
|
||||
///
|
||||
/// \param sniffer dng_abort_sniffer to use to check for user cancellation
|
||||
/// and progress updates.
|
||||
|
||||
virtual void Process (uint32 threadIndex,
|
||||
const dng_rect &area,
|
||||
dng_abort_sniffer *sniffer);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,618 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_fingerprint.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_flags.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_fingerprint::dng_fingerprint ()
|
||||
{
|
||||
|
||||
for (uint32 j = 0; j < kDNGFingerprintSize; j++)
|
||||
{
|
||||
|
||||
data [j] = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_fingerprint::dng_fingerprint (const char *hex)
|
||||
{
|
||||
|
||||
if (!hex || strlen (hex) != kDNGFingerprintSize * 2 || !FromUtf8HexString (hex))
|
||||
{
|
||||
|
||||
Clear ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_fingerprint::IsNull () const
|
||||
{
|
||||
|
||||
for (uint32 j = 0; j < kDNGFingerprintSize; j++)
|
||||
{
|
||||
|
||||
if (data [j] != 0)
|
||||
{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_fingerprint::operator== (const dng_fingerprint &print) const
|
||||
{
|
||||
|
||||
for (uint32 j = 0; j < kDNGFingerprintSize; j++)
|
||||
{
|
||||
|
||||
if (data [j] != print.data [j])
|
||||
{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool dng_fingerprint::operator< (const dng_fingerprint &print) const
|
||||
{
|
||||
|
||||
for (uint32 j = 0; j < kDNGFingerprintSize; j++)
|
||||
{
|
||||
|
||||
if (data [j] != print.data [j])
|
||||
{
|
||||
|
||||
return data [j] < print.data [j];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32 dng_fingerprint::Collapse32 () const
|
||||
{
|
||||
|
||||
uint32 x = 0;
|
||||
|
||||
for (uint32 j = 0; j < 4; j++)
|
||||
{
|
||||
|
||||
uint32 y = 0;
|
||||
|
||||
for (uint32 k = 0; k < 4; k++)
|
||||
{
|
||||
|
||||
y = (y << 8) + (uint32) data [j * 4 + k];
|
||||
|
||||
}
|
||||
|
||||
x = x ^ y;
|
||||
|
||||
}
|
||||
|
||||
return x;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static char NumToHexChar (unsigned int c)
|
||||
{
|
||||
|
||||
if (c < 10)
|
||||
{
|
||||
return (char) ('0' + c);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return (char) ('A' + c - 10);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_fingerprint::ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const
|
||||
{
|
||||
|
||||
for (size_t i = 0; i < kDNGFingerprintSize; i++)
|
||||
{
|
||||
|
||||
unsigned char c = data [i];
|
||||
|
||||
resultStr [i * 2 ] = NumToHexChar (c >> 4);
|
||||
resultStr [i * 2 + 1] = NumToHexChar (c & 15);
|
||||
|
||||
}
|
||||
|
||||
resultStr [kDNGFingerprintSize * 2] = '\0';
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int HexCharToNum (char hexChar)
|
||||
{
|
||||
|
||||
if (hexChar >= '0' && hexChar <= '9')
|
||||
{
|
||||
return hexChar - '0';
|
||||
}
|
||||
|
||||
else if (hexChar >= 'A' && hexChar <= 'F')
|
||||
{
|
||||
return hexChar - 'A' + 10;
|
||||
}
|
||||
|
||||
else if (hexChar >= 'a' && hexChar <= 'f')
|
||||
{
|
||||
return hexChar - 'a' + 10;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_fingerprint::FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1])
|
||||
{
|
||||
|
||||
for (size_t i = 0; i < kDNGFingerprintSize; i++)
|
||||
{
|
||||
|
||||
int highNibble = HexCharToNum (inputStr [i * 2]);
|
||||
|
||||
if (highNibble < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lowNibble = HexCharToNum (inputStr [i * 2 + 1]);
|
||||
|
||||
if (lowNibble < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
data [i] = (uint8) ((highNibble << 4) + lowNibble);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
|
||||
|
||||
// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
// rights reserved.
|
||||
//
|
||||
// License to copy and use this software is granted provided that it
|
||||
// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
// Algorithm" in all material mentioning or referencing this software
|
||||
// or this function.
|
||||
//
|
||||
// License is also granted to make and use derivative works provided
|
||||
// that such works are identified as "derived from the RSA Data
|
||||
// Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
// mentioning or referencing the derived work.
|
||||
//
|
||||
// RSA Data Security, Inc. makes no representations concerning either
|
||||
// the merchantability of this software or the suitability of this
|
||||
// software for any particular purpose. It is provided "as is"
|
||||
// without express or implied warranty of any kind.
|
||||
//
|
||||
// These notices must be retained in any copies of any part of this
|
||||
// documentation and/or software.
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
dng_md5_printer::dng_md5_printer ()
|
||||
|
||||
: final (false)
|
||||
, result ()
|
||||
|
||||
{
|
||||
|
||||
Reset ();
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void dng_md5_printer::Reset ()
|
||||
{
|
||||
|
||||
// No bits processed yet.
|
||||
|
||||
count [0] = 0;
|
||||
count [1] = 0;
|
||||
|
||||
// Load magic initialization constants.
|
||||
|
||||
state [0] = 0x67452301;
|
||||
state [1] = 0xefcdab89;
|
||||
state [2] = 0x98badcfe;
|
||||
state [3] = 0x10325476;
|
||||
|
||||
// Not finalized yet.
|
||||
|
||||
final = false;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void dng_md5_printer::Process (const void *data,
|
||||
uint32 inputLen)
|
||||
{
|
||||
|
||||
DNG_ASSERT (!final, "Fingerprint already finalized!");
|
||||
|
||||
const uint8 *input = (const uint8 *) data;
|
||||
|
||||
// Compute number of bytes mod 64
|
||||
|
||||
uint32 index = (count [0] >> 3) & 0x3F;
|
||||
|
||||
// Update number of bits
|
||||
|
||||
if ((count [0] += inputLen << 3) < (inputLen << 3))
|
||||
{
|
||||
count [1]++;
|
||||
}
|
||||
|
||||
count [1] += inputLen >> 29;
|
||||
|
||||
// Transform as many times as possible.
|
||||
|
||||
uint32 i = 0;
|
||||
|
||||
uint32 partLen = 64 - index;
|
||||
|
||||
if (inputLen >= partLen)
|
||||
{
|
||||
|
||||
memcpy (&buffer [index],
|
||||
input,
|
||||
partLen);
|
||||
|
||||
MD5Transform (state, buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
{
|
||||
|
||||
MD5Transform (state, &input [i]);
|
||||
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
}
|
||||
|
||||
// Buffer remaining input
|
||||
|
||||
memcpy (&buffer [index],
|
||||
&input [i],
|
||||
inputLen - i);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const dng_fingerprint & dng_md5_printer::Result ()
|
||||
{
|
||||
|
||||
if (!final)
|
||||
{
|
||||
|
||||
static uint8 PADDING [64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
// Save number of bits
|
||||
|
||||
uint8 bits [8];
|
||||
|
||||
Encode (bits, count, 8);
|
||||
|
||||
// Pad out to 56 mod 64.
|
||||
|
||||
uint32 index = (count [0] >> 3) & 0x3f;
|
||||
|
||||
uint32 padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
|
||||
Process (PADDING, padLen);
|
||||
|
||||
// Append length (before padding)
|
||||
|
||||
Process (bits, 8);
|
||||
|
||||
// Store state in digest
|
||||
|
||||
Encode (result.data, state, 16);
|
||||
|
||||
// We are now finalized.
|
||||
|
||||
final = true;
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Encodes input (uint32) into output (uint8). Assumes len is
|
||||
// a multiple of 4.
|
||||
|
||||
void dng_md5_printer::Encode (uint8 *output,
|
||||
const uint32 *input,
|
||||
uint32 len)
|
||||
{
|
||||
|
||||
uint32 i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
output [j ] = (uint8) ((input [i] ) & 0xff);
|
||||
output [j+1] = (uint8) ((input [i] >> 8) & 0xff);
|
||||
output [j+2] = (uint8) ((input [i] >> 16) & 0xff);
|
||||
output [j+3] = (uint8) ((input [i] >> 24) & 0xff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Decodes input (uint8) into output (uint32). Assumes len is
|
||||
// a multiple of 4.
|
||||
|
||||
void dng_md5_printer::Decode (uint32 *output,
|
||||
const uint8 *input,
|
||||
uint32 len)
|
||||
{
|
||||
|
||||
// Check for non-aligned case.
|
||||
|
||||
if (((uintptr) input) & 3)
|
||||
{
|
||||
|
||||
uint32 i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
|
||||
output [i] = (((uint32) input [j ]) ) |
|
||||
(((uint32) input [j+1]) << 8) |
|
||||
(((uint32) input [j+2]) << 16) |
|
||||
(((uint32) input [j+3]) << 24);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Else use optimized code for aligned case.
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
len = len >> 2;
|
||||
|
||||
const uint32 *sPtr = (const uint32 *) input;
|
||||
|
||||
uint32 *dPtr = output;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
|
||||
#if qDNGBigEndian
|
||||
|
||||
uint32 data = *(sPtr++);
|
||||
|
||||
data = (data >> 24) |
|
||||
((data >> 8) & 0x0000FF00) |
|
||||
((data << 8) & 0x00FF0000) |
|
||||
(data << 24);
|
||||
|
||||
*(dPtr++) = data;
|
||||
|
||||
#else
|
||||
|
||||
*(dPtr++) = *(sPtr++);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// MD5 basic transformation. Transforms state based on block.
|
||||
|
||||
DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
void dng_md5_printer::MD5Transform (uint32 state [4],
|
||||
const uint8 block [64])
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
S11 = 7,
|
||||
S12 = 12,
|
||||
S13 = 17,
|
||||
S14 = 22,
|
||||
S21 = 5,
|
||||
S22 = 9,
|
||||
S23 = 14,
|
||||
S24 = 20,
|
||||
S31 = 4,
|
||||
S32 = 11,
|
||||
S33 = 16,
|
||||
S34 = 23,
|
||||
S41 = 6,
|
||||
S42 = 10,
|
||||
S43 = 15,
|
||||
S44 = 21
|
||||
};
|
||||
|
||||
#if qDNGBigEndian
|
||||
|
||||
uint32 x [16];
|
||||
|
||||
Decode (x, block, 64);
|
||||
|
||||
#else
|
||||
|
||||
uint32 temp [16];
|
||||
|
||||
const uint32 *x;
|
||||
|
||||
if (((uintptr) block) & 3)
|
||||
{
|
||||
|
||||
Decode (temp, block, 64);
|
||||
|
||||
x = temp;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
x = (const uint32 *) block;
|
||||
|
||||
#endif
|
||||
|
||||
uint32 a = state [0];
|
||||
uint32 b = state [1];
|
||||
uint32 c = state [2];
|
||||
uint32 d = state [3];
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state [0] += a;
|
||||
state [1] += b;
|
||||
state [2] += c;
|
||||
state [3] += d;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// End of RSA Data Security, Inc. derived code.
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,400 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Fingerprint (cryptographic hashing) support for generating strong hashes of image
|
||||
* data.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_fingerprint__
|
||||
#define __dng_fingerprint__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_stream.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Container fingerprint (MD5 only at present).
|
||||
|
||||
class dng_fingerprint
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static const size_t kDNGFingerprintSize = 16;
|
||||
|
||||
uint8 data [kDNGFingerprintSize];
|
||||
|
||||
public:
|
||||
|
||||
dng_fingerprint ();
|
||||
|
||||
dng_fingerprint (const char *hex);
|
||||
|
||||
/// Check if fingerprint is all zeros.
|
||||
|
||||
bool IsNull () const;
|
||||
|
||||
/// Same as IsNull but expresses intention of testing validity.
|
||||
|
||||
bool IsValid () const
|
||||
{
|
||||
return !IsNull ();
|
||||
}
|
||||
|
||||
/// Set to all zeros, a value used to indicate an invalid fingerprint.
|
||||
|
||||
void Clear ()
|
||||
{
|
||||
*this = dng_fingerprint ();
|
||||
}
|
||||
|
||||
/// Test if two fingerprints are equal.
|
||||
|
||||
bool operator== (const dng_fingerprint &print) const;
|
||||
|
||||
/// Test if two fingerprints are not equal.
|
||||
|
||||
bool operator!= (const dng_fingerprint &print) const
|
||||
{
|
||||
return !(*this == print);
|
||||
}
|
||||
|
||||
/// Comparision test for fingerprints.
|
||||
|
||||
bool operator< (const dng_fingerprint &print) const;
|
||||
|
||||
/// Produce a 32-bit hash value from fingerprint used for faster hashing of
|
||||
/// fingerprints.
|
||||
|
||||
uint32 Collapse32 () const;
|
||||
|
||||
/// Convert fingerprint to UTF-8 string.
|
||||
///
|
||||
/// \param resultStr The output array to which the UTF-8 encoding of the
|
||||
/// fingerprint will be written.
|
||||
|
||||
void ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const;
|
||||
|
||||
/// Convert UTF-8 string to fingerprint. Returns true on success, false on
|
||||
/// failure.
|
||||
///
|
||||
/// \param inputStr The input array from which the UTF-8 encoding of the
|
||||
/// fingerprint will be read.
|
||||
///
|
||||
/// \retval True indicates success.
|
||||
|
||||
bool FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1]);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Utility to compare fingerprints (e.g., for sorting).
|
||||
|
||||
struct dng_fingerprint_less_than
|
||||
{
|
||||
|
||||
/// Less-than comparison.
|
||||
|
||||
bool operator() (const dng_fingerprint &a,
|
||||
const dng_fingerprint &b) const
|
||||
{
|
||||
|
||||
return memcmp (a.data,
|
||||
b.data,
|
||||
sizeof (a.data)) < 0;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/// \brief Utility to hash fingerprints (e.g., for hashtables).
|
||||
|
||||
struct dng_fingerprint_hash
|
||||
{
|
||||
|
||||
/// Hash function.
|
||||
|
||||
size_t operator () (const dng_fingerprint &digest) const
|
||||
{
|
||||
|
||||
return (size_t) digest.Collapse32 ();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
|
||||
|
||||
// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
// rights reserved.
|
||||
//
|
||||
// License to copy and use this software is granted provided that it
|
||||
// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
// Algorithm" in all material mentioning or referencing this software
|
||||
// or this function.
|
||||
//
|
||||
// License is also granted to make and use derivative works provided
|
||||
// that such works are identified as "derived from the RSA Data
|
||||
// Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
// mentioning or referencing the derived work.
|
||||
//
|
||||
// RSA Data Security, Inc. makes no representations concerning either
|
||||
// the merchantability of this software or the suitability of this
|
||||
// software for any particular purpose. It is provided "as is"
|
||||
// without express or implied warranty of any kind.
|
||||
//
|
||||
// These notices must be retained in any copies of any part of this
|
||||
// documentation and/or software.
|
||||
|
||||
/// \brief Class to hash binary data to a fingerprint using the MD5 Message-Digest
|
||||
/// Algorithm.
|
||||
|
||||
class dng_md5_printer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_md5_printer ();
|
||||
|
||||
virtual ~dng_md5_printer ()
|
||||
{
|
||||
}
|
||||
|
||||
/// Reset the fingerprint.
|
||||
|
||||
void Reset ();
|
||||
|
||||
/// Append the data to the stream to be hashed.
|
||||
/// \param data The data to be hashed.
|
||||
/// \param inputLen The length of data, in bytes.
|
||||
|
||||
void Process (const void *data,
|
||||
uint32 inputLen);
|
||||
|
||||
/// Append the string to the stream to be hashed.
|
||||
/// \param text The string to be hashed.
|
||||
|
||||
void Process (const char *text)
|
||||
{
|
||||
|
||||
Process (text, (uint32) strlen (text));
|
||||
|
||||
}
|
||||
|
||||
/// Get the fingerprint (i.e., result of the hash).
|
||||
|
||||
const dng_fingerprint & Result ();
|
||||
|
||||
private:
|
||||
|
||||
static void Encode (uint8 *output,
|
||||
const uint32 *input,
|
||||
uint32 len);
|
||||
|
||||
static void Decode (uint32 *output,
|
||||
const uint8 *input,
|
||||
uint32 len);
|
||||
|
||||
// F, G, H and I are basic MD5 functions.
|
||||
|
||||
static inline uint32 F (uint32 x,
|
||||
uint32 y,
|
||||
uint32 z)
|
||||
{
|
||||
return (x & y) | (~x & z);
|
||||
}
|
||||
|
||||
static inline uint32 G (uint32 x,
|
||||
uint32 y,
|
||||
uint32 z)
|
||||
{
|
||||
return (x & z) | (y & ~z);
|
||||
}
|
||||
|
||||
static inline uint32 H (uint32 x,
|
||||
uint32 y,
|
||||
uint32 z)
|
||||
{
|
||||
return x ^ y ^ z;
|
||||
}
|
||||
|
||||
static inline uint32 I (uint32 x,
|
||||
uint32 y,
|
||||
uint32 z)
|
||||
{
|
||||
return y ^ (x | ~z);
|
||||
}
|
||||
|
||||
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
|
||||
DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static inline void FF (uint32 &a,
|
||||
uint32 b,
|
||||
uint32 c,
|
||||
uint32 d,
|
||||
uint32 x,
|
||||
uint32 s,
|
||||
uint32 ac)
|
||||
{
|
||||
a += F (b, c, d) + x + ac;
|
||||
a = (a << s) | (a >> (32 - s));
|
||||
a += b;
|
||||
}
|
||||
|
||||
DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static inline void GG (uint32 &a,
|
||||
uint32 b,
|
||||
uint32 c,
|
||||
uint32 d,
|
||||
uint32 x,
|
||||
uint32 s,
|
||||
uint32 ac)
|
||||
{
|
||||
a += G (b, c, d) + x + ac;
|
||||
a = (a << s) | (a >> (32 - s));
|
||||
a += b;
|
||||
}
|
||||
|
||||
DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static inline void HH (uint32 &a,
|
||||
uint32 b,
|
||||
uint32 c,
|
||||
uint32 d,
|
||||
uint32 x,
|
||||
uint32 s,
|
||||
uint32 ac)
|
||||
{
|
||||
a += H (b, c, d) + x + ac;
|
||||
a = (a << s) | (a >> (32 - s));
|
||||
a += b;
|
||||
}
|
||||
|
||||
DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static inline void II (uint32 &a,
|
||||
uint32 b,
|
||||
uint32 c,
|
||||
uint32 d,
|
||||
uint32 x,
|
||||
uint32 s,
|
||||
uint32 ac)
|
||||
{
|
||||
a += I (b, c, d) + x + ac;
|
||||
a = (a << s) | (a >> (32 - s));
|
||||
a += b;
|
||||
}
|
||||
|
||||
static void MD5Transform (uint32 state [4],
|
||||
const uint8 block [64]);
|
||||
|
||||
private:
|
||||
|
||||
uint32 state [4];
|
||||
|
||||
uint32 count [2];
|
||||
|
||||
uint8 buffer [64];
|
||||
|
||||
bool final;
|
||||
|
||||
dng_fingerprint result;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A dng_stream based interface to the MD5 printing logic.
|
||||
|
||||
class dng_md5_printer_stream : public dng_stream, dng_md5_printer
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
uint64 fNextOffset;
|
||||
|
||||
public:
|
||||
|
||||
/// Create an empty MD5 printer stream.
|
||||
|
||||
dng_md5_printer_stream ()
|
||||
|
||||
: fNextOffset (0)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
virtual uint64 DoGetLength ()
|
||||
{
|
||||
|
||||
return fNextOffset;
|
||||
|
||||
}
|
||||
|
||||
virtual void DoRead (void * /* data */,
|
||||
uint32 /* count */,
|
||||
uint64 /* offset */)
|
||||
{
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
virtual void DoSetLength (uint64 length)
|
||||
{
|
||||
|
||||
if (length != fNextOffset)
|
||||
{
|
||||
ThrowProgramError ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void DoWrite (const void *data,
|
||||
uint32 count2,
|
||||
uint64 offset)
|
||||
{
|
||||
|
||||
if (offset != fNextOffset)
|
||||
{
|
||||
ThrowProgramError ();
|
||||
}
|
||||
|
||||
Process (data, count2);
|
||||
|
||||
fNextOffset += count2;
|
||||
|
||||
}
|
||||
|
||||
const dng_fingerprint & Result ()
|
||||
{
|
||||
|
||||
Flush ();
|
||||
|
||||
return dng_md5_printer::Result ();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,402 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Conditional compilation flags for DNG SDK.
|
||||
*
|
||||
* All conditional compilation macros for the DNG SDK begin with a lowercase 'q'.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_flags__
|
||||
#define __dng_flags__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qMacOS
|
||||
/// 1 if compiling for Mac OS X.
|
||||
|
||||
/// \def qWinOS
|
||||
/// 1 if compiling for Windows.
|
||||
|
||||
// Make sure a platform is defined
|
||||
|
||||
#if !(defined(qMacOS) || defined(qWinOS) || defined(qAndroid) || defined(qiPhone) || defined(qLinux))
|
||||
#include "RawEnvironment.h"
|
||||
#endif
|
||||
|
||||
// This requires a force include or compiler define. These are the unique platforms.
|
||||
|
||||
#if !(defined(qMacOS) || defined(qWinOS) || defined(qAndroid) || defined(qiPhone) || defined(qLinux))
|
||||
#error Unable to figure out platform
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Platforms.
|
||||
// Zeros out any undefined platforms, so that #if can be used in place of #ifdef.
|
||||
|
||||
#ifndef qMacOS
|
||||
#define qMacOS 0
|
||||
#endif
|
||||
|
||||
#ifndef qiPhone
|
||||
#define qiPhone 0
|
||||
#endif
|
||||
|
||||
#ifndef qiPhoneSimulator
|
||||
#define qiPhoneSimulator 0
|
||||
#endif
|
||||
|
||||
#ifndef qAndroid
|
||||
#define qAndroid 0
|
||||
#endif
|
||||
|
||||
#ifndef qWinOS
|
||||
#define qWinOS 0
|
||||
#endif
|
||||
|
||||
#ifndef qWinRT
|
||||
#define qWinRT 0
|
||||
#endif
|
||||
|
||||
#ifndef qLinux
|
||||
#define qLinux 0
|
||||
#endif
|
||||
|
||||
#ifndef qWeb
|
||||
#define qWeb 0
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qiPhoneSimulator
|
||||
#if !qiPhone
|
||||
#error "qiPhoneSimulator set and not qiPhone"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if qWinRT
|
||||
#if !qWinOS
|
||||
#error "qWinRT set but not qWinOS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// arm and neon support
|
||||
|
||||
// arm detect (apple vs. win)
|
||||
#if defined(__arm__) || defined(__arm64__) || defined(_M_ARM)
|
||||
#define qARM 1
|
||||
#endif
|
||||
|
||||
// arm_neon detect
|
||||
#if defined(__ARM_NEON__) || defined(_M_ARM)
|
||||
#define qARMNeon 1
|
||||
#endif
|
||||
|
||||
#ifndef qARM
|
||||
#define qARM 0
|
||||
#endif
|
||||
|
||||
#ifndef qARMNeon
|
||||
#define qARMNeon 0
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Establish WIN32 and WIN64 definitions.
|
||||
|
||||
#if defined(_WIN32) && !defined(WIN32)
|
||||
#define WIN32 1
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64) && !defined(WIN64)
|
||||
#define WIN64 1
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGDebug
|
||||
/// 1 if debug code is compiled in, 0 otherwise. Enables assertions and other debug
|
||||
/// checks in exchange for slower processing.
|
||||
|
||||
// Figure out if debug build or not.
|
||||
|
||||
#ifndef qDNGDebug
|
||||
|
||||
#if defined(Debug)
|
||||
#define qDNGDebug Debug
|
||||
|
||||
#elif defined(_DEBUG)
|
||||
#define qDNGDebug _DEBUG
|
||||
|
||||
#else
|
||||
#define qDNGDebug 0
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
// Support Intel Thread Building Blocks (TBB)?
|
||||
//
|
||||
// This flag needs to be configured via the project, because there are sources
|
||||
// outside the cr_sdk (such as the CTJPEG and ACE libs) that need to use the
|
||||
// same flag to determine whether to use TBB or not.
|
||||
//
|
||||
// By default, configure to 0 (disabled).
|
||||
|
||||
#ifndef qCRSupportTBB
|
||||
#define qCRSupportTBB 0
|
||||
#endif
|
||||
|
||||
#if qCRSupportTBB
|
||||
#ifndef TBB_DEPRECATED
|
||||
#define TBB_DEPRECATED 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This is not really a switch, but rather a shorthand for determining whether
|
||||
// or not we're building a particular translation unit (source file) using the
|
||||
// Intel Compiler.
|
||||
|
||||
#ifndef qDNGIntelCompiler
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define qDNGIntelCompiler (__INTEL_COMPILER >= 1700)
|
||||
#else
|
||||
#define qDNGIntelCompiler 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Figure out byte order.
|
||||
|
||||
/// \def qDNGBigEndian
|
||||
/// 1 if this target platform is big endian (e.g. PowerPC Macintosh), else 0.
|
||||
///
|
||||
/// \def qDNGLittleEndian
|
||||
/// 1 if this target platform is little endian (e.g. x86 processors), else 0.
|
||||
|
||||
#ifndef qDNGBigEndian
|
||||
|
||||
#if defined(qDNGLittleEndian)
|
||||
#define qDNGBigEndian !qDNGLittleEndian
|
||||
|
||||
#elif defined(__POWERPC__)
|
||||
#define qDNGBigEndian 1
|
||||
|
||||
#elif defined(__INTEL__)
|
||||
#define qDNGBigEndian 0
|
||||
|
||||
#elif defined(_M_IX86)
|
||||
#define qDNGBigEndian 0
|
||||
|
||||
#elif defined(_M_X64) || defined(__amd64__)
|
||||
#define qDNGBigEndian 0
|
||||
|
||||
#elif defined(__LITTLE_ENDIAN__)
|
||||
#define qDNGBigEndian 0
|
||||
|
||||
#elif defined(__BIG_ENDIAN__)
|
||||
#define qDNGBigEndian 1
|
||||
|
||||
#elif defined(_ARM_)
|
||||
#define qDNGBigEndian 0
|
||||
|
||||
#else
|
||||
|
||||
#ifndef qXCodeRez
|
||||
#error Unable to figure out byte order.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef qXCodeRez
|
||||
|
||||
#ifndef qDNGLittleEndian
|
||||
#define qDNGLittleEndian !qDNGBigEndian
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNG64Bit
|
||||
/// 1 if this target platform uses 64-bit addresses, 0 otherwise.
|
||||
|
||||
#ifndef qDNG64Bit
|
||||
|
||||
#if qMacOS
|
||||
|
||||
#ifdef __LP64__
|
||||
#if __LP64__
|
||||
#define qDNG64Bit 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif qWinOS
|
||||
|
||||
#ifdef WIN64
|
||||
#if WIN64
|
||||
#define qDNG64Bit 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif qLinux
|
||||
|
||||
#ifdef __LP64__
|
||||
#if __LP64__
|
||||
#define qDNG64Bit 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef qDNG64Bit
|
||||
#define qDNG64Bit 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGThreadSafe
|
||||
/// 1 if target platform has thread support and threadsafe libraries, 0 otherwise.
|
||||
|
||||
#ifndef qDNGThreadSafe
|
||||
#define qDNGThreadSafe (qMacOS || qWinOS)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGValidateTarget
|
||||
/// 1 if dng_validate command line tool is being built, 0 otherwise.
|
||||
|
||||
#ifndef qDNGValidateTarget
|
||||
#define qDNGValidateTarget 0
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGValidate
|
||||
/// 1 if DNG validation code is enabled, 0 otherwise.
|
||||
|
||||
#ifndef qDNGValidate
|
||||
#define qDNGValidate qDNGValidateTarget
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGPrintMessages
|
||||
/// 1 if dng_show_message should use fprintf to stderr. 0 if it should use a platform
|
||||
/// specific interrupt mechanism.
|
||||
|
||||
#ifndef qDNGPrintMessages
|
||||
#define qDNGPrintMessages qDNGValidate
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Experimental features -- work in progress for Lightroom and Camera Raw
|
||||
// major releases. Turn this off for Lightroom & Camera Raw dot releases.
|
||||
|
||||
#ifndef qDNGExperimental
|
||||
#define qDNGExperimental 1
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGXMPFiles
|
||||
/// 1 to use XMPFiles.
|
||||
|
||||
#ifndef qDNGXMPFiles
|
||||
#define qDNGXMPFiles 1
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGXMPDocOps
|
||||
/// 1 to use XMPDocOps.
|
||||
|
||||
#ifndef qDNGXMPDocOps
|
||||
#define qDNGXMPDocOps (!qDNGValidateTarget)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGUseLibJPEG
|
||||
/// 1 to use open-source libjpeg for lossy jpeg processing.
|
||||
|
||||
#ifndef qDNGUseLibJPEG
|
||||
#define qDNGUseLibJPEG qDNGValidateTarget
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef qDNGAVXSupport
|
||||
#define qDNGAVXSupport ((qMacOS || qWinOS) && qDNG64Bit && !qARM && 1)
|
||||
#endif
|
||||
|
||||
#if qDNGAVXSupport && !(qDNG64Bit && !qARM)
|
||||
#error AVX support is enabled when 64-bit support is not or ARM is
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef qDNGSupportVC5
|
||||
#define qDNGSupportVC5 (1)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGUsingSanitizer
|
||||
/// Set to 1 when using a Sanitizer tool.
|
||||
|
||||
#ifndef qDNGUsingSanitizer
|
||||
#define qDNGUsingSanitizer (0)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_ATTRIB_NO_SANITIZE
|
||||
#if qDNGUsingSanitizer && defined(__clang__)
|
||||
#define DNG_ATTRIB_NO_SANITIZE(type) __attribute__((no_sanitize(type)))
|
||||
#else
|
||||
#define DNG_ATTRIB_NO_SANITIZE(type)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGDepthSupport
|
||||
/// 1 to add support for depth maps in DNG format.
|
||||
/// Deprecated 2018-09-19.
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define qDNGDepthSupport #error
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \def qDNGPreserveBlackPoint
|
||||
/// 1 to add support for non-zero black point in early raw pipeline.
|
||||
/// Deprecated 2018-09-19.
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define qDNGPreserveBlackPoint #error
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,644 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_gain_map.h"
|
||||
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_globals.h"
|
||||
#include "dng_host.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_pixel_buffer.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_tag_values.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_gain_map_interpolator
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
const dng_gain_map &fMap;
|
||||
|
||||
dng_point_real64 fScale;
|
||||
dng_point_real64 fOffset;
|
||||
|
||||
int32 fColumn;
|
||||
int32 fPlane;
|
||||
|
||||
uint32 fRowIndex1;
|
||||
uint32 fRowIndex2;
|
||||
real32 fRowFract;
|
||||
|
||||
int32 fResetColumn;
|
||||
|
||||
real32 fValueBase;
|
||||
real32 fValueStep;
|
||||
real32 fValueIndex;
|
||||
|
||||
public:
|
||||
|
||||
dng_gain_map_interpolator (const dng_gain_map &map,
|
||||
const dng_rect &mapBounds,
|
||||
int32 row,
|
||||
int32 column,
|
||||
uint32 plane);
|
||||
|
||||
real32 Interpolate () const
|
||||
{
|
||||
|
||||
return fValueBase + fValueStep * fValueIndex;
|
||||
|
||||
}
|
||||
|
||||
void Increment ()
|
||||
{
|
||||
|
||||
if (++fColumn >= fResetColumn)
|
||||
{
|
||||
|
||||
ResetColumn ();
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
fValueIndex += 1.0f;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
real32 InterpolateEntry (uint32 colIndex);
|
||||
|
||||
void ResetColumn ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_gain_map_interpolator::dng_gain_map_interpolator (const dng_gain_map &map,
|
||||
const dng_rect &mapBounds,
|
||||
int32 row,
|
||||
int32 column,
|
||||
uint32 plane)
|
||||
|
||||
: fMap (map)
|
||||
|
||||
, fScale (1.0 / mapBounds.H (),
|
||||
1.0 / mapBounds.W ())
|
||||
|
||||
, fOffset (0.5 - mapBounds.t,
|
||||
0.5 - mapBounds.l)
|
||||
|
||||
, fColumn (column)
|
||||
, fPlane (plane)
|
||||
|
||||
, fRowIndex1 (0)
|
||||
, fRowIndex2 (0)
|
||||
, fRowFract (0.0f)
|
||||
|
||||
, fResetColumn (0)
|
||||
|
||||
, fValueBase (0.0f)
|
||||
, fValueStep (0.0f)
|
||||
, fValueIndex (0.0f)
|
||||
|
||||
{
|
||||
|
||||
real64 rowIndexF = (fScale.v * (row + fOffset.v) -
|
||||
fMap.Origin ().v) / fMap.Spacing ().v;
|
||||
|
||||
if (rowIndexF <= 0.0)
|
||||
{
|
||||
|
||||
fRowIndex1 = 0;
|
||||
fRowIndex2 = 0;
|
||||
|
||||
fRowFract = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
if (fMap.Points ().v < 1)
|
||||
{
|
||||
ThrowProgramError ("Empty gain map");
|
||||
}
|
||||
|
||||
uint32 lastRow = static_cast<uint32> (fMap.Points ().v - 1);
|
||||
|
||||
if (rowIndexF >= static_cast<real64> (lastRow))
|
||||
{
|
||||
|
||||
fRowIndex1 = lastRow;
|
||||
fRowIndex2 = fRowIndex1;
|
||||
|
||||
fRowFract = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
// If we got here, we know that rowIndexF can safely be converted to
|
||||
// a uint32 and that static_cast<uint32> (rowIndexF) < lastRow. This
|
||||
// implies fRowIndex2 <= lastRow below.
|
||||
|
||||
fRowIndex1 = static_cast<uint32> (rowIndexF);
|
||||
fRowIndex2 = fRowIndex1 + 1;
|
||||
|
||||
fRowFract = (real32) (rowIndexF - (real64) fRowIndex1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ResetColumn ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real32 dng_gain_map_interpolator::InterpolateEntry (uint32 colIndex)
|
||||
{
|
||||
|
||||
return fMap.Entry (fRowIndex1, colIndex, fPlane) * (1.0f - fRowFract) +
|
||||
fMap.Entry (fRowIndex2, colIndex, fPlane) * ( fRowFract);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_gain_map_interpolator::ResetColumn ()
|
||||
{
|
||||
|
||||
real64 colIndexF = ((fScale.h * (fColumn + fOffset.h)) -
|
||||
fMap.Origin ().h) / fMap.Spacing ().h;
|
||||
|
||||
if (colIndexF <= 0.0)
|
||||
{
|
||||
|
||||
fValueBase = InterpolateEntry (0);
|
||||
|
||||
fValueStep = 0.0f;
|
||||
|
||||
fResetColumn = (int32) ceil (fMap.Origin ().h / fScale.h - fOffset.h);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
if (fMap.Points ().h < 1)
|
||||
{
|
||||
ThrowProgramError ("Empty gain map");
|
||||
}
|
||||
|
||||
uint32 lastCol = static_cast<uint32> (fMap.Points ().h - 1);
|
||||
|
||||
if (colIndexF >= static_cast<real64> (lastCol))
|
||||
{
|
||||
|
||||
fValueBase = InterpolateEntry (lastCol);
|
||||
|
||||
fValueStep = 0.0f;
|
||||
|
||||
fResetColumn = 0x7FFFFFFF;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
// If we got here, we know that colIndexF can safely be converted
|
||||
// to a uint32 and that static_cast<uint32> (colIndexF) < lastCol.
|
||||
// This implies colIndex + 1 <= lastCol, i.e. the argument to
|
||||
// InterpolateEntry() below is valid.
|
||||
|
||||
uint32 colIndex = static_cast<uint32> (colIndexF);
|
||||
|
||||
real64 base = InterpolateEntry (colIndex);
|
||||
real64 delta = InterpolateEntry (colIndex + 1) - base;
|
||||
|
||||
fValueBase = (real32) (base + delta * (colIndexF - (real64) colIndex));
|
||||
|
||||
fValueStep = (real32) ((delta * fScale.h) / fMap.Spacing ().h);
|
||||
|
||||
fResetColumn = (int32) ceil (((colIndex + 1) * fMap.Spacing ().h +
|
||||
fMap.Origin ().h) / fScale.h - fOffset.h);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fValueIndex = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
|
||||
dng_gain_map::dng_gain_map (dng_memory_allocator &allocator,
|
||||
const dng_point &points,
|
||||
const dng_point_real64 &spacing,
|
||||
const dng_point_real64 &origin,
|
||||
uint32 planes)
|
||||
|
||||
: fPoints (points)
|
||||
, fSpacing (spacing)
|
||||
, fOrigin (origin)
|
||||
, fPlanes (planes)
|
||||
|
||||
, fRowStep (planes * points.h)
|
||||
|
||||
, fBuffer ()
|
||||
|
||||
{
|
||||
|
||||
fBuffer.Reset (allocator.Allocate (ComputeBufferSize (ttFloat,
|
||||
fPoints,
|
||||
fPlanes,
|
||||
padSIMDBytes)));
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real32 dng_gain_map::Interpolate (int32 row,
|
||||
int32 col,
|
||||
uint32 plane,
|
||||
const dng_rect &bounds) const
|
||||
{
|
||||
|
||||
dng_gain_map_interpolator interp (*this,
|
||||
bounds,
|
||||
row,
|
||||
col,
|
||||
plane);
|
||||
|
||||
return interp.Interpolate ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 dng_gain_map::PutStreamSize () const
|
||||
{
|
||||
|
||||
return 44 + fPoints.v * fPoints.h * fPlanes * 4;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_gain_map::PutStream (dng_stream &stream) const
|
||||
{
|
||||
|
||||
stream.Put_uint32 (fPoints.v);
|
||||
stream.Put_uint32 (fPoints.h);
|
||||
|
||||
stream.Put_real64 (fSpacing.v);
|
||||
stream.Put_real64 (fSpacing.h);
|
||||
|
||||
stream.Put_real64 (fOrigin.v);
|
||||
stream.Put_real64 (fOrigin.h);
|
||||
|
||||
stream.Put_uint32 (fPlanes);
|
||||
|
||||
for (int32 rowIndex = 0; rowIndex < fPoints.v; rowIndex++)
|
||||
{
|
||||
|
||||
for (int32 colIndex = 0; colIndex < fPoints.h; colIndex++)
|
||||
{
|
||||
|
||||
for (uint32 plane = 0; plane < fPlanes; plane++)
|
||||
{
|
||||
|
||||
stream.Put_real32 (Entry (rowIndex,
|
||||
colIndex,
|
||||
plane));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_gain_map * dng_gain_map::GetStream (dng_host &host,
|
||||
dng_stream &stream)
|
||||
{
|
||||
|
||||
dng_point mapPoints;
|
||||
|
||||
mapPoints.v = stream.Get_uint32 ();
|
||||
mapPoints.h = stream.Get_uint32 ();
|
||||
|
||||
dng_point_real64 mapSpacing;
|
||||
|
||||
mapSpacing.v = stream.Get_real64 ();
|
||||
mapSpacing.h = stream.Get_real64 ();
|
||||
|
||||
dng_point_real64 mapOrigin;
|
||||
|
||||
mapOrigin.v = stream.Get_real64 ();
|
||||
mapOrigin.h = stream.Get_real64 ();
|
||||
|
||||
uint32 mapPlanes = stream.Get_uint32 ();
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
if (gVerbose)
|
||||
{
|
||||
|
||||
printf ("Points: v=%d, h=%d\n",
|
||||
(int) mapPoints.v,
|
||||
(int) mapPoints.h);
|
||||
|
||||
printf ("Spacing: v=%.6f, h=%.6f\n",
|
||||
mapSpacing.v,
|
||||
mapSpacing.h);
|
||||
|
||||
printf ("Origin: v=%.6f, h=%.6f\n",
|
||||
mapOrigin.v,
|
||||
mapOrigin.h);
|
||||
|
||||
printf ("Planes: %u\n",
|
||||
(unsigned) mapPlanes);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (mapPoints.v == 1)
|
||||
{
|
||||
mapSpacing.v = 1.0;
|
||||
mapOrigin.v = 0.0;
|
||||
}
|
||||
|
||||
if (mapPoints.h == 1)
|
||||
{
|
||||
mapSpacing.h = 1.0;
|
||||
mapOrigin.h = 0.0;
|
||||
}
|
||||
|
||||
if (mapPoints.v < 1 ||
|
||||
mapPoints.h < 1 ||
|
||||
mapSpacing.v <= 0.0 ||
|
||||
mapSpacing.h <= 0.0 ||
|
||||
mapPlanes < 1)
|
||||
{
|
||||
ThrowBadFormat ();
|
||||
}
|
||||
|
||||
AutoPtr<dng_gain_map> map (new dng_gain_map (host.Allocator (),
|
||||
mapPoints,
|
||||
mapSpacing,
|
||||
mapOrigin,
|
||||
mapPlanes));
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
uint32 linesPrinted = 0;
|
||||
uint32 linesSkipped = 0;
|
||||
|
||||
#endif
|
||||
|
||||
for (int32 rowIndex = 0; rowIndex < mapPoints.v; rowIndex++)
|
||||
{
|
||||
|
||||
for (int32 colIndex = 0; colIndex < mapPoints.h; colIndex++)
|
||||
{
|
||||
|
||||
for (uint32 plane = 0; plane < mapPlanes; plane++)
|
||||
{
|
||||
|
||||
real32 x = stream.Get_real32 ();
|
||||
|
||||
map->Entry (rowIndex, colIndex, plane) = x;
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
if (gVerbose)
|
||||
{
|
||||
|
||||
if (linesPrinted < gDumpLineLimit)
|
||||
{
|
||||
|
||||
printf (" Map [%3u] [%3u] [%u] = %.4f\n",
|
||||
(unsigned) rowIndex,
|
||||
(unsigned) colIndex,
|
||||
(unsigned) plane,
|
||||
x);
|
||||
|
||||
linesPrinted++;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
linesSkipped++;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
if (linesSkipped)
|
||||
{
|
||||
|
||||
printf (" ... %u map entries skipped\n", (unsigned) linesSkipped);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return map.Release ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode_GainMap::dng_opcode_GainMap (const dng_area_spec &areaSpec,
|
||||
AutoPtr<dng_gain_map> &gainMap)
|
||||
|
||||
: dng_inplace_opcode (dngOpcode_GainMap,
|
||||
dngVersion_1_3_0_0,
|
||||
kFlag_None)
|
||||
|
||||
, fAreaSpec (areaSpec)
|
||||
|
||||
, fGainMap ()
|
||||
|
||||
{
|
||||
|
||||
fGainMap.Reset (gainMap.Release ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode_GainMap::dng_opcode_GainMap (dng_host &host,
|
||||
dng_stream &stream)
|
||||
|
||||
: dng_inplace_opcode (dngOpcode_GainMap,
|
||||
stream,
|
||||
"GainMap")
|
||||
|
||||
, fAreaSpec ()
|
||||
|
||||
, fGainMap ()
|
||||
|
||||
{
|
||||
|
||||
uint32 byteCount = stream.Get_uint32 ();
|
||||
|
||||
uint64 startPosition = stream.Position ();
|
||||
|
||||
fAreaSpec.GetData (stream);
|
||||
|
||||
fGainMap.Reset (dng_gain_map::GetStream (host, stream));
|
||||
|
||||
if (stream.Position () != startPosition + byteCount)
|
||||
{
|
||||
ThrowBadFormat ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_GainMap::PutData (dng_stream &stream) const
|
||||
{
|
||||
|
||||
stream.Put_uint32 (dng_area_spec::kDataSize +
|
||||
fGainMap->PutStreamSize ());
|
||||
|
||||
fAreaSpec.PutData (stream);
|
||||
|
||||
fGainMap->PutStream (stream);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_GainMap::ProcessArea (dng_negative &negative,
|
||||
uint32 /* threadIndex */,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds)
|
||||
{
|
||||
|
||||
dng_rect overlap = fAreaSpec.Overlap (dstArea);
|
||||
|
||||
if (overlap.NotEmpty ())
|
||||
{
|
||||
|
||||
uint16 blackLevel = (Stage () >= 2) ? negative.Stage3BlackLevel () : 0;
|
||||
|
||||
real32 blackScale1 = 1.0f;
|
||||
real32 blackScale2 = 1.0f;
|
||||
real32 blackOffset1 = 0.0f;
|
||||
real32 blackOffset2 = 0.0f;
|
||||
|
||||
if (blackLevel != 0)
|
||||
{
|
||||
|
||||
blackOffset2 = ((real32) blackLevel) / 65535.0f;
|
||||
blackScale2 = 1.0f - blackOffset2;
|
||||
blackScale1 = 1.0f / blackScale2;
|
||||
blackOffset1 = 1.0f - blackScale1;
|
||||
|
||||
}
|
||||
|
||||
uint32 cols = overlap.W ();
|
||||
|
||||
uint32 colPitch = fAreaSpec.ColPitch ();
|
||||
|
||||
colPitch = Min_uint32 (colPitch, cols);
|
||||
|
||||
for (uint32 plane = fAreaSpec.Plane ();
|
||||
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
||||
plane < buffer.Planes ();
|
||||
plane++)
|
||||
{
|
||||
|
||||
uint32 mapPlane = Min_uint32 (plane, fGainMap->Planes () - 1);
|
||||
|
||||
for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
|
||||
{
|
||||
|
||||
real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
|
||||
|
||||
dng_gain_map_interpolator interp (*fGainMap,
|
||||
imageBounds,
|
||||
row,
|
||||
overlap.l,
|
||||
mapPlane);
|
||||
|
||||
if (blackLevel != 0)
|
||||
{
|
||||
|
||||
for (uint32 col = 0; col < cols; col += colPitch)
|
||||
{
|
||||
|
||||
dPtr [col] = dPtr [col] * blackScale1 + blackOffset1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (uint32 col = 0; col < cols; col += colPitch)
|
||||
{
|
||||
|
||||
real32 gain = interp.Interpolate ();
|
||||
|
||||
dPtr [col] = Min_real32 (dPtr [col] * gain, 1.0f);
|
||||
|
||||
for (uint32 j = 0; j < colPitch; j++)
|
||||
{
|
||||
interp.Increment ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (blackLevel != 0)
|
||||
{
|
||||
|
||||
for (uint32 col = 0; col < cols; col += colPitch)
|
||||
{
|
||||
|
||||
dPtr [col] = dPtr [col] * blackScale2 + blackOffset2;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,200 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Opcode to fix 2D uniformity defects, such as shading.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_gain_map__
|
||||
#define __dng_gain_map__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_memory.h"
|
||||
#include "dng_misc_opcodes.h"
|
||||
#include "dng_tag_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Holds a discrete (i.e., sampled) 2D representation of a gain map. This is
|
||||
/// effectively an image containing scale factors.
|
||||
|
||||
class dng_gain_map: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_point fPoints;
|
||||
|
||||
dng_point_real64 fSpacing;
|
||||
|
||||
dng_point_real64 fOrigin;
|
||||
|
||||
uint32 fPlanes;
|
||||
|
||||
uint32 fRowStep;
|
||||
|
||||
AutoPtr<dng_memory_block> fBuffer;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct a gain map with the specified memory allocator, number of
|
||||
/// samples (points), sample spacing, origin, and number of color planes.
|
||||
|
||||
dng_gain_map (dng_memory_allocator &allocator,
|
||||
const dng_point &points,
|
||||
const dng_point_real64 &spacing,
|
||||
const dng_point_real64 &origin,
|
||||
uint32 planes);
|
||||
|
||||
/// The number of samples in the horizontal and vertical directions.
|
||||
|
||||
const dng_point & Points () const
|
||||
{
|
||||
return fPoints;
|
||||
}
|
||||
|
||||
/// The space between adjacent samples in the horizontal and vertical
|
||||
/// directions.
|
||||
|
||||
const dng_point_real64 & Spacing () const
|
||||
{
|
||||
return fSpacing;
|
||||
}
|
||||
|
||||
/// The 2D coordinate for the first (i.e., top-left-most) sample.
|
||||
|
||||
const dng_point_real64 & Origin () const
|
||||
{
|
||||
return fOrigin;
|
||||
}
|
||||
|
||||
/// The number of color planes.
|
||||
|
||||
uint32 Planes () const
|
||||
{
|
||||
return fPlanes;
|
||||
}
|
||||
|
||||
/// Getter for a gain map sample (specified by row, column, and plane).
|
||||
|
||||
real32 & Entry (uint32 rowIndex,
|
||||
uint32 colIndex,
|
||||
uint32 plane)
|
||||
{
|
||||
|
||||
return *(fBuffer->Buffer_real32 () +
|
||||
rowIndex * fRowStep +
|
||||
colIndex * fPlanes +
|
||||
plane);
|
||||
|
||||
}
|
||||
|
||||
/// Getter for a gain map sample (specified by row index, column index, and
|
||||
/// plane index).
|
||||
|
||||
const real32 & Entry (uint32 rowIndex,
|
||||
uint32 colIndex,
|
||||
uint32 plane) const
|
||||
{
|
||||
|
||||
return *(fBuffer->Buffer_real32 () +
|
||||
rowIndex * fRowStep +
|
||||
colIndex * fPlanes +
|
||||
plane);
|
||||
|
||||
}
|
||||
|
||||
/// Compute the interpolated gain (i.e., scale factor) at the specified pixel
|
||||
/// position and color plane, within the specified image bounds (in pixels).
|
||||
|
||||
real32 Interpolate (int32 row,
|
||||
int32 col,
|
||||
uint32 plane,
|
||||
const dng_rect &bounds) const;
|
||||
|
||||
/// The number of bytes needed to hold the gain map data.
|
||||
|
||||
uint32 PutStreamSize () const;
|
||||
|
||||
/// Write the gain map to the specified stream.
|
||||
|
||||
void PutStream (dng_stream &stream) const;
|
||||
|
||||
/// Read a gain map from the specified stream.
|
||||
|
||||
static dng_gain_map * GetStream (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to fix 2D spatially-varying light falloff or color casts (i.e.,
|
||||
/// uniformity issues). This is commonly due to shading.
|
||||
|
||||
class dng_opcode_GainMap: public dng_inplace_opcode,
|
||||
private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
AutoPtr<dng_gain_map> fGainMap;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct a GainMap opcode for the specified image area and the specified
|
||||
/// gain map.
|
||||
|
||||
dng_opcode_GainMap (const dng_area_spec &areaSpec,
|
||||
AutoPtr<dng_gain_map> &gainMap);
|
||||
|
||||
/// Construct a GainMap opcode from the specified stream.
|
||||
|
||||
dng_opcode_GainMap (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
/// Write the opcode to the specified stream.
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
/// The pixel data type of this opcode.
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 /* imagePixelType */)
|
||||
{
|
||||
return ttFloat;
|
||||
}
|
||||
|
||||
/// The adjusted bounds (processing area) of this opcode. It is limited to
|
||||
/// the intersection of the specified image area and the GainMap area.
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
|
||||
{
|
||||
return fAreaSpec.Overlap (imageBounds);
|
||||
}
|
||||
|
||||
/// Apply the gain map.
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,52 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_globals.h"
|
||||
#include "dng_simd_type.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
bool gVerbose = false;
|
||||
|
||||
uint32 gDumpLineLimit = 100;
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool gDNGUseFakeTimeZonesInXMP = false;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool gDNGShowTimers = true;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 gDNGStreamBlockSize = 4096;
|
||||
|
||||
uint32 gDNGMaxStreamBufferSize = 1024 * 1024;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool gImagecore = false;
|
||||
|
||||
bool gPrintTimings = false;
|
||||
|
||||
bool gPrintAsserts = true;
|
||||
|
||||
bool gBreakOnAsserts = true;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// This is declared in dng_simd_type.h
|
||||
|
||||
SIMDType gDNGMaxSIMD = Scalar;
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,85 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Definitions of global variables controling DNG SDK behavior.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_globals__
|
||||
#define __dng_globals__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_flags.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
/// When validation (qValidate) is turned on, this global enables verbose
|
||||
/// output about DNG tags and other properties.
|
||||
|
||||
extern bool gVerbose;
|
||||
|
||||
/// When validation (qValidate) is turned on, and verbose mode (gVerbose) is
|
||||
/// enabled, limits the number of lines of text that are dumped for each tag.
|
||||
|
||||
extern uint32 gDumpLineLimit;
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Print out results from dng_timers?
|
||||
|
||||
extern bool gDNGShowTimers;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// MWG says don't use fake time zones in XMP, but there is some
|
||||
// old software that requires them to work correctly.
|
||||
|
||||
extern bool gDNGUseFakeTimeZonesInXMP;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Stream block size. Choose a size that the OS likes for file system
|
||||
// efficent read/write alignment.
|
||||
|
||||
extern uint32 gDNGStreamBlockSize;
|
||||
|
||||
// Maximum stream buffer size to use on large reads and writes.
|
||||
|
||||
extern uint32 gDNGMaxStreamBufferSize;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Are we running as part of the imagecore library?
|
||||
|
||||
extern bool gImagecore;
|
||||
|
||||
// Print out timing info for area tasks?
|
||||
|
||||
extern bool gPrintTimings;
|
||||
|
||||
// Print assert messages?
|
||||
|
||||
extern bool gPrintAsserts;
|
||||
|
||||
// Break into debugger on asserts?
|
||||
|
||||
extern bool gBreakOnAsserts;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,587 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_host.h"
|
||||
|
||||
#include "dng_abort_sniffer.h"
|
||||
#include "dng_area_task.h"
|
||||
#include "dng_bad_pixels.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_exif.h"
|
||||
#include "dng_gain_map.h"
|
||||
#include "dng_ifd.h"
|
||||
#include "dng_lens_correction.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_misc_opcodes.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_resample.h"
|
||||
#include "dng_shared.h"
|
||||
#include "dng_simple_image.h"
|
||||
#include "dng_xmp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_host::dng_host (dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer *sniffer)
|
||||
|
||||
: fAllocator (allocator)
|
||||
, fSniffer (sniffer)
|
||||
|
||||
, fNeedsMeta (true)
|
||||
, fNeedsImage (true)
|
||||
, fForPreview (false)
|
||||
, fMinimumSize (0)
|
||||
, fPreferredSize (0)
|
||||
, fMaximumSize (0)
|
||||
, fCropFactor (1.0)
|
||||
, fSaveDNGVersion (dngVersion_None)
|
||||
, fSaveLinearDNG (false)
|
||||
, fKeepOriginalFile (false)
|
||||
, fForFastSaveToDNG (false)
|
||||
, fFastSaveToDNGSize (0)
|
||||
, fPreserveStage2 (false)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_host::~dng_host ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_allocator & dng_host::Allocator ()
|
||||
{
|
||||
|
||||
if (fAllocator)
|
||||
{
|
||||
|
||||
return *fAllocator;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
return gDefaultDNGMemoryAllocator;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_block * dng_host::Allocate (uint32 logicalSize)
|
||||
{
|
||||
|
||||
return Allocator ().Allocate (logicalSize);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_host::SniffForAbort ()
|
||||
{
|
||||
|
||||
dng_abort_sniffer::SniffForAbort (Sniffer ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_host::ValidateSizes ()
|
||||
{
|
||||
|
||||
// The maximum size limits the other two sizes.
|
||||
|
||||
if (MaximumSize ())
|
||||
{
|
||||
SetMinimumSize (Min_uint32 (MinimumSize (), MaximumSize ()));
|
||||
SetPreferredSize (Min_uint32 (PreferredSize (), MaximumSize ()));
|
||||
}
|
||||
|
||||
// If we have a preferred size, it limits the minimum size.
|
||||
|
||||
if (PreferredSize ())
|
||||
{
|
||||
SetMinimumSize (Min_uint32 (MinimumSize (), PreferredSize ()));
|
||||
}
|
||||
|
||||
// Else find default value for preferred size.
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
// If preferred size is zero, then we want the maximim
|
||||
// size image.
|
||||
|
||||
if (MaximumSize ())
|
||||
{
|
||||
SetPreferredSize (MaximumSize ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we don't have a minimum size, find default.
|
||||
|
||||
if (!MinimumSize ())
|
||||
{
|
||||
|
||||
// A common size for embedded thumbnails is 120 by 160 pixels,
|
||||
// So allow 120 by 160 pixels to be used for thumbnails when the
|
||||
// preferred size is 256 pixel.
|
||||
|
||||
if (PreferredSize () >= 160 && PreferredSize () <= 256)
|
||||
{
|
||||
SetMinimumSize (160);
|
||||
}
|
||||
|
||||
// Many sensors are near a multiple of 1024 pixels in size, but after
|
||||
// the default crop, they are a just under. We can get an extra factor
|
||||
// of size reduction if we allow a slight undershoot in the final size
|
||||
// when computing large previews.
|
||||
|
||||
else if (PreferredSize () >= 490 && PreferredSize () <= 512)
|
||||
{
|
||||
SetMinimumSize (490);
|
||||
}
|
||||
|
||||
else if (PreferredSize () >= 980 && PreferredSize () <= 1024)
|
||||
{
|
||||
SetMinimumSize (980);
|
||||
}
|
||||
|
||||
else if (PreferredSize () >= 1470 && PreferredSize () <= 1536)
|
||||
{
|
||||
SetMinimumSize (1470);
|
||||
}
|
||||
|
||||
else if (PreferredSize () >= 1960 && PreferredSize () <= 2048)
|
||||
{
|
||||
SetMinimumSize (1960);
|
||||
}
|
||||
|
||||
else if (PreferredSize () >= 2400 && PreferredSize () <= 2560)
|
||||
{
|
||||
SetMinimumSize (2400);
|
||||
}
|
||||
|
||||
// The following resolutions are typically on HiDPI displays where a
|
||||
// greater degree of upsampling remains visually ok for previews. The
|
||||
// following ratios are all based on 20% upsampling in a linear
|
||||
// dimension.
|
||||
|
||||
else if (PreferredSize () >= 2448 && PreferredSize () <= 2880)
|
||||
{
|
||||
SetMinimumSize (2448);
|
||||
}
|
||||
|
||||
// 1st-generation Surface Book.
|
||||
|
||||
else if (PreferredSize () >= 2560 && PreferredSize () <= 3000)
|
||||
{
|
||||
SetMinimumSize (2560);
|
||||
}
|
||||
|
||||
// 4K (actually 3840).
|
||||
|
||||
else if (PreferredSize () >= 3480 && PreferredSize () <= 4096)
|
||||
{
|
||||
SetMinimumSize (3480);
|
||||
}
|
||||
|
||||
// Surface Studio.
|
||||
|
||||
else if (PreferredSize () >= 3824 && PreferredSize () <= 4500)
|
||||
{
|
||||
SetMinimumSize (3824);
|
||||
}
|
||||
|
||||
// 5K.
|
||||
|
||||
else if (PreferredSize () >= 4352 && PreferredSize () <= 5120)
|
||||
{
|
||||
SetMinimumSize (4352);
|
||||
}
|
||||
|
||||
// 8K.
|
||||
|
||||
else if (PreferredSize () >= 6528 && PreferredSize () <= 7680)
|
||||
{
|
||||
SetMinimumSize (6528);
|
||||
}
|
||||
|
||||
// Else minimum size is same as preferred size.
|
||||
|
||||
else
|
||||
{
|
||||
SetMinimumSize (PreferredSize ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 dng_host::SaveDNGVersion () const
|
||||
{
|
||||
|
||||
return fSaveDNGVersion;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_host::SaveLinearDNG (const dng_negative & /* negative */) const
|
||||
{
|
||||
|
||||
return fSaveLinearDNG;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_host::IsTransientError (dng_error_code code)
|
||||
{
|
||||
|
||||
switch (code)
|
||||
{
|
||||
|
||||
case dng_error_memory:
|
||||
case dng_error_user_canceled:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_host::PerformAreaTask (dng_area_task &task,
|
||||
const dng_rect &area,
|
||||
dng_area_task_progress *progress)
|
||||
{
|
||||
|
||||
dng_area_task::Perform (task,
|
||||
area,
|
||||
&Allocator (),
|
||||
Sniffer (),
|
||||
progress);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 dng_host::PerformAreaTaskThreads ()
|
||||
{
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_exif * dng_host::Make_dng_exif ()
|
||||
{
|
||||
|
||||
dng_exif *result = new dng_exif ();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_xmp * dng_host::Make_dng_xmp ()
|
||||
{
|
||||
|
||||
dng_xmp *result = new dng_xmp (Allocator ());
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_shared * dng_host::Make_dng_shared ()
|
||||
{
|
||||
|
||||
dng_shared *result = new dng_shared ();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_ifd * dng_host::Make_dng_ifd ()
|
||||
{
|
||||
|
||||
dng_ifd *result = new dng_ifd ();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_negative * dng_host::Make_dng_negative ()
|
||||
{
|
||||
|
||||
return dng_negative::Make (*this);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_image * dng_host::Make_dng_image (const dng_rect &bounds,
|
||||
uint32 planes,
|
||||
uint32 pixelType)
|
||||
{
|
||||
|
||||
dng_image *result = new dng_simple_image (bounds,
|
||||
planes,
|
||||
pixelType,
|
||||
Allocator ());
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode * dng_host::Make_dng_opcode (uint32 opcodeID,
|
||||
dng_stream &stream)
|
||||
{
|
||||
|
||||
dng_opcode *result = NULL;
|
||||
|
||||
switch (opcodeID)
|
||||
{
|
||||
|
||||
case dngOpcode_WarpRectilinear:
|
||||
{
|
||||
|
||||
result = new dng_opcode_WarpRectilinear (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_WarpFisheye:
|
||||
{
|
||||
|
||||
result = new dng_opcode_WarpFisheye (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_FixVignetteRadial:
|
||||
{
|
||||
|
||||
result = new dng_opcode_FixVignetteRadial (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_FixBadPixelsConstant:
|
||||
{
|
||||
|
||||
result = new dng_opcode_FixBadPixelsConstant (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_FixBadPixelsList:
|
||||
{
|
||||
|
||||
result = new dng_opcode_FixBadPixelsList (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_TrimBounds:
|
||||
{
|
||||
|
||||
result = new dng_opcode_TrimBounds (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_MapTable:
|
||||
{
|
||||
|
||||
result = new dng_opcode_MapTable (*this,
|
||||
stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_MapPolynomial:
|
||||
{
|
||||
|
||||
result = new dng_opcode_MapPolynomial (stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_GainMap:
|
||||
{
|
||||
|
||||
result = new dng_opcode_GainMap (*this,
|
||||
stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_DeltaPerRow:
|
||||
{
|
||||
|
||||
result = new dng_opcode_DeltaPerRow (*this,
|
||||
stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_DeltaPerColumn:
|
||||
{
|
||||
|
||||
result = new dng_opcode_DeltaPerColumn (*this,
|
||||
stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_ScalePerRow:
|
||||
{
|
||||
|
||||
result = new dng_opcode_ScalePerRow (*this,
|
||||
stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case dngOpcode_ScalePerColumn:
|
||||
{
|
||||
|
||||
result = new dng_opcode_ScalePerColumn (*this,
|
||||
stream);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
result = new dng_opcode_Unknown (*this,
|
||||
opcodeID,
|
||||
stream);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_host::ApplyOpcodeList (dng_opcode_list &list,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image)
|
||||
{
|
||||
|
||||
list.Apply (*this,
|
||||
negative,
|
||||
image);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_host::ResampleImage (const dng_image &srcImage,
|
||||
dng_image &dstImage)
|
||||
{
|
||||
|
||||
::ResampleImage (*this,
|
||||
srcImage,
|
||||
dstImage,
|
||||
srcImage.Bounds (),
|
||||
dstImage.Bounds (),
|
||||
dng_resample_bicubic::Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,444 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Class definition for dng_host, initial point of contact and control between
|
||||
* host application and DNG SDK.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_host__
|
||||
#define __dng_host__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_errors.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief The main class for communication between the application and the
|
||||
/// DNG SDK. Used to customize memory allocation and other behaviors.
|
||||
///
|
||||
/// dng_host allows setting parameters for the DNG conversion, mediates callback
|
||||
/// style interactions between the host application and the DNG SDK, and allows
|
||||
/// controlling certain internal behavior of the SDK such as memory allocation.
|
||||
/// Many applications will be able to use the default implementation of dng_host
|
||||
/// by just setting the dng_memory_allocator and dng_abort_sniffer in the
|
||||
/// constructor. More complex interactions will require deriving a class from
|
||||
/// dng_host.
|
||||
///
|
||||
/// Multiple dng_host objects can be allocated in a single process. This may
|
||||
/// be useful for DNG processing on separate threads. (Distinct dng_host objects
|
||||
/// are completely threadsafe for read/write. The application is responsible for
|
||||
/// establishing mutual exclusion for read/write access to a single dng_host
|
||||
/// object if it is used in multiple threads.)
|
||||
|
||||
class dng_host: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_memory_allocator *fAllocator;
|
||||
|
||||
dng_abort_sniffer *fSniffer;
|
||||
|
||||
// Does the host require all the image metadata (vs. just checking
|
||||
// to see if the file is readable)?
|
||||
|
||||
bool fNeedsMeta;
|
||||
|
||||
// Does the host require actual image data (vs. just getting metadata
|
||||
// or just checking to see if the file is readable)?
|
||||
|
||||
bool fNeedsImage;
|
||||
|
||||
// If we need the image data, can it be read at preview quality?
|
||||
|
||||
bool fForPreview;
|
||||
|
||||
// If non-zero, the minimum size (longer of the two pixel dimensions)
|
||||
// image to read. If zero, or if the full size image is smaller than
|
||||
// this, read the full size image.
|
||||
|
||||
uint32 fMinimumSize;
|
||||
|
||||
// What is the preferred size for a preview image? This can
|
||||
// be slightly larger than the minimum size. Zero if we want
|
||||
// the full resolution image.
|
||||
|
||||
uint32 fPreferredSize;
|
||||
|
||||
// What is the maximum size for a preview image? Zero if there
|
||||
// is no maximum size limit.
|
||||
|
||||
uint32 fMaximumSize;
|
||||
|
||||
// The fraction of the image kept after a crop. This is used to
|
||||
// adjust the sizes to take into account the cropping that
|
||||
// will be peformed.
|
||||
|
||||
real64 fCropFactor;
|
||||
|
||||
// What DNG version should we keep enough data to save?
|
||||
|
||||
uint32 fSaveDNGVersion;
|
||||
|
||||
// Do we want to force saving to a linear DNG?
|
||||
|
||||
bool fSaveLinearDNG;
|
||||
|
||||
// Keep the original raw file data block?
|
||||
|
||||
bool fKeepOriginalFile;
|
||||
|
||||
// Is this host being used to perform a negative read for fast
|
||||
// conversion to DNG?
|
||||
|
||||
bool fForFastSaveToDNG;
|
||||
|
||||
uint32 fFastSaveToDNGSize;
|
||||
|
||||
bool fPreserveStage2;
|
||||
|
||||
public:
|
||||
|
||||
/// Allocate a dng_host object, possiblly with custom allocator and sniffer.
|
||||
/// \param allocator Allows controlling all memory allocation done via this
|
||||
/// dng_host. Defaults to singleton global dng_memory_allocator, which calls
|
||||
/// new/delete dng_malloc_block for appropriate size.
|
||||
/// \param sniffer Used to periodically check if pending DNG conversions
|
||||
/// should be aborted and to communicate progress updates. Defaults to singleton
|
||||
/// global dng_abort_sniffer, which never aborts and ignores progress updated.
|
||||
|
||||
dng_host (dng_memory_allocator *allocator = NULL,
|
||||
dng_abort_sniffer *sniffer = NULL);
|
||||
|
||||
/// Clean up direct memory for dng_host. Memory allocator and abort sniffer
|
||||
/// are not deleted. Objects such as dng_image and others returned from
|
||||
/// host can still be used after host is deleted.
|
||||
|
||||
virtual ~dng_host ();
|
||||
|
||||
/// Getter for host's memory allocator.
|
||||
|
||||
dng_memory_allocator & Allocator ();
|
||||
|
||||
/// Alocate a new dng_memory_block using the host's memory allocator.
|
||||
/// Uses the Allocator() property of host to allocate a new block of memory.
|
||||
/// Will call ThrowMemoryFull if block cannot be allocated.
|
||||
/// \param logicalSize Number of usable bytes returned dng_memory_block
|
||||
/// must contain.
|
||||
|
||||
virtual dng_memory_block * Allocate (uint32 logicalSize);
|
||||
|
||||
/// Setter for host's abort sniffer.
|
||||
|
||||
void SetSniffer (dng_abort_sniffer *sniffer)
|
||||
{
|
||||
fSniffer = sniffer;
|
||||
}
|
||||
|
||||
/// Getter for host's abort sniffer.
|
||||
|
||||
dng_abort_sniffer * Sniffer ()
|
||||
{
|
||||
return fSniffer;
|
||||
}
|
||||
|
||||
/// Check for pending abort. Should call ThrowUserCanceled if an abort
|
||||
/// is pending.
|
||||
|
||||
virtual void SniffForAbort ();
|
||||
|
||||
/// Setter for flag determining whether all XMP metadata should be parsed.
|
||||
/// Defaults to true. One might not want metadata when doing a quick check
|
||||
/// to see if a file is readable.
|
||||
/// \param needs If true, metadata is needed.
|
||||
|
||||
void SetNeedsMeta (bool needs)
|
||||
{
|
||||
fNeedsMeta = needs;
|
||||
}
|
||||
|
||||
/// Getter for flag determining whether all XMP metadata should be parsed.
|
||||
|
||||
bool NeedsMeta () const
|
||||
{
|
||||
return fNeedsMeta;
|
||||
}
|
||||
|
||||
/// Setter for flag determining whether DNG image data is needed. Defaults
|
||||
/// to true. Image data might not be needed for applications which only
|
||||
/// manipulate metadata.
|
||||
/// \param needs If true, image data is needed.
|
||||
|
||||
void SetNeedsImage (bool needs)
|
||||
{
|
||||
fNeedsImage = needs;
|
||||
}
|
||||
|
||||
/// Setter for flag determining whether DNG image data is needed.
|
||||
|
||||
bool NeedsImage () const
|
||||
{
|
||||
return fNeedsImage;
|
||||
}
|
||||
|
||||
/// Setter for flag determining whether image should be preview quality,
|
||||
/// or full quality.
|
||||
/// \param preview If true, rendered images are for preview.
|
||||
|
||||
void SetForPreview (bool preview)
|
||||
{
|
||||
fForPreview = preview;
|
||||
}
|
||||
|
||||
/// Getter for flag determining whether image should be preview quality.
|
||||
/// Preview quality images may be rendered more quickly. Current DNG SDK
|
||||
/// does not change rendering behavior based on this flag, but derived
|
||||
/// versions may use this getter to choose between a slower more accurate path
|
||||
/// and a faster "good enough for preview" one. Data produce with ForPreview set
|
||||
/// to true should not be written back to a DNG file, except as a preview image.
|
||||
|
||||
bool ForPreview () const
|
||||
{
|
||||
return fForPreview;
|
||||
}
|
||||
|
||||
/// Setter for the minimum preview size.
|
||||
/// \param size Minimum pixel size (long side of image).
|
||||
|
||||
void SetMinimumSize (uint32 size)
|
||||
{
|
||||
fMinimumSize = size;
|
||||
}
|
||||
|
||||
/// Getter for the minimum preview size.
|
||||
|
||||
uint32 MinimumSize () const
|
||||
{
|
||||
return fMinimumSize;
|
||||
}
|
||||
|
||||
/// Setter for the preferred preview size.
|
||||
/// \param size Preferred pixel size (long side of image).
|
||||
|
||||
void SetPreferredSize (uint32 size)
|
||||
{
|
||||
fPreferredSize = size;
|
||||
}
|
||||
|
||||
/// Getter for the preferred preview size.
|
||||
|
||||
uint32 PreferredSize () const
|
||||
{
|
||||
return fPreferredSize;
|
||||
}
|
||||
|
||||
/// Setter for the maximum preview size.
|
||||
/// \param size Maximum pixel size (long side of image).
|
||||
|
||||
void SetMaximumSize (uint32 size)
|
||||
{
|
||||
fMaximumSize = size;
|
||||
}
|
||||
|
||||
/// Getter for the maximum preview size.
|
||||
|
||||
uint32 MaximumSize () const
|
||||
{
|
||||
return fMaximumSize;
|
||||
}
|
||||
|
||||
/// Setter for the perform fast save to DNG.
|
||||
/// \param flag True if the host is being used to perform a negative
|
||||
/// read for fast conversion to DNG, false otherwise.
|
||||
|
||||
void SetForFastSaveToDNG (bool flag,
|
||||
uint32 size)
|
||||
{
|
||||
fForFastSaveToDNG = flag;
|
||||
fFastSaveToDNGSize = size;
|
||||
}
|
||||
|
||||
/// Getter for the Boolean value that indicates whether this host is
|
||||
/// being used to perform a negative read for fast conversion to DNG.
|
||||
|
||||
bool ForFastSaveToDNG () const
|
||||
{
|
||||
return fForFastSaveToDNG;
|
||||
}
|
||||
|
||||
uint32 FastSaveToDNGSize () const
|
||||
{
|
||||
return fFastSaveToDNGSize;
|
||||
}
|
||||
|
||||
/// Setter for the cropping factor.
|
||||
/// \param cropFactor Fraction of image to be used after crop.
|
||||
|
||||
void SetCropFactor (real64 cropFactor)
|
||||
{
|
||||
fCropFactor = cropFactor;
|
||||
}
|
||||
|
||||
/// Getter for the cropping factor.
|
||||
|
||||
real64 CropFactor () const
|
||||
{
|
||||
return fCropFactor;
|
||||
}
|
||||
|
||||
/// Makes sures minimum, preferred, and maximum sizes are reasonable.
|
||||
|
||||
void ValidateSizes ();
|
||||
|
||||
/// Setter for what version to save DNG file compatible with.
|
||||
/// \param version What version to save DNG file compatible with.
|
||||
|
||||
void SetSaveDNGVersion (uint32 version)
|
||||
{
|
||||
fSaveDNGVersion = version;
|
||||
}
|
||||
|
||||
/// Getter for what version to save DNG file compatible with.
|
||||
|
||||
virtual uint32 SaveDNGVersion () const;
|
||||
|
||||
/// Setter for flag determining whether to force saving a linear DNG file.
|
||||
/// \param linear If true, we should force saving a linear DNG file.
|
||||
|
||||
void SetSaveLinearDNG (bool linear)
|
||||
{
|
||||
fSaveLinearDNG = linear;
|
||||
}
|
||||
|
||||
/// Getter for flag determining whether to save a linear DNG file.
|
||||
|
||||
virtual bool SaveLinearDNG (const dng_negative &negative) const;
|
||||
|
||||
/// Setter for flag determining whether to keep original RAW file data.
|
||||
/// \param keep If true, origianl RAW data will be kept.
|
||||
|
||||
void SetKeepOriginalFile (bool keep)
|
||||
{
|
||||
fKeepOriginalFile = keep;
|
||||
}
|
||||
|
||||
/// Getter for flag determining whether to keep original RAW file data.
|
||||
|
||||
bool KeepOriginalFile ()
|
||||
{
|
||||
return fKeepOriginalFile;
|
||||
}
|
||||
|
||||
/// Determine if an error is the result of a temporary, but planned-for
|
||||
/// occurence such as user cancellation or memory exhaustion. This method is
|
||||
/// sometimes used to determine whether to try and continue processing a DNG
|
||||
/// file despite errors in the file format, etc. In such cases, processing will
|
||||
/// be continued if IsTransientError returns false. This is so that user cancellation
|
||||
/// and memory exhaustion always terminate processing.
|
||||
/// \param code Error to test for transience.
|
||||
|
||||
virtual bool IsTransientError (dng_error_code code);
|
||||
|
||||
/// General top-level botttleneck for image processing tasks.
|
||||
/// Default implementation calls dng_area_task::PerformAreaTask method on
|
||||
/// task. Can be overridden in derived classes to support multiprocessing,
|
||||
/// for example.
|
||||
/// \param task Image processing task to perform on area.
|
||||
/// \param area Rectangle over which to perform image processing task.
|
||||
|
||||
virtual void PerformAreaTask (dng_area_task &task,
|
||||
const dng_rect &area,
|
||||
dng_area_task_progress *progress = NULL);
|
||||
|
||||
/// How many multiprocessing threads does PerformAreaTask use?
|
||||
/// Default implementation always returns 1 since it is single threaded.
|
||||
|
||||
virtual uint32 PerformAreaTaskThreads ();
|
||||
|
||||
/// Factory method for dng_exif class. Can be used to customize allocation or
|
||||
/// to ensure a derived class is used instead of dng_exif.
|
||||
|
||||
virtual dng_exif * Make_dng_exif ();
|
||||
|
||||
/// Factory method for dng_xmp class. Can be used to customize allocation or
|
||||
/// to ensure a derived class is used instead of dng_xmp.
|
||||
|
||||
virtual dng_xmp * Make_dng_xmp ();
|
||||
|
||||
/// Factory method for dng_shared class. Can be used to customize allocation
|
||||
/// or to ensure a derived class is used instead of dng_shared.
|
||||
|
||||
virtual dng_shared * Make_dng_shared ();
|
||||
|
||||
/// Factory method for dng_ifd class. Can be used to customize allocation or
|
||||
/// to ensure a derived class is used instead of dng_ifd.
|
||||
|
||||
virtual dng_ifd * Make_dng_ifd ();
|
||||
|
||||
/// Factory method for dng_negative class. Can be used to customize allocation
|
||||
/// or to ensure a derived class is used instead of dng_negative.
|
||||
|
||||
virtual dng_negative * Make_dng_negative ();
|
||||
|
||||
/// Factory method for dng_image class. Can be used to customize allocation
|
||||
/// or to ensure a derived class is used instead of dng_simple_image.
|
||||
|
||||
virtual dng_image * Make_dng_image (const dng_rect &bounds,
|
||||
uint32 planes,
|
||||
uint32 pixelType);
|
||||
|
||||
/// Factory method for parsing dng_opcode based classs. Can be used to
|
||||
/// override opcode implementations.
|
||||
|
||||
virtual dng_opcode * Make_dng_opcode (uint32 opcodeID,
|
||||
dng_stream &stream);
|
||||
|
||||
/// Factory method to apply a dng_opcode_list. Can be used to override
|
||||
/// opcode list applications.
|
||||
|
||||
virtual void ApplyOpcodeList (dng_opcode_list &list,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
/// Factory method to resample an image. Can be used to override
|
||||
/// image method used to resample images.
|
||||
|
||||
virtual void ResampleImage (const dng_image &srcImage,
|
||||
dng_image &dstImage);
|
||||
|
||||
/// Getter for flag determining whether we should preserve the stage 2
|
||||
/// image after building the stage 3 image.
|
||||
|
||||
bool WantsPreserveStage2 () const
|
||||
{
|
||||
return fPreserveStage2;
|
||||
}
|
||||
|
||||
/// Setter for flag determining whether we should preserve the stage 2
|
||||
/// image after building the stage 3 image.
|
||||
|
||||
void SetWantsPreserveStage2 (bool flag)
|
||||
{
|
||||
fPreserveStage2 = flag;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,405 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2007-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_hue_sat_map.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_bottlenecks.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_host.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
std::atomic<uint64> dng_hue_sat_map::sRuntimeFingerprintCounter (0);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_hue_sat_map::dng_hue_sat_map ()
|
||||
|
||||
: fHueDivisions (0)
|
||||
, fSatDivisions (0)
|
||||
, fValDivisions (0)
|
||||
, fHueStep (0)
|
||||
, fValStep (0)
|
||||
, fRuntimeFingerprint ()
|
||||
, fDeltas ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_hue_sat_map::dng_hue_sat_map (const dng_hue_sat_map &src)
|
||||
|
||||
: fHueDivisions (0)
|
||||
, fSatDivisions (0)
|
||||
, fValDivisions (0)
|
||||
, fHueStep (0)
|
||||
, fValStep (0)
|
||||
, fRuntimeFingerprint ()
|
||||
, fDeltas ()
|
||||
|
||||
{
|
||||
|
||||
*this = src;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_hue_sat_map &dng_hue_sat_map::operator= (const dng_hue_sat_map &rhs)
|
||||
{
|
||||
|
||||
if (this != &rhs)
|
||||
{
|
||||
|
||||
if (!rhs.IsValid ())
|
||||
{
|
||||
|
||||
SetInvalid ();
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
fHueDivisions = rhs.fHueDivisions;
|
||||
fSatDivisions = rhs.fSatDivisions;
|
||||
fValDivisions = rhs.fValDivisions;
|
||||
|
||||
fHueStep = rhs.fHueStep;
|
||||
fValStep = rhs.fValStep;
|
||||
|
||||
fRuntimeFingerprint = rhs.fRuntimeFingerprint;
|
||||
|
||||
fDeltas = rhs.fDeltas;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_hue_sat_map::~dng_hue_sat_map ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_hue_sat_map::SetDivisions (uint32 hueDivisions,
|
||||
uint32 satDivisions,
|
||||
uint32 valDivisions)
|
||||
{
|
||||
|
||||
DNG_ASSERT (hueDivisions >= 1, "Must have at least 1 hue division.");
|
||||
DNG_ASSERT (satDivisions >= 2, "Must have at least 2 sat divisions.");
|
||||
|
||||
if (valDivisions == 0)
|
||||
valDivisions = 1;
|
||||
|
||||
if (hueDivisions == fHueDivisions &&
|
||||
satDivisions == fSatDivisions &&
|
||||
valDivisions == fValDivisions)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fHueDivisions = hueDivisions;
|
||||
fSatDivisions = satDivisions;
|
||||
fValDivisions = valDivisions;
|
||||
|
||||
fHueStep = satDivisions;
|
||||
fValStep = hueDivisions * fHueStep;
|
||||
|
||||
dng_safe_uint32 size (DeltasCount ());
|
||||
|
||||
size *= (uint32) sizeof (HSBModify);
|
||||
|
||||
fDeltas.Allocate (size.Get ());
|
||||
|
||||
DoZeroBytes (fDeltas.Buffer (), size.Get ());
|
||||
|
||||
fRuntimeFingerprint.Clear ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_hue_sat_map::GetDelta (uint32 hueDiv,
|
||||
uint32 satDiv,
|
||||
uint32 valDiv,
|
||||
HSBModify &modify) const
|
||||
{
|
||||
|
||||
if (hueDiv >= fHueDivisions ||
|
||||
satDiv >= fSatDivisions ||
|
||||
valDiv >= fValDivisions ||
|
||||
fDeltas.Buffer () == NULL)
|
||||
{
|
||||
|
||||
DNG_REPORT ("Bad parameters to dng_hue_sat_map::GetDelta");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
int32 offset = valDiv * fValStep +
|
||||
hueDiv * fHueStep +
|
||||
satDiv;
|
||||
|
||||
const HSBModify *deltas = GetConstDeltas ();
|
||||
|
||||
modify.fHueShift = deltas [offset].fHueShift;
|
||||
modify.fSatScale = deltas [offset].fSatScale;
|
||||
modify.fValScale = deltas [offset].fValScale;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_hue_sat_map::SetDeltaKnownWriteable (uint32 hueDiv,
|
||||
uint32 satDiv,
|
||||
uint32 valDiv,
|
||||
const HSBModify &modify)
|
||||
{
|
||||
|
||||
if (hueDiv >= fHueDivisions ||
|
||||
satDiv >= fSatDivisions ||
|
||||
valDiv >= fValDivisions ||
|
||||
fDeltas.Buffer () == NULL)
|
||||
{
|
||||
|
||||
DNG_REPORT ("Bad parameters to dng_hue_sat_map::SetDelta");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
// Set this entry.
|
||||
|
||||
int32 offset = valDiv * fValStep +
|
||||
hueDiv * fHueStep +
|
||||
satDiv;
|
||||
|
||||
SafeGetDeltas () [offset] = modify;
|
||||
|
||||
// The zero saturation entry is required to have a value scale
|
||||
// of 1.0f.
|
||||
|
||||
if (satDiv == 0)
|
||||
{
|
||||
|
||||
if (modify.fValScale != 1.0f)
|
||||
{
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
ReportWarning ("Value scale for zero saturation entries must be 1.0");
|
||||
|
||||
#endif
|
||||
|
||||
SafeGetDeltas () [offset] . fValScale = 1.0f;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we are settings the first saturation entry and we have not
|
||||
// set the zero saturation entry yet, fill in the zero saturation entry
|
||||
// by extrapolating first saturation entry.
|
||||
|
||||
if (satDiv == 1)
|
||||
{
|
||||
|
||||
HSBModify zeroSatModify;
|
||||
|
||||
GetDelta (hueDiv, 0, valDiv, zeroSatModify);
|
||||
|
||||
if (zeroSatModify.fValScale != 1.0f)
|
||||
{
|
||||
|
||||
zeroSatModify.fHueShift = modify.fHueShift;
|
||||
zeroSatModify.fSatScale = modify.fSatScale;
|
||||
zeroSatModify.fValScale = 1.0f;
|
||||
|
||||
SetDelta (hueDiv, 0, valDiv, zeroSatModify);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_hue_sat_map::AssignNewUniqueRuntimeFingerprint ()
|
||||
{
|
||||
|
||||
const uint64 uid = ++sRuntimeFingerprintCounter;
|
||||
|
||||
dng_md5_printer printer;
|
||||
printer.Process (&uid, sizeof (uid));
|
||||
fRuntimeFingerprint = printer.Result ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_hue_sat_map::operator== (const dng_hue_sat_map &rhs) const
|
||||
{
|
||||
|
||||
if (fHueDivisions != rhs.fHueDivisions ||
|
||||
fSatDivisions != rhs.fSatDivisions ||
|
||||
fValDivisions != rhs.fValDivisions)
|
||||
return false;
|
||||
|
||||
if (!IsValid ())
|
||||
return true;
|
||||
|
||||
return memcmp (GetConstDeltas (),
|
||||
rhs.GetConstDeltas (),
|
||||
DeltasCount () * sizeof (HSBModify)) == 0;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_hue_sat_map * dng_hue_sat_map::Interpolate (const dng_hue_sat_map &map1,
|
||||
const dng_hue_sat_map &map2,
|
||||
real64 weight1)
|
||||
{
|
||||
|
||||
if (weight1 >= 1.0)
|
||||
{
|
||||
|
||||
if (!map1.IsValid ())
|
||||
{
|
||||
|
||||
DNG_REPORT ("map1 is not valid");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
return new dng_hue_sat_map (map1);
|
||||
|
||||
}
|
||||
|
||||
if (weight1 <= 0.0)
|
||||
{
|
||||
|
||||
if (!map2.IsValid ())
|
||||
{
|
||||
DNG_REPORT ("map2 is not valid");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
return new dng_hue_sat_map (map2);
|
||||
|
||||
}
|
||||
|
||||
// Both maps must be valid if we are using both.
|
||||
|
||||
if (!map1.IsValid () || !map2.IsValid ())
|
||||
{
|
||||
|
||||
DNG_REPORT ("map1 or map2 is not valid");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
// Must have the same dimensions.
|
||||
|
||||
if (map1.fHueDivisions != map2.fHueDivisions ||
|
||||
map1.fSatDivisions != map2.fSatDivisions ||
|
||||
map1.fValDivisions != map2.fValDivisions)
|
||||
{
|
||||
|
||||
DNG_REPORT ("map1 and map2 have different sizes");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
// Make table to hold interpolated results.
|
||||
|
||||
AutoPtr<dng_hue_sat_map> result (new dng_hue_sat_map);
|
||||
|
||||
result->SetDivisions (map1.fHueDivisions,
|
||||
map1.fSatDivisions,
|
||||
map1.fValDivisions);
|
||||
|
||||
// Interpolate between the tables.
|
||||
|
||||
real32 w1 = (real32) weight1;
|
||||
real32 w2 = 1.0f - w1;
|
||||
|
||||
const HSBModify *data1 = map1.GetConstDeltas ();
|
||||
const HSBModify *data2 = map2.GetConstDeltas ();
|
||||
|
||||
HSBModify *data3 = result->SafeGetDeltas ();
|
||||
|
||||
uint32 count = map1.DeltasCount ();
|
||||
|
||||
for (uint32 index = 0; index < count; index++)
|
||||
{
|
||||
|
||||
data3->fHueShift = w1 * data1->fHueShift +
|
||||
w2 * data2->fHueShift;
|
||||
|
||||
data3->fSatScale = w1 * data1->fSatScale +
|
||||
w2 * data2->fSatScale;
|
||||
|
||||
data3->fValScale = w1 * data1->fValScale +
|
||||
w2 * data2->fValScale;
|
||||
|
||||
data1++;
|
||||
data2++;
|
||||
data3++;
|
||||
|
||||
}
|
||||
|
||||
// Compute a fingerprint based on the inputs for the new dng_hue_sat_map
|
||||
// so that repeated interpolations of the same objects with the same
|
||||
// parameters produce the same fingerprint each time.
|
||||
|
||||
{
|
||||
|
||||
dng_md5_printer printer;
|
||||
|
||||
printer.Process ("Interpolate", 11);
|
||||
|
||||
printer.Process (&weight1, sizeof(weight1));
|
||||
|
||||
printer.Process (map1.RuntimeFingerprint ().data,
|
||||
dng_fingerprint::kDNGFingerprintSize);
|
||||
|
||||
printer.Process (map2.RuntimeFingerprint ().data,
|
||||
dng_fingerprint::kDNGFingerprintSize);
|
||||
|
||||
result->SetRuntimeFingerprint (printer.Result ());
|
||||
|
||||
}
|
||||
|
||||
// Return interpolated tables.
|
||||
|
||||
return result.Release ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,258 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2007-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Table-based color correction data structure.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_hue_sat_map__
|
||||
#define __dng_hue_sat_map__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_fingerprint.h"
|
||||
#include "dng_ref_counted_block.h"
|
||||
#include "dng_safe_arithmetic.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 3D table that maps HSV (hue, saturation, and value) floating-point
|
||||
/// input coordinates in the range [0,1] to delta signals. The table must have at
|
||||
/// least 1 sample in the hue dimension, at least 2 samples in the saturation
|
||||
/// dimension, and at least 1 sample in the value dimension. Tables are stored in
|
||||
/// value-hue-saturation order.
|
||||
|
||||
class dng_hue_sat_map
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// HSV delta signal. fHueShift is a delta value specified in degrees.
|
||||
/// This parameter, added to the original hue, determines the output hue. A
|
||||
/// value of 0 means no change. fSatScale and fValScale are
|
||||
/// scale factors that are applied to saturation and value components,
|
||||
/// respectively. These scale factors, multiplied by the original saturation
|
||||
/// and value, determine the output saturation and value. A scale factor of
|
||||
/// 1.0 means no change.
|
||||
|
||||
struct HSBModify
|
||||
{
|
||||
real32 fHueShift;
|
||||
real32 fSatScale;
|
||||
real32 fValScale;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
uint32 fHueDivisions;
|
||||
uint32 fSatDivisions;
|
||||
uint32 fValDivisions;
|
||||
|
||||
uint32 fHueStep;
|
||||
uint32 fValStep;
|
||||
|
||||
// This fingerprint is intended to be used for certain rendering
|
||||
// optimizations. Also, it can vary from session to session.
|
||||
// In general, dng_hue_sat_map objects loaded from raw data
|
||||
// will be given unique values for the session while dng_hue_sat_map
|
||||
// objects derived from other dng_hue_sat_map objects will be
|
||||
// given fingerprint values based on their inputs so that if they
|
||||
// are recomputed, they get the same value (again, in that sesssion).
|
||||
|
||||
dng_fingerprint fRuntimeFingerprint;
|
||||
|
||||
static std::atomic<uint64> sRuntimeFingerprintCounter;
|
||||
|
||||
dng_ref_counted_block fDeltas;
|
||||
|
||||
HSBModify *SafeGetDeltas ()
|
||||
{
|
||||
return (HSBModify *) fDeltas.Buffer_real32 ();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an empty (and invalid) hue sat map.
|
||||
|
||||
dng_hue_sat_map ();
|
||||
|
||||
/// Copy an existing hue sat map.
|
||||
|
||||
dng_hue_sat_map (const dng_hue_sat_map &src);
|
||||
|
||||
/// Copy an existing hue sat map.
|
||||
|
||||
dng_hue_sat_map & operator= (const dng_hue_sat_map &rhs);
|
||||
|
||||
/// Destructor.
|
||||
|
||||
virtual ~dng_hue_sat_map ();
|
||||
|
||||
/// Is this hue sat map invalid?
|
||||
|
||||
bool IsNull () const
|
||||
{
|
||||
return !IsValid ();
|
||||
}
|
||||
|
||||
/// Is this hue sat map valid?
|
||||
|
||||
bool IsValid () const
|
||||
{
|
||||
|
||||
return fHueDivisions > 0 &&
|
||||
fSatDivisions > 1 &&
|
||||
fValDivisions > 0 &&
|
||||
fDeltas.Buffer ();
|
||||
|
||||
}
|
||||
|
||||
/// Clear the hue sat map, making it invalid.
|
||||
|
||||
void SetInvalid ()
|
||||
{
|
||||
|
||||
fHueDivisions = 0;
|
||||
fSatDivisions = 0;
|
||||
fValDivisions = 0;
|
||||
|
||||
fHueStep = 0;
|
||||
fValStep = 0;
|
||||
|
||||
fRuntimeFingerprint.Clear ();
|
||||
|
||||
fDeltas.Clear ();
|
||||
|
||||
}
|
||||
|
||||
/// Get the table dimensions (number of samples in each dimension).
|
||||
|
||||
void GetDivisions (uint32 &hueDivisions,
|
||||
uint32 &satDivisions,
|
||||
uint32 &valDivisions) const
|
||||
{
|
||||
hueDivisions = fHueDivisions;
|
||||
satDivisions = fSatDivisions;
|
||||
valDivisions = fValDivisions;
|
||||
}
|
||||
|
||||
/// Set the table dimensions (number of samples in each dimension). This
|
||||
/// erases any existing table data.
|
||||
|
||||
void SetDivisions (uint32 hueDivisions,
|
||||
uint32 satDivisions,
|
||||
uint32 valDivisions = 1);
|
||||
|
||||
/// Get a specific table entry, specified by table indices.
|
||||
|
||||
void GetDelta (uint32 hueDiv,
|
||||
uint32 satDiv,
|
||||
uint32 valDiv,
|
||||
HSBModify &modify) const;
|
||||
|
||||
/// Make sure the table is writeable.
|
||||
|
||||
void EnsureWriteable ()
|
||||
{
|
||||
fDeltas.EnsureWriteable ();
|
||||
}
|
||||
|
||||
/// Set a specific table entry, specified by table indices.
|
||||
|
||||
void SetDelta (uint32 hueDiv,
|
||||
uint32 satDiv,
|
||||
uint32 valDiv,
|
||||
const HSBModify &modify)
|
||||
{
|
||||
|
||||
EnsureWriteable ();
|
||||
|
||||
SetDeltaKnownWriteable (hueDiv,
|
||||
satDiv,
|
||||
valDiv,
|
||||
modify);
|
||||
|
||||
}
|
||||
|
||||
/// Same as SetDelta, without checking that the table is writeable.
|
||||
|
||||
void SetDeltaKnownWriteable (uint32 hueDiv,
|
||||
uint32 satDiv,
|
||||
uint32 valDiv,
|
||||
const HSBModify &modify);
|
||||
|
||||
/// Get the total number of samples (across all dimensions).
|
||||
|
||||
uint32 DeltasCount () const
|
||||
{
|
||||
return (dng_safe_uint32 (fValDivisions) *
|
||||
dng_safe_uint32 (fHueDivisions) *
|
||||
dng_safe_uint32 (fSatDivisions)).Get ();
|
||||
}
|
||||
|
||||
/// Direct read/write access to table entries. The entries are stored in
|
||||
/// value-hue-saturation order (outer to inner).
|
||||
|
||||
HSBModify *GetDeltas ()
|
||||
{
|
||||
|
||||
EnsureWriteable ();
|
||||
|
||||
return (HSBModify *) fDeltas.Buffer_real32 ();
|
||||
|
||||
}
|
||||
|
||||
/// Direct read-only access to table entries. The entries are stored in
|
||||
/// value-hue-saturation order (outer to inner).
|
||||
|
||||
const HSBModify *GetConstDeltas () const
|
||||
{
|
||||
return (const HSBModify *) fDeltas.Buffer_real32 ();
|
||||
}
|
||||
|
||||
void AssignNewUniqueRuntimeFingerprint ();
|
||||
|
||||
/// Set Fingerprint. Rare use cases want to set the fingerprint.
|
||||
|
||||
void SetRuntimeFingerprint (const dng_fingerprint fingerprint)
|
||||
{
|
||||
fRuntimeFingerprint = fingerprint;
|
||||
}
|
||||
|
||||
/// Get the runtime fingerprint of this hue sat map.
|
||||
|
||||
const dng_fingerprint & RuntimeFingerprint () const
|
||||
{
|
||||
return fRuntimeFingerprint;
|
||||
}
|
||||
|
||||
/// Equality test.
|
||||
|
||||
bool operator== (const dng_hue_sat_map &rhs) const;
|
||||
|
||||
/// Compute a linearly-interpolated hue sat map (i.e., delta and scale factors)
|
||||
/// from the specified tables, with the specified weight. map1 and map2 must
|
||||
/// have the same dimensions.
|
||||
|
||||
static dng_hue_sat_map * Interpolate (const dng_hue_sat_map &map1,
|
||||
const dng_hue_sat_map &map2,
|
||||
real64 weight1);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,311 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* DNG image file directory support.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_ifd__
|
||||
#define __dng_ifd__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_fingerprint.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_shared.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
#include "dng_tag_values.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_preview_info
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
bool fIsPrimary;
|
||||
|
||||
dng_string fApplicationName;
|
||||
|
||||
dng_string fApplicationVersion;
|
||||
|
||||
dng_string fSettingsName;
|
||||
|
||||
dng_fingerprint fSettingsDigest;
|
||||
|
||||
PreviewColorSpaceEnum fColorSpace;
|
||||
|
||||
dng_string fDateTime;
|
||||
|
||||
real64 fRawToPreviewGain;
|
||||
|
||||
uint32 fCacheVersion;
|
||||
|
||||
public:
|
||||
|
||||
dng_preview_info ();
|
||||
|
||||
~dng_preview_info ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Container for a single image file directory of a digital negative.
|
||||
///
|
||||
/// See \ref spec_dng "DNG 1.1.0 specification" for documentation of specific tags.
|
||||
|
||||
class dng_ifd
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
bool fUsesNewSubFileType;
|
||||
|
||||
uint32 fNewSubFileType;
|
||||
|
||||
uint32 fImageWidth;
|
||||
uint32 fImageLength;
|
||||
|
||||
uint32 fBitsPerSample [kMaxSamplesPerPixel];
|
||||
|
||||
uint32 fCompression;
|
||||
|
||||
uint32 fPredictor;
|
||||
|
||||
uint32 fPhotometricInterpretation;
|
||||
|
||||
uint32 fFillOrder;
|
||||
|
||||
uint32 fOrientation;
|
||||
uint32 fOrientationType;
|
||||
uint64 fOrientationOffset;
|
||||
bool fOrientationBigEndian;
|
||||
|
||||
uint32 fSamplesPerPixel;
|
||||
|
||||
uint32 fPlanarConfiguration;
|
||||
|
||||
real64 fXResolution;
|
||||
real64 fYResolution;
|
||||
|
||||
uint32 fResolutionUnit;
|
||||
|
||||
bool fUsesStrips;
|
||||
bool fUsesTiles;
|
||||
|
||||
uint32 fTileWidth;
|
||||
uint32 fTileLength;
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxTileInfo = 32
|
||||
};
|
||||
|
||||
uint32 fTileOffsetsType;
|
||||
uint32 fTileOffsetsCount;
|
||||
uint64 fTileOffsetsOffset;
|
||||
uint64 fTileOffset [kMaxTileInfo];
|
||||
|
||||
uint32 fTileByteCountsType;
|
||||
uint32 fTileByteCountsCount;
|
||||
uint64 fTileByteCountsOffset;
|
||||
uint32 fTileByteCount [kMaxTileInfo];
|
||||
|
||||
uint32 fSubIFDsCount;
|
||||
uint64 fSubIFDsOffset;
|
||||
|
||||
uint32 fExtraSamplesCount;
|
||||
uint32 fExtraSamples [kMaxSamplesPerPixel];
|
||||
|
||||
uint32 fSampleFormat [kMaxSamplesPerPixel];
|
||||
|
||||
uint32 fJPEGTablesCount;
|
||||
uint64 fJPEGTablesOffset;
|
||||
|
||||
uint64 fJPEGInterchangeFormat;
|
||||
uint32 fJPEGInterchangeFormatLength;
|
||||
|
||||
real64 fYCbCrCoefficientR;
|
||||
real64 fYCbCrCoefficientG;
|
||||
real64 fYCbCrCoefficientB;
|
||||
|
||||
uint32 fYCbCrSubSampleH;
|
||||
uint32 fYCbCrSubSampleV;
|
||||
|
||||
uint32 fYCbCrPositioning;
|
||||
|
||||
real64 fReferenceBlackWhite [6];
|
||||
|
||||
uint32 fCFARepeatPatternRows;
|
||||
uint32 fCFARepeatPatternCols;
|
||||
|
||||
uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
|
||||
|
||||
uint8 fCFAPlaneColor [kMaxColorPlanes];
|
||||
|
||||
uint32 fCFALayout;
|
||||
|
||||
uint32 fLinearizationTableType;
|
||||
uint32 fLinearizationTableCount;
|
||||
uint64 fLinearizationTableOffset;
|
||||
|
||||
uint32 fBlackLevelRepeatRows;
|
||||
uint32 fBlackLevelRepeatCols;
|
||||
|
||||
real64 fBlackLevel [kMaxBlackPattern] [kMaxBlackPattern] [kMaxSamplesPerPixel];
|
||||
|
||||
uint32 fBlackLevelDeltaHType;
|
||||
uint32 fBlackLevelDeltaHCount;
|
||||
uint64 fBlackLevelDeltaHOffset;
|
||||
|
||||
uint32 fBlackLevelDeltaVType;
|
||||
uint32 fBlackLevelDeltaVCount;
|
||||
uint64 fBlackLevelDeltaVOffset;
|
||||
|
||||
real64 fWhiteLevel [kMaxSamplesPerPixel];
|
||||
|
||||
dng_urational fDefaultScaleH;
|
||||
dng_urational fDefaultScaleV;
|
||||
|
||||
dng_urational fBestQualityScale;
|
||||
|
||||
dng_urational fDefaultCropOriginH;
|
||||
dng_urational fDefaultCropOriginV;
|
||||
|
||||
dng_urational fDefaultCropSizeH;
|
||||
dng_urational fDefaultCropSizeV;
|
||||
|
||||
dng_urational fDefaultUserCropT;
|
||||
dng_urational fDefaultUserCropL;
|
||||
dng_urational fDefaultUserCropB;
|
||||
dng_urational fDefaultUserCropR;
|
||||
|
||||
uint32 fBayerGreenSplit;
|
||||
|
||||
dng_urational fChromaBlurRadius;
|
||||
|
||||
dng_urational fAntiAliasStrength;
|
||||
|
||||
dng_rect fActiveArea;
|
||||
|
||||
uint32 fMaskedAreaCount;
|
||||
dng_rect fMaskedArea [kMaxMaskedAreas];
|
||||
|
||||
uint32 fRowInterleaveFactor;
|
||||
|
||||
uint32 fSubTileBlockRows;
|
||||
uint32 fSubTileBlockCols;
|
||||
|
||||
dng_preview_info fPreviewInfo;
|
||||
|
||||
uint32 fOpcodeList1Count;
|
||||
uint64 fOpcodeList1Offset;
|
||||
|
||||
uint32 fOpcodeList2Count;
|
||||
uint64 fOpcodeList2Offset;
|
||||
|
||||
uint32 fOpcodeList3Count;
|
||||
uint64 fOpcodeList3Offset;
|
||||
|
||||
dng_noise_profile fNoiseProfile;
|
||||
|
||||
dng_string fEnhanceParams;
|
||||
|
||||
dng_urational fBaselineSharpness;
|
||||
|
||||
dng_urational fNoiseReductionApplied;
|
||||
|
||||
bool fLosslessJPEGBug16;
|
||||
|
||||
uint32 fSampleBitShift;
|
||||
|
||||
uint64 fThisIFD;
|
||||
uint64 fNextIFD;
|
||||
|
||||
int32 fCompressionQuality;
|
||||
|
||||
bool fPatchFirstJPEGByte;
|
||||
|
||||
public:
|
||||
|
||||
dng_ifd ();
|
||||
|
||||
virtual ~dng_ifd ();
|
||||
|
||||
virtual dng_ifd * Clone () const;
|
||||
|
||||
virtual bool ParseTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset);
|
||||
|
||||
virtual void PostParse ();
|
||||
|
||||
virtual bool IsValidDNG (dng_shared &shared,
|
||||
uint32 parentCode);
|
||||
|
||||
dng_rect Bounds () const
|
||||
{
|
||||
return dng_rect (0,
|
||||
0,
|
||||
fImageLength,
|
||||
fImageWidth);
|
||||
}
|
||||
|
||||
uint32 TilesAcross () const;
|
||||
|
||||
uint32 TilesDown () const;
|
||||
|
||||
uint32 TilesPerImage () const;
|
||||
|
||||
dng_rect TileArea (uint32 rowIndex,
|
||||
uint32 colIndex) const;
|
||||
|
||||
virtual uint32 TileByteCount (const dng_rect &tile) const;
|
||||
|
||||
void SetSingleStrip ();
|
||||
|
||||
void FindTileSize (uint32 bytesPerTile = 128 * 1024,
|
||||
uint32 cellH = 16,
|
||||
uint32 cellV = 16);
|
||||
|
||||
void FindStripSize (uint32 bytesPerStrip = 128 * 1024,
|
||||
uint32 cellV = 16);
|
||||
|
||||
virtual uint32 PixelType () const;
|
||||
|
||||
virtual bool IsBaselineJPEG () const;
|
||||
|
||||
virtual bool CanRead () const;
|
||||
|
||||
virtual void ReadImage (dng_host &host,
|
||||
dng_stream &stream,
|
||||
dng_image &image,
|
||||
dng_jpeg_image *jpegImage = NULL,
|
||||
dng_fingerprint *jpegDigest = NULL) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool IsValidCFA (dng_shared &shared,
|
||||
uint32 parentCode);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,854 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_image.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_orientation.h"
|
||||
#include "dng_pixel_buffer.h"
|
||||
#include "dng_tag_types.h"
|
||||
#include "dng_tile_iterator.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_tile_buffer::dng_tile_buffer (const dng_image &image,
|
||||
const dng_rect &tile,
|
||||
bool dirty)
|
||||
|
||||
: fImage (image)
|
||||
, fRefData (NULL)
|
||||
|
||||
{
|
||||
|
||||
fImage.AcquireTileBuffer (*this,
|
||||
tile,
|
||||
dirty);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_tile_buffer::~dng_tile_buffer ()
|
||||
{
|
||||
|
||||
fImage.ReleaseTileBuffer (*this);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image,
|
||||
const dng_rect &tile)
|
||||
|
||||
: dng_tile_buffer (image, tile, false)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_const_tile_buffer::~dng_const_tile_buffer ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image,
|
||||
const dng_rect &tile)
|
||||
|
||||
: dng_tile_buffer (image, tile, true)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_dirty_tile_buffer::~dng_dirty_tile_buffer ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_image::dng_image (const dng_rect &bounds,
|
||||
uint32 planes,
|
||||
uint32 pixelType)
|
||||
|
||||
: fBounds (bounds)
|
||||
, fPlanes (planes)
|
||||
, fPixelType (pixelType)
|
||||
|
||||
{
|
||||
|
||||
if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0)
|
||||
{
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
ReportError ("Fuzz: Attempt to create zero size image");
|
||||
|
||||
#endif
|
||||
|
||||
ThrowBadFormat ();
|
||||
|
||||
}
|
||||
|
||||
// Allow up to 2 * kMaxImageSide to deal with intermediate image objects
|
||||
// (e.g., rotated and padded).
|
||||
|
||||
static const uint32 kLimit = 2 * kMaxImageSide;
|
||||
|
||||
if (bounds.W () > kLimit ||
|
||||
bounds.H () > kLimit)
|
||||
{
|
||||
|
||||
ThrowBadFormat ("dng_image bounds too large");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_image::~dng_image ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_image * dng_image::Clone () const
|
||||
{
|
||||
|
||||
ThrowProgramError ("Clone is not supported by this dng_image subclass");
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::SetPixelType (uint32 pixelType)
|
||||
{
|
||||
|
||||
if (TagTypeSize (pixelType) != PixelSize ())
|
||||
{
|
||||
|
||||
ThrowProgramError ("Cannot change pixel size for existing image");
|
||||
|
||||
}
|
||||
|
||||
fPixelType = pixelType;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 dng_image::PixelSize () const
|
||||
{
|
||||
|
||||
return TagTypeSize (PixelType ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 dng_image::PixelRange () const
|
||||
{
|
||||
|
||||
switch (fPixelType)
|
||||
{
|
||||
|
||||
case ttByte:
|
||||
case ttSByte:
|
||||
{
|
||||
return 0x0FF;
|
||||
}
|
||||
|
||||
case ttShort:
|
||||
case ttSShort:
|
||||
{
|
||||
return 0x0FFFF;
|
||||
}
|
||||
|
||||
case ttLong:
|
||||
case ttSLong:
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_rect dng_image::RepeatingTile () const
|
||||
{
|
||||
|
||||
return fBounds;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */,
|
||||
const dng_rect & /* area */,
|
||||
bool /* dirty */) const
|
||||
{
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::DoGet (dng_pixel_buffer &buffer) const
|
||||
{
|
||||
|
||||
dng_rect tile;
|
||||
|
||||
dng_tile_iterator iter (*this, buffer.fArea);
|
||||
|
||||
while (iter.GetOneTile (tile))
|
||||
{
|
||||
|
||||
dng_const_tile_buffer tileBuffer (*this, tile);
|
||||
|
||||
buffer.CopyArea (tileBuffer,
|
||||
tile,
|
||||
buffer.fPlane,
|
||||
buffer.fPlanes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::DoPut (const dng_pixel_buffer &buffer)
|
||||
{
|
||||
|
||||
dng_rect tile;
|
||||
|
||||
dng_tile_iterator iter (*this, buffer.fArea);
|
||||
|
||||
while (iter.GetOneTile (tile))
|
||||
{
|
||||
|
||||
dng_dirty_tile_buffer tileBuffer (*this, tile);
|
||||
|
||||
tileBuffer.CopyArea (buffer,
|
||||
tile,
|
||||
buffer.fPlane,
|
||||
buffer.fPlanes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::GetRepeat (dng_pixel_buffer &buffer,
|
||||
const dng_rect &srcArea,
|
||||
const dng_rect &dstArea) const
|
||||
{
|
||||
|
||||
// If we already have the entire srcArea in the
|
||||
// buffer, we can just repeat that.
|
||||
|
||||
if ((srcArea & buffer.fArea) == srcArea)
|
||||
{
|
||||
|
||||
buffer.RepeatArea (srcArea,
|
||||
dstArea);
|
||||
|
||||
}
|
||||
|
||||
// Else we first need to get the srcArea into the buffer area.
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
// Find repeating pattern size.
|
||||
|
||||
dng_point repeat = srcArea.Size ();
|
||||
|
||||
// Find pattern phase at top-left corner of destination area.
|
||||
|
||||
dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea,
|
||||
dstArea);
|
||||
|
||||
// Find new source area at top-left of dstArea.
|
||||
|
||||
dng_rect newArea = srcArea + (dstArea.TL () -
|
||||
srcArea.TL ());
|
||||
|
||||
// Find quadrant split coordinates.
|
||||
|
||||
int32 splitV = newArea.t + repeat.v - phase.v;
|
||||
int32 splitH = newArea.l + repeat.h - phase.h;
|
||||
|
||||
// Top-left quadrant.
|
||||
|
||||
dng_rect dst1 (dng_rect (newArea.t,
|
||||
newArea.l,
|
||||
splitV,
|
||||
splitH) & dstArea);
|
||||
|
||||
if (dst1.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_pixel_buffer temp (buffer);
|
||||
|
||||
temp.fArea = dst1 + (srcArea.TL () -
|
||||
dstArea.TL () +
|
||||
dng_point (phase.v, phase.h));
|
||||
|
||||
temp.fData = buffer.DirtyPixel (dst1.t,
|
||||
dst1.l,
|
||||
buffer.fPlane);
|
||||
|
||||
DoGet (temp);
|
||||
|
||||
}
|
||||
|
||||
// Top-right quadrant.
|
||||
|
||||
dng_rect dst2 (dng_rect (newArea.t,
|
||||
splitH,
|
||||
splitV,
|
||||
newArea.r) & dstArea);
|
||||
|
||||
if (dst2.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_pixel_buffer temp (buffer);
|
||||
|
||||
temp.fArea = dst2 + (srcArea.TL () -
|
||||
dstArea.TL () +
|
||||
dng_point (phase.v, -phase.h));
|
||||
|
||||
temp.fData = buffer.DirtyPixel (dst2.t,
|
||||
dst2.l,
|
||||
buffer.fPlane);
|
||||
|
||||
DoGet (temp);
|
||||
|
||||
}
|
||||
|
||||
// Bottom-left quadrant.
|
||||
|
||||
dng_rect dst3 (dng_rect (splitV,
|
||||
newArea.l,
|
||||
newArea.b,
|
||||
splitH) & dstArea);
|
||||
|
||||
if (dst3.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_pixel_buffer temp (buffer);
|
||||
|
||||
temp.fArea = dst3 + (srcArea.TL () -
|
||||
dstArea.TL () +
|
||||
dng_point (-phase.v, phase.h));
|
||||
|
||||
temp.fData = buffer.DirtyPixel (dst3.t,
|
||||
dst3.l,
|
||||
buffer.fPlane);
|
||||
|
||||
DoGet (temp);
|
||||
|
||||
}
|
||||
|
||||
// Bottom-right quadrant.
|
||||
|
||||
dng_rect dst4 (dng_rect (splitV,
|
||||
splitH,
|
||||
newArea.b,
|
||||
newArea.r) & dstArea);
|
||||
|
||||
if (dst4.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_pixel_buffer temp (buffer);
|
||||
|
||||
temp.fArea = dst4 + (srcArea.TL () -
|
||||
dstArea.TL () +
|
||||
dng_point (-phase.v, -phase.h));
|
||||
|
||||
temp.fData = buffer.DirtyPixel (dst4.t,
|
||||
dst4.l,
|
||||
buffer.fPlane);
|
||||
|
||||
DoGet (temp);
|
||||
|
||||
}
|
||||
|
||||
// Replicate this new source area.
|
||||
|
||||
buffer.RepeatArea (newArea,
|
||||
dstArea);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::GetEdge (dng_pixel_buffer &buffer,
|
||||
edge_option edgeOption,
|
||||
const dng_rect &srcArea,
|
||||
const dng_rect &dstArea) const
|
||||
{
|
||||
|
||||
switch (edgeOption)
|
||||
{
|
||||
|
||||
case edge_zero:
|
||||
{
|
||||
|
||||
buffer.SetZero (dstArea,
|
||||
buffer.fPlane,
|
||||
buffer.fPlanes);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case edge_repeat:
|
||||
{
|
||||
|
||||
GetRepeat (buffer,
|
||||
srcArea,
|
||||
dstArea);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case edge_repeat_zero_last:
|
||||
{
|
||||
|
||||
if (buffer.fPlanes > 1)
|
||||
{
|
||||
|
||||
dng_pixel_buffer buffer1 (buffer);
|
||||
|
||||
buffer1.fPlanes--;
|
||||
|
||||
GetEdge (buffer1,
|
||||
edge_repeat,
|
||||
srcArea,
|
||||
dstArea);
|
||||
|
||||
}
|
||||
|
||||
dng_pixel_buffer buffer2 (buffer);
|
||||
|
||||
buffer2.fPlane = buffer.fPlanes - 1;
|
||||
buffer2.fPlanes = 1;
|
||||
|
||||
buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t,
|
||||
buffer2.fArea.l,
|
||||
buffer2.fPlane);
|
||||
|
||||
GetEdge (buffer2,
|
||||
edge_zero,
|
||||
srcArea,
|
||||
dstArea);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::Get (dng_pixel_buffer &buffer,
|
||||
edge_option edgeOption,
|
||||
uint32 repeatV,
|
||||
uint32 repeatH) const
|
||||
{
|
||||
|
||||
// Find the overlap with the image bounds.
|
||||
|
||||
dng_rect overlap = buffer.fArea & fBounds;
|
||||
|
||||
// Move the overlapping pixels.
|
||||
|
||||
if (overlap.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_pixel_buffer temp (buffer);
|
||||
|
||||
temp.fArea = overlap;
|
||||
|
||||
temp.fData = buffer.DirtyPixel (overlap.t,
|
||||
overlap.l,
|
||||
buffer.fPlane);
|
||||
|
||||
DoGet (temp);
|
||||
|
||||
}
|
||||
|
||||
// See if we need to pad the edge values.
|
||||
|
||||
if ((edgeOption != edge_none) && (overlap != buffer.fArea))
|
||||
{
|
||||
|
||||
dng_rect areaT (buffer.fArea);
|
||||
dng_rect areaL (buffer.fArea);
|
||||
dng_rect areaB (buffer.fArea);
|
||||
dng_rect areaR (buffer.fArea);
|
||||
|
||||
areaT.b = Min_int32 (areaT.b, fBounds.t);
|
||||
areaL.r = Min_int32 (areaL.r, fBounds.l);
|
||||
areaB.t = Max_int32 (areaB.t, fBounds.b);
|
||||
areaR.l = Max_int32 (areaR.l, fBounds.r);
|
||||
|
||||
dng_rect areaH (buffer.fArea);
|
||||
dng_rect areaV (buffer.fArea);
|
||||
|
||||
areaH.l = Max_int32 (areaH.l, fBounds.l);
|
||||
areaH.r = Min_int32 (areaH.r, fBounds.r);
|
||||
|
||||
areaV.t = Max_int32 (areaV.t, fBounds.t);
|
||||
areaV.b = Min_int32 (areaV.b, fBounds.b);
|
||||
|
||||
// Top left.
|
||||
|
||||
dng_rect areaTL = areaT & areaL;
|
||||
|
||||
if (areaTL.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (fBounds.t,
|
||||
fBounds.l,
|
||||
fBounds.t + repeatV,
|
||||
fBounds.l + repeatH),
|
||||
areaTL);
|
||||
|
||||
}
|
||||
|
||||
// Top middle.
|
||||
|
||||
dng_rect areaTM = areaT & areaH;
|
||||
|
||||
if (areaTM.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (fBounds.t,
|
||||
areaTM.l,
|
||||
fBounds.t + repeatV,
|
||||
areaTM.r),
|
||||
areaTM);
|
||||
|
||||
}
|
||||
|
||||
// Top right.
|
||||
|
||||
dng_rect areaTR = areaT & areaR;
|
||||
|
||||
if (areaTR.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (fBounds.t,
|
||||
fBounds.r - repeatH,
|
||||
fBounds.t + repeatV,
|
||||
fBounds.r),
|
||||
areaTR);
|
||||
|
||||
}
|
||||
|
||||
// Left middle.
|
||||
|
||||
dng_rect areaLM = areaL & areaV;
|
||||
|
||||
if (areaLM.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (areaLM.t,
|
||||
fBounds.l,
|
||||
areaLM.b,
|
||||
fBounds.l + repeatH),
|
||||
areaLM);
|
||||
|
||||
}
|
||||
|
||||
// Right middle.
|
||||
|
||||
dng_rect areaRM = areaR & areaV;
|
||||
|
||||
if (areaRM.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (areaRM.t,
|
||||
fBounds.r - repeatH,
|
||||
areaRM.b,
|
||||
fBounds.r),
|
||||
areaRM);
|
||||
|
||||
}
|
||||
|
||||
// Bottom left.
|
||||
|
||||
dng_rect areaBL = areaB & areaL;
|
||||
|
||||
if (areaBL.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (fBounds.b - repeatV,
|
||||
fBounds.l,
|
||||
fBounds.b,
|
||||
fBounds.l + repeatH),
|
||||
areaBL);
|
||||
|
||||
}
|
||||
|
||||
// Bottom middle.
|
||||
|
||||
dng_rect areaBM = areaB & areaH;
|
||||
|
||||
if (areaBM.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (fBounds.b - repeatV,
|
||||
areaBM.l,
|
||||
fBounds.b,
|
||||
areaBM.r),
|
||||
areaBM);
|
||||
|
||||
}
|
||||
|
||||
// Bottom right.
|
||||
|
||||
dng_rect areaBR = areaB & areaR;
|
||||
|
||||
if (areaBR.NotEmpty ())
|
||||
{
|
||||
|
||||
GetEdge (buffer,
|
||||
edgeOption,
|
||||
dng_rect (fBounds.b - repeatV,
|
||||
fBounds.r - repeatH,
|
||||
fBounds.b,
|
||||
fBounds.r),
|
||||
areaBR);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::Put (const dng_pixel_buffer &buffer)
|
||||
{
|
||||
|
||||
// Move the overlapping pixels.
|
||||
|
||||
dng_rect overlap = buffer.fArea & fBounds;
|
||||
|
||||
if (overlap.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_pixel_buffer temp (buffer);
|
||||
|
||||
temp.fArea = overlap;
|
||||
|
||||
temp.fData = (void *) buffer.ConstPixel (overlap.t,
|
||||
overlap.l,
|
||||
buffer.fPlane);
|
||||
|
||||
// Move the overlapping planes.
|
||||
|
||||
if (temp.fPlane < Planes ())
|
||||
{
|
||||
|
||||
temp.fPlanes = Min_uint32 (temp.fPlanes,
|
||||
Planes () - temp.fPlane);
|
||||
|
||||
DoPut (temp);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::Trim (const dng_rect &r)
|
||||
{
|
||||
|
||||
if (r != Bounds ())
|
||||
{
|
||||
|
||||
ThrowProgramError ("Trim is not support by this dng_image subclass");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::Rotate (const dng_orientation &orientation)
|
||||
{
|
||||
|
||||
if (orientation != dng_orientation::Normal ())
|
||||
{
|
||||
|
||||
ThrowProgramError ("Rotate is not support by this dng_image subclass");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::DoCopyArea (const dng_image &src,
|
||||
const dng_rect &area,
|
||||
uint32 srcPlane,
|
||||
uint32 dstPlane,
|
||||
uint32 planes)
|
||||
{
|
||||
|
||||
if (&src == this)
|
||||
return;
|
||||
|
||||
dng_tile_iterator destIter(*this, area);
|
||||
dng_rect destTileArea;
|
||||
|
||||
while (destIter.GetOneTile(destTileArea))
|
||||
{
|
||||
dng_tile_iterator srcIter(src, destTileArea);
|
||||
dng_rect srcTileArea;
|
||||
|
||||
while (srcIter.GetOneTile(srcTileArea))
|
||||
{
|
||||
|
||||
dng_dirty_tile_buffer destTile(*this, srcTileArea);
|
||||
dng_const_tile_buffer srcTile(src, srcTileArea);
|
||||
|
||||
destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_image::EqualArea (const dng_image &src,
|
||||
const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes) const
|
||||
{
|
||||
|
||||
if (&src == this)
|
||||
return true;
|
||||
|
||||
dng_tile_iterator destIter (*this, area);
|
||||
|
||||
dng_rect destTileArea;
|
||||
|
||||
while (destIter.GetOneTile (destTileArea))
|
||||
{
|
||||
|
||||
dng_tile_iterator srcIter (src, destTileArea);
|
||||
|
||||
dng_rect srcTileArea;
|
||||
|
||||
while (srcIter.GetOneTile (srcTileArea))
|
||||
{
|
||||
|
||||
dng_const_tile_buffer destTile (*this, srcTileArea);
|
||||
dng_const_tile_buffer srcTile (src , srcTileArea);
|
||||
|
||||
if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image::SetConstant (uint32 value,
|
||||
const dng_rect &area)
|
||||
{
|
||||
|
||||
dng_tile_iterator iter (*this, area);
|
||||
|
||||
dng_rect tileArea;
|
||||
|
||||
while (iter.GetOneTile (tileArea))
|
||||
{
|
||||
|
||||
dng_dirty_tile_buffer buffer (*this, tileArea);
|
||||
|
||||
buffer.SetConstant (tileArea,
|
||||
0,
|
||||
fPlanes,
|
||||
value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,433 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Support for working with image data in DNG SDK.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_image__
|
||||
#define __dng_image__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_pixel_buffer.h"
|
||||
#include "dng_point.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_tag_types.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to get resource acquisition is instantiation behavior for tile
|
||||
/// buffers. Can be dirty or constant tile access.
|
||||
|
||||
class dng_tile_buffer: public dng_pixel_buffer,
|
||||
private dng_uncopyable
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
const dng_image &fImage;
|
||||
|
||||
void *fRefData;
|
||||
|
||||
protected:
|
||||
|
||||
/// Obtain a tile from an image.
|
||||
/// \param image Image tile will come from.
|
||||
/// \param tile Rectangle denoting extent of tile.
|
||||
/// \param dirty Flag indicating whether this is read-only or read-write acesss.
|
||||
|
||||
dng_tile_buffer (const dng_image &image,
|
||||
const dng_rect &tile,
|
||||
bool dirty);
|
||||
|
||||
virtual ~dng_tile_buffer ();
|
||||
|
||||
public:
|
||||
|
||||
void SetRefData (void *refData)
|
||||
{
|
||||
fRefData = refData;
|
||||
}
|
||||
|
||||
void * GetRefData () const
|
||||
{
|
||||
return fRefData;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to get resource acquisition is instantiation behavior for
|
||||
/// constant (read-only) tile buffers.
|
||||
|
||||
class dng_const_tile_buffer: public dng_tile_buffer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// Obtain a read-only tile from an image.
|
||||
/// \param image Image tile will come from.
|
||||
/// \param tile Rectangle denoting extent of tile.
|
||||
|
||||
dng_const_tile_buffer (const dng_image &image,
|
||||
const dng_rect &tile);
|
||||
|
||||
virtual ~dng_const_tile_buffer ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to get resource acquisition is instantiation behavior for
|
||||
/// dirty (writable) tile buffers.
|
||||
|
||||
class dng_dirty_tile_buffer: public dng_tile_buffer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// Obtain a writable tile from an image.
|
||||
/// \param image Image tile will come from.
|
||||
/// \param tile Rectangle denoting extent of tile.
|
||||
|
||||
dng_dirty_tile_buffer (dng_image &image,
|
||||
const dng_rect &tile);
|
||||
|
||||
virtual ~dng_dirty_tile_buffer ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Base class for holding image data in DNG SDK. See dng_simple_image
|
||||
/// for derived class most often used in DNG SDK.
|
||||
|
||||
class dng_image
|
||||
{
|
||||
|
||||
friend class dng_tile_buffer;
|
||||
|
||||
protected:
|
||||
|
||||
// Bounds for this image.
|
||||
|
||||
dng_rect fBounds;
|
||||
|
||||
// Number of image planes.
|
||||
|
||||
uint32 fPlanes;
|
||||
|
||||
// Basic pixel type (TIFF tag type code).
|
||||
|
||||
uint32 fPixelType;
|
||||
|
||||
public:
|
||||
|
||||
/// How to handle requests to get image areas outside the image bounds.
|
||||
|
||||
enum edge_option
|
||||
{
|
||||
|
||||
/// Leave edge pixels unchanged.
|
||||
|
||||
edge_none,
|
||||
|
||||
/// Pad with zeros.
|
||||
|
||||
edge_zero,
|
||||
|
||||
/// Repeat edge pixels.
|
||||
|
||||
edge_repeat,
|
||||
|
||||
/// Repeat edge pixels, except for last plane which is zero padded.
|
||||
|
||||
edge_repeat_zero_last
|
||||
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
dng_image (const dng_rect &bounds,
|
||||
uint32 planes,
|
||||
uint32 pixelType);
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_image ();
|
||||
|
||||
virtual dng_image * Clone () const;
|
||||
|
||||
/// Getter method for bounds of an image.
|
||||
|
||||
const dng_rect & Bounds () const
|
||||
{
|
||||
return fBounds;
|
||||
}
|
||||
|
||||
/// Getter method for size of an image.
|
||||
|
||||
dng_point Size () const
|
||||
{
|
||||
return Bounds ().Size ();
|
||||
}
|
||||
|
||||
/// Getter method for width of an image.
|
||||
|
||||
uint32 Width () const
|
||||
{
|
||||
return Bounds ().W ();
|
||||
}
|
||||
|
||||
/// Getter method for height of an image.
|
||||
|
||||
uint32 Height () const
|
||||
{
|
||||
return Bounds ().H ();
|
||||
}
|
||||
|
||||
/// Getter method for number of planes in an image.
|
||||
|
||||
uint32 Planes () const
|
||||
{
|
||||
return fPlanes;
|
||||
}
|
||||
|
||||
/// Getter for pixel type.
|
||||
/// \retval See dng_tagtypes.h . Valid values are ttByte, ttShort, ttSShort,
|
||||
/// ttLong, ttFloat .
|
||||
|
||||
uint32 PixelType () const
|
||||
{
|
||||
return fPixelType;
|
||||
}
|
||||
|
||||
/// Setter for pixel type.
|
||||
/// \param pixelType The new pixel type .
|
||||
|
||||
virtual void SetPixelType (uint32 pixelType);
|
||||
|
||||
/// Getter for pixel size.
|
||||
/// \retval Size, in bytes, of pixel type for this image .
|
||||
|
||||
uint32 PixelSize () const;
|
||||
|
||||
/// Getter for pixel range.
|
||||
/// For unsigned types, range is 0 to return value.
|
||||
/// For signed types, range is return value - 0x8000U.
|
||||
/// For ttFloat type, pixel range is 0.0 to 1.0 and this routine returns 1.
|
||||
|
||||
uint32 PixelRange () const;
|
||||
|
||||
/// Getter for best "tile stride" for accessing image.
|
||||
|
||||
virtual dng_rect RepeatingTile () const;
|
||||
|
||||
/// Get a pixel buffer of data on image with proper edge padding.
|
||||
/// \param buffer Receives resulting pixel buffer.
|
||||
/// \param edgeOption edge_option describing how to pad edges.
|
||||
/// \param repeatV Amount of repeated padding needed in vertical for
|
||||
/// edge_repeat and edge_repeat_zero_last edgeOption cases.
|
||||
/// \param repeatH Amount of repeated padding needed in horizontal for
|
||||
/// edge_repeat and edge_repeat_zero_last edgeOption cases.
|
||||
|
||||
void Get (dng_pixel_buffer &buffer,
|
||||
edge_option edgeOption = edge_none,
|
||||
uint32 repeatV = 1,
|
||||
uint32 repeatH = 1) const;
|
||||
|
||||
/// Put a pixel buffer into image.
|
||||
/// \param buffer Pixel buffer to copy from.
|
||||
|
||||
void Put (const dng_pixel_buffer &buffer);
|
||||
|
||||
/// Shrink bounds of image to given rectangle.
|
||||
/// \param r Rectangle to crop to.
|
||||
|
||||
virtual void Trim (const dng_rect &r);
|
||||
|
||||
/// Rotate image to reflect given orientation change.
|
||||
/// \param orientation Directive to rotate image in a certain way.
|
||||
|
||||
virtual void Rotate (const dng_orientation &orientation);
|
||||
|
||||
/// Copy image data from an area of one image to same area of another.
|
||||
/// \param src Image to copy from.
|
||||
/// \param area Rectangle of images to copy.
|
||||
/// \param srcPlane Plane to start copying in src.
|
||||
/// \param dstPlane Plane to start copying in this.
|
||||
/// \param planes Number of planes to copy.
|
||||
|
||||
void CopyArea (const dng_image &src,
|
||||
const dng_rect &area,
|
||||
uint32 srcPlane,
|
||||
uint32 dstPlane,
|
||||
uint32 planes)
|
||||
{
|
||||
|
||||
DoCopyArea (src, area, srcPlane, dstPlane, planes);
|
||||
|
||||
}
|
||||
|
||||
/// Copy image data from an area of one image to same area of another.
|
||||
/// \param src Image to copy from.
|
||||
/// \param area Rectangle of images to copy.
|
||||
/// \param plane Plane to start copying in src and this.
|
||||
/// \param planes Number of planes to copy.
|
||||
|
||||
void CopyArea (const dng_image &src,
|
||||
const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes)
|
||||
{
|
||||
|
||||
DoCopyArea (src, area, plane, plane, planes);
|
||||
|
||||
}
|
||||
|
||||
/// Return true if the contents of an area of the image are the same as those of another.
|
||||
/// \param rhs Image to compare against.
|
||||
/// \param area Rectangle of image to test.
|
||||
/// \param plane Plane to start comparing.
|
||||
/// \param planes Number of planes to compare.
|
||||
|
||||
virtual bool EqualArea (const dng_image &rhs,
|
||||
const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes) const;
|
||||
|
||||
// Routines to set the entire image to a constant value.
|
||||
|
||||
void SetConstant_uint8 (uint8 value,
|
||||
const dng_rect &area)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttByte, "Mismatched pixel type");
|
||||
|
||||
SetConstant ((uint32) value, area);
|
||||
|
||||
}
|
||||
|
||||
void SetConstant_uint8 (uint8 value)
|
||||
{
|
||||
SetConstant (value, Bounds ());
|
||||
}
|
||||
|
||||
void SetConstant_uint16 (uint16 value,
|
||||
const dng_rect &area)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttShort, "Mismatched pixel type");
|
||||
|
||||
SetConstant ((uint32) value, area);
|
||||
|
||||
}
|
||||
|
||||
void SetConstant_uint16 (uint16 value)
|
||||
{
|
||||
SetConstant_uint16 (value, Bounds ());
|
||||
}
|
||||
|
||||
void SetConstant_int16 (int16 value,
|
||||
const dng_rect &area)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttSShort, "Mismatched pixel type");
|
||||
|
||||
SetConstant ((uint32) (uint16) value, area);
|
||||
|
||||
}
|
||||
|
||||
void SetConstant_int16 (int16 value)
|
||||
{
|
||||
SetConstant_int16 (value, Bounds ());
|
||||
}
|
||||
|
||||
void SetConstant_uint32 (uint32 value,
|
||||
const dng_rect &area)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttLong, "Mismatched pixel type");
|
||||
|
||||
SetConstant (value, area);
|
||||
|
||||
}
|
||||
|
||||
void SetConstant_uint32 (uint32 value)
|
||||
{
|
||||
SetConstant_uint32 (value, Bounds ());
|
||||
}
|
||||
|
||||
void SetConstant_real32 (real32 value,
|
||||
const dng_rect &area)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttFloat, "Mismatched pixel type");
|
||||
|
||||
union
|
||||
{
|
||||
uint32 i;
|
||||
real32 f;
|
||||
} x;
|
||||
|
||||
x.f = value;
|
||||
|
||||
SetConstant (x.i, area);
|
||||
|
||||
}
|
||||
|
||||
void SetConstant_real32 (real32 value)
|
||||
{
|
||||
SetConstant_real32 (value, Bounds ());
|
||||
}
|
||||
|
||||
virtual void GetRepeat (dng_pixel_buffer &buffer,
|
||||
const dng_rect &srcArea,
|
||||
const dng_rect &dstArea) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void AcquireTileBuffer (dng_tile_buffer &buffer,
|
||||
const dng_rect &area,
|
||||
bool dirty) const;
|
||||
|
||||
virtual void ReleaseTileBuffer (dng_tile_buffer &buffer) const;
|
||||
|
||||
virtual void DoGet (dng_pixel_buffer &buffer) const;
|
||||
|
||||
virtual void DoPut (const dng_pixel_buffer &buffer);
|
||||
|
||||
virtual void DoCopyArea (const dng_image &src,
|
||||
const dng_rect &area,
|
||||
uint32 srcPlane,
|
||||
uint32 dstPlane,
|
||||
uint32 planes);
|
||||
|
||||
void GetEdge (dng_pixel_buffer &buffer,
|
||||
edge_option edgeOption,
|
||||
const dng_rect &srcArea,
|
||||
const dng_rect &dstArea) const;
|
||||
|
||||
virtual void SetConstant (uint32 value,
|
||||
const dng_rect &area);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,179 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Class for holding top-level information about a DNG image.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_info__
|
||||
#define __dng_info__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_errors.h"
|
||||
#include "dng_exif.h"
|
||||
#include "dng_ifd.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
#include "dng_shared.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Top-level structure of DNG file with access to metadata.
|
||||
///
|
||||
/// See \ref spec_dng "DNG 1.1.0 specification" for information on member fields of this class.
|
||||
|
||||
class dng_info: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
uint64 fTIFFBlockOffset;
|
||||
|
||||
uint64 fTIFFBlockOriginalOffset;
|
||||
|
||||
bool fBigEndian;
|
||||
|
||||
uint32 fMagic;
|
||||
|
||||
AutoPtr<dng_exif> fExif;
|
||||
|
||||
AutoPtr<dng_shared> fShared;
|
||||
|
||||
int32 fMainIndex;
|
||||
|
||||
int32 fMaskIndex;
|
||||
|
||||
int32 fDepthIndex;
|
||||
|
||||
int32 fEnhancedIndex;
|
||||
|
||||
std::vector <dng_ifd *> fIFD;
|
||||
|
||||
std::vector <dng_ifd *> fChainedIFD;
|
||||
|
||||
std::vector <std::vector <dng_ifd *> > fChainedSubIFD;
|
||||
|
||||
protected:
|
||||
|
||||
uint32 fMakerNoteNextIFD;
|
||||
|
||||
public:
|
||||
|
||||
dng_info ();
|
||||
|
||||
virtual ~dng_info ();
|
||||
|
||||
/// Returns the number of parsed SubIFDs (including the main IFD).
|
||||
|
||||
uint32 IFDCount () const
|
||||
{
|
||||
return (uint32) fIFD.size ();
|
||||
}
|
||||
|
||||
/// Returns the number of chained IFDs.
|
||||
|
||||
uint32 ChainedIFDCount () const
|
||||
{
|
||||
return (uint32) fChainedIFD.size ();
|
||||
}
|
||||
|
||||
/// Returns number SubIFDs for a chained IFD.
|
||||
|
||||
uint32 ChainedSubIFDCount (uint32 chainIndex) const
|
||||
{
|
||||
if (chainIndex >= fChainedSubIFD.size ())
|
||||
return 0;
|
||||
else
|
||||
return (uint32) fChainedSubIFD [chainIndex].size ();
|
||||
}
|
||||
|
||||
/// Read dng_info from a dng_stream
|
||||
/// \param host DNG host used for progress updating, abort testing, buffer allocation, etc.
|
||||
/// \param stream Stream to read DNG data from.
|
||||
|
||||
virtual void Parse (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
/// Must be called immediately after a successful Parse operation.
|
||||
|
||||
virtual void PostParse (dng_host &host);
|
||||
|
||||
/// Test validity of DNG data.
|
||||
/// \retval true if stream provided a valid DNG.
|
||||
|
||||
virtual bool IsValidDNG ();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void ValidateMagic ();
|
||||
|
||||
virtual void ParseTag (dng_host &host,
|
||||
dng_stream &stream,
|
||||
dng_exif *exif,
|
||||
dng_shared *shared,
|
||||
dng_ifd *ifd,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint64 tagOffset,
|
||||
int64 offsetDelta);
|
||||
|
||||
virtual bool ValidateIFD (dng_stream &stream,
|
||||
uint64 ifdOffset,
|
||||
int64 offsetDelta);
|
||||
|
||||
virtual void ParseIFD (dng_host &host,
|
||||
dng_stream &stream,
|
||||
dng_exif *exif,
|
||||
dng_shared *shared,
|
||||
dng_ifd *ifd,
|
||||
uint64 ifdOffset,
|
||||
int64 offsetDelta,
|
||||
uint32 parentCode);
|
||||
|
||||
virtual bool ParseMakerNoteIFD (dng_host &host,
|
||||
dng_stream &stream,
|
||||
uint64 ifdSize,
|
||||
uint64 ifdOffset,
|
||||
int64 offsetDelta,
|
||||
uint64 minOffset,
|
||||
uint64 maxOffset,
|
||||
uint32 parentCode);
|
||||
|
||||
virtual void ParseMakerNote (dng_host &host,
|
||||
dng_stream &stream,
|
||||
uint32 makerNoteCount,
|
||||
uint64 makerNoteOffset,
|
||||
int64 offsetDelta,
|
||||
uint64 minOffset,
|
||||
uint64 maxOffset);
|
||||
|
||||
virtual void ParseSonyPrivateData (dng_host &host,
|
||||
dng_stream &stream,
|
||||
uint64 count,
|
||||
uint64 oldOffset,
|
||||
uint64 newOffset);
|
||||
|
||||
virtual void ParseDNGPrivateData (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,978 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_iptc.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_memory_stream.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_iptc::dng_iptc ()
|
||||
|
||||
: fTitle ()
|
||||
|
||||
, fUrgency (-1)
|
||||
|
||||
, fCategory ()
|
||||
|
||||
, fSupplementalCategories ()
|
||||
|
||||
, fKeywords ()
|
||||
|
||||
, fInstructions ()
|
||||
|
||||
, fDateTimeCreated ()
|
||||
|
||||
, fDigitalCreationDateTime ()
|
||||
|
||||
, fAuthors ()
|
||||
, fAuthorsPosition ()
|
||||
|
||||
, fCity ()
|
||||
, fState ()
|
||||
, fCountry ()
|
||||
, fCountryCode ()
|
||||
|
||||
, fLocation ()
|
||||
|
||||
, fTransmissionReference ()
|
||||
|
||||
, fHeadline ()
|
||||
|
||||
, fCredit ()
|
||||
|
||||
, fSource ()
|
||||
|
||||
, fCopyrightNotice ()
|
||||
|
||||
, fDescription ()
|
||||
, fDescriptionWriter ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_iptc::~dng_iptc ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_iptc::IsEmpty () const
|
||||
{
|
||||
|
||||
if (fTitle.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fUrgency >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fCategory.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fSupplementalCategories.Count () > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fKeywords.Count () > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fInstructions.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fDateTimeCreated.IsValid ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fDigitalCreationDateTime.IsValid ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fAuthors.Count () != 0 ||
|
||||
fAuthorsPosition.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fCity .NotEmpty () ||
|
||||
fState .NotEmpty () ||
|
||||
fCountry.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fCountryCode.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fLocation.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fTransmissionReference.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fHeadline.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fCredit.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fSource.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fCopyrightNotice.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fDescription .NotEmpty () ||
|
||||
fDescriptionWriter.NotEmpty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_iptc::ParseString (dng_stream &stream,
|
||||
dng_string &s,
|
||||
CharSet charSet)
|
||||
{
|
||||
|
||||
uint32 length = stream.Get_uint16 ();
|
||||
|
||||
dng_memory_data buffer (length + 1);
|
||||
|
||||
char *c = buffer.Buffer_char ();
|
||||
|
||||
stream.Get (c, length);
|
||||
|
||||
c [length] = 0;
|
||||
|
||||
switch (charSet)
|
||||
{
|
||||
|
||||
case kCharSetUTF8:
|
||||
{
|
||||
s.Set_UTF8 (c);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
s.Set_SystemEncoding (c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s.SetLineEndingsToNewLines ();
|
||||
|
||||
s.StripLowASCII ();
|
||||
|
||||
s.TrimTrailingBlanks ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_iptc::Parse (const void *blockData,
|
||||
uint32 blockSize,
|
||||
uint64 offsetInOriginalFile)
|
||||
{
|
||||
|
||||
dng_stream stream (blockData,
|
||||
blockSize,
|
||||
offsetInOriginalFile);
|
||||
|
||||
stream.SetBigEndian ();
|
||||
|
||||
// Make a first pass though the data, trying to figure out the
|
||||
// character set.
|
||||
|
||||
CharSet charSet = kCharSetUnknown;
|
||||
|
||||
bool isValidUTF8 = true;
|
||||
|
||||
bool hasEncodingMarker = false;
|
||||
|
||||
uint64 firstOffset = stream.Position ();
|
||||
|
||||
uint64 nextOffset = firstOffset;
|
||||
|
||||
while (nextOffset + 5 < stream.Length ())
|
||||
{
|
||||
|
||||
stream.SetReadPosition (nextOffset);
|
||||
|
||||
uint8 firstByte = stream.Get_uint8 ();
|
||||
|
||||
if (firstByte != 0x1C) break;
|
||||
|
||||
uint8 record = stream.Get_uint8 ();
|
||||
uint8 dataSet = stream.Get_uint8 ();
|
||||
uint32 dataSize = stream.Get_uint16 ();
|
||||
|
||||
nextOffset = stream.Position () + dataSize;
|
||||
|
||||
if (record == 1)
|
||||
{
|
||||
|
||||
switch (dataSet)
|
||||
{
|
||||
|
||||
case 90:
|
||||
{
|
||||
|
||||
hasEncodingMarker = true;
|
||||
|
||||
if (dataSize == 3)
|
||||
{
|
||||
|
||||
uint32 byte1 = stream.Get_uint8 ();
|
||||
uint32 byte2 = stream.Get_uint8 ();
|
||||
uint32 byte3 = stream.Get_uint8 ();
|
||||
|
||||
if (byte1 == 27 /* Escape */ &&
|
||||
byte2 == 0x25 &&
|
||||
byte3 == 0x47)
|
||||
{
|
||||
|
||||
charSet = kCharSetUTF8;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (record == 2)
|
||||
{
|
||||
|
||||
dng_memory_data buffer (dataSize + 1);
|
||||
|
||||
char *s = buffer.Buffer_char ();
|
||||
|
||||
stream.Get (s, dataSize);
|
||||
|
||||
s [dataSize] = 0;
|
||||
|
||||
isValidUTF8 = isValidUTF8 && dng_string::IsUTF8 (s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we don't have an encoding marker, and the data is valid
|
||||
// UTF-8, then assume that it is UTF-8 (rather than system encoding).
|
||||
|
||||
if (!hasEncodingMarker && isValidUTF8)
|
||||
{
|
||||
|
||||
charSet = kCharSetUTF8;
|
||||
|
||||
}
|
||||
|
||||
// Make a second pass though the data, actually reading the data.
|
||||
|
||||
nextOffset = firstOffset;
|
||||
|
||||
while (nextOffset + 5 < stream.Length ())
|
||||
{
|
||||
|
||||
stream.SetReadPosition (nextOffset);
|
||||
|
||||
uint8 firstByte = stream.Get_uint8 ();
|
||||
|
||||
if (firstByte != 0x1C) break;
|
||||
|
||||
uint8 record = stream.Get_uint8 ();
|
||||
uint8 dataSet = stream.Get_uint8 ();
|
||||
uint32 dataSize = stream.Get_uint16 ();
|
||||
|
||||
nextOffset = stream.Position () + dataSize;
|
||||
|
||||
if (record == 2)
|
||||
{
|
||||
|
||||
stream.SetReadPosition (stream.Position () - 2);
|
||||
|
||||
switch ((DataSet) dataSet)
|
||||
{
|
||||
|
||||
case kObjectNameSet:
|
||||
{
|
||||
ParseString (stream, fTitle, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kUrgencySet:
|
||||
{
|
||||
|
||||
int32 size = stream.Get_uint16 ();
|
||||
|
||||
if (size == 1)
|
||||
{
|
||||
|
||||
char c = stream.Get_int8 ();
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
fUrgency = c - '0';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kCategorySet:
|
||||
{
|
||||
ParseString (stream, fCategory, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kSupplementalCategoriesSet:
|
||||
{
|
||||
|
||||
dng_string category;
|
||||
|
||||
ParseString (stream, category, charSet);
|
||||
|
||||
if (category.NotEmpty ())
|
||||
{
|
||||
fSupplementalCategories.Append (category);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kKeywordsSet:
|
||||
{
|
||||
|
||||
dng_string keyword;
|
||||
|
||||
ParseString (stream, keyword, charSet);
|
||||
|
||||
if (keyword.NotEmpty ())
|
||||
{
|
||||
fKeywords.Append (keyword);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kSpecialInstructionsSet:
|
||||
{
|
||||
ParseString (stream, fInstructions, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kDateCreatedSet:
|
||||
{
|
||||
|
||||
uint32 length = stream.Get_uint16 ();
|
||||
|
||||
if (length == 8)
|
||||
{
|
||||
|
||||
char date [9];
|
||||
|
||||
stream.Get (date, 8);
|
||||
|
||||
date [8] = 0;
|
||||
|
||||
fDateTimeCreated.Decode_IPTC_Date (date);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kTimeCreatedSet:
|
||||
{
|
||||
|
||||
uint32 length = stream.Get_uint16 ();
|
||||
|
||||
if (length >= 4 && length <= 11)
|
||||
{
|
||||
|
||||
char time [12];
|
||||
|
||||
stream.Get (time, length);
|
||||
|
||||
time [length] = 0;
|
||||
|
||||
fDateTimeCreated.Decode_IPTC_Time (time);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kDigitalCreationDateSet:
|
||||
{
|
||||
|
||||
uint32 length = stream.Get_uint16 ();
|
||||
|
||||
if (length == 8)
|
||||
{
|
||||
|
||||
char date [9];
|
||||
|
||||
stream.Get (date, 8);
|
||||
|
||||
date [8] = 0;
|
||||
|
||||
fDigitalCreationDateTime.Decode_IPTC_Date (date);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kDigitalCreationTimeSet:
|
||||
{
|
||||
|
||||
uint32 length = stream.Get_uint16 ();
|
||||
|
||||
if (length >= 4 && length <= 11)
|
||||
{
|
||||
|
||||
char time [12];
|
||||
|
||||
stream.Get (time, length);
|
||||
|
||||
time [length] = 0;
|
||||
|
||||
fDigitalCreationDateTime.Decode_IPTC_Time (time);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kBylineSet:
|
||||
{
|
||||
|
||||
dng_string author;
|
||||
|
||||
ParseString (stream, author, charSet);
|
||||
|
||||
if (author.NotEmpty ())
|
||||
{
|
||||
fAuthors.Append (author);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case kBylineTitleSet:
|
||||
{
|
||||
ParseString (stream, fAuthorsPosition, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCitySet:
|
||||
{
|
||||
ParseString (stream, fCity, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kProvinceStateSet:
|
||||
{
|
||||
ParseString (stream, fState, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCountryNameSet:
|
||||
{
|
||||
ParseString (stream, fCountry, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCountryCodeSet:
|
||||
{
|
||||
ParseString (stream, fCountryCode, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kSublocationSet:
|
||||
{
|
||||
ParseString (stream, fLocation, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kOriginalTransmissionReferenceSet:
|
||||
{
|
||||
ParseString (stream, fTransmissionReference, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kHeadlineSet:
|
||||
{
|
||||
ParseString (stream, fHeadline, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCreditSet:
|
||||
{
|
||||
ParseString (stream, fCredit, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kSourceSet:
|
||||
{
|
||||
ParseString (stream, fSource, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCopyrightNoticeSet:
|
||||
{
|
||||
ParseString (stream, fCopyrightNotice, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCaptionSet:
|
||||
{
|
||||
ParseString (stream, fDescription, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
case kCaptionWriterSet:
|
||||
{
|
||||
ParseString (stream, fDescriptionWriter, charSet);
|
||||
break;
|
||||
}
|
||||
|
||||
// All other IPTC records are not part of the IPTC core
|
||||
// and/or are not kept in sync with XMP tags, so we ignore
|
||||
// them.
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_iptc::SpoolString (dng_stream &stream,
|
||||
const dng_string &s,
|
||||
uint8 dataSet,
|
||||
uint32 maxChars,
|
||||
CharSet charSet)
|
||||
{
|
||||
|
||||
if (s.IsEmpty ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (dataSet);
|
||||
|
||||
dng_string ss (s);
|
||||
|
||||
ss.SetLineEndingsToReturns ();
|
||||
|
||||
if (charSet == kCharSetUTF8)
|
||||
{
|
||||
|
||||
// UTF-8 encoding.
|
||||
|
||||
if (ss.Length () > maxChars)
|
||||
{
|
||||
ss.Truncate (maxChars);
|
||||
}
|
||||
|
||||
uint32 len = ss.Length ();
|
||||
|
||||
stream.Put_uint16 ((uint16) len);
|
||||
|
||||
stream.Put (ss.Get (), len);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
// System character set encoding.
|
||||
|
||||
dng_memory_data buffer;
|
||||
|
||||
uint32 len = ss.Get_SystemEncoding (buffer);
|
||||
|
||||
if (len > maxChars)
|
||||
{
|
||||
|
||||
uint32 lower = 0;
|
||||
uint32 upper = ss.Length () - 1;
|
||||
|
||||
while (upper > lower)
|
||||
{
|
||||
|
||||
uint32 middle = (upper + lower + 1) >> 1;
|
||||
|
||||
dng_string sss (ss);
|
||||
|
||||
sss.Truncate (middle);
|
||||
|
||||
len = sss.Get_SystemEncoding (buffer);
|
||||
|
||||
if (len <= maxChars)
|
||||
{
|
||||
|
||||
lower = middle;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
upper = middle - 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ss.Truncate (lower);
|
||||
|
||||
len = ss.Get_SystemEncoding (buffer);
|
||||
|
||||
}
|
||||
|
||||
stream.Put_uint16 ((uint16) len);
|
||||
|
||||
stream.Put (buffer.Buffer_char (), len);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_block * dng_iptc::Spool (dng_memory_allocator &allocator,
|
||||
bool padForTIFF)
|
||||
{
|
||||
|
||||
uint32 j;
|
||||
|
||||
char s [64];
|
||||
|
||||
dng_memory_stream stream (allocator, NULL, 2048);
|
||||
|
||||
stream.SetBigEndian ();
|
||||
|
||||
// Medata working group - now we just always write UTF-8.
|
||||
|
||||
CharSet charSet = kCharSetUTF8;
|
||||
|
||||
// UTF-8 encoding marker.
|
||||
|
||||
if (charSet == kCharSetUTF8)
|
||||
{
|
||||
|
||||
stream.Put_uint16 (0x1C01);
|
||||
stream.Put_uint8 (90);
|
||||
stream.Put_uint16 (3);
|
||||
stream.Put_uint8 (27);
|
||||
stream.Put_uint8 (0x25);
|
||||
stream.Put_uint8 (0x47);
|
||||
|
||||
}
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (kRecordVersionSet);
|
||||
stream.Put_uint16 (2);
|
||||
stream.Put_uint16 (4);
|
||||
|
||||
SpoolString (stream,
|
||||
fTitle,
|
||||
kObjectNameSet,
|
||||
64,
|
||||
charSet);
|
||||
|
||||
if (fUrgency >= 0)
|
||||
{
|
||||
|
||||
sprintf (s, "%1u", (unsigned) fUrgency);
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (kUrgencySet);
|
||||
|
||||
stream.Put_uint16 (1);
|
||||
|
||||
stream.Put (s, 1);
|
||||
|
||||
}
|
||||
|
||||
SpoolString (stream,
|
||||
fCategory,
|
||||
kCategorySet,
|
||||
3,
|
||||
charSet);
|
||||
|
||||
for (j = 0; j < fSupplementalCategories.Count (); j++)
|
||||
{
|
||||
|
||||
SpoolString (stream,
|
||||
fSupplementalCategories [j],
|
||||
kSupplementalCategoriesSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
}
|
||||
|
||||
for (j = 0; j < fKeywords.Count (); j++)
|
||||
{
|
||||
|
||||
SpoolString (stream,
|
||||
fKeywords [j],
|
||||
kKeywordsSet,
|
||||
64,
|
||||
charSet);
|
||||
|
||||
}
|
||||
|
||||
SpoolString (stream,
|
||||
fInstructions,
|
||||
kSpecialInstructionsSet,
|
||||
255,
|
||||
charSet);
|
||||
|
||||
if (fDateTimeCreated.IsValid ())
|
||||
{
|
||||
|
||||
dng_string dateString = fDateTimeCreated.Encode_IPTC_Date ();
|
||||
|
||||
if (dateString.NotEmpty ())
|
||||
{
|
||||
|
||||
DNG_ASSERT (dateString.Length () == 8, "Wrong length IPTC date");
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (kDateCreatedSet);
|
||||
|
||||
stream.Put_uint16 (8);
|
||||
|
||||
stream.Put (dateString.Get (), 8);
|
||||
|
||||
}
|
||||
|
||||
dng_string timeString = fDateTimeCreated.Encode_IPTC_Time ();
|
||||
|
||||
if (timeString.NotEmpty ())
|
||||
{
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (kTimeCreatedSet);
|
||||
|
||||
stream.Put_uint16 ((uint16)timeString.Length ());
|
||||
|
||||
stream.Put (timeString.Get (), timeString.Length ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (fDigitalCreationDateTime.IsValid ())
|
||||
{
|
||||
|
||||
dng_string dateString = fDigitalCreationDateTime.Encode_IPTC_Date ();
|
||||
|
||||
if (dateString.NotEmpty ())
|
||||
{
|
||||
|
||||
DNG_ASSERT (dateString.Length () == 8, "Wrong length IPTC date");
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (kDigitalCreationDateSet);
|
||||
|
||||
stream.Put_uint16 (8);
|
||||
|
||||
stream.Put (dateString.Get (), 8);
|
||||
|
||||
}
|
||||
|
||||
dng_string timeString = fDigitalCreationDateTime.Encode_IPTC_Time ();
|
||||
|
||||
if (timeString.NotEmpty ())
|
||||
{
|
||||
|
||||
stream.Put_uint16 (0x1C02);
|
||||
stream.Put_uint8 (kDigitalCreationTimeSet);
|
||||
|
||||
stream.Put_uint16 ((uint16)timeString.Length ());
|
||||
|
||||
stream.Put (timeString.Get (), timeString.Length ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (j = 0; j < fAuthors.Count (); j++)
|
||||
{
|
||||
|
||||
SpoolString (stream,
|
||||
fAuthors [j],
|
||||
kBylineSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
}
|
||||
|
||||
SpoolString (stream,
|
||||
fAuthorsPosition,
|
||||
kBylineTitleSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fCity,
|
||||
kCitySet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fLocation,
|
||||
kSublocationSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fState,
|
||||
kProvinceStateSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fCountryCode,
|
||||
kCountryCodeSet,
|
||||
3,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fCountry,
|
||||
kCountryNameSet,
|
||||
64,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fTransmissionReference,
|
||||
kOriginalTransmissionReferenceSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fHeadline,
|
||||
kHeadlineSet,
|
||||
255,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fCredit,
|
||||
kCreditSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fSource,
|
||||
kSourceSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fCopyrightNotice,
|
||||
kCopyrightNoticeSet,
|
||||
128,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fDescription,
|
||||
kCaptionSet,
|
||||
2000,
|
||||
charSet);
|
||||
|
||||
SpoolString (stream,
|
||||
fDescriptionWriter,
|
||||
kCaptionWriterSet,
|
||||
32,
|
||||
charSet);
|
||||
|
||||
if (padForTIFF)
|
||||
{
|
||||
|
||||
while (stream.Length () & 3)
|
||||
{
|
||||
stream.Put_uint8 (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream.Flush ();
|
||||
|
||||
return stream.AsMemoryBlock (allocator);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,167 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Support for IPTC metadata within DNG files.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_iptc__
|
||||
#define __dng_iptc__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_date_time.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_string_list.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class for reading and holding IPTC metadata associated with a DNG file.
|
||||
///
|
||||
/// See the \ref spec_iptc "IPTC specification"
|
||||
/// for information on member fields of this class.
|
||||
|
||||
class dng_iptc
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_string fTitle;
|
||||
|
||||
int32 fUrgency;
|
||||
|
||||
dng_string fCategory;
|
||||
|
||||
dng_string_list fSupplementalCategories;
|
||||
|
||||
dng_string_list fKeywords;
|
||||
|
||||
dng_string fInstructions;
|
||||
|
||||
dng_date_time_info fDateTimeCreated;
|
||||
|
||||
dng_date_time_info fDigitalCreationDateTime;
|
||||
|
||||
dng_string_list fAuthors;
|
||||
|
||||
dng_string fAuthorsPosition;
|
||||
|
||||
dng_string fCity;
|
||||
dng_string fState;
|
||||
dng_string fCountry;
|
||||
dng_string fCountryCode;
|
||||
|
||||
dng_string fLocation;
|
||||
|
||||
dng_string fTransmissionReference;
|
||||
|
||||
dng_string fHeadline;
|
||||
|
||||
dng_string fCredit;
|
||||
|
||||
dng_string fSource;
|
||||
|
||||
dng_string fCopyrightNotice;
|
||||
|
||||
dng_string fDescription;
|
||||
dng_string fDescriptionWriter;
|
||||
|
||||
protected:
|
||||
|
||||
enum DataSet
|
||||
{
|
||||
kRecordVersionSet = 0,
|
||||
kObjectNameSet = 5,
|
||||
kUrgencySet = 10,
|
||||
kCategorySet = 15,
|
||||
kSupplementalCategoriesSet = 20,
|
||||
kKeywordsSet = 25,
|
||||
kSpecialInstructionsSet = 40,
|
||||
kDateCreatedSet = 55,
|
||||
kTimeCreatedSet = 60,
|
||||
kDigitalCreationDateSet = 62,
|
||||
kDigitalCreationTimeSet = 63,
|
||||
kBylineSet = 80,
|
||||
kBylineTitleSet = 85,
|
||||
kCitySet = 90,
|
||||
kSublocationSet = 92,
|
||||
kProvinceStateSet = 95,
|
||||
kCountryCodeSet = 100,
|
||||
kCountryNameSet = 101,
|
||||
kOriginalTransmissionReferenceSet = 103,
|
||||
kHeadlineSet = 105,
|
||||
kCreditSet = 110,
|
||||
kSourceSet = 115,
|
||||
kCopyrightNoticeSet = 116,
|
||||
kCaptionSet = 120,
|
||||
kCaptionWriterSet = 122
|
||||
};
|
||||
|
||||
enum CharSet
|
||||
{
|
||||
kCharSetUnknown = 0,
|
||||
kCharSetUTF8 = 1
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
dng_iptc ();
|
||||
|
||||
virtual ~dng_iptc ();
|
||||
|
||||
/// Test if IPTC metadata exists.
|
||||
/// \retval true if no IPTC metadata exists for this DNG.
|
||||
|
||||
bool IsEmpty () const;
|
||||
|
||||
/// Test if IPTC metadata exists.
|
||||
/// \retval true if IPTC metadata exists for this DNG.
|
||||
|
||||
bool NotEmpty () const
|
||||
{
|
||||
return !IsEmpty ();
|
||||
}
|
||||
|
||||
/// Parse a complete block of IPTC data.
|
||||
/// \param blockData The block of IPTC data.
|
||||
/// \param blockSize Size in bytes of data block.
|
||||
/// \param offsetInOriginalFile Used to enable certain file patching operations such as updating date/time in place.
|
||||
|
||||
void Parse (const void *blockData,
|
||||
uint32 blockSize,
|
||||
uint64 offsetInOriginalFile);
|
||||
|
||||
/// Serialize IPTC data to a memory block.
|
||||
/// \param allocator Memory allocator used to acquire memory block.
|
||||
/// \param padForTIFF Forces length of block to be a multiple of four bytes in accordance with TIFF standard.
|
||||
/// \retval Memory block
|
||||
|
||||
dng_memory_block * Spool (dng_memory_allocator &allocator,
|
||||
bool padForTIFF);
|
||||
|
||||
protected:
|
||||
|
||||
void ParseString (dng_stream &stream,
|
||||
dng_string &s,
|
||||
CharSet charSet);
|
||||
|
||||
void SpoolString (dng_stream &stream,
|
||||
const dng_string &s,
|
||||
uint8 dataSet,
|
||||
uint32 maxChars,
|
||||
CharSet charSet);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,354 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2011-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_jpeg_image.h"
|
||||
|
||||
#include "dng_abort_sniffer.h"
|
||||
#include "dng_area_task.h"
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_host.h"
|
||||
#include "dng_ifd.h"
|
||||
#include "dng_image.h"
|
||||
#include "dng_image_writer.h"
|
||||
#include "dng_memory_stream.h"
|
||||
#include "dng_safe_arithmetic.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_jpeg_image::dng_jpeg_image ()
|
||||
|
||||
: fImageSize ()
|
||||
, fTileSize ()
|
||||
, fUsesStrips (false)
|
||||
, fJPEGTables ()
|
||||
, fJPEGData ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_jpeg_image_encode_task : public dng_area_task,
|
||||
private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_host &fHost;
|
||||
|
||||
dng_image_writer &fWriter;
|
||||
|
||||
const dng_image &fImage;
|
||||
|
||||
dng_jpeg_image &fJPEGImage;
|
||||
|
||||
uint32 fTileCount;
|
||||
|
||||
const dng_ifd &fIFD;
|
||||
|
||||
std::atomic_uint fNextTileIndex;
|
||||
|
||||
public:
|
||||
|
||||
dng_jpeg_image_encode_task (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
const dng_image &image,
|
||||
dng_jpeg_image &jpegImage,
|
||||
uint32 tileCount,
|
||||
const dng_ifd &ifd)
|
||||
|
||||
: dng_area_task ("dng_jpeg_image_encode_task")
|
||||
|
||||
, fHost (host)
|
||||
, fWriter (writer)
|
||||
, fImage (image)
|
||||
, fJPEGImage (jpegImage)
|
||||
, fTileCount (tileCount)
|
||||
, fIFD (ifd)
|
||||
, fNextTileIndex (0)
|
||||
|
||||
{
|
||||
|
||||
fMinTaskArea = 16 * 16;
|
||||
fUnitCell = dng_point (16, 16);
|
||||
fMaxTileSize = dng_point (16, 16);
|
||||
|
||||
}
|
||||
|
||||
void Process (uint32 /* threadIndex */,
|
||||
const dng_rect & /* tile */,
|
||||
dng_abort_sniffer *sniffer)
|
||||
{
|
||||
|
||||
AutoPtr<dng_memory_block> compressedBuffer;
|
||||
AutoPtr<dng_memory_block> uncompressedBuffer;
|
||||
AutoPtr<dng_memory_block> subTileBlockBuffer;
|
||||
AutoPtr<dng_memory_block> tempBuffer;
|
||||
|
||||
uint32 uncompressedSize = SafeUint32Mult (fIFD.fTileLength,
|
||||
fIFD.fTileWidth,
|
||||
fIFD.fSamplesPerPixel);
|
||||
|
||||
uncompressedBuffer.Reset (fHost.Allocate (uncompressedSize));
|
||||
|
||||
uint32 tilesAcross = fIFD.TilesAcross ();
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
// Note: fNextTileIndex is atomic
|
||||
|
||||
uint32 tileIndex = fNextTileIndex++;
|
||||
|
||||
if (tileIndex >= fTileCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dng_abort_sniffer::SniffForAbort (sniffer);
|
||||
|
||||
uint32 rowIndex = tileIndex / tilesAcross;
|
||||
uint32 colIndex = tileIndex % tilesAcross;
|
||||
|
||||
dng_rect tileArea = fIFD.TileArea (rowIndex, colIndex);
|
||||
|
||||
dng_memory_stream stream (fHost.Allocator ());
|
||||
|
||||
fWriter.WriteTile (fHost,
|
||||
fIFD,
|
||||
stream,
|
||||
fImage,
|
||||
tileArea,
|
||||
1,
|
||||
compressedBuffer,
|
||||
uncompressedBuffer,
|
||||
subTileBlockBuffer,
|
||||
tempBuffer,
|
||||
true);
|
||||
|
||||
fJPEGImage.fJPEGData [tileIndex].Reset (stream.AsMemoryBlock (fHost.Allocator ()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_jpeg_image::Encode (dng_host &host,
|
||||
const dng_negative &negative,
|
||||
dng_image_writer &writer,
|
||||
const dng_image &image)
|
||||
{
|
||||
|
||||
#if qDNGValidate
|
||||
dng_timer timer ("Encode JPEG Proxy time");
|
||||
#endif
|
||||
|
||||
DNG_ASSERT (image.PixelType () == ttByte, "Cannot JPEG encode non-byte image");
|
||||
|
||||
fImageSize = image.Bounds ().Size ();
|
||||
|
||||
dng_ifd ifd;
|
||||
|
||||
ifd.fImageWidth = fImageSize.h;
|
||||
ifd.fImageLength = fImageSize.v;
|
||||
|
||||
ifd.fSamplesPerPixel = image.Planes ();
|
||||
|
||||
ifd.fBitsPerSample [0] = 8;
|
||||
ifd.fBitsPerSample [1] = 8;
|
||||
ifd.fBitsPerSample [2] = 8;
|
||||
ifd.fBitsPerSample [3] = 8;
|
||||
|
||||
ifd.fPhotometricInterpretation = piLinearRaw;
|
||||
|
||||
ifd.fCompression = ccLossyJPEG;
|
||||
|
||||
ifd.FindTileSize (512 * 512 * ifd.fSamplesPerPixel);
|
||||
|
||||
fTileSize.h = ifd.fTileWidth;
|
||||
fTileSize.v = ifd.fTileLength;
|
||||
|
||||
// Need a higher quality for raw proxies than non-raw proxies, since users
|
||||
// often perform much greater color changes. Also, if we are targeting a
|
||||
// "large" size proxy (larger than 5 MP), or this is a full size proxy,
|
||||
// then use a higher quality.
|
||||
|
||||
bool useHigherQuality = (uint64) ifd.fImageWidth *
|
||||
(uint64) ifd.fImageLength > 5000000 ||
|
||||
image.Bounds ().Size () == negative.OriginalDefaultFinalSize ();
|
||||
|
||||
if (negative.ColorimetricReference () == crSceneReferred)
|
||||
{
|
||||
ifd.fCompressionQuality = useHigherQuality ? 11 : 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
ifd.fCompressionQuality = useHigherQuality ? 10 : 8;
|
||||
}
|
||||
|
||||
uint32 tilesAcross = ifd.TilesAcross ();
|
||||
uint32 tilesDown = ifd.TilesDown ();
|
||||
|
||||
uint32 tileCount = tilesAcross * tilesDown;
|
||||
|
||||
fJPEGData.Reset (new dng_jpeg_image_tile_ptr [tileCount]);
|
||||
|
||||
uint32 threadCount = Min_uint32 (tileCount,
|
||||
host.PerformAreaTaskThreads ());
|
||||
|
||||
dng_jpeg_image_encode_task task (host,
|
||||
writer,
|
||||
image,
|
||||
*this,
|
||||
tileCount,
|
||||
ifd);
|
||||
|
||||
host.PerformAreaTask (task,
|
||||
dng_rect (0, 0, 16, 16 * threadCount));
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_jpeg_image_find_digest_task : public dng_area_task,
|
||||
private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
const dng_jpeg_image &fJPEGImage;
|
||||
|
||||
uint32 fTileCount;
|
||||
|
||||
dng_fingerprint *fDigests;
|
||||
|
||||
std::atomic_uint fNextTileIndex;
|
||||
|
||||
public:
|
||||
|
||||
dng_jpeg_image_find_digest_task (const dng_jpeg_image &jpegImage,
|
||||
uint32 tileCount,
|
||||
dng_fingerprint *digests)
|
||||
|
||||
: dng_area_task ("dng_jpeg_image_find_digest_task")
|
||||
|
||||
, fJPEGImage (jpegImage)
|
||||
, fTileCount (tileCount)
|
||||
, fDigests (digests)
|
||||
, fNextTileIndex (0)
|
||||
|
||||
{
|
||||
|
||||
fMinTaskArea = 16 * 16;
|
||||
fUnitCell = dng_point (16, 16);
|
||||
fMaxTileSize = dng_point (16, 16);
|
||||
|
||||
}
|
||||
|
||||
void Process (uint32 /* threadIndex */,
|
||||
const dng_rect & /* tile */,
|
||||
dng_abort_sniffer *sniffer)
|
||||
{
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
// Note: fNextTileIndex is atomic
|
||||
|
||||
uint32 tileIndex = fNextTileIndex++;
|
||||
|
||||
if (tileIndex >= fTileCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dng_abort_sniffer::SniffForAbort (sniffer);
|
||||
|
||||
dng_md5_printer printer;
|
||||
|
||||
printer.Process (fJPEGImage.fJPEGData [tileIndex]->Buffer (),
|
||||
fJPEGImage.fJPEGData [tileIndex]->LogicalSize ());
|
||||
|
||||
fDigests [tileIndex] = printer.Result ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_fingerprint dng_jpeg_image::FindDigest (dng_host &host) const
|
||||
{
|
||||
|
||||
uint32 tileCount = TileCount ();
|
||||
|
||||
uint32 arrayCount = tileCount + (fJPEGTables.Get () ? 1 : 0);
|
||||
|
||||
AutoArray<dng_fingerprint> digests (new dng_fingerprint [arrayCount]);
|
||||
|
||||
// Compute digest of each compressed tile.
|
||||
|
||||
{
|
||||
|
||||
uint32 threadCount = Min_uint32 (tileCount,
|
||||
host.PerformAreaTaskThreads ());
|
||||
|
||||
dng_jpeg_image_find_digest_task task (*this,
|
||||
tileCount,
|
||||
digests.Get ());
|
||||
|
||||
host.PerformAreaTask (task,
|
||||
dng_rect (0, 0, 16, 16 * threadCount));
|
||||
|
||||
}
|
||||
|
||||
// Compute digest of JPEG tables, if any.
|
||||
|
||||
if (fJPEGTables.Get ())
|
||||
{
|
||||
|
||||
dng_md5_printer printer;
|
||||
|
||||
printer.Process (fJPEGTables->Buffer (),
|
||||
fJPEGTables->LogicalSize ());
|
||||
|
||||
digests [tileCount] = printer.Result ();
|
||||
|
||||
}
|
||||
|
||||
// Combine digests into a single digest.
|
||||
|
||||
{
|
||||
|
||||
dng_md5_printer printer;
|
||||
|
||||
for (uint32 k = 0; k < arrayCount; k++)
|
||||
{
|
||||
|
||||
printer.Process (digests [k].data,
|
||||
dng_fingerprint::kDNGFingerprintSize);
|
||||
|
||||
}
|
||||
|
||||
return printer.Result ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2011-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_jpeg_image__
|
||||
#define __dng_jpeg_image__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_point.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef AutoPtr<dng_memory_block> dng_jpeg_image_tile_ptr;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_jpeg_image
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_point fImageSize;
|
||||
|
||||
dng_point fTileSize;
|
||||
|
||||
bool fUsesStrips;
|
||||
|
||||
AutoPtr<dng_memory_block> fJPEGTables;
|
||||
|
||||
AutoArray<dng_jpeg_image_tile_ptr> fJPEGData;
|
||||
|
||||
public:
|
||||
|
||||
dng_jpeg_image ();
|
||||
|
||||
uint32 TilesAcross () const
|
||||
{
|
||||
if (fTileSize.h)
|
||||
{
|
||||
return (fImageSize.h + fTileSize.h - 1) / fTileSize.h;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 TilesDown () const
|
||||
{
|
||||
if (fTileSize.v)
|
||||
{
|
||||
return (fImageSize.v + fTileSize.v - 1) / fTileSize.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 TileCount () const
|
||||
{
|
||||
return TilesAcross () * TilesDown ();
|
||||
}
|
||||
|
||||
void Encode (dng_host &host,
|
||||
const dng_negative &negative,
|
||||
dng_image_writer &writer,
|
||||
const dng_image &image);
|
||||
|
||||
dng_fingerprint FindDigest (dng_host &host) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,670 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Opcodes to fix lens aberrations such as geometric distortion, lateral chromatic
|
||||
* aberration, and vignetting (peripheral illumination falloff).
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_lens_correction__
|
||||
#define __dng_lens_correction__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_1d_function.h"
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_opcodes.h"
|
||||
#include "dng_pixel_buffer.h"
|
||||
#include "dng_point.h"
|
||||
#include "dng_resample.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Abstract base class holding common warp opcode parameters (e.g.,
|
||||
/// number of planes, optical center) and common warp routines.
|
||||
|
||||
class dng_warp_params
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Number of planes to be warped. Must be either 1 or equal to the
|
||||
// number of planes of the image to be processed. If set to 1, then a
|
||||
// single set of warp parameters applies to all planes of the image.
|
||||
// fPlanes must be at least 1 and no greater than kMaxColorPlanes (see
|
||||
// dng_sdk_limits.h).
|
||||
|
||||
uint32 fPlanes;
|
||||
|
||||
// The optical center of the lens in normalized [0,1] coordinates with
|
||||
// respect to the image's active area. For example, a value of (0.5,
|
||||
// 0.5) indicates that the optical center of the lens is at the center
|
||||
// of the image's active area. A normalized radius of 1.0 corresponds to
|
||||
// the distance from fCenter to the farthest corner of the image's
|
||||
// active area. Each component of fCenter must lie in the range [0,1].
|
||||
|
||||
dng_point_real64 fCenter;
|
||||
|
||||
public:
|
||||
|
||||
/// Create empty (invalid) warp parameters.
|
||||
|
||||
dng_warp_params ();
|
||||
|
||||
/// Create warp parameters with specified number of planes and image
|
||||
/// center.
|
||||
///
|
||||
/// \param planes The number of planes of parameters specified: It must
|
||||
/// be either 1 or equal to the number of planes of the image to be
|
||||
/// processed.
|
||||
///
|
||||
/// \param fCenter The image center in relative coordinates.
|
||||
|
||||
dng_warp_params (uint32 planes,
|
||||
const dng_point_real64 &fCenter);
|
||||
|
||||
virtual ~dng_warp_params ();
|
||||
|
||||
/// Is the entire correction a NOP for all planes?
|
||||
|
||||
virtual bool IsNOPAll () const;
|
||||
|
||||
/// Is the entire correction a NOP for the specified plane?
|
||||
|
||||
virtual bool IsNOP (uint32 plane) const;
|
||||
|
||||
/// Is the radial correction a NOP for all planes?
|
||||
|
||||
virtual bool IsRadNOPAll () const;
|
||||
|
||||
/// Is the radial correction a NOP for the specified plane?
|
||||
|
||||
virtual bool IsRadNOP (uint32 plane) const;
|
||||
|
||||
/// Is the tangential correction a NOP for all planes?
|
||||
|
||||
virtual bool IsTanNOPAll () const;
|
||||
|
||||
/// Is the tangential correction a NOP for the specified plane?
|
||||
|
||||
virtual bool IsTanNOP (uint32 plane) const;
|
||||
|
||||
/// Do these warp params appear valid?
|
||||
|
||||
virtual bool IsValid () const;
|
||||
|
||||
/// Are these warp params valid for the specified negative?
|
||||
|
||||
virtual bool IsValidForNegative (const dng_negative &negative) const;
|
||||
|
||||
/// Propagate warp parameters from first plane to all other planes.
|
||||
|
||||
virtual void PropagateToAllPlanes (uint32 totalPlanes) = 0;
|
||||
|
||||
/// Evaluate the 1D radial warp function for the specified plane.
|
||||
/// Parameter r is the destination (i.e., corrected) normalized radius,
|
||||
/// i.e., the normalized Euclidean distance between a corrected pixel
|
||||
/// position and the optical center in the image. r lies in the range
|
||||
/// [0,1]. The returned result is non-negative.
|
||||
|
||||
virtual real64 Evaluate (uint32 plane,
|
||||
real64 r) const = 0;
|
||||
|
||||
/// Compute and return the inverse of Evaluate () above. The base
|
||||
/// implementation uses Newton's method to perform the inversion.
|
||||
/// Parameter r is the source (i.e., uncorrected) normalized radius,
|
||||
/// i.e., normalized Euclidean distance between a corrected pixel
|
||||
/// position and the optical center in the image. Both r and the
|
||||
/// computed result are non-negative.
|
||||
|
||||
virtual real64 EvaluateInverse (uint32 plane,
|
||||
real64 r) const;
|
||||
|
||||
/// Evaluate the 1D radial warp ratio function for the specified plane.
|
||||
/// Parameter r2 is the square of the destination (i.e., corrected)
|
||||
/// normalized radius, i.e., the square of the normalized Euclidean
|
||||
/// distance between a corrected pixel position and the optical center
|
||||
/// in the image. r2 must lie in the range [0,1]. Note that this is
|
||||
/// different than the Evaluate () function, above, in that the argument
|
||||
/// to EvaluateRatio () is the square of the radius, not the radius
|
||||
/// itself. The returned result is non-negative. Mathematically,
|
||||
/// EvaluateRatio (r * r) is the same as Evaluate (r) / r.
|
||||
|
||||
virtual real64 EvaluateRatio (uint32 plane,
|
||||
real64 r2) const = 0;
|
||||
|
||||
/// Evaluate the 2D tangential warp for the specified plane. Parameter
|
||||
/// r2 is the square of the destination (i.e., corrected) normalized
|
||||
/// radius, i.e., the square of the normalized Euclidean distance
|
||||
/// between a corrected pixel position P and the optical center in the
|
||||
/// image. r2 must lie in the range [0,1]. diff contains the vertical
|
||||
/// and horizontal Euclidean distances (in pixels) between P and the
|
||||
/// optical center. diff2 contains the squares of the vertical and
|
||||
/// horizontal Euclidean distances (in pixels) between P and the optical
|
||||
/// center. The returned result is the tangential warp offset, measured
|
||||
/// in pixels.
|
||||
|
||||
virtual dng_point_real64 EvaluateTangential (uint32 plane,
|
||||
real64 r2,
|
||||
const dng_point_real64 &diff,
|
||||
const dng_point_real64 &diff2) const = 0;
|
||||
|
||||
/// Evaluate the 2D tangential warp for the specified plane. diff
|
||||
/// contains the vertical and horizontal Euclidean distances (in pixels)
|
||||
/// between the destination (i.e., corrected) pixel position and the
|
||||
/// optical center in the image. The returned result is the tangential
|
||||
/// warp offset, measured in pixels.
|
||||
|
||||
dng_point_real64 EvaluateTangential2 (uint32 plane,
|
||||
const dng_point_real64 &diff) const;
|
||||
|
||||
/// Evaluate the 2D tangential warp for the specified plane. Parameter
|
||||
/// r2 is the square of the destination (i.e., corrected) normalized
|
||||
/// radius, i.e., the square of the normalized Euclidean distance
|
||||
/// between a corrected pixel position P and the optical center in the
|
||||
/// image. r2 must lie in the range [0,1]. diff contains the vertical
|
||||
/// and horizontal Euclidean distances (in pixels) between P and the
|
||||
/// optical center. The returned result is the tangential warp offset,
|
||||
/// measured in pixels.
|
||||
|
||||
dng_point_real64 EvaluateTangential3 (uint32 plane,
|
||||
real64 r2,
|
||||
const dng_point_real64 &diff) const;
|
||||
|
||||
/// Compute and return the maximum warped radius gap. Let D be a
|
||||
/// rectangle in a destination (corrected) image. Let rDstFar and
|
||||
/// rDstNear be the farthest and nearest points to the image center,
|
||||
/// respectively. Then the specified parameter maxDstGap is the
|
||||
/// Euclidean distance between rDstFar and rDstNear. Warp D through this
|
||||
/// warp function to a closed and bounded (generally not rectangular)
|
||||
/// region S. Let rSrcfar and rSrcNear be the farthest and nearest
|
||||
/// points to the image center, respectively. This routine returns a
|
||||
/// value that is at least (rSrcFar - rSrcNear).
|
||||
|
||||
virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const = 0;
|
||||
|
||||
/// Compute and return the maximum warped tangential gap. minDst is the
|
||||
/// top-left pixel of the image in normalized pixel coordinates. maxDst
|
||||
/// is the bottom-right pixel of the image in normalized pixel
|
||||
/// coordinates. MaxSrcTanGap () computes the maximum absolute shift in
|
||||
/// normalized pixels in the horizontal and vertical directions that can
|
||||
/// occur as a result of the tangential warp.
|
||||
|
||||
virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
|
||||
dng_point_real64 maxDst) const = 0;
|
||||
|
||||
/// Compute and return the minimum src/dst ratio that should be used
|
||||
/// for this warp.
|
||||
|
||||
virtual real64 SafeMinRatio () const = 0;
|
||||
|
||||
/// Compute and return the maximum src/dst ratio that should be used
|
||||
/// for this warp.
|
||||
|
||||
virtual real64 SafeMaxRatio () const = 0;
|
||||
|
||||
/// Debug parameters.
|
||||
|
||||
virtual void Dump () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Warp parameters for pinhole perspective rectilinear (not fisheye)
|
||||
/// camera model. Supports radial and tangential (decentering) distortion
|
||||
/// correction parameters.
|
||||
///
|
||||
/// Note the restrictions described below.
|
||||
|
||||
class dng_warp_params_rectilinear: public dng_warp_params
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Radial and tangential polynomial coefficients. These define a warp
|
||||
// from corrected pixel coordinates (xDst, yDst) to uncorrected pixel
|
||||
// coordinates (xSrc, ySrc) for each plane P as follows:
|
||||
//
|
||||
// Let kr0 = fRadParams [P][0]
|
||||
// kr1 = fRadParams [P][1]
|
||||
// kr2 = fRadParams [P][2]
|
||||
// kr3 = fRadParams [P][3]
|
||||
//
|
||||
// kt0 = fTanParams [P][0]
|
||||
// kt1 = fTanParams [P][1]
|
||||
//
|
||||
// Let (xCenter, yCenter) be the optical image center (see fCenter,
|
||||
// below) expressed in pixel coordinates. Let maxDist be the Euclidean
|
||||
// distance (in pixels) from (xCenter, yCenter) to the farthest image
|
||||
// corner.
|
||||
//
|
||||
// First, compute the normalized distance of the corrected pixel
|
||||
// position (xDst, yDst) from the image center:
|
||||
//
|
||||
// dx = (xDst - xCenter) / maxDist
|
||||
// dy = (yDst - yCenter) / maxDist
|
||||
//
|
||||
// r^2 = dx^2 + dy^2
|
||||
//
|
||||
// Compute the radial correction term:
|
||||
//
|
||||
// ratio = kr0 + (kr1 * r^2) + (kr2 * r^4) + (kr3 * r^6)
|
||||
//
|
||||
// dxRad = dx * ratio
|
||||
// dyRad = dy * ratio
|
||||
//
|
||||
// Compute the tangential correction term:
|
||||
//
|
||||
// dxTan = (2 * kt0 * dx * dy) + kt1 * (r^2 + 2 * dx^2)
|
||||
// dyTan = (2 * kt1 * dx * dy) + kt0 * (r^2 + 2 * dy^2)
|
||||
//
|
||||
// Compute the uncorrected pixel position (xSrc, ySrc):
|
||||
//
|
||||
// xSrc = xCenter + (dxRad + dxTan) * maxDist
|
||||
// ySrc = yCenter + (dyRad + dyTan) * maxDist
|
||||
//
|
||||
// Mathematical definitions and restrictions:
|
||||
//
|
||||
// Let { xSrc, ySrc } = f (xDst, yDst) be the warp function defined
|
||||
// above.
|
||||
//
|
||||
// Let xSrc = fx (xDst, yDst) be the x-component of the warp function.
|
||||
// Let ySrc = fy (xDst, yDst) be the y-component of the warp function.
|
||||
//
|
||||
// f (x, y) must be an invertible function.
|
||||
//
|
||||
// fx (x, y) must be an increasing function of x.
|
||||
// fy (x, y) must be an increasing function of x.
|
||||
//
|
||||
// The parameters kr0, kr1, kr2, and kr3 must define an increasing
|
||||
// radial warp function. Specifically, let w (r) be the radial warp
|
||||
// function:
|
||||
//
|
||||
// w (r) = (kr0 * r) + (kr1 * r^3) + (kr2 * r^5) + (kr3 * r^7).
|
||||
//
|
||||
// w (r) must be an increasing function.
|
||||
|
||||
dng_vector fRadParams [kMaxColorPlanes];
|
||||
dng_vector fTanParams [kMaxColorPlanes];
|
||||
|
||||
public:
|
||||
|
||||
/// Create empty (invalid) rectilinear warp parameters.
|
||||
|
||||
dng_warp_params_rectilinear ();
|
||||
|
||||
/// Create rectilinear warp parameters with the specified number of
|
||||
/// planes, radial component terms, tangential component terms, and
|
||||
/// image center in relative coordinates.
|
||||
|
||||
dng_warp_params_rectilinear (uint32 planes,
|
||||
const dng_vector radParams [],
|
||||
const dng_vector tanParams [],
|
||||
const dng_point_real64 &fCenter);
|
||||
|
||||
virtual ~dng_warp_params_rectilinear ();
|
||||
|
||||
// Overridden methods.
|
||||
|
||||
virtual bool IsRadNOP (uint32 plane) const;
|
||||
|
||||
virtual bool IsTanNOP (uint32 plane) const;
|
||||
|
||||
virtual bool IsValid () const;
|
||||
|
||||
virtual void PropagateToAllPlanes (uint32 totalPlanes);
|
||||
|
||||
virtual real64 Evaluate (uint32 plane,
|
||||
real64 r) const;
|
||||
|
||||
virtual real64 EvaluateRatio (uint32 plane,
|
||||
real64 r2) const;
|
||||
|
||||
virtual dng_point_real64 EvaluateTangential (uint32 plane,
|
||||
real64 r2,
|
||||
const dng_point_real64 &diff,
|
||||
const dng_point_real64 &diff2) const;
|
||||
|
||||
virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const;
|
||||
|
||||
virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
|
||||
dng_point_real64 maxDst) const;
|
||||
|
||||
virtual real64 SafeMinRatio () const;
|
||||
|
||||
virtual real64 SafeMaxRatio () const;
|
||||
|
||||
virtual void Dump () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Warp parameters for fisheye camera model (radial component only).
|
||||
/// Note the restrictions described below.
|
||||
|
||||
class dng_warp_params_fisheye: public dng_warp_params
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Radial warp coefficients. These define a warp from corrected pixel
|
||||
// coordinates (xDst, yDst) to uncorrected pixel coordinates (xSrc,
|
||||
// ySrc) for each plane P as follows:
|
||||
//
|
||||
// Let kr0 = fRadParams [P][0]
|
||||
// kr1 = fRadParams [P][1]
|
||||
// kr2 = fRadParams [P][2]
|
||||
// kr3 = fRadParams [P][3]
|
||||
//
|
||||
// Let (xCenter, yCenter) be the optical image center (see fCenter,
|
||||
// below) expressed in pixel coordinates. Let maxDist be the Euclidean
|
||||
// distance (in pixels) from (xCenter, yCenter) to the farthest image
|
||||
// corner.
|
||||
//
|
||||
// First, compute the normalized distance of the corrected pixel
|
||||
// position (xDst, yDst) from the image center:
|
||||
//
|
||||
// dx = (xDst - xCenter) / maxDist
|
||||
// dy = (yDst - yCenter) / maxDist
|
||||
//
|
||||
// r = sqrt (dx^2 + dy^2)
|
||||
//
|
||||
// Compute the radial correction term:
|
||||
//
|
||||
// t = atan (r)
|
||||
//
|
||||
// rWarp = (kr0 * t) + (kr1 * t^3) + (kr2 * t^5) + (kr3 * t^7)
|
||||
//
|
||||
// ratio = rWarp / r
|
||||
//
|
||||
// dxRad = dx * ratio
|
||||
// dyRad = dy * ratio
|
||||
//
|
||||
// Compute the uncorrected pixel position (xSrc, ySrc):
|
||||
//
|
||||
// xSrc = xCenter + (dxRad * maxDist)
|
||||
// ySrc = yCenter + (dyRad * maxDist)
|
||||
//
|
||||
// The parameters kr0, kr1, kr2, and kr3 must define an increasing
|
||||
// radial warp function. Specifically, let w (r) be the radial warp
|
||||
// function:
|
||||
//
|
||||
// t = atan (r)
|
||||
//
|
||||
// w (r) = (kr0 * t) + (kr1 * t^3) + (kr2 * t^5) + (kr3 * t^7).
|
||||
//
|
||||
// w (r) must be an increasing function.
|
||||
|
||||
dng_vector fRadParams [kMaxColorPlanes];
|
||||
|
||||
public:
|
||||
|
||||
/// Create empty (invalid) fisheye warp parameters.
|
||||
|
||||
dng_warp_params_fisheye ();
|
||||
|
||||
/// Create rectilinear warp parameters with the specified number of
|
||||
/// planes, radial component terms, and image center in relative
|
||||
/// coordinates.
|
||||
|
||||
dng_warp_params_fisheye (uint32 planes,
|
||||
const dng_vector radParams [],
|
||||
const dng_point_real64 &fCenter);
|
||||
|
||||
virtual ~dng_warp_params_fisheye ();
|
||||
|
||||
// Overridden methods.
|
||||
|
||||
virtual bool IsRadNOP (uint32 plane) const;
|
||||
|
||||
virtual bool IsTanNOP (uint32 plane) const;
|
||||
|
||||
virtual bool IsValid () const;
|
||||
|
||||
virtual void PropagateToAllPlanes (uint32 totalPlanes);
|
||||
|
||||
virtual real64 Evaluate (uint32 plane,
|
||||
real64 r) const;
|
||||
|
||||
virtual real64 EvaluateRatio (uint32 plane,
|
||||
real64 r2) const;
|
||||
|
||||
virtual dng_point_real64 EvaluateTangential (uint32 plane,
|
||||
real64 r2,
|
||||
const dng_point_real64 &diff,
|
||||
const dng_point_real64 &diff2) const;
|
||||
|
||||
virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const;
|
||||
|
||||
virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
|
||||
dng_point_real64 maxDst) const;
|
||||
|
||||
virtual real64 SafeMinRatio () const;
|
||||
|
||||
virtual real64 SafeMaxRatio () const;
|
||||
|
||||
virtual void Dump () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Warp opcode for pinhole perspective (rectilinear) camera model.
|
||||
|
||||
class dng_opcode_WarpRectilinear: public dng_opcode
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_warp_params_rectilinear fWarpParams;
|
||||
|
||||
public:
|
||||
|
||||
dng_opcode_WarpRectilinear (const dng_warp_params_rectilinear ¶ms,
|
||||
uint32 flags);
|
||||
|
||||
explicit dng_opcode_WarpRectilinear (dng_stream &stream);
|
||||
|
||||
// Overridden methods.
|
||||
|
||||
virtual bool IsNOP () const;
|
||||
|
||||
virtual bool IsValidForNegative (const dng_negative &negative) const;
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
// Other methods.
|
||||
|
||||
bool HasDistort () const;
|
||||
|
||||
bool HasLateralCA () const;
|
||||
|
||||
const dng_warp_params_rectilinear & Params () const
|
||||
{
|
||||
return fWarpParams;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static uint32 ParamBytes (uint32 planes);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Warp opcode for fisheye camera model.
|
||||
|
||||
class dng_opcode_WarpFisheye: public dng_opcode
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_warp_params_fisheye fWarpParams;
|
||||
|
||||
public:
|
||||
|
||||
dng_opcode_WarpFisheye (const dng_warp_params_fisheye ¶ms,
|
||||
uint32 flags);
|
||||
|
||||
explicit dng_opcode_WarpFisheye (dng_stream &stream);
|
||||
|
||||
// Overridden methods.
|
||||
|
||||
virtual bool IsNOP () const;
|
||||
|
||||
virtual bool IsValidForNegative (const dng_negative &negative) const;
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
protected:
|
||||
|
||||
static uint32 ParamBytes (uint32 planes);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Radially-symmetric vignette (peripheral illuminational falloff)
|
||||
/// correction parameters.
|
||||
|
||||
class dng_vignette_radial_params
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
static const uint32 kNumTerms = 5;
|
||||
|
||||
public:
|
||||
|
||||
// Let v be an uncorrected pixel value of a pixel p in linear space.
|
||||
//
|
||||
// Let r be the Euclidean distance between p and the optical center.
|
||||
//
|
||||
// Compute corrected pixel value v' = v * g, where g is the gain.
|
||||
//
|
||||
// Let k0 = fParams [0]
|
||||
// Let k1 = fParams [1]
|
||||
// Let k2 = fParams [2]
|
||||
// Let k3 = fParams [3]
|
||||
// Let k4 = fParams [4]
|
||||
//
|
||||
// Gain g = 1 + (k0 * r^2) + (k1 * r^4) + (k2 * r^6) + (k3 * r^8) + (k4 * r^10)
|
||||
|
||||
dng_std_vector<real64> fParams;
|
||||
|
||||
dng_point_real64 fCenter;
|
||||
|
||||
public:
|
||||
|
||||
dng_vignette_radial_params ();
|
||||
|
||||
dng_vignette_radial_params (const dng_std_vector<real64> ¶ms,
|
||||
const dng_point_real64 ¢er);
|
||||
|
||||
dng_vignette_radial_params (const dng_vignette_radial_params ¶ms);
|
||||
|
||||
bool IsNOP () const;
|
||||
|
||||
bool IsValid () const;
|
||||
|
||||
// For debugging.
|
||||
|
||||
void Dump () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Radially-symmetric lens vignette correction opcode.
|
||||
|
||||
class dng_opcode_FixVignetteRadial: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_vignette_radial_params fParams;
|
||||
|
||||
uint32 fImagePlanes;
|
||||
|
||||
int64 fSrcOriginH;
|
||||
int64 fSrcOriginV;
|
||||
|
||||
int64 fSrcStepH;
|
||||
int64 fSrcStepV;
|
||||
|
||||
uint32 fTableInputBits;
|
||||
uint32 fTableOutputBits;
|
||||
|
||||
AutoPtr<dng_memory_block> fGainTable;
|
||||
|
||||
AutoPtr<dng_memory_block> fMaskBuffers [kMaxMPThreads];
|
||||
|
||||
public:
|
||||
|
||||
dng_opcode_FixVignetteRadial (const dng_vignette_radial_params ¶ms,
|
||||
uint32 flags);
|
||||
|
||||
explicit dng_opcode_FixVignetteRadial (dng_stream &stream);
|
||||
|
||||
const dng_vignette_radial_params & Params () const
|
||||
{
|
||||
return fParams;
|
||||
}
|
||||
|
||||
virtual bool IsNOP () const;
|
||||
|
||||
virtual bool IsValidForNegative (const dng_negative &) const;
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 /* imagePixelType */)
|
||||
{
|
||||
return ttFloat;
|
||||
}
|
||||
|
||||
virtual void Prepare (dng_negative &negative,
|
||||
uint32 threadCount,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes,
|
||||
uint32 bufferPixelType,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
protected:
|
||||
|
||||
static uint32 ParamBytes ();
|
||||
|
||||
virtual dng_vignette_radial_params MakeParamsForRender (const dng_negative &negative);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,161 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Support for linearization table and black level tags.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_linearization_info__
|
||||
#define __dng_linearization_info__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_rational.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class for managing data values related to DNG linearization.
|
||||
///
|
||||
/// See LinearizationTable, BlackLevel, BlackLevelRepeatDim, BlackLevelDeltaH,
|
||||
/// BlackLevelDeltaV and WhiteLevel tags in the \ref spec_dng "DNG 1.1.0 specification".
|
||||
|
||||
class dng_linearization_info
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// This rectangle defines the active (non-masked) pixels of the sensor.
|
||||
/// The order of the rectangle coordinates is: top, left, bottom, right.
|
||||
|
||||
dng_rect fActiveArea;
|
||||
|
||||
/// Number of rectangles in fMaskedArea
|
||||
|
||||
uint32 fMaskedAreaCount;
|
||||
|
||||
/// List of non-overlapping rectangle coordinates of fully masked pixels.
|
||||
/// Can be optionally used by DNG readers to measure the black encoding level.
|
||||
/// The order of each rectangle's coordinates is: top, left, bottom, right.
|
||||
/// If the raw image data has already had its black encoding level subtracted, then this tag should
|
||||
/// not be used, since the masked pixels are no longer useful.
|
||||
/// Note that DNG writers are still required to include an estimate and store the black encoding level
|
||||
/// using the black level DNG tags. Support for the MaskedAreas tag is not required of DNG
|
||||
/// readers.
|
||||
|
||||
dng_rect fMaskedArea [kMaxMaskedAreas];
|
||||
|
||||
/// A lookup table that maps stored values into linear values.
|
||||
/// This tag is typically used to increase compression ratios by storing the raw data in a non-linear, more
|
||||
/// visually uniform space with fewer total encoding levels.
|
||||
/// If SamplesPerPixel is not equal to one, e.g. Fuji S3 type sensor, this single table applies to all the samples for each
|
||||
/// pixel.
|
||||
|
||||
AutoPtr<dng_memory_block> fLinearizationTable;
|
||||
|
||||
/// Actual number of rows in fBlackLevel pattern
|
||||
|
||||
uint32 fBlackLevelRepeatRows;
|
||||
|
||||
/// Actual number of columns in fBlackLevel pattern
|
||||
|
||||
uint32 fBlackLevelRepeatCols;
|
||||
|
||||
/// Repeating pattern of black level deltas fBlackLevelRepeatRows by fBlackLevelRepeatCols in size.
|
||||
|
||||
real64 fBlackLevel [kMaxBlackPattern] [kMaxBlackPattern] [kMaxSamplesPerPixel];
|
||||
|
||||
/// Memory block of double-precision floating point deltas between baseline black level and a given column's black level
|
||||
|
||||
AutoPtr<dng_memory_block> fBlackDeltaH;
|
||||
|
||||
/// Memory block of double-precision floating point deltas between baseline black level and a given row's black level
|
||||
|
||||
AutoPtr<dng_memory_block> fBlackDeltaV;
|
||||
|
||||
/// Single white level (maximum sensor value) for each sample plane.
|
||||
|
||||
real64 fWhiteLevel [kMaxSamplesPerPixel];
|
||||
|
||||
protected:
|
||||
|
||||
int32 fBlackDenom;
|
||||
|
||||
public:
|
||||
|
||||
dng_linearization_info ();
|
||||
|
||||
virtual ~dng_linearization_info ();
|
||||
|
||||
void RoundBlacks ();
|
||||
|
||||
virtual void Parse (dng_host &host,
|
||||
dng_stream &stream,
|
||||
dng_info &info);
|
||||
|
||||
virtual void PostParse (dng_host &host,
|
||||
dng_negative &negative);
|
||||
|
||||
/// Compute the maximum black level for a given sample plane taking into account base
|
||||
/// black level, repeated black level patter, and row/column delta maps.
|
||||
|
||||
real64 MaxBlackLevel (uint32 plane) const;
|
||||
|
||||
/// Convert raw data from in-file format to a true linear image using linearization data from DNG.
|
||||
/// \param host Used to allocate buffers, check for aborts, and post progress updates.
|
||||
/// \param negative Used to remember preserved black point.
|
||||
/// \param srcImage Input pre-linearization RAW samples.
|
||||
/// \param dstImage Output linearized image.
|
||||
|
||||
virtual void Linearize (dng_host &host,
|
||||
dng_negative &negative,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage);
|
||||
|
||||
/// Compute black level for one coordinate and sample plane in the image.
|
||||
/// \param row Row to compute black level for.
|
||||
/// \param col Column to compute black level for.
|
||||
/// \param plane Sample plane to compute black level for.
|
||||
|
||||
dng_urational BlackLevel (uint32 row,
|
||||
uint32 col,
|
||||
uint32 plane) const;
|
||||
|
||||
/// Number of per-row black level deltas in fBlackDeltaV.
|
||||
|
||||
uint32 RowBlackCount () const;
|
||||
|
||||
/// Lookup black level delta for a given row.
|
||||
/// \param row Row to get black level for.
|
||||
/// \retval black level for indicated row.
|
||||
|
||||
dng_srational RowBlack (uint32 row) const;
|
||||
|
||||
/// Number of per-column black level deltas in fBlackDeltaV.
|
||||
|
||||
uint32 ColumnBlackCount () const;
|
||||
|
||||
/// Lookup black level delta for a given column.
|
||||
/// \param col Column to get black level for.
|
||||
/// \retval black level for indicated column.
|
||||
|
||||
dng_srational ColumnBlack (uint32 col) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,191 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2015-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_local_string.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_local_string::dng_local_string ()
|
||||
|
||||
: fDefaultText ()
|
||||
, fDictionary ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_local_string::dng_local_string (const dng_string &s)
|
||||
|
||||
: fDefaultText (s)
|
||||
, fDictionary ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_local_string::~dng_local_string ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_local_string::Clear ()
|
||||
{
|
||||
|
||||
fDefaultText.Clear ();
|
||||
|
||||
fDictionary.clear ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_local_string::SetDefaultText (const dng_string &s)
|
||||
{
|
||||
|
||||
fDefaultText = s;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_local_string::AddTranslation (const dng_string &language,
|
||||
const dng_string &translation)
|
||||
{
|
||||
|
||||
dng_string safeLanguage (language);
|
||||
|
||||
safeLanguage.Truncate (255);
|
||||
|
||||
fDictionary.push_back (dictionary_entry (safeLanguage,
|
||||
translation));
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_local_string::Set (const char *s)
|
||||
{
|
||||
|
||||
dng_string defaultText;
|
||||
|
||||
defaultText.Set (s);
|
||||
|
||||
*this = dng_local_string (defaultText);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const dng_string & dng_local_string::LocalText (const dng_string &locale) const
|
||||
{
|
||||
|
||||
// Pass 1 - try for a match starting with the entire locale string.
|
||||
|
||||
if (locale.Length () >= 5)
|
||||
{
|
||||
|
||||
for (uint32 index = 0; index < TranslationCount (); index++)
|
||||
{
|
||||
|
||||
if (Language (index).StartsWith (locale.Get (), false))
|
||||
{
|
||||
|
||||
return Translation (index);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Pass 2 - try for a language only match.
|
||||
|
||||
if (locale.Length () >= 2)
|
||||
{
|
||||
|
||||
dng_string languageOnly (locale);
|
||||
|
||||
languageOnly.Truncate (2);
|
||||
|
||||
for (uint32 index = 0; index < TranslationCount (); index++)
|
||||
{
|
||||
|
||||
if (Language (index).StartsWith (languageOnly.Get (), false))
|
||||
{
|
||||
|
||||
return Translation (index);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Otherwise use default text.
|
||||
|
||||
return DefaultText ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_local_string::operator== (const dng_local_string &s) const
|
||||
{
|
||||
|
||||
if (DefaultText () != s.DefaultText ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TranslationCount () != s.TranslationCount ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32 index = 0; index < TranslationCount (); index++)
|
||||
{
|
||||
|
||||
if (Language (index) != s.Language (index))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Translation (index) != s.Translation (index))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_local_string::Truncate (uint32 maxBytes)
|
||||
{
|
||||
|
||||
fDefaultText.Truncate (maxBytes);
|
||||
|
||||
for (uint32 index = 0; index < TranslationCount (); index++)
|
||||
{
|
||||
|
||||
fDictionary [index] . fTranslation . Truncate (maxBytes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,119 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2015-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_local_string__
|
||||
#define __dng_local_string__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_local_string
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_string fDefaultText;
|
||||
|
||||
struct dictionary_entry
|
||||
{
|
||||
|
||||
dng_string fLanguage;
|
||||
|
||||
dng_string fTranslation;
|
||||
|
||||
dictionary_entry (const dng_string &language,
|
||||
const dng_string &translation)
|
||||
|
||||
: fLanguage (language)
|
||||
, fTranslation (translation)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
std::vector<dictionary_entry> fDictionary;
|
||||
|
||||
public:
|
||||
|
||||
dng_local_string ();
|
||||
|
||||
dng_local_string (const dng_string &s);
|
||||
|
||||
~dng_local_string ();
|
||||
|
||||
void Clear ();
|
||||
|
||||
void SetDefaultText (const dng_string &s);
|
||||
|
||||
void AddTranslation (const dng_string &language,
|
||||
const dng_string &translation);
|
||||
|
||||
void Set (const char *s);
|
||||
|
||||
const dng_string & DefaultText () const
|
||||
{
|
||||
return fDefaultText;
|
||||
}
|
||||
|
||||
dng_string & DefaultText ()
|
||||
{
|
||||
return fDefaultText;
|
||||
}
|
||||
|
||||
uint32 TranslationCount () const
|
||||
{
|
||||
return (uint32) fDictionary.size ();
|
||||
}
|
||||
|
||||
const dng_string & Language (uint32 index) const
|
||||
{
|
||||
return fDictionary [index] . fLanguage;
|
||||
}
|
||||
|
||||
const dng_string & Translation (uint32 index) const
|
||||
{
|
||||
return fDictionary [index] . fTranslation;
|
||||
}
|
||||
|
||||
const dng_string & LocalText (const dng_string &locale) const;
|
||||
|
||||
bool IsEmpty () const
|
||||
{
|
||||
return DefaultText ().IsEmpty ();
|
||||
}
|
||||
|
||||
bool NotEmpty () const
|
||||
{
|
||||
return !IsEmpty ();
|
||||
}
|
||||
|
||||
bool operator== (const dng_local_string &s) const;
|
||||
|
||||
bool operator!= (const dng_local_string &s) const
|
||||
{
|
||||
return !(*this == s);
|
||||
}
|
||||
|
||||
void Truncate (uint32 maxBytes);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Functions for encoding and decoding lossless JPEG format.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_lossless_jpeg__
|
||||
#define __dng_lossless_jpeg__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_spooler
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~dng_spooler ()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual void Spool (const void *data,
|
||||
uint32 count) = 0;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void DecodeLosslessJPEG (dng_stream &stream,
|
||||
dng_spooler &spooler,
|
||||
uint32 minDecodedSize,
|
||||
uint32 maxDecodedSize,
|
||||
bool bug16,
|
||||
uint64 endOfData);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void EncodeLosslessJPEG (const uint16 *srcData,
|
||||
uint32 srcRows,
|
||||
uint32 srcCols,
|
||||
uint32 srcChannels,
|
||||
uint32 srcBitDepth,
|
||||
int32 srcRowStep,
|
||||
int32 srcColStep,
|
||||
dng_stream &stream);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,365 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Matrix and vector classes, including specialized 3x3 and 4x3 versions as
|
||||
* well as length 3 vectors.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_matrix__
|
||||
#define __dng_matrix__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_sdk_limits.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to represent 2D matrix up to kMaxColorPlanes x kMaxColorPlanes
|
||||
/// in size.
|
||||
|
||||
class dng_matrix
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
uint32 fRows;
|
||||
uint32 fCols;
|
||||
|
||||
real64 fData [kMaxColorPlanes] [kMaxColorPlanes];
|
||||
|
||||
public:
|
||||
|
||||
dng_matrix ();
|
||||
|
||||
dng_matrix (uint32 rows,
|
||||
uint32 cols);
|
||||
|
||||
dng_matrix (const dng_matrix &m);
|
||||
|
||||
virtual ~dng_matrix ()
|
||||
{
|
||||
}
|
||||
|
||||
void Clear ();
|
||||
|
||||
void SetIdentity (uint32 count);
|
||||
|
||||
uint32 Rows () const
|
||||
{
|
||||
return fRows;
|
||||
}
|
||||
|
||||
uint32 Cols () const
|
||||
{
|
||||
return fCols;
|
||||
}
|
||||
|
||||
real64 * operator [] (uint32 row)
|
||||
{
|
||||
return fData [row];
|
||||
}
|
||||
|
||||
const real64 * operator [] (uint32 row) const
|
||||
{
|
||||
return fData [row];
|
||||
}
|
||||
|
||||
bool operator== (const dng_matrix &m) const;
|
||||
|
||||
bool operator!= (const dng_matrix &m) const
|
||||
{
|
||||
return !(*this == m);
|
||||
}
|
||||
|
||||
bool IsEmpty () const
|
||||
{
|
||||
return fRows == 0 || fCols == 0;
|
||||
}
|
||||
|
||||
bool NotEmpty () const
|
||||
{
|
||||
return !IsEmpty ();
|
||||
}
|
||||
|
||||
bool IsDiagonal () const;
|
||||
|
||||
bool IsIdentity () const;
|
||||
|
||||
real64 MaxEntry () const;
|
||||
|
||||
real64 MinEntry () const;
|
||||
|
||||
void Scale (real64 factor);
|
||||
|
||||
void Round (real64 factor);
|
||||
|
||||
void SafeRound (real64 factor);
|
||||
|
||||
bool AlmostEqual (const dng_matrix &m,
|
||||
real64 slop = 1.0e-8) const;
|
||||
|
||||
bool AlmostIdentity (real64 slop = 1.0e-8) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 3x3 matrix.
|
||||
|
||||
class dng_matrix_3by3: public dng_matrix
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_matrix_3by3 ();
|
||||
|
||||
dng_matrix_3by3 (const dng_matrix &m);
|
||||
|
||||
dng_matrix_3by3 (real64 a00, real64 a01, real64 a02,
|
||||
real64 a10, real64 a11, real64 a12,
|
||||
real64 a20, real64 a21, real64 a22);
|
||||
|
||||
dng_matrix_3by3 (real64 a00, real64 a11, real64 a22);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 4x3 matrix. Handy for working with 4-color cameras.
|
||||
|
||||
class dng_matrix_4by3: public dng_matrix
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_matrix_4by3 ();
|
||||
|
||||
dng_matrix_4by3 (const dng_matrix &m);
|
||||
|
||||
dng_matrix_4by3 (real64 a00, real64 a01, real64 a02,
|
||||
real64 a10, real64 a11, real64 a12,
|
||||
real64 a20, real64 a21, real64 a22,
|
||||
real64 a30, real64 a31, real64 a32);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 4x4 matrix. Handy for GPU APIs.
|
||||
|
||||
class dng_matrix_4by4: public dng_matrix
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_matrix_4by4 ();
|
||||
|
||||
dng_matrix_4by4 (const dng_matrix &m);
|
||||
|
||||
dng_matrix_4by4 (real64 a00, real64 a01, real64 a02, real64 a03,
|
||||
real64 a10, real64 a11, real64 a12, real64 a13,
|
||||
real64 a20, real64 a21, real64 a22, real64 a23,
|
||||
real64 a30, real64 a31, real64 a32, real64 a33);
|
||||
|
||||
dng_matrix_4by4 (real64 a00, real64 a11, real64 a22, real64 a33);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to represent 1-dimensional vector with up to kMaxColorPlanes
|
||||
/// components.
|
||||
|
||||
class dng_vector
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
uint32 fCount;
|
||||
|
||||
real64 fData [kMaxColorPlanes];
|
||||
|
||||
public:
|
||||
|
||||
dng_vector ();
|
||||
|
||||
dng_vector (uint32 count);
|
||||
|
||||
dng_vector (const dng_vector &v);
|
||||
|
||||
virtual ~dng_vector ()
|
||||
{
|
||||
}
|
||||
|
||||
void Clear ();
|
||||
|
||||
void SetIdentity (uint32 count);
|
||||
|
||||
uint32 Count () const
|
||||
{
|
||||
return fCount;
|
||||
}
|
||||
|
||||
real64 & operator [] (uint32 index)
|
||||
{
|
||||
return fData [index];
|
||||
}
|
||||
|
||||
const real64 & operator [] (uint32 index) const
|
||||
{
|
||||
return fData [index];
|
||||
}
|
||||
|
||||
bool operator== (const dng_vector &v) const;
|
||||
|
||||
bool operator!= (const dng_vector &v) const
|
||||
{
|
||||
return !(*this == v);
|
||||
}
|
||||
|
||||
bool IsEmpty () const
|
||||
{
|
||||
return fCount == 0;
|
||||
}
|
||||
|
||||
bool NotEmpty () const
|
||||
{
|
||||
return !IsEmpty ();
|
||||
}
|
||||
|
||||
real64 MaxEntry () const;
|
||||
|
||||
real64 MinEntry () const;
|
||||
|
||||
void Scale (real64 factor);
|
||||
|
||||
void Round (real64 factor);
|
||||
|
||||
dng_matrix AsDiagonal () const;
|
||||
|
||||
dng_matrix AsColumn () const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 3-element vector.
|
||||
|
||||
class dng_vector_3: public dng_vector
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_vector_3 ();
|
||||
|
||||
dng_vector_3 (const dng_vector &v);
|
||||
|
||||
dng_vector_3 (real64 a0,
|
||||
real64 a1,
|
||||
real64 a2);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A 4-element vector.
|
||||
|
||||
class dng_vector_4: public dng_vector
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_vector_4 ();
|
||||
|
||||
dng_vector_4 (const dng_vector &v);
|
||||
|
||||
dng_vector_4 (real64 a0,
|
||||
real64 a1,
|
||||
real64 a2,
|
||||
real64 a3);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_matrix operator* (const dng_matrix &A,
|
||||
const dng_matrix &B);
|
||||
|
||||
dng_vector operator* (const dng_matrix &A,
|
||||
const dng_vector &B);
|
||||
|
||||
dng_matrix operator* (real64 scale,
|
||||
const dng_matrix &A);
|
||||
|
||||
dng_vector operator* (real64 scale,
|
||||
const dng_vector &A);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_matrix operator+ (const dng_matrix &A,
|
||||
const dng_matrix &B);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_vector operator- (const dng_vector &a,
|
||||
const dng_vector &b);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_matrix Transpose (const dng_matrix &A);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_matrix Invert (const dng_matrix &A);
|
||||
|
||||
dng_matrix Invert (const dng_matrix &A,
|
||||
const dng_matrix &hint);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline real64 MaxEntry (const dng_matrix &A)
|
||||
{
|
||||
return A.MaxEntry ();
|
||||
}
|
||||
|
||||
inline real64 MaxEntry (const dng_vector &A)
|
||||
{
|
||||
return A.MaxEntry ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline real64 MinEntry (const dng_matrix &A)
|
||||
{
|
||||
return A.MinEntry ();
|
||||
}
|
||||
|
||||
inline real64 MinEntry (const dng_vector &A)
|
||||
{
|
||||
return A.MinEntry ();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 Dot (const dng_vector &a,
|
||||
const dng_vector &b);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
real64 Distance (const dng_vector &a,
|
||||
const dng_vector &b);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,284 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_memory.h"
|
||||
|
||||
#include "dng_bottlenecks.h"
|
||||
#include "dng_exceptions.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_data::dng_memory_data ()
|
||||
|
||||
: fBuffer (NULL)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_data::dng_memory_data (uint32 size)
|
||||
|
||||
: fBuffer (NULL)
|
||||
|
||||
{
|
||||
|
||||
Allocate (size);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_data::dng_memory_data (const dng_safe_uint32 &size)
|
||||
|
||||
: fBuffer (NULL)
|
||||
|
||||
{
|
||||
|
||||
Allocate (size.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_data::dng_memory_data (uint32 count,
|
||||
std::size_t elementSize)
|
||||
|
||||
: fBuffer (NULL)
|
||||
|
||||
{
|
||||
|
||||
Allocate (count, elementSize);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_data::~dng_memory_data ()
|
||||
{
|
||||
|
||||
Clear ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_data::Allocate (uint32 size)
|
||||
{
|
||||
|
||||
Clear ();
|
||||
|
||||
if (size)
|
||||
{
|
||||
//printf("Calling malloc from %s\n", __FUNCTION__);
|
||||
fBuffer = (char *) malloc (size);
|
||||
|
||||
if (!fBuffer)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_data::Allocate (const dng_safe_uint32 &size)
|
||||
{
|
||||
|
||||
Allocate (size.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_data::Allocate (uint32 count,
|
||||
std::size_t elementSize)
|
||||
{
|
||||
|
||||
// Convert elementSize to a uint32.
|
||||
|
||||
const uint32 elementSizeAsUint32 = static_cast<uint32> (elementSize);
|
||||
|
||||
if (static_cast<std::size_t> (elementSizeAsUint32) != elementSize)
|
||||
{
|
||||
ThrowOverflow ("elementSize overflow");
|
||||
}
|
||||
|
||||
// Compute required number of bytes and allocate memory.
|
||||
|
||||
dng_safe_uint32 numBytes = dng_safe_uint32 (count) * elementSizeAsUint32;
|
||||
|
||||
Allocate (numBytes.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_data::Allocate (const dng_safe_uint32 &count,
|
||||
std::size_t elementSize)
|
||||
{
|
||||
|
||||
Allocate (count.Get (), elementSize);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_data::Clear ()
|
||||
{
|
||||
|
||||
if (fBuffer)
|
||||
{
|
||||
|
||||
free (fBuffer);
|
||||
|
||||
fBuffer = NULL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_block * dng_memory_block::Clone (dng_memory_allocator &allocator) const
|
||||
{
|
||||
|
||||
uint32 size = LogicalSize ();
|
||||
|
||||
dng_memory_block * result = allocator.Allocate (size);
|
||||
|
||||
DoCopyBytes (Buffer (), result->Buffer (), size);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_malloc_block::dng_malloc_block (uint32 logicalSize)
|
||||
|
||||
: dng_memory_block (logicalSize)
|
||||
|
||||
, fMalloc (NULL)
|
||||
|
||||
{
|
||||
|
||||
#if qLinux
|
||||
|
||||
// TO DO: Need to change this alignment for AVX support?
|
||||
|
||||
int err = ::posix_memalign ((void **) &fMalloc,
|
||||
16,
|
||||
(size_t) PhysicalSize ());
|
||||
|
||||
if (err)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
#elif qAndroid
|
||||
|
||||
fMalloc = memalign (16, (size_t) PhysicalSize ());
|
||||
|
||||
if (!fMalloc)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//fMalloc = (char *) VirtualAlloc (NULL, PhysicalSize (), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
//printf("Calling malloc from %s\n", __FUNCTION__);
|
||||
fMalloc = (char *)malloc(PhysicalSize());
|
||||
|
||||
if (!fMalloc)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
//*(size_t*)(fMalloc) = size_t(PhysicalSize() + 16);
|
||||
//fMalloc = (char*)fMalloc+16;
|
||||
|
||||
#endif
|
||||
|
||||
SetBuffer (fMalloc);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_malloc_block::~dng_malloc_block ()
|
||||
{
|
||||
|
||||
if (fMalloc)
|
||||
{
|
||||
|
||||
//size_t size = *(size_t*)((char*)fMalloc - 16);
|
||||
//VirtualFree(fMalloc, 0, MEM_RELEASE);
|
||||
free (fMalloc);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_block * dng_memory_allocator::Allocate (uint32 size)
|
||||
{
|
||||
|
||||
dng_memory_block *result = new dng_malloc_block (size);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void * dng_memory_allocator::Malloc (size_t size)
|
||||
{
|
||||
|
||||
return malloc (size);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_allocator::Free (void *ptr)
|
||||
{
|
||||
|
||||
free (ptr);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_allocator gDefaultDNGMemoryAllocator;
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,652 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Support for memory allocation.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_memory__
|
||||
#define __dng_memory__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_flags.h"
|
||||
#include "dng_safe_arithmetic.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGAVXSupport
|
||||
#define DNG_ALIGN_SIMD(x) ((((uintptr) (x)) + 31) & ~((uintptr) 31))
|
||||
#else
|
||||
#define DNG_ALIGN_SIMD(x) ((((uintptr) (x)) + 15) & ~((uintptr) 15))
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to provide resource acquisition is instantiation discipline
|
||||
/// for small memory allocations.
|
||||
///
|
||||
/// This class does not use dng_memory_allocator for memory allocation.
|
||||
|
||||
class dng_memory_data: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
char *fBuffer;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct an empty memory buffer using malloc.
|
||||
/// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
|
||||
|
||||
dng_memory_data ();
|
||||
|
||||
/// Construct memory buffer of size bytes using malloc.
|
||||
/// \param size Number of bytes of memory needed.
|
||||
/// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
|
||||
|
||||
dng_memory_data (uint32 size);
|
||||
|
||||
dng_memory_data (const dng_safe_uint32 &size);
|
||||
|
||||
/// Note: This constructor is for internal use only and should not be
|
||||
/// considered part of the DNG SDK API.
|
||||
///
|
||||
/// Construct memory buffer of count elements of elementSize bytes each.
|
||||
/// \param count Number of elements.
|
||||
/// \param elementSize Size of each element.
|
||||
/// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
|
||||
|
||||
dng_memory_data (uint32 count,
|
||||
std::size_t elementSize);
|
||||
|
||||
/// Release memory buffer using free.
|
||||
|
||||
~dng_memory_data ();
|
||||
|
||||
/// Clear existing memory buffer and allocate new memory of size bytes.
|
||||
/// \param size Number of bytes of memory needed.
|
||||
/// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
|
||||
|
||||
void Allocate (uint32 size);
|
||||
|
||||
void Allocate (const dng_safe_uint32 &size);
|
||||
|
||||
/// Note: This method is for internal use only and should not be
|
||||
/// considered part of the DNG SDK API.
|
||||
///
|
||||
/// Clear existing memory buffer and allocate new memory of count
|
||||
/// elements of elementSize bytes each.
|
||||
/// \param count Number of elements.
|
||||
/// \param elementSize Size of each element.
|
||||
/// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
|
||||
|
||||
void Allocate (uint32 count,
|
||||
std::size_t elementSize);
|
||||
|
||||
void Allocate (const dng_safe_uint32 &count,
|
||||
std::size_t elementSize);
|
||||
|
||||
/// Release any allocated memory using free. Object is still valid and
|
||||
/// Allocate can be called again.
|
||||
|
||||
void Clear ();
|
||||
|
||||
/// Return pointer to allocated memory as a void *..
|
||||
/// \retval void * valid for as many bytes as were allocated.
|
||||
|
||||
void * Buffer ()
|
||||
{
|
||||
return fBuffer;
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const void *.
|
||||
/// \retval const void * valid for as many bytes as were allocated.
|
||||
|
||||
const void * Buffer () const
|
||||
{
|
||||
return fBuffer;
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a char *.
|
||||
/// \retval char * valid for as many bytes as were allocated.
|
||||
|
||||
char * Buffer_char ()
|
||||
{
|
||||
return (char *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const char *.
|
||||
/// \retval const char * valid for as many bytes as were allocated.
|
||||
|
||||
const char * Buffer_char () const
|
||||
{
|
||||
return (const char *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint8 *.
|
||||
/// \retval uint8 * valid for as many bytes as were allocated.
|
||||
|
||||
uint8 * Buffer_uint8 ()
|
||||
{
|
||||
return (uint8 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const uint8 *.
|
||||
/// \retval const uint8 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint8 * Buffer_uint8 () const
|
||||
{
|
||||
return (const uint8 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint16 *.
|
||||
/// \retval uint16 * valid for as many bytes as were allocated.
|
||||
|
||||
uint16 * Buffer_uint16 ()
|
||||
{
|
||||
return (uint16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const uint16 *.
|
||||
/// \retval const uint16 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint16 * Buffer_uint16 () const
|
||||
{
|
||||
return (const uint16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a int16 *.
|
||||
/// \retval int16 * valid for as many bytes as were allocated.
|
||||
|
||||
int16 * Buffer_int16 ()
|
||||
{
|
||||
return (int16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int16 *.
|
||||
/// \retval const int16 * valid for as many bytes as were allocated.
|
||||
|
||||
const int16 * Buffer_int16 () const
|
||||
{
|
||||
return (const int16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint32 *.
|
||||
/// \retval uint32 * valid for as many bytes as were allocated.
|
||||
|
||||
uint32 * Buffer_uint32 ()
|
||||
{
|
||||
return (uint32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint32 *.
|
||||
/// \retval uint32 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint32 * Buffer_uint32 () const
|
||||
{
|
||||
return (const uint32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int32 *.
|
||||
/// \retval const int32 * valid for as many bytes as were allocated.
|
||||
|
||||
int32 * Buffer_int32 ()
|
||||
{
|
||||
return (int32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int32 *.
|
||||
/// \retval const int32 * valid for as many bytes as were allocated.
|
||||
|
||||
const int32 * Buffer_int32 () const
|
||||
{
|
||||
return (const int32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint64 *.
|
||||
/// \retval uint64 * valid for as many bytes as were allocated.
|
||||
|
||||
uint64 * Buffer_uint64 ()
|
||||
{
|
||||
return (uint64 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint64 *.
|
||||
/// \retval uint64 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint64 * Buffer_uint64 () const
|
||||
{
|
||||
return (const uint64 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int64 *.
|
||||
/// \retval const int64 * valid for as many bytes as were allocated.
|
||||
|
||||
int64 * Buffer_int64 ()
|
||||
{
|
||||
return (int64 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int64 *.
|
||||
/// \retval const int64 * valid for as many bytes as were allocated.
|
||||
|
||||
const int64 * Buffer_int64 () const
|
||||
{
|
||||
return (const int64 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a real32 *.
|
||||
/// \retval real32 * valid for as many bytes as were allocated.
|
||||
|
||||
real32 * Buffer_real32 ()
|
||||
{
|
||||
return (real32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const real32 *.
|
||||
/// \retval const real32 * valid for as many bytes as were allocated.
|
||||
|
||||
const real32 * Buffer_real32 () const
|
||||
{
|
||||
return (const real32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a real64 *.
|
||||
/// \retval real64 * valid for as many bytes as were allocated.
|
||||
|
||||
real64 * Buffer_real64 ()
|
||||
{
|
||||
return (real64 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const real64 *.
|
||||
/// \retval const real64 * valid for as many bytes as were allocated.
|
||||
|
||||
const real64 * Buffer_real64 () const
|
||||
{
|
||||
return (const real64 *) Buffer ();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to provide resource acquisition is instantiation discipline for
|
||||
/// image buffers and other larger memory allocations.
|
||||
///
|
||||
/// This class requires a dng_memory_allocator for allocation.
|
||||
|
||||
class dng_memory_block: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
uint32 fLogicalSize;
|
||||
|
||||
char *fBuffer;
|
||||
|
||||
protected:
|
||||
|
||||
dng_memory_block (uint32 logicalSize)
|
||||
: fLogicalSize (logicalSize)
|
||||
, fBuffer (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
uint32 PhysicalSize ()
|
||||
{
|
||||
|
||||
// This size is padded for TWO reasons! The first is allow
|
||||
// alignment to 16-byte boundaries if the allocator does not do
|
||||
// that already. The second, which is very important, so to
|
||||
// provide safe overread areas for SSE2-type bottlenecks, which
|
||||
// can often be written faster by allowing them to reading
|
||||
// slightly block. Someone on the image core them did not
|
||||
// understand this and removed this padding. I'm undoing this
|
||||
// removal and restoring this padding, since removing it might
|
||||
// lead to memory access crashes in some cases.
|
||||
//
|
||||
// Please do NOT change the following padding unless you are very
|
||||
// sure what you are doing.
|
||||
|
||||
dng_safe_uint32 safeLogicalSize (fLogicalSize);
|
||||
|
||||
#if qDNGAVXSupport
|
||||
|
||||
// Allow 32-byte alignment + 64-byte overread in both directions:
|
||||
// 32 + 64 + 64 = 160.
|
||||
|
||||
return (safeLogicalSize + 160u).Get ();
|
||||
|
||||
#else
|
||||
|
||||
// Allow 16-byte alignment + overread.
|
||||
|
||||
return (safeLogicalSize + 64u).Get ();
|
||||
|
||||
#endif // qDNGAVXSupport
|
||||
|
||||
}
|
||||
|
||||
void SetBuffer (void *p)
|
||||
{
|
||||
fBuffer = (char *) DNG_ALIGN_SIMD (p);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_memory_block ()
|
||||
{
|
||||
}
|
||||
|
||||
dng_memory_block * Clone (dng_memory_allocator &allocator) const;
|
||||
|
||||
/// Getter for available size, in bytes, of memory block.
|
||||
/// \retval size in bytes of available memory in memory block.
|
||||
|
||||
uint32 LogicalSize () const
|
||||
{
|
||||
return fLogicalSize;
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a void *..
|
||||
/// \retval void * valid for as many bytes as were allocated.
|
||||
|
||||
void * Buffer ()
|
||||
{
|
||||
return fBuffer;
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const void *.
|
||||
/// \retval const void * valid for as many bytes as were allocated.
|
||||
|
||||
const void * Buffer () const
|
||||
{
|
||||
return fBuffer;
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a char *.
|
||||
/// \retval char * valid for as many bytes as were allocated.
|
||||
|
||||
char * Buffer_char ()
|
||||
{
|
||||
return (char *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const char *.
|
||||
/// \retval const char * valid for as many bytes as were allocated.
|
||||
|
||||
const char * Buffer_char () const
|
||||
{
|
||||
return (const char *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint8 *.
|
||||
/// \retval uint8 * valid for as many bytes as were allocated.
|
||||
|
||||
uint8 * Buffer_uint8 ()
|
||||
{
|
||||
return (uint8 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const uint8 *.
|
||||
/// \retval const uint8 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint8 * Buffer_uint8 () const
|
||||
{
|
||||
return (const uint8 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint16 *.
|
||||
/// \retval uint16 * valid for as many bytes as were allocated.
|
||||
|
||||
uint16 * Buffer_uint16 ()
|
||||
{
|
||||
return (uint16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const uint16 *.
|
||||
/// \retval const uint16 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint16 * Buffer_uint16 () const
|
||||
{
|
||||
return (const uint16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a int16 *.
|
||||
/// \retval int16 * valid for as many bytes as were allocated.
|
||||
|
||||
int16 * Buffer_int16 ()
|
||||
{
|
||||
return (int16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int16 *.
|
||||
/// \retval const int16 * valid for as many bytes as were allocated.
|
||||
|
||||
const int16 * Buffer_int16 () const
|
||||
{
|
||||
return (const int16 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a uint32 *.
|
||||
/// \retval uint32 * valid for as many bytes as were allocated.
|
||||
|
||||
uint32 * Buffer_uint32 ()
|
||||
{
|
||||
return (uint32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const uint32 *.
|
||||
/// \retval const uint32 * valid for as many bytes as were allocated.
|
||||
|
||||
const uint32 * Buffer_uint32 () const
|
||||
{
|
||||
return (const uint32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a int32 *.
|
||||
/// \retval int32 * valid for as many bytes as were allocated.
|
||||
|
||||
int32 * Buffer_int32 ()
|
||||
{
|
||||
return (int32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const int32 *.
|
||||
/// \retval const int32 * valid for as many bytes as were allocated.
|
||||
|
||||
const int32 * Buffer_int32 () const
|
||||
{
|
||||
return (const int32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a real32 *.
|
||||
/// \retval real32 * valid for as many bytes as were allocated.
|
||||
|
||||
real32 * Buffer_real32 ()
|
||||
{
|
||||
return (real32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const real32 *.
|
||||
/// \retval const real32 * valid for as many bytes as were allocated.
|
||||
|
||||
const real32 * Buffer_real32 () const
|
||||
{
|
||||
return (const real32 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a real64 *.
|
||||
/// \retval real64 * valid for as many bytes as were allocated.
|
||||
|
||||
real64 * Buffer_real64 ()
|
||||
{
|
||||
return (real64 *) Buffer ();
|
||||
}
|
||||
|
||||
/// Return pointer to allocated memory as a const real64 *.
|
||||
/// \retval const real64 * valid for as many bytes as were allocated.
|
||||
|
||||
const real64 * Buffer_real64 () const
|
||||
{
|
||||
return (const real64 *) Buffer ();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Interface for dng_memory_block allocator.
|
||||
|
||||
class dng_memory_allocator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_memory_allocator ()
|
||||
{
|
||||
}
|
||||
|
||||
/// Allocate a dng_memory block.
|
||||
/// \param size Number of bytes in memory block.
|
||||
/// \retval A dng_memory_block with at least size bytes of valid storage.
|
||||
/// \exception dng_exception with fErrorCode equal to dng_error_memory.
|
||||
|
||||
virtual dng_memory_block * Allocate (uint32 size);
|
||||
|
||||
/// Directly allocate a block of at least 'size' bytes.
|
||||
/// \param size Number of bytes in memory block.
|
||||
/// \retval A pointer to a contiguous block of memory with at least
|
||||
/// size bytes of valid storage.
|
||||
/// Caller is responsible for freeing the memory with Free.
|
||||
/// Default implementation uses standard library 'malloc' routine.
|
||||
|
||||
virtual void * Malloc (size_t size);
|
||||
|
||||
/// Free the specified block of memory previously allocated with Malloc.
|
||||
/// Default implementation uses standard library 'free' routine.
|
||||
|
||||
virtual void Free (void *ptr);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_malloc_block : public dng_memory_block
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
void *fMalloc;
|
||||
|
||||
public:
|
||||
|
||||
dng_malloc_block (uint32 logicalSize);
|
||||
|
||||
virtual ~dng_malloc_block ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Default memory allocator used if NULL is passed in for allocator
|
||||
/// when constructing a dng_host.
|
||||
///
|
||||
/// Uses new and delete for memory block object and malloc/free for underlying
|
||||
/// buffer.
|
||||
|
||||
extern dng_memory_allocator gDefaultDNGMemoryAllocator;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief C++ allocator (i.e. an implementation of the Allocator concept)
|
||||
/// that throws a dng_exception with error code dng_error_memory if it cannot
|
||||
/// allocate memory.
|
||||
|
||||
template <typename T>
|
||||
class dng_std_allocator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
|
||||
// Default implementations of default constructor and copy
|
||||
// constructor.
|
||||
|
||||
dng_std_allocator () = default;
|
||||
|
||||
// dng_std_allocator (const dng_std_allocator &) = default;
|
||||
|
||||
template<class U> dng_std_allocator (const dng_std_allocator<U> &) {}
|
||||
|
||||
#endif
|
||||
|
||||
T * allocate (size_t n)
|
||||
{
|
||||
const size_t size = SafeSizetMult (n, sizeof (T));
|
||||
T *retval = static_cast<T *> (malloc (size));
|
||||
if (!retval)
|
||||
{
|
||||
ThrowMemoryFull ();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void deallocate (T *ptr,
|
||||
size_t /* n */)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
bool operator== (const dng_std_allocator<T> & /* a1 */,
|
||||
const dng_std_allocator<T> & /* a2 */)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!= (const dng_std_allocator<T> & /* a1 */,
|
||||
const dng_std_allocator<T> & /* a2 */)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// std::vector specialized to use dng_std_allocator for allocation.
|
||||
|
||||
#if 0
|
||||
// original implementation without using custom allocator
|
||||
#define dng_std_vector std::vector
|
||||
#else
|
||||
// preferred implementation using custom allocator, requires C++11
|
||||
template <class T> using dng_std_vector = std::vector<T, dng_std_allocator<T> >;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,282 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_memory_stream.h"
|
||||
|
||||
#include "dng_bottlenecks.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_safe_arithmetic.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_stream::dng_memory_stream (dng_memory_allocator &allocator,
|
||||
dng_abort_sniffer *sniffer,
|
||||
uint32 pageSize)
|
||||
|
||||
: dng_stream (sniffer,
|
||||
kDefaultBufferSize,
|
||||
kDNGStreamInvalidOffset)
|
||||
|
||||
, fAllocator (allocator)
|
||||
, fPageSize (pageSize )
|
||||
|
||||
, fPageCount (0)
|
||||
, fPagesAllocated (0)
|
||||
, fPageList (NULL)
|
||||
|
||||
, fMemoryStreamLength (0)
|
||||
|
||||
, fLengthLimit (0)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_stream::~dng_memory_stream ()
|
||||
{
|
||||
|
||||
if (fPageList)
|
||||
{
|
||||
|
||||
for (uint32 index = 0; index < fPageCount; index++)
|
||||
{
|
||||
|
||||
delete fPageList [index];
|
||||
|
||||
}
|
||||
|
||||
free (fPageList);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint64 dng_memory_stream::DoGetLength ()
|
||||
{
|
||||
|
||||
return fMemoryStreamLength;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_stream::DoRead (void *data,
|
||||
uint32 count,
|
||||
uint64 offset)
|
||||
{
|
||||
|
||||
if (offset + count > fMemoryStreamLength)
|
||||
{
|
||||
|
||||
ThrowEndOfFile ();
|
||||
|
||||
}
|
||||
|
||||
uint64 baseOffset = offset;
|
||||
|
||||
while (count)
|
||||
{
|
||||
|
||||
uint32 pageIndex = (uint32) (offset / fPageSize);
|
||||
uint32 pageOffset = (uint32) (offset % fPageSize);
|
||||
|
||||
uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count);
|
||||
|
||||
const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () +
|
||||
pageOffset;
|
||||
|
||||
uint8 *dPtr = ((uint8 *) data) + (uint32) (offset - baseOffset);
|
||||
|
||||
DoCopyBytes (sPtr, dPtr, blockCount);
|
||||
|
||||
offset += blockCount;
|
||||
count -= blockCount;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_stream::DoSetLength (uint64 length)
|
||||
{
|
||||
|
||||
if (fLengthLimit && length > fLengthLimit)
|
||||
{
|
||||
|
||||
Throw_dng_error (dng_error_end_of_file,
|
||||
"dng_memory_stream::fLengthLimit",
|
||||
NULL,
|
||||
true);
|
||||
|
||||
}
|
||||
|
||||
while (length > fPageCount * (uint64) fPageSize)
|
||||
{
|
||||
|
||||
if (fPageCount == fPagesAllocated)
|
||||
{
|
||||
|
||||
uint32 newSizeTemp1 = 0;
|
||||
uint32 newSizeTemp2 = 0;
|
||||
|
||||
if (!SafeUint32Add (fPagesAllocated, 32u, &newSizeTemp1) ||
|
||||
!SafeUint32Mult (fPagesAllocated, 2u, &newSizeTemp2))
|
||||
{
|
||||
ThrowOverflow ("Arithmetic overflow in DoSetLength");
|
||||
}
|
||||
|
||||
uint32 newSize = Max_uint32 (newSizeTemp1,
|
||||
newSizeTemp2);
|
||||
|
||||
uint32 numBytes;
|
||||
|
||||
if (!SafeUint32Mult (newSize,
|
||||
sizeof (dng_memory_block *),
|
||||
&numBytes))
|
||||
{
|
||||
ThrowOverflow ("Arithmetic overflow in DoSetLength");
|
||||
}
|
||||
|
||||
dng_memory_block **list = (dng_memory_block **) malloc (numBytes);
|
||||
|
||||
if (!list)
|
||||
{
|
||||
|
||||
ThrowMemoryFull ();
|
||||
|
||||
}
|
||||
|
||||
if (fPageCount)
|
||||
{
|
||||
|
||||
// The multiplication here is safe against overflow.
|
||||
// fPageCount can never reach a value that is large enough to
|
||||
// cause overflow because the computation of numBytes above
|
||||
// would fail before a list of that size could be allocated.
|
||||
|
||||
DoCopyBytes (fPageList,
|
||||
list,
|
||||
fPageCount * (uint32) sizeof (dng_memory_block *));
|
||||
|
||||
}
|
||||
|
||||
if (fPageList)
|
||||
{
|
||||
|
||||
free (fPageList);
|
||||
|
||||
}
|
||||
|
||||
fPageList = list;
|
||||
|
||||
fPagesAllocated = newSize;
|
||||
|
||||
}
|
||||
|
||||
fPageList [fPageCount] = fAllocator.Allocate (fPageSize);
|
||||
|
||||
fPageCount++;
|
||||
|
||||
}
|
||||
|
||||
fMemoryStreamLength = length;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_stream::DoWrite (const void *data,
|
||||
uint32 count,
|
||||
uint64 offset)
|
||||
{
|
||||
|
||||
DoSetLength (Max_uint64 (fMemoryStreamLength,
|
||||
offset + count));
|
||||
|
||||
uint64 baseOffset = offset;
|
||||
|
||||
while (count)
|
||||
{
|
||||
|
||||
uint32 pageIndex = (uint32) (offset / fPageSize);
|
||||
uint32 pageOffset = (uint32) (offset % fPageSize);
|
||||
|
||||
uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count);
|
||||
|
||||
const uint8 *sPtr = ((const uint8 *) data) + (uint32) (offset - baseOffset);
|
||||
|
||||
uint8 *dPtr = fPageList [pageIndex]->Buffer_uint8 () +
|
||||
pageOffset;
|
||||
|
||||
DoCopyBytes (sPtr, dPtr, blockCount);
|
||||
|
||||
offset += blockCount;
|
||||
count -= blockCount;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_memory_stream::CopyToStream (dng_stream &dstStream,
|
||||
uint64 count)
|
||||
{
|
||||
|
||||
if (count < kBigBufferSize)
|
||||
{
|
||||
|
||||
dng_stream::CopyToStream (dstStream, count);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
Flush ();
|
||||
|
||||
uint64 offset = Position ();
|
||||
|
||||
if (offset + count > Length ())
|
||||
{
|
||||
|
||||
ThrowEndOfFile ();
|
||||
|
||||
}
|
||||
|
||||
while (count)
|
||||
{
|
||||
|
||||
uint32 pageIndex = (uint32) (offset / fPageSize);
|
||||
uint32 pageOffset = (uint32) (offset % fPageSize);
|
||||
|
||||
uint32 blockCount = (uint32) Min_uint64 (fPageSize - pageOffset, count);
|
||||
|
||||
const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () +
|
||||
pageOffset;
|
||||
|
||||
dstStream.Put (sPtr, blockCount);
|
||||
|
||||
offset += blockCount;
|
||||
count -= blockCount;
|
||||
|
||||
}
|
||||
|
||||
SetReadPosition (offset);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,93 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Stream abstraction to/from in-memory data.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_memory_stream__
|
||||
#define __dng_memory_stream__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_stream.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A dng_stream which can be read from or written to memory.
|
||||
///
|
||||
/// Stream is populated via writing and either read or accessed by asking for contents as a pointer.
|
||||
|
||||
class dng_memory_stream: public dng_stream
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_memory_allocator &fAllocator;
|
||||
|
||||
uint32 fPageSize;
|
||||
|
||||
uint32 fPageCount;
|
||||
uint32 fPagesAllocated;
|
||||
|
||||
dng_memory_block **fPageList;
|
||||
|
||||
uint64 fMemoryStreamLength;
|
||||
|
||||
uint64 fLengthLimit;
|
||||
|
||||
public:
|
||||
|
||||
/// Construct a new memory-based stream.
|
||||
/// \param allocator Allocator to use to allocate memory in stream as needed.
|
||||
/// \param sniffer If non-NULL used to check for user cancellation.
|
||||
/// \param pageSize Unit of allocation for data stored in stream.
|
||||
|
||||
dng_memory_stream (dng_memory_allocator &allocator,
|
||||
dng_abort_sniffer *sniffer = NULL,
|
||||
uint32 pageSize = 64 * 1024);
|
||||
|
||||
virtual ~dng_memory_stream ();
|
||||
|
||||
/// Sets a maximum length limit.
|
||||
|
||||
void SetLengthLimit (uint64 limit)
|
||||
{
|
||||
fLengthLimit = limit;
|
||||
}
|
||||
|
||||
/// Copy a specified number of bytes to a target stream.
|
||||
/// \param dstStream The target stream.
|
||||
/// \param count The number of bytes to copy.
|
||||
|
||||
virtual void CopyToStream (dng_stream &dstStream,
|
||||
uint64 count);
|
||||
|
||||
protected:
|
||||
|
||||
virtual uint64 DoGetLength ();
|
||||
|
||||
virtual void DoRead (void *data,
|
||||
uint32 count,
|
||||
uint64 offset);
|
||||
|
||||
virtual void DoSetLength (uint64 length);
|
||||
|
||||
virtual void DoWrite (const void *data,
|
||||
uint32 count,
|
||||
uint64 offset);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,445 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Miscellaneous DNG opcodes.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_misc_opcodes__
|
||||
#define __dng_misc_opcodes__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
|
||||
#include "dng_opcodes.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Opcode to trim image to a specified rectangle.
|
||||
|
||||
class dng_opcode_TrimBounds: public dng_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_rect fBounds;
|
||||
|
||||
public:
|
||||
|
||||
/// Create opcode to trim image to the specified bounds.
|
||||
|
||||
dng_opcode_TrimBounds (const dng_rect &bounds);
|
||||
|
||||
dng_opcode_TrimBounds (dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief A class to describe an area of an image, including a pixel subrectangle,
|
||||
/// plane range, and row/column pitch (e.g., for mosaic images). Useful for
|
||||
/// specifying opcodes that only apply to specific color planes or pixel types (e.g.,
|
||||
/// only one of the two green Bayer pixels).
|
||||
|
||||
class dng_area_spec
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDataSize = 32
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
dng_rect fArea;
|
||||
|
||||
uint32 fPlane;
|
||||
uint32 fPlanes;
|
||||
|
||||
uint32 fRowPitch;
|
||||
uint32 fColPitch;
|
||||
|
||||
public:
|
||||
|
||||
/// Create an empty area.
|
||||
|
||||
dng_area_spec (const dng_rect &area = dng_rect (),
|
||||
uint32 plane = 0,
|
||||
uint32 planes = 1,
|
||||
uint32 rowPitch = 1,
|
||||
uint32 colPitch = 1)
|
||||
|
||||
: fArea (area)
|
||||
, fPlane (plane)
|
||||
, fPlanes (planes)
|
||||
, fRowPitch (rowPitch)
|
||||
, fColPitch (colPitch)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
/// The pixel area.
|
||||
|
||||
const dng_rect & Area () const
|
||||
{
|
||||
return fArea;
|
||||
}
|
||||
|
||||
/// The first plane.
|
||||
|
||||
uint32 Plane () const
|
||||
{
|
||||
return fPlane;
|
||||
}
|
||||
|
||||
/// The total number of planes.
|
||||
|
||||
uint32 Planes () const
|
||||
{
|
||||
return fPlanes;
|
||||
}
|
||||
|
||||
/// The row pitch (i.e., stride). A pitch of 1 means all rows.
|
||||
|
||||
uint32 RowPitch () const
|
||||
{
|
||||
return fRowPitch;
|
||||
}
|
||||
|
||||
/// The column pitch (i.e., stride). A pitch of 1 means all columns.
|
||||
|
||||
uint32 ColPitch () const
|
||||
{
|
||||
return fColPitch;
|
||||
}
|
||||
|
||||
/// Read area data from the specified stream.
|
||||
|
||||
void GetData (dng_stream &stream);
|
||||
|
||||
/// Write area data to the specified stream.
|
||||
|
||||
void PutData (dng_stream &stream) const;
|
||||
|
||||
/// Compute and return pixel area overlap (i.e., intersection) between this
|
||||
/// area and the specified tile.
|
||||
|
||||
dng_rect Overlap (const dng_rect &tile) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to apply a 1D function (represented as a 16-bit table) to an
|
||||
/// image area.
|
||||
|
||||
class dng_opcode_MapTable: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
AutoPtr<dng_memory_block> fTable;
|
||||
|
||||
uint32 fCount;
|
||||
|
||||
AutoPtr<dng_memory_block> fBlackAdjustedTable;
|
||||
|
||||
public:
|
||||
|
||||
/// Create a MapTable opcode with the specified area, table, and number of
|
||||
/// table entries.
|
||||
|
||||
dng_opcode_MapTable (dng_host &host,
|
||||
const dng_area_spec &areaSpec,
|
||||
const uint16 *table,
|
||||
uint32 count = 0x10000);
|
||||
|
||||
dng_opcode_MapTable (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType);
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
|
||||
|
||||
virtual void Prepare (dng_negative &negative,
|
||||
uint32 threadCount,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes,
|
||||
uint32 bufferPixelType,
|
||||
dng_memory_allocator &allocator);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
private:
|
||||
|
||||
void ReplicateLastEntry ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to apply a 1D function (represented as a polynomial) to an
|
||||
/// image area.
|
||||
|
||||
class dng_opcode_MapPolynomial: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxDegree = 8
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
uint32 fDegree;
|
||||
|
||||
real64 fCoefficient [kMaxDegree + 1];
|
||||
|
||||
real32 fCoefficient32 [kMaxDegree + 1];
|
||||
|
||||
public:
|
||||
|
||||
/// Create a MapPolynomial opcode with the specified area, polynomial
|
||||
/// degree, and polynomial coefficients. The function that will be
|
||||
/// applied to each pixel x is:
|
||||
///
|
||||
/// f (x) = coefficient [0] + ((x * coefficient [1]) +
|
||||
/// (x^2 * coefficient [2]) +
|
||||
/// (x^3 * coefficient [3]) +
|
||||
/// (x^4 * coefficient [4]) ...
|
||||
|
||||
dng_opcode_MapPolynomial (const dng_area_spec &areaSpec,
|
||||
uint32 degree,
|
||||
const real64 *coefficient);
|
||||
|
||||
dng_opcode_MapPolynomial (dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType);
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
uint32 Degree () const
|
||||
{
|
||||
return fDegree;
|
||||
}
|
||||
|
||||
const real64 * Coefficients () const
|
||||
{
|
||||
return fCoefficient;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void DoProcess (dng_pixel_buffer &buffer,
|
||||
const dng_rect &area,
|
||||
const uint32 plane,
|
||||
const uint32 rowPitch,
|
||||
const uint32 colPitch,
|
||||
const real32 *coefficients,
|
||||
const uint32 degree,
|
||||
uint16 blackLevel) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to apply a delta (i.e., offset) that varies per row. Within
|
||||
/// a row, the same delta value is applied to all specified pixels.
|
||||
|
||||
class dng_opcode_DeltaPerRow: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
AutoPtr<dng_memory_block> fTable;
|
||||
|
||||
real32 fScale;
|
||||
|
||||
public:
|
||||
|
||||
/// Create a DeltaPerRow opcode with the specified area and row deltas
|
||||
/// (specified as a table of 32-bit floats).
|
||||
|
||||
dng_opcode_DeltaPerRow (const dng_area_spec &areaSpec,
|
||||
AutoPtr<dng_memory_block> &table);
|
||||
|
||||
dng_opcode_DeltaPerRow (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType);
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to apply a delta (i.e., offset) that varies per column.
|
||||
/// Within a column, the same delta value is applied to all specified pixels.
|
||||
|
||||
class dng_opcode_DeltaPerColumn: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
AutoPtr<dng_memory_block> fTable;
|
||||
|
||||
real32 fScale;
|
||||
|
||||
public:
|
||||
|
||||
/// Create a DeltaPerColumn opcode with the specified area and column
|
||||
/// deltas (specified as a table of 32-bit floats).
|
||||
|
||||
dng_opcode_DeltaPerColumn (const dng_area_spec &areaSpec,
|
||||
AutoPtr<dng_memory_block> &table);
|
||||
|
||||
dng_opcode_DeltaPerColumn (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType);
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to apply a scale factor that varies per row. Within a row,
|
||||
/// the same scale factor is applied to all specified pixels.
|
||||
|
||||
class dng_opcode_ScalePerRow: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
AutoPtr<dng_memory_block> fTable;
|
||||
|
||||
public:
|
||||
|
||||
/// Create a ScalePerRow opcode with the specified area and row scale
|
||||
/// factors (specified as a table of 32-bit floats).
|
||||
|
||||
dng_opcode_ScalePerRow (const dng_area_spec &areaSpec,
|
||||
AutoPtr<dng_memory_block> &table);
|
||||
|
||||
dng_opcode_ScalePerRow (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType);
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief An opcode to apply a scale factor that varies per column. Within a
|
||||
/// column, the same scale factor is applied to all specified pixels.
|
||||
|
||||
class dng_opcode_ScalePerColumn: public dng_inplace_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_area_spec fAreaSpec;
|
||||
|
||||
AutoPtr<dng_memory_block> fTable;
|
||||
|
||||
public:
|
||||
|
||||
/// Create a ScalePerColumn opcode with the specified area and column
|
||||
/// scale factors (specified as a table of 32-bit floats).
|
||||
|
||||
dng_opcode_ScalePerColumn (const dng_area_spec &areaSpec,
|
||||
AutoPtr<dng_memory_block> &table);
|
||||
|
||||
dng_opcode_ScalePerColumn (dng_host &host,
|
||||
dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType);
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,198 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Support for descriptive information about color filter array patterns.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_mosaic_info__
|
||||
#define __dng_mosaic_info__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Support for describing color filter array patterns and manipulating mosaic sample data.
|
||||
///
|
||||
/// See CFAPattern tag in \ref spec_tiff_ep "TIFF/EP specification" and CFAPlaneColor, CFALayout, and BayerGreenSplit
|
||||
/// tags in the \ref spec_dng "DNG 1.1.0 specification".
|
||||
|
||||
class dng_mosaic_info
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// Size of fCFAPattern.
|
||||
|
||||
dng_point fCFAPatternSize;
|
||||
|
||||
/// CFA pattern from CFAPattern tag in the \ref spec_tiff_ep "TIFF/EP specification."
|
||||
|
||||
uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
|
||||
|
||||
/// Number of color planes in DNG input.
|
||||
|
||||
uint32 fColorPlanes;
|
||||
|
||||
uint8 fCFAPlaneColor [kMaxColorPlanes];
|
||||
|
||||
/// Value of CFALayout tag in the \ref spec_dng "DNG 1.3 specification."
|
||||
/// CFALayout describes the spatial layout of the CFA. The currently defined values are:
|
||||
/// - 1 = Rectangular (or square) layout.
|
||||
/// - 2 = Staggered layout A: even columns are offset down by 1/2 row.
|
||||
/// - 3 = Staggered layout B: even columns are offset up by 1/2 row.
|
||||
/// - 4 = Staggered layout C: even rows are offset right by 1/2 column.
|
||||
/// - 5 = Staggered layout D: even rows are offset left by 1/2 column.
|
||||
/// - 6 = Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column.
|
||||
/// - 7 = Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column.
|
||||
/// - 8 = Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column.
|
||||
/// - 9 = Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column.
|
||||
|
||||
uint32 fCFALayout;
|
||||
|
||||
/// Value of BayerGreeSplit tag in DNG file.
|
||||
/// BayerGreenSplit only applies to CFA images using a Bayer pattern filter array. This tag
|
||||
/// specifies, in arbitrary units, how closely the values of the green pixels in the blue/green rows
|
||||
/// track the values of the green pixels in the red/green rows.
|
||||
///
|
||||
/// A value of zero means the two kinds of green pixels track closely, while a non-zero value
|
||||
/// means they sometimes diverge. The useful range for this tag is from 0 (no divergence) to about
|
||||
/// 5000 (large divergence).
|
||||
|
||||
uint32 fBayerGreenSplit;
|
||||
|
||||
protected:
|
||||
|
||||
dng_point fSrcSize;
|
||||
|
||||
dng_point fCroppedSize;
|
||||
|
||||
real64 fAspectRatio;
|
||||
|
||||
public:
|
||||
|
||||
dng_mosaic_info ();
|
||||
|
||||
virtual ~dng_mosaic_info ();
|
||||
|
||||
virtual void Parse (dng_host &host,
|
||||
dng_stream &stream,
|
||||
dng_info &info);
|
||||
|
||||
virtual void PostParse (dng_host &host,
|
||||
dng_negative &negative);
|
||||
|
||||
/// Returns whether the RAW data in this DNG file from a color filter array (mosaiced) source.
|
||||
/// \retval true if this DNG file is from a color filter array (mosiaced) source.
|
||||
|
||||
bool IsColorFilterArray () const
|
||||
{
|
||||
return fCFAPatternSize != dng_point (0, 0);
|
||||
}
|
||||
|
||||
/// Enable generating four-plane output from three-plane Bayer input.
|
||||
/// Extra plane is a second version of the green channel. First green is produced
|
||||
/// using green mosaic samples from one set of rows/columns (even/odd) and the second
|
||||
/// green channel is produced using the other set of rows/columns. One can compare the
|
||||
/// two versions to judge whether BayerGreenSplit needs to be set for a given input source.
|
||||
|
||||
virtual bool SetFourColorBayer ();
|
||||
|
||||
/// Returns scaling factor relative to input size needed to capture output data.
|
||||
/// Staggered (or rotated) sensing arrays are produced to a larger output than the number of input samples.
|
||||
/// This method indicates how much larger.
|
||||
/// \retval a point with integer scaling factors for the horizotal and vertical dimensions.
|
||||
|
||||
virtual dng_point FullScale () const;
|
||||
|
||||
/// Returns integer factors by which mosaic data must be downsampled to produce an image which is as close
|
||||
/// to prefSize as possible in longer dimension, but no smaller than minSize.
|
||||
/// \param minSize Number of pixels as minium for longer dimension of downsampled image.
|
||||
/// \param prefSize Number of pixels as target for longer dimension of downsampled image.
|
||||
/// \param cropFactor Faction of the image to be used after cropping.
|
||||
/// \retval Point containing integer factors by which image must be downsampled.
|
||||
|
||||
virtual dng_point DownScale (uint32 minSize,
|
||||
uint32 prefSize,
|
||||
real64 cropFactor) const;
|
||||
|
||||
/// Return size of demosaiced image for passed in downscaling factor.
|
||||
/// \param downScale Integer downsampling factor obtained from DownScale method.
|
||||
/// \retval Size of resulting demosaiced image.
|
||||
|
||||
virtual dng_point DstSize (const dng_point &downScale) const;
|
||||
|
||||
/// Demosaic interpolation of a single plane for non-downsampled case.
|
||||
/// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
|
||||
/// \param negative DNG negative of mosaiced data.
|
||||
/// \param srcImage Source image for mosaiced data.
|
||||
/// \param dstImage Destination image for resulting interpolated data.
|
||||
/// \param srcPlane Which plane to interpolate.
|
||||
|
||||
virtual void InterpolateGeneric (dng_host &host,
|
||||
dng_negative &negative,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage,
|
||||
uint32 srcPlane = 0) const;
|
||||
|
||||
/// Demosaic interpolation of a single plane for downsampled case.
|
||||
/// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
|
||||
/// \param negative DNG negative of mosaiced data.
|
||||
/// \param srcImage Source image for mosaiced data.
|
||||
/// \param dstImage Destination image for resulting interpolated data.
|
||||
/// \param downScale Amount (in horizontal and vertical) by which to subsample image.
|
||||
/// \param srcPlane Which plane to interpolate.
|
||||
|
||||
virtual void InterpolateFast (dng_host &host,
|
||||
dng_negative &negative,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage,
|
||||
const dng_point &downScale,
|
||||
uint32 srcPlane = 0) const;
|
||||
|
||||
/// Demosaic interpolation of a single plane. Chooses between generic and fast interpolators based on parameters.
|
||||
/// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
|
||||
/// \param negative DNG negative of mosaiced data.
|
||||
/// \param srcImage Source image for mosaiced data.
|
||||
/// \param dstImage Destination image for resulting interpolated data.
|
||||
/// \param downScale Amount (in horizontal and vertical) by which to subsample image.
|
||||
/// \param srcPlane Which plane to interpolate.
|
||||
|
||||
virtual void Interpolate (dng_host &host,
|
||||
dng_negative &negative,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage,
|
||||
const dng_point &downScale,
|
||||
uint32 srcPlane = 0,
|
||||
dng_matrix *scaleTransforms = NULL) const;
|
||||
|
||||
virtual bool SupportsPreservedBlackLevels () const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool IsSafeDownScale (const dng_point &downScale) const;
|
||||
|
||||
uint32 SizeForDownScale (const dng_point &downScale) const;
|
||||
|
||||
virtual bool ValidSizeDownScale (const dng_point &downScale,
|
||||
uint32 minSize) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,516 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_abort_sniffer.h"
|
||||
#include "dng_mutex.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_exceptions.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// do mutex lock level tracking, asserts stripped in non-debug so don't track there
|
||||
#ifndef qDNGThreadTestMutexLevels
|
||||
#define qDNGThreadTestMutexLevels (qDNGThreadSafe && qDNGDebug)
|
||||
#endif
|
||||
|
||||
#if qDNGThreadTestMutexLevels
|
||||
namespace
|
||||
{
|
||||
|
||||
class InnermostMutexHolder
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
pthread_key_t fInnermostMutexKey;
|
||||
|
||||
public:
|
||||
|
||||
InnermostMutexHolder ()
|
||||
|
||||
: fInnermostMutexKey ()
|
||||
|
||||
{
|
||||
|
||||
int result = pthread_key_create (&fInnermostMutexKey, NULL);
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_key_create failed.");
|
||||
|
||||
if (result != 0)
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
~InnermostMutexHolder ()
|
||||
{
|
||||
|
||||
pthread_key_delete (fInnermostMutexKey);
|
||||
|
||||
}
|
||||
|
||||
void SetInnermostMutex (dng_mutex *mutex)
|
||||
{
|
||||
|
||||
int result;
|
||||
|
||||
result = pthread_setspecific (fInnermostMutexKey, (void *)mutex);
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_setspecific failed.");
|
||||
|
||||
(void) result;
|
||||
|
||||
#if 0 // Hard failure here was causing crash on quit.
|
||||
|
||||
if (result != 0)
|
||||
ThrowProgramError ();
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
dng_mutex *GetInnermostMutex ()
|
||||
{
|
||||
|
||||
void *result = pthread_getspecific (fInnermostMutexKey);
|
||||
|
||||
return reinterpret_cast<dng_mutex *> (result);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
InnermostMutexHolder gInnermostMutexHolder;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_mutex::dng_mutex (const char *mutexName, uint32 mutexLevel)
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
: fPthreadMutex ()
|
||||
, fMutexLevel (mutexLevel)
|
||||
, fRecursiveLockCount (0)
|
||||
, fPrevHeldMutex (NULL)
|
||||
, fMutexName (mutexName)
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
#if qWinOS
|
||||
|
||||
// Win is already a recursive mutex by default
|
||||
if (pthread_mutex_init (&fPthreadMutex, NULL) != 0)
|
||||
{
|
||||
ThrowMemoryFull ();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// make recursive mutex, can lock within itself
|
||||
pthread_mutexattr_t mta;
|
||||
pthread_mutexattr_init(&mta);
|
||||
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
if (pthread_mutex_init (&fPthreadMutex, &mta) != 0)
|
||||
{
|
||||
ThrowMemoryFull ();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_mutex::~dng_mutex ()
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
pthread_mutex_destroy (&fPthreadMutex);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_mutex::Lock ()
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
#if qDNGThreadTestMutexLevels
|
||||
|
||||
dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
|
||||
|
||||
if (innermostMutex != NULL)
|
||||
{
|
||||
|
||||
if (innermostMutex == this)
|
||||
{
|
||||
|
||||
int result = pthread_mutex_lock (&fPthreadMutex);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_mutex_lock failed.");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
fRecursiveLockCount++;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
bool lockOrderPreserved = fMutexLevel > innermostMutex->fMutexLevel;
|
||||
|
||||
// to allow cloning of class internals both with a dng_mutex and get closer to the C++ mutex,
|
||||
// test for MutexLevelIgnore and don't generate level violations
|
||||
if (!lockOrderPreserved)
|
||||
{
|
||||
|
||||
if ((fMutexLevel == kDNGMutexLevelIgnore) || (innermostMutex->fMutexLevel == kDNGMutexLevelIgnore))
|
||||
lockOrderPreserved = true;
|
||||
|
||||
}
|
||||
|
||||
if (!lockOrderPreserved)
|
||||
{
|
||||
|
||||
char msg[1024];
|
||||
|
||||
sprintf(msg,
|
||||
"Lock order violation: This mutex: %s v Innermost mutex: %s",
|
||||
this->MutexName (),
|
||||
innermostMutex->MutexName ());
|
||||
|
||||
DNG_REPORT(msg); // asserts inside of mutex lock, any locks within that must be lower
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int result = pthread_mutex_lock (&fPthreadMutex);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_mutex_lock failed.");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
fPrevHeldMutex = innermostMutex;
|
||||
|
||||
gInnermostMutexHolder.SetInnermostMutex (this);
|
||||
|
||||
#else
|
||||
|
||||
// Register the fact that we're trying to lock this mutex.
|
||||
|
||||
int result = pthread_mutex_lock (&fPthreadMutex);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
|
||||
DNG_REPORT ("pthread_mutex_lock failed");
|
||||
|
||||
ThrowProgramError ();
|
||||
|
||||
}
|
||||
|
||||
// Register the fact that we've now successfully acquired the mutex.
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_mutex::Unlock ()
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
#if qDNGThreadTestMutexLevels
|
||||
|
||||
DNG_ASSERT (gInnermostMutexHolder.GetInnermostMutex () == this, "Mutexes unlocked out of order!!!");
|
||||
|
||||
if (fRecursiveLockCount > 0)
|
||||
{
|
||||
|
||||
fRecursiveLockCount--;
|
||||
|
||||
pthread_mutex_unlock (&fPthreadMutex);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
gInnermostMutexHolder.SetInnermostMutex (fPrevHeldMutex);
|
||||
|
||||
fPrevHeldMutex = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock (&fPthreadMutex);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *dng_mutex::MutexName () const
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
if (fMutexName)
|
||||
return fMutexName;
|
||||
|
||||
#endif
|
||||
|
||||
return "< unknown >";
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_lock_mutex::dng_lock_mutex (dng_mutex *mutex)
|
||||
|
||||
: fMutex (mutex)
|
||||
|
||||
{
|
||||
|
||||
if (fMutex)
|
||||
fMutex->Lock ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_lock_mutex::dng_lock_mutex (dng_mutex &mutex)
|
||||
|
||||
: fMutex (&mutex)
|
||||
|
||||
{
|
||||
|
||||
if (fMutex)
|
||||
fMutex->Lock ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_lock_mutex::~dng_lock_mutex ()
|
||||
{
|
||||
|
||||
if (fMutex)
|
||||
fMutex->Unlock ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_unlock_mutex::dng_unlock_mutex (dng_mutex *mutex)
|
||||
|
||||
: fMutex (mutex)
|
||||
|
||||
{
|
||||
|
||||
if (fMutex)
|
||||
fMutex->Unlock ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_unlock_mutex::dng_unlock_mutex (dng_mutex &mutex)
|
||||
|
||||
: fMutex (&mutex)
|
||||
|
||||
{
|
||||
|
||||
if (fMutex)
|
||||
fMutex->Unlock ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_unlock_mutex::~dng_unlock_mutex ()
|
||||
{
|
||||
|
||||
if (fMutex)
|
||||
fMutex->Lock ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_condition::dng_condition ()
|
||||
|
||||
#if qDNGThreadSafe
|
||||
: fPthreadCondition ()
|
||||
#endif
|
||||
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
int result;
|
||||
|
||||
result = pthread_cond_init (&fPthreadCondition, NULL);
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_cond_init failed.");
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
ThrowProgramError ();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_condition::~dng_condition ()
|
||||
{
|
||||
#if qDNGThreadSafe
|
||||
pthread_cond_destroy (&fPthreadCondition);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_condition::Wait (dng_mutex &mutex, double timeoutSecs)
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
bool timedOut = false;
|
||||
|
||||
#if qDNGThreadTestMutexLevels
|
||||
|
||||
dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
|
||||
|
||||
DNG_ASSERT (innermostMutex == &mutex, "Attempt to wait on non-innermost mutex.");
|
||||
|
||||
(void) innermostMutex;
|
||||
|
||||
innermostMutex = mutex.fPrevHeldMutex;
|
||||
|
||||
gInnermostMutexHolder.SetInnermostMutex (innermostMutex);
|
||||
|
||||
mutex.fPrevHeldMutex = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
if (timeoutSecs < 0)
|
||||
{
|
||||
|
||||
pthread_cond_wait (&fPthreadCondition, &mutex.fPthreadMutex);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
struct timespec now;
|
||||
|
||||
dng_pthread_now (&now);
|
||||
|
||||
timeoutSecs += now.tv_sec;
|
||||
timeoutSecs += now.tv_nsec / 1000000000.0;
|
||||
|
||||
now.tv_sec = (long) timeoutSecs;
|
||||
now.tv_nsec = (long) ((timeoutSecs - now.tv_sec) * 1000000000);
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
|
||||
struct dng_timespec tempNow;
|
||||
|
||||
tempNow.tv_sec = (long) now.tv_sec;
|
||||
tempNow.tv_nsec = now.tv_nsec;
|
||||
|
||||
timedOut = (pthread_cond_timedwait (&fPthreadCondition, &mutex.fPthreadMutex, &tempNow) == ETIMEDOUT);
|
||||
|
||||
#else
|
||||
|
||||
timedOut = (pthread_cond_timedwait (&fPthreadCondition, &mutex.fPthreadMutex, &now) == ETIMEDOUT);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if qDNGThreadTestMutexLevels
|
||||
|
||||
mutex.fPrevHeldMutex = innermostMutex;
|
||||
|
||||
gInnermostMutexHolder.SetInnermostMutex (&mutex);
|
||||
|
||||
#endif
|
||||
|
||||
return !timedOut;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_condition::Signal ()
|
||||
{
|
||||
|
||||
#if qDNGThreadSafe
|
||||
int result;
|
||||
|
||||
result = pthread_cond_signal (&fPthreadCondition);
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_cond_signal failed.");
|
||||
|
||||
if (result != 0)
|
||||
ThrowProgramError ();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_condition::Broadcast ()
|
||||
{
|
||||
#if qDNGThreadSafe
|
||||
|
||||
int result;
|
||||
|
||||
result = pthread_cond_broadcast (&fPthreadCondition);
|
||||
|
||||
DNG_ASSERT (result == 0, "pthread_cond_broadcast failed.");
|
||||
|
||||
if (result != 0)
|
||||
ThrowProgramError ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,145 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_MUTEX
|
||||
#define DNG_MUTEX
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "dng_flags.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
#if qDNGThreadSafe
|
||||
#include "dng_pthread.h"
|
||||
#endif
|
||||
|
||||
#include <mutex>
|
||||
|
||||
typedef std::mutex dng_std_mutex;
|
||||
typedef std::lock_guard<std::mutex> dng_lock_std_mutex;
|
||||
typedef std::unique_lock<std::mutex> dng_unique_lock;
|
||||
|
||||
// We should try to phase out use of dng_mutex over time.
|
||||
//
|
||||
// Note that dng_mutex differs from dng_std_mutex (std::mutex) in that
|
||||
// dng_mutex supports recursive locking (hierarchical mutex).
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class dng_mutex: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDNGMutexLevelLeaf = 0x70000000u,
|
||||
kDNGMutexLevelIgnore = 0x7FFFFFFFu
|
||||
};
|
||||
|
||||
dng_mutex (const char *mutexName,
|
||||
uint32 mutexLevel = kDNGMutexLevelLeaf);
|
||||
|
||||
virtual ~dng_mutex ();
|
||||
|
||||
void Lock ();
|
||||
|
||||
void Unlock ();
|
||||
|
||||
const char *MutexName () const;
|
||||
|
||||
protected:
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
pthread_mutex_t fPthreadMutex;
|
||||
|
||||
const uint32 fMutexLevel;
|
||||
|
||||
uint32 fRecursiveLockCount;
|
||||
|
||||
dng_mutex *fPrevHeldMutex;
|
||||
|
||||
const char * const fMutexName;
|
||||
|
||||
friend class dng_condition;
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_lock_mutex: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_mutex *fMutex;
|
||||
|
||||
public:
|
||||
|
||||
dng_lock_mutex (dng_mutex *mutex);
|
||||
|
||||
dng_lock_mutex (dng_mutex &mutex);
|
||||
|
||||
~dng_lock_mutex ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_unlock_mutex: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_mutex *fMutex;
|
||||
|
||||
public:
|
||||
|
||||
dng_unlock_mutex (dng_mutex *mutex);
|
||||
|
||||
dng_unlock_mutex (dng_mutex &mutex);
|
||||
|
||||
~dng_unlock_mutex ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_condition: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_condition ();
|
||||
|
||||
~dng_condition ();
|
||||
|
||||
bool Wait (dng_mutex &mutex, double timeoutSecs = -1.0);
|
||||
|
||||
void Signal ();
|
||||
|
||||
void Broadcast ();
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
#if qDNGThreadSafe
|
||||
pthread_cond_t fPthreadCondition;
|
||||
#endif // qDNGThreadSafe
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,272 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_opcode_list.h"
|
||||
|
||||
#include "dng_globals.h"
|
||||
#include "dng_host.h"
|
||||
#include "dng_memory_stream.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_tag_values.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode_list::dng_opcode_list (uint32 stage)
|
||||
|
||||
: fList ()
|
||||
, fAlwaysApply (false)
|
||||
, fStage (stage)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
dng_opcode_list::~dng_opcode_list ()
|
||||
{
|
||||
|
||||
Clear ();
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void dng_opcode_list::Clear ()
|
||||
{
|
||||
|
||||
for (size_t index = 0; index < fList.size (); index++)
|
||||
{
|
||||
|
||||
if (fList [index])
|
||||
{
|
||||
|
||||
delete fList [index];
|
||||
|
||||
fList [index] = NULL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fList.clear ();
|
||||
|
||||
fAlwaysApply = false;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void dng_opcode_list::Swap (dng_opcode_list &otherList)
|
||||
{
|
||||
|
||||
fList.swap (otherList.fList);
|
||||
|
||||
std::swap (fAlwaysApply, otherList.fAlwaysApply);
|
||||
|
||||
std::swap (fStage, otherList.fStage);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uint32 dng_opcode_list::MinVersion (bool includeOptional) const
|
||||
{
|
||||
|
||||
uint32 result = dngVersion_None;
|
||||
|
||||
for (size_t index = 0; index < fList.size (); index++)
|
||||
{
|
||||
|
||||
if (includeOptional || !fList [index]->Optional ())
|
||||
{
|
||||
|
||||
result = Max_uint32 (result, fList [index]->MinVersion ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_list::Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image)
|
||||
{
|
||||
|
||||
DNG_REQUIRE (image.Get (), "Bad image in dng_opcode_list::Apply");
|
||||
|
||||
for (uint32 index = 0; index < Count (); index++)
|
||||
{
|
||||
|
||||
dng_opcode &opcode (Entry (index));
|
||||
|
||||
if (opcode.AboutToApply (host,
|
||||
negative,
|
||||
image->Bounds (),
|
||||
image->Planes ()))
|
||||
{
|
||||
|
||||
opcode.Apply (host,
|
||||
negative,
|
||||
image);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_list::Append (AutoPtr<dng_opcode> &opcode)
|
||||
{
|
||||
|
||||
if (opcode->OpcodeID () == dngOpcode_Private)
|
||||
{
|
||||
SetAlwaysApply ();
|
||||
}
|
||||
|
||||
opcode->SetStage (fStage);
|
||||
|
||||
fList.push_back (NULL);
|
||||
|
||||
fList [fList.size () - 1] = opcode.Release ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_memory_block * dng_opcode_list::Spool (dng_host &host) const
|
||||
{
|
||||
|
||||
if (IsEmpty ())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (AlwaysApply ())
|
||||
{
|
||||
ThrowProgramError ();
|
||||
}
|
||||
|
||||
dng_memory_stream stream (host.Allocator ());
|
||||
|
||||
stream.SetBigEndian ();
|
||||
|
||||
stream.Put_uint32 ((uint32) fList.size ());
|
||||
|
||||
for (size_t index = 0; index < fList.size (); index++)
|
||||
{
|
||||
|
||||
stream.Put_uint32 (fList [index]->OpcodeID ());
|
||||
stream.Put_uint32 (fList [index]->MinVersion ());
|
||||
stream.Put_uint32 (fList [index]->Flags ());
|
||||
|
||||
fList [index]->PutData (stream);
|
||||
|
||||
}
|
||||
|
||||
return stream.AsMemoryBlock (host.Allocator ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_list::FingerprintToStream (dng_stream &stream) const
|
||||
{
|
||||
|
||||
if (IsEmpty ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stream.Put_uint32 ((uint32) fList.size ());
|
||||
|
||||
for (size_t index = 0; index < fList.size (); index++)
|
||||
{
|
||||
|
||||
stream.Put_uint32 (fList [index]->OpcodeID ());
|
||||
stream.Put_uint32 (fList [index]->MinVersion ());
|
||||
stream.Put_uint32 (fList [index]->Flags ());
|
||||
|
||||
if (fList [index]->OpcodeID () != dngOpcode_Private)
|
||||
{
|
||||
|
||||
fList [index]->PutData (stream);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_list::Parse (dng_host &host,
|
||||
dng_stream &stream,
|
||||
uint32 byteCount,
|
||||
uint64 streamOffset)
|
||||
{
|
||||
|
||||
Clear ();
|
||||
|
||||
TempBigEndian tempBigEndian (stream);
|
||||
|
||||
stream.SetReadPosition (streamOffset);
|
||||
|
||||
uint32 count = stream.Get_uint32 ();
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
if (gVerbose)
|
||||
{
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
printf ("1 opcode\n");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
printf ("%u opcodes\n", (unsigned) count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for (uint32 index = 0; index < count; index++)
|
||||
{
|
||||
|
||||
uint32 opcodeID = stream.Get_uint32 ();
|
||||
|
||||
AutoPtr<dng_opcode> opcode (host.Make_dng_opcode (opcodeID,
|
||||
stream));
|
||||
|
||||
Append (opcode);
|
||||
|
||||
}
|
||||
|
||||
if (stream.Position () != streamOffset + byteCount)
|
||||
{
|
||||
|
||||
ThrowBadFormat ("Error parsing opcode list");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,153 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* List of opcodes.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_opcode_list__
|
||||
#define __dng_opcode_list__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_opcodes.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// A list of opcodes.
|
||||
|
||||
class dng_opcode_list: private dng_uncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_std_vector<dng_opcode *> fList;
|
||||
|
||||
bool fAlwaysApply;
|
||||
|
||||
uint32 fStage;
|
||||
|
||||
public:
|
||||
|
||||
/// Create an empty opcode list for the specific image stage (1, 2, or 3).
|
||||
|
||||
dng_opcode_list (uint32 stage);
|
||||
|
||||
~dng_opcode_list ();
|
||||
|
||||
/// Is the opcode list empty?
|
||||
|
||||
bool IsEmpty () const
|
||||
{
|
||||
return fList.size () == 0;
|
||||
}
|
||||
|
||||
/// Does the list contain at least 1 opcode?
|
||||
|
||||
bool NotEmpty () const
|
||||
{
|
||||
return !IsEmpty ();
|
||||
}
|
||||
|
||||
/// Should the opcode list always be applied to the image?
|
||||
|
||||
bool AlwaysApply () const
|
||||
{
|
||||
return fAlwaysApply && NotEmpty ();
|
||||
}
|
||||
|
||||
/// Set internal flag to indicate this opcode list should always be
|
||||
/// applied.
|
||||
|
||||
void SetAlwaysApply ()
|
||||
{
|
||||
fAlwaysApply = true;
|
||||
}
|
||||
|
||||
/// The number of opcodes in this list.
|
||||
|
||||
uint32 Count () const
|
||||
{
|
||||
return (uint32) fList.size ();
|
||||
}
|
||||
|
||||
/// Retrieve read/write opcode by index (must be in the range 0 to Count
|
||||
/// () - 1).
|
||||
|
||||
dng_opcode & Entry (uint32 index)
|
||||
{
|
||||
return *fList [index];
|
||||
}
|
||||
|
||||
/// Retrieve read-only opcode by index (must be in the range 0 to Count
|
||||
/// () - 1).
|
||||
|
||||
const dng_opcode & Entry (uint32 index) const
|
||||
{
|
||||
return *fList [index];
|
||||
}
|
||||
|
||||
/// Remove all opcodes from the list.
|
||||
|
||||
void Clear ();
|
||||
|
||||
/// Swap two opcode lists.
|
||||
|
||||
void Swap (dng_opcode_list &otherList);
|
||||
|
||||
/// Return minimum DNG version required to support all opcodes in this
|
||||
/// list. If includeOptional is set to true, then this calculation will
|
||||
/// include optional opcodes.
|
||||
|
||||
uint32 MinVersion (bool includeOptional) const;
|
||||
|
||||
/// Apply this opcode list to the specified image with corresponding
|
||||
/// negative.
|
||||
|
||||
void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
/// Append the specified opcode to this list.
|
||||
|
||||
void Append (AutoPtr<dng_opcode> &opcode);
|
||||
|
||||
/// Serialize this opcode list to a block of memory. The caller is
|
||||
/// responsible for deleting this block.
|
||||
|
||||
dng_memory_block * Spool (dng_host &host) const;
|
||||
|
||||
/// Write a fingerprint of this opcode list to the specified stream.
|
||||
|
||||
void FingerprintToStream (dng_stream &stream) const;
|
||||
|
||||
/// Read an opcode list from the specified stream, starting at the
|
||||
/// specified offset (streamOffset, in bytes). byteCount is provided for
|
||||
/// error checking purposes. A bad format exception
|
||||
/// will be thrown if the length of the opcode stream does not exactly
|
||||
/// match byteCount.
|
||||
|
||||
void Parse (dng_host &host,
|
||||
dng_stream &stream,
|
||||
uint32 byteCount,
|
||||
uint64 streamOffset);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,563 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_opcodes.h"
|
||||
|
||||
#include "dng_bottlenecks.h"
|
||||
#include "dng_exceptions.h"
|
||||
#include "dng_filter_task.h"
|
||||
#include "dng_globals.h"
|
||||
#include "dng_host.h"
|
||||
#include "dng_image.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_parse_utils.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_tag_values.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode::dng_opcode (uint32 opcodeID,
|
||||
uint32 minVersion,
|
||||
uint32 flags)
|
||||
|
||||
: fOpcodeID (opcodeID)
|
||||
, fMinVersion (minVersion)
|
||||
, fFlags (flags)
|
||||
, fWasReadFromStream (false)
|
||||
, fStage (0)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode::dng_opcode (uint32 opcodeID,
|
||||
dng_stream &stream,
|
||||
const char *name)
|
||||
|
||||
: fOpcodeID (opcodeID)
|
||||
, fMinVersion (0)
|
||||
, fFlags (0)
|
||||
, fWasReadFromStream (true)
|
||||
, fStage (0)
|
||||
|
||||
{
|
||||
|
||||
fMinVersion = stream.Get_uint32 ();
|
||||
fFlags = stream.Get_uint32 ();
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
if (gVerbose)
|
||||
{
|
||||
|
||||
printf ("\nOpcode: ");
|
||||
|
||||
if (name)
|
||||
{
|
||||
printf ("%s", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Unknown (%u)", (unsigned) opcodeID);
|
||||
}
|
||||
|
||||
printf (", minVersion = %u.%u.%u.%u",
|
||||
(unsigned) ((fMinVersion >> 24) & 0x0FF),
|
||||
(unsigned) ((fMinVersion >> 16) & 0x0FF),
|
||||
(unsigned) ((fMinVersion >> 8) & 0x0FF),
|
||||
(unsigned) ((fMinVersion ) & 0x0FF));
|
||||
|
||||
printf (", flags = %u\n", (unsigned) fFlags);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
(void) name;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode::~dng_opcode ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode::PutData (dng_stream &stream) const
|
||||
{
|
||||
|
||||
// No data by default
|
||||
|
||||
stream.Put_uint32 (0);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_opcode::AboutToApply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes)
|
||||
{
|
||||
|
||||
if (SkipIfPreview () && host.ForPreview ())
|
||||
{
|
||||
|
||||
negative.SetIsPreview (true);
|
||||
|
||||
}
|
||||
|
||||
else if (MinVersion () > dngVersion_Current &&
|
||||
WasReadFromStream ())
|
||||
{
|
||||
|
||||
if (!Optional ())
|
||||
{
|
||||
|
||||
// Somebody screwed up computing the DNGBackwardVersion...
|
||||
|
||||
ThrowBadFormat ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (!IsValidForNegative (negative))
|
||||
{
|
||||
|
||||
ThrowBadFormat ();
|
||||
|
||||
}
|
||||
|
||||
else if (!IsNOP ())
|
||||
{
|
||||
|
||||
DoAboutToApply (host,
|
||||
negative,
|
||||
imageBounds,
|
||||
imagePlanes);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_opcode_Unknown::dng_opcode_Unknown (dng_host &host,
|
||||
uint32 opcodeID,
|
||||
dng_stream &stream)
|
||||
|
||||
: dng_opcode (opcodeID,
|
||||
stream,
|
||||
NULL)
|
||||
|
||||
, fData ()
|
||||
|
||||
{
|
||||
|
||||
uint32 size = stream.Get_uint32 ();
|
||||
|
||||
if (size)
|
||||
{
|
||||
|
||||
fData.Reset (host.Allocate (size));
|
||||
|
||||
stream.Get (fData->Buffer (),
|
||||
fData->LogicalSize ());
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
if (gVerbose)
|
||||
{
|
||||
|
||||
DumpHexAscii (fData->Buffer_uint8 (),
|
||||
fData->LogicalSize ());
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_Unknown::PutData (dng_stream &stream) const
|
||||
{
|
||||
|
||||
if (fData.Get ())
|
||||
{
|
||||
|
||||
stream.Put_uint32 (fData->LogicalSize ());
|
||||
|
||||
stream.Put (fData->Buffer (),
|
||||
fData->LogicalSize ());
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
stream.Put_uint32 (0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_opcode_Unknown::Apply (dng_host & /* host */,
|
||||
dng_negative & /* negative */,
|
||||
AutoPtr<dng_image> & /* image */)
|
||||
{
|
||||
|
||||
// We should never need to apply an unknown opcode.
|
||||
|
||||
if (!Optional ())
|
||||
{
|
||||
|
||||
ThrowBadFormat ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_filter_opcode_task: public dng_filter_task
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_filter_opcode &fOpcode;
|
||||
|
||||
dng_negative &fNegative;
|
||||
|
||||
public:
|
||||
|
||||
dng_filter_opcode_task (dng_filter_opcode &opcode,
|
||||
dng_negative &negative,
|
||||
const dng_image &srcImage,
|
||||
dng_image &dstImage)
|
||||
|
||||
: dng_filter_task ("dng_filter_opcode_task",
|
||||
srcImage,
|
||||
dstImage)
|
||||
|
||||
, fOpcode (opcode)
|
||||
, fNegative (negative)
|
||||
|
||||
{
|
||||
|
||||
fSrcPixelType = fOpcode.BufferPixelType (srcImage.PixelType ());
|
||||
|
||||
fDstPixelType = fSrcPixelType;
|
||||
|
||||
fSrcRepeat = opcode.SrcRepeat ();
|
||||
|
||||
}
|
||||
|
||||
virtual dng_rect SrcArea (const dng_rect &dstArea)
|
||||
{
|
||||
|
||||
return fOpcode.SrcArea (dstArea,
|
||||
fDstImage.Bounds ());
|
||||
|
||||
}
|
||||
|
||||
virtual dng_point SrcTileSize (const dng_point &dstTileSize)
|
||||
{
|
||||
|
||||
return fOpcode.SrcTileSize (dstTileSize,
|
||||
fDstImage.Bounds ());
|
||||
|
||||
}
|
||||
|
||||
virtual void ProcessArea (uint32 threadIndex,
|
||||
dng_pixel_buffer &srcBuffer,
|
||||
dng_pixel_buffer &dstBuffer)
|
||||
{
|
||||
|
||||
fOpcode.ProcessArea (fNegative,
|
||||
threadIndex,
|
||||
srcBuffer,
|
||||
dstBuffer,
|
||||
dstBuffer.Area (),
|
||||
fDstImage.Bounds ());
|
||||
|
||||
}
|
||||
|
||||
virtual void Start (uint32 threadCount,
|
||||
const dng_rect &dstArea,
|
||||
const dng_point &tileSize,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer *sniffer)
|
||||
{
|
||||
|
||||
dng_filter_task::Start (threadCount,
|
||||
dstArea,
|
||||
tileSize,
|
||||
allocator,
|
||||
sniffer);
|
||||
|
||||
fOpcode.Prepare (fNegative,
|
||||
threadCount,
|
||||
tileSize,
|
||||
fDstImage.Bounds (),
|
||||
fDstImage.Planes (),
|
||||
fDstPixelType,
|
||||
*allocator);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
|
||||
uint32 minVersion,
|
||||
uint32 flags)
|
||||
|
||||
: dng_opcode (opcodeID,
|
||||
minVersion,
|
||||
flags)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
|
||||
dng_stream &stream,
|
||||
const char *name)
|
||||
|
||||
: dng_opcode (opcodeID,
|
||||
stream,
|
||||
name)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_filter_opcode::Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image)
|
||||
{
|
||||
|
||||
dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
|
||||
|
||||
if (modifiedBounds.NotEmpty ())
|
||||
{
|
||||
|
||||
// Allocate destination image.
|
||||
|
||||
AutoPtr<dng_image> dstImage;
|
||||
|
||||
// If we are processing the entire image, allocate an
|
||||
// undefined image.
|
||||
|
||||
if (modifiedBounds == image->Bounds ())
|
||||
{
|
||||
|
||||
dstImage.Reset (host.Make_dng_image (image->Bounds (),
|
||||
image->Planes (),
|
||||
image->PixelType ()));
|
||||
|
||||
}
|
||||
|
||||
// Else start with a clone of the existing image.
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
dstImage.Reset (image->Clone ());
|
||||
|
||||
}
|
||||
|
||||
// Filter the image.
|
||||
|
||||
dng_filter_opcode_task task (*this,
|
||||
negative,
|
||||
*image,
|
||||
*dstImage);
|
||||
|
||||
host.PerformAreaTask (task,
|
||||
modifiedBounds);
|
||||
|
||||
// Return the new image.
|
||||
|
||||
image.Reset (dstImage.Release ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_inplace_opcode_task: public dng_area_task
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_inplace_opcode &fOpcode;
|
||||
|
||||
dng_negative &fNegative;
|
||||
|
||||
dng_image &fImage;
|
||||
|
||||
uint32 fPixelType;
|
||||
|
||||
AutoPtr<dng_memory_block> fBuffer [kMaxMPThreads];
|
||||
|
||||
public:
|
||||
|
||||
dng_inplace_opcode_task (dng_inplace_opcode &opcode,
|
||||
dng_negative &negative,
|
||||
dng_image &image)
|
||||
|
||||
: dng_area_task ("dng_inplace_opcode_task")
|
||||
|
||||
, fOpcode (opcode)
|
||||
, fNegative (negative)
|
||||
, fImage (image)
|
||||
, fPixelType (opcode.BufferPixelType (image.PixelType ()))
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void Start (uint32 threadCount,
|
||||
const dng_rect & /* dstArea */,
|
||||
const dng_point &tileSize,
|
||||
dng_memory_allocator *allocator,
|
||||
dng_abort_sniffer * /* sniffer */)
|
||||
{
|
||||
|
||||
uint32 bufferSize = ComputeBufferSize (fPixelType,
|
||||
tileSize,
|
||||
fImage.Planes (),
|
||||
padSIMDBytes);
|
||||
|
||||
for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
|
||||
{
|
||||
|
||||
fBuffer [threadIndex] . Reset (allocator->Allocate (bufferSize));
|
||||
|
||||
}
|
||||
|
||||
fOpcode.Prepare (fNegative,
|
||||
threadCount,
|
||||
tileSize,
|
||||
fImage.Bounds (),
|
||||
fImage.Planes (),
|
||||
fPixelType,
|
||||
*allocator);
|
||||
|
||||
}
|
||||
|
||||
virtual void Process (uint32 threadIndex,
|
||||
const dng_rect &tile,
|
||||
dng_abort_sniffer * /* sniffer */)
|
||||
{
|
||||
|
||||
// Setup buffer.
|
||||
|
||||
dng_pixel_buffer buffer (tile,
|
||||
0,
|
||||
fImage.Planes (),
|
||||
fPixelType,
|
||||
pcRowInterleavedAlignSIMD,
|
||||
fBuffer [threadIndex]->Buffer ());
|
||||
|
||||
// Get source pixels.
|
||||
|
||||
fImage.Get (buffer);
|
||||
|
||||
// Process area.
|
||||
|
||||
fOpcode.ProcessArea (fNegative,
|
||||
threadIndex,
|
||||
buffer,
|
||||
tile,
|
||||
fImage.Bounds ());
|
||||
|
||||
// Save result pixels.
|
||||
|
||||
fImage.Put (buffer);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
|
||||
uint32 minVersion,
|
||||
uint32 flags)
|
||||
|
||||
: dng_opcode (opcodeID,
|
||||
minVersion,
|
||||
flags)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
|
||||
dng_stream &stream,
|
||||
const char *name)
|
||||
|
||||
: dng_opcode (opcodeID,
|
||||
stream,
|
||||
name)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_inplace_opcode::Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image)
|
||||
{
|
||||
|
||||
dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
|
||||
|
||||
if (modifiedBounds.NotEmpty ())
|
||||
{
|
||||
|
||||
dng_inplace_opcode_task task (*this,
|
||||
negative,
|
||||
*image);
|
||||
|
||||
host.PerformAreaTask (task,
|
||||
modifiedBounds);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,523 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2008-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Base class and common data structures for opcodes (introduced in DNG 1.3).
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_opcodes__
|
||||
#define __dng_opcodes__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief List of supported opcodes (by ID).
|
||||
|
||||
enum dng_opcode_id
|
||||
{
|
||||
|
||||
// Internal use only opcode. Never written to DNGs.
|
||||
|
||||
dngOpcode_Private = 0,
|
||||
|
||||
// Warp image to correct distortion and lateral chromatic aberration for
|
||||
// rectilinear lenses.
|
||||
|
||||
dngOpcode_WarpRectilinear = 1,
|
||||
|
||||
// Warp image to correction distortion for fisheye lenses (i.e., map the
|
||||
// fisheye projection to a perspective projection).
|
||||
|
||||
dngOpcode_WarpFisheye = 2,
|
||||
|
||||
// Radial vignette correction.
|
||||
|
||||
dngOpcode_FixVignetteRadial = 3,
|
||||
|
||||
// Patch bad Bayer pixels which are marked with a special value in the image.
|
||||
|
||||
dngOpcode_FixBadPixelsConstant = 4,
|
||||
|
||||
// Patch bad Bayer pixels/rectangles at a list of specified coordinates.
|
||||
|
||||
dngOpcode_FixBadPixelsList = 5,
|
||||
|
||||
// Trim image to specified bounds.
|
||||
|
||||
dngOpcode_TrimBounds = 6,
|
||||
|
||||
// Map an area through a 16-bit LUT.
|
||||
|
||||
dngOpcode_MapTable = 7,
|
||||
|
||||
// Map an area using a polynomial function.
|
||||
|
||||
dngOpcode_MapPolynomial = 8,
|
||||
|
||||
// Apply a gain map to an area.
|
||||
|
||||
dngOpcode_GainMap = 9,
|
||||
|
||||
// Apply a per-row delta to an area.
|
||||
|
||||
dngOpcode_DeltaPerRow = 10,
|
||||
|
||||
// Apply a per-column delta to an area.
|
||||
|
||||
dngOpcode_DeltaPerColumn = 11,
|
||||
|
||||
// Apply a per-row scale to an area.
|
||||
|
||||
dngOpcode_ScalePerRow = 12,
|
||||
|
||||
// Apply a per-column scale to an area.
|
||||
|
||||
dngOpcode_ScalePerColumn = 13
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Virtual base class for opcode.
|
||||
|
||||
class dng_opcode
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/// Opcode flags.
|
||||
|
||||
enum
|
||||
{
|
||||
kFlag_None = 0, //!< No flag.
|
||||
kFlag_Optional = 1, //!< This opcode is optional.
|
||||
kFlag_SkipIfPreview = 2 //!< May skip opcode for preview images.
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
uint32 fOpcodeID;
|
||||
|
||||
uint32 fMinVersion;
|
||||
|
||||
uint32 fFlags;
|
||||
|
||||
bool fWasReadFromStream;
|
||||
|
||||
uint32 fStage;
|
||||
|
||||
protected:
|
||||
|
||||
dng_opcode (uint32 opcodeID,
|
||||
uint32 minVersion,
|
||||
uint32 flags);
|
||||
|
||||
dng_opcode (uint32 opcodeID,
|
||||
dng_stream &stream,
|
||||
const char *name);
|
||||
|
||||
// This helper routine will be called by AboutToApply if AboutToApply
|
||||
// passes its internal checking and plans to return true. This is an
|
||||
// opportunity for subclasses to perform some internal preparation
|
||||
// based on the negative, image bounds, and number of image planes.
|
||||
|
||||
virtual void DoAboutToApply (dng_host & /* host */,
|
||||
dng_negative & /* negative */,
|
||||
const dng_rect & /* imageBounds */,
|
||||
uint32 /* imagePlanes */)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_opcode ();
|
||||
|
||||
/// The ID of this opcode.
|
||||
|
||||
uint32 OpcodeID () const
|
||||
{
|
||||
return fOpcodeID;
|
||||
}
|
||||
|
||||
/// The first DNG version that supports this opcode.
|
||||
|
||||
uint32 MinVersion () const
|
||||
{
|
||||
return fMinVersion;
|
||||
}
|
||||
|
||||
/// The flags for this opcode.
|
||||
|
||||
uint32 Flags () const
|
||||
{
|
||||
return fFlags;
|
||||
}
|
||||
|
||||
/// Is this opcode optional?
|
||||
|
||||
bool Optional () const
|
||||
{
|
||||
return (Flags () & kFlag_Optional) != 0;
|
||||
}
|
||||
|
||||
/// Should the opcode be skipped when rendering preview images?
|
||||
|
||||
bool SkipIfPreview () const
|
||||
{
|
||||
return (Flags () & kFlag_SkipIfPreview) != 0;
|
||||
}
|
||||
|
||||
/// Was this opcode read from a data stream?
|
||||
|
||||
bool WasReadFromStream () const
|
||||
{
|
||||
return fWasReadFromStream;
|
||||
}
|
||||
|
||||
/// Which image processing stage (1, 2, 3) is associated with this
|
||||
/// opcode?
|
||||
|
||||
uint32 Stage () const
|
||||
{
|
||||
return fStage;
|
||||
}
|
||||
|
||||
/// Set the image processing stage (1, 2, 3) for this opcode. Stage 1 is
|
||||
/// the original image data, including masked areas. Stage 2 is
|
||||
/// linearized image data and trimmed to the active area. Stage 3 is
|
||||
/// demosaiced and trimmed to the active area.
|
||||
|
||||
void SetStage (uint32 stage)
|
||||
{
|
||||
fStage = stage;
|
||||
}
|
||||
|
||||
/// Is the opcode a NOP (i.e., does nothing)? An opcode could be a NOP
|
||||
/// for some specific parameters.
|
||||
|
||||
virtual bool IsNOP () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Is this opcode valid for the specified negative?
|
||||
|
||||
virtual bool IsValidForNegative (const dng_negative & /* negative */) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Write opcode to a stream.
|
||||
/// \param stream The stream to which to write the opcode data.
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
/// Perform error checking prior to applying this opcode to the
|
||||
/// specified negative. Returns true if this opcode should be applied to
|
||||
/// the negative, false otherwise.
|
||||
|
||||
bool AboutToApply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes);
|
||||
|
||||
/// Apply this opcode to the specified image with associated negative.
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image) = 0;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to represent unknown opcodes (e.g, opcodes defined in future
|
||||
/// DNG versions).
|
||||
|
||||
class dng_opcode_Unknown: public dng_opcode
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
AutoPtr<dng_memory_block> fData;
|
||||
|
||||
public:
|
||||
|
||||
dng_opcode_Unknown (dng_host &host,
|
||||
uint32 opcodeID,
|
||||
dng_stream &stream);
|
||||
|
||||
virtual void PutData (dng_stream &stream) const;
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to represent a filter opcode, such as a convolution.
|
||||
|
||||
class dng_filter_opcode: public dng_opcode
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_filter_opcode (uint32 opcodeID,
|
||||
uint32 minVersion,
|
||||
uint32 flags);
|
||||
|
||||
dng_filter_opcode (uint32 opcodeID,
|
||||
dng_stream &stream,
|
||||
const char *name);
|
||||
|
||||
public:
|
||||
|
||||
/// The pixel data type of this opcode.
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType)
|
||||
{
|
||||
return imagePixelType;
|
||||
}
|
||||
|
||||
/// The adjusted bounds (processing area) of this opcode. It is limited to
|
||||
/// the intersection of the specified image area and the GainMap area.
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
|
||||
{
|
||||
return imageBounds;
|
||||
}
|
||||
|
||||
/// Returns the width and height (in pixels) of the repeating mosaic pattern.
|
||||
|
||||
virtual dng_point SrcRepeat ()
|
||||
{
|
||||
return dng_point (1, 1);
|
||||
}
|
||||
|
||||
/// Returns the source pixel area needed to process a destination pixel area
|
||||
/// that lies within the specified bounds.
|
||||
/// \param dstArea The destination pixel area to be computed.
|
||||
/// \param imageBounds The overall image area (dstArea will lie within these
|
||||
/// bounds).
|
||||
/// \retval The source pixel area needed to process the specified dstArea.
|
||||
|
||||
virtual dng_rect SrcArea (const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds)
|
||||
{
|
||||
(void) imageBounds;
|
||||
return dstArea;
|
||||
}
|
||||
|
||||
/// Given a destination tile size, calculate input tile size. Simlar to
|
||||
/// SrcArea, and should seldom be overridden.
|
||||
///
|
||||
/// \param dstTileSize The destination tile size that is targeted for output.
|
||||
///
|
||||
/// \param imageBounds The image bounds (the destination tile will
|
||||
/// always lie within these bounds).
|
||||
///
|
||||
/// \retval The source tile size needed to compute a tile of the destination
|
||||
/// size.
|
||||
|
||||
virtual dng_point SrcTileSize (const dng_point &dstTileSize,
|
||||
const dng_rect &imageBounds)
|
||||
{
|
||||
return SrcArea (dng_rect (dstTileSize),
|
||||
imageBounds).Size ();
|
||||
}
|
||||
|
||||
/// Startup method called before any processing is performed on pixel areas.
|
||||
/// It can be used to allocate (per-thread) memory and setup tasks.
|
||||
///
|
||||
/// \param negative The negative object to be processed.
|
||||
///
|
||||
/// \param threadCount Total number of threads that will be used for
|
||||
/// processing. Less than or equal to MaxThreads.
|
||||
///
|
||||
/// \param tileSize Size of source tiles which will be processed. (Not all
|
||||
/// tiles will be this size due to edge conditions.)
|
||||
///
|
||||
/// \param imageBounds Total size of image to be processed.
|
||||
///
|
||||
/// \param imagePlanes Number of planes in the image. Less than or equal to
|
||||
/// kMaxColorPlanes.
|
||||
///
|
||||
/// \param bufferPixelType Pixel type of image buffer (see dng_tag_types.h).
|
||||
///
|
||||
/// \param allocator dng_memory_allocator to use for allocating temporary
|
||||
/// buffers, etc.
|
||||
|
||||
virtual void Prepare (dng_negative &negative,
|
||||
uint32 threadCount,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes,
|
||||
uint32 bufferPixelType,
|
||||
dng_memory_allocator &allocator)
|
||||
{
|
||||
(void) negative;
|
||||
(void) threadCount;
|
||||
(void) tileSize;
|
||||
(void) imageBounds;
|
||||
(void) imagePlanes;
|
||||
(void) bufferPixelType;
|
||||
(void) allocator;
|
||||
}
|
||||
|
||||
/// Implements filtering operation from one buffer to another. Source
|
||||
/// and destination pixels are set up in member fields of this class.
|
||||
/// Ideally, no allocation should be done in this routine.
|
||||
///
|
||||
/// \param negative The negative associated with the pixels to be
|
||||
/// processed.
|
||||
///
|
||||
/// \param threadIndex The thread on which this routine is being called,
|
||||
/// between 0 and threadCount - 1 for the threadCount passed to Prepare
|
||||
/// method.
|
||||
///
|
||||
/// \param srcBuffer Input area and source pixels.
|
||||
///
|
||||
/// \param dstBuffer Destination pixels.
|
||||
///
|
||||
/// \param dstArea Destination pixel processing area.
|
||||
///
|
||||
/// \param imageBounds Total image area to be processed; dstArea will
|
||||
/// always lie within these bounds.
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &srcBuffer,
|
||||
dng_pixel_buffer &dstBuffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds) = 0;
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Class to represent an in-place (i.e., pointwise, per-pixel) opcode,
|
||||
/// such as a global tone curve.
|
||||
|
||||
class dng_inplace_opcode: public dng_opcode
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
dng_inplace_opcode (uint32 opcodeID,
|
||||
uint32 minVersion,
|
||||
uint32 flags);
|
||||
|
||||
dng_inplace_opcode (uint32 opcodeID,
|
||||
dng_stream &stream,
|
||||
const char *name);
|
||||
|
||||
public:
|
||||
|
||||
/// The pixel data type of this opcode.
|
||||
|
||||
virtual uint32 BufferPixelType (uint32 imagePixelType)
|
||||
{
|
||||
return imagePixelType;
|
||||
}
|
||||
|
||||
/// The adjusted bounds (processing area) of this opcode. It is limited to
|
||||
/// the intersection of the specified image area and the GainMap area.
|
||||
|
||||
virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
|
||||
{
|
||||
return imageBounds;
|
||||
}
|
||||
|
||||
/// Startup method called before any processing is performed on pixel areas.
|
||||
/// It can be used to allocate (per-thread) memory and setup tasks.
|
||||
///
|
||||
/// \param negative The negative object to be processed.
|
||||
///
|
||||
/// \param threadCount Total number of threads that will be used for
|
||||
/// processing. Less than or equal to MaxThreads.
|
||||
///
|
||||
/// \param tileSize Size of source tiles which will be processed. (Not all
|
||||
/// tiles will be this size due to edge conditions.)
|
||||
///
|
||||
/// \param imageBounds Total size of image to be processed.
|
||||
///
|
||||
/// \param imagePlanes Number of planes in the image. Less than or equal to
|
||||
/// kMaxColorPlanes.
|
||||
///
|
||||
/// \param bufferPixelType Pixel type of image buffer (see dng_tag_types.h).
|
||||
///
|
||||
/// \param allocator dng_memory_allocator to use for allocating temporary
|
||||
/// buffers, etc.
|
||||
|
||||
virtual void Prepare (dng_negative &negative,
|
||||
uint32 threadCount,
|
||||
const dng_point &tileSize,
|
||||
const dng_rect &imageBounds,
|
||||
uint32 imagePlanes,
|
||||
uint32 bufferPixelType,
|
||||
dng_memory_allocator &allocator)
|
||||
{
|
||||
(void) negative;
|
||||
(void) threadCount;
|
||||
(void) tileSize;
|
||||
(void) imageBounds;
|
||||
(void) imagePlanes;
|
||||
(void) bufferPixelType;
|
||||
(void) allocator;
|
||||
}
|
||||
|
||||
/// Implements image processing operation in a single buffer. The source
|
||||
/// pixels are provided as input to the buffer, and this routine
|
||||
/// calculates and writes the destination pixels to the same buffer.
|
||||
/// Ideally, no allocation should be done in this routine.
|
||||
///
|
||||
/// \param negative The negative associated with the pixels to be
|
||||
/// processed.
|
||||
///
|
||||
/// \param threadIndex The thread on which this routine is being called,
|
||||
/// between 0 and threadCount - 1 for the threadCount passed to Prepare
|
||||
/// method.
|
||||
///
|
||||
/// \param buffer Source and Destination pixels.
|
||||
///
|
||||
/// \param dstArea Destination pixel processing area.
|
||||
///
|
||||
/// \param imageBounds Total image area to be processed; dstArea will
|
||||
/// always lie within these bounds.
|
||||
|
||||
virtual void ProcessArea (dng_negative &negative,
|
||||
uint32 threadIndex,
|
||||
dng_pixel_buffer &buffer,
|
||||
const dng_rect &dstArea,
|
||||
const dng_rect &imageBounds) = 0;
|
||||
|
||||
virtual void Apply (dng_host &host,
|
||||
dng_negative &negative,
|
||||
AutoPtr<dng_image> &image);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,391 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_orientation.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_orientation::SetTIFF (uint32 tiff)
|
||||
{
|
||||
|
||||
switch (tiff)
|
||||
{
|
||||
|
||||
case 1:
|
||||
{
|
||||
fAdobeOrientation = kNormal;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
fAdobeOrientation = kMirror;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
fAdobeOrientation = kRotate180;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
fAdobeOrientation = kMirror180;
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
fAdobeOrientation = kMirror90CCW;
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
fAdobeOrientation = kRotate90CW;
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
fAdobeOrientation = kMirror90CW;
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
fAdobeOrientation = kRotate90CCW;
|
||||
break;
|
||||
}
|
||||
|
||||
case 9:
|
||||
{
|
||||
fAdobeOrientation = kUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
fAdobeOrientation = kNormal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
uint32 dng_orientation::GetTIFF () const
|
||||
{
|
||||
|
||||
switch (fAdobeOrientation)
|
||||
{
|
||||
|
||||
case kNormal:
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
case kMirror:
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
case kRotate180:
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
case kMirror180:
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
case kMirror90CCW:
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
case kRotate90CW:
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
case kMirror90CW:
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
case kRotate90CCW:
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
case kUnknown:
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_orientation::FlipD () const
|
||||
{
|
||||
|
||||
return (fAdobeOrientation & 1) != 0;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_orientation::FlipH () const
|
||||
{
|
||||
|
||||
if (fAdobeOrientation & 4)
|
||||
return (fAdobeOrientation & 2) == 0;
|
||||
|
||||
else
|
||||
return (fAdobeOrientation & 2) != 0;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_orientation::FlipV () const
|
||||
{
|
||||
|
||||
if (fAdobeOrientation & 4)
|
||||
return FlipD () == FlipH ();
|
||||
|
||||
else
|
||||
return FlipD () != FlipH ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_orientation dng_orientation::operator- () const
|
||||
{
|
||||
|
||||
uint32 x = GetAdobe ();
|
||||
|
||||
if ((x & 5) == 5)
|
||||
{
|
||||
|
||||
x ^= 2;
|
||||
|
||||
}
|
||||
|
||||
dng_orientation result;
|
||||
|
||||
result.SetAdobe (((4 - x) & 3) | (x & 4));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_orientation dng_orientation::operator+ (const dng_orientation &b) const
|
||||
{
|
||||
|
||||
uint32 x = GetAdobe ();
|
||||
|
||||
uint32 y = b.GetAdobe ();
|
||||
|
||||
if (y & 4)
|
||||
{
|
||||
|
||||
if (x & 1)
|
||||
x ^= 6;
|
||||
else
|
||||
x ^= 4;
|
||||
|
||||
}
|
||||
|
||||
dng_orientation result;
|
||||
|
||||
result.SetAdobe (((x + y) & 3) | (x & 4));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_orientation::CalcForwardMatrix3by3 (dng_matrix &orientationMatrix,
|
||||
const bool horizontalFirstRow) const
|
||||
{
|
||||
|
||||
bool hasOrient = false;
|
||||
|
||||
orientationMatrix.SetIdentity (3);
|
||||
|
||||
if (FlipH ())
|
||||
{
|
||||
|
||||
hasOrient = true;
|
||||
|
||||
if (horizontalFirstRow)
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_3by3 (-1.0, 0.0, 1.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_3by3 (1.0, 0.0, 0.0,
|
||||
0.0, -1.0, 1.0,
|
||||
0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (FlipV ())
|
||||
{
|
||||
|
||||
hasOrient = true;
|
||||
|
||||
if (horizontalFirstRow)
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_3by3 (1.0, 0.0, 0.0,
|
||||
0.0, -1.0, 1.0,
|
||||
0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_3by3 (-1.0, 0.0, 1.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (FlipD ())
|
||||
{
|
||||
|
||||
hasOrient = true;
|
||||
|
||||
orientationMatrix = dng_matrix_3by3 (0.0, 1.0, 0.0,
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
return hasOrient;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool dng_orientation::CalcForwardMatrix4by4 (dng_matrix &orientationMatrix,
|
||||
const bool horizontalFirstRow) const
|
||||
{
|
||||
|
||||
bool hasOrient = false;
|
||||
|
||||
orientationMatrix.SetIdentity (4);
|
||||
|
||||
if (FlipH ())
|
||||
{
|
||||
|
||||
hasOrient = true;
|
||||
|
||||
if (horizontalFirstRow)
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_4by4 (-1.0, 0.0, 0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_4by4 (1.0, 0.0, 0.0, 0.0,
|
||||
0.0, -1.0, 0.0, 1.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (FlipV ())
|
||||
{
|
||||
|
||||
hasOrient = true;
|
||||
|
||||
if (horizontalFirstRow)
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_4by4 (1.0, 0.0, 0.0, 0.0,
|
||||
0.0, -1.0, 0.0, 1.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
orientationMatrix = dng_matrix_4by4 (-1.0, 0.0, 0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (FlipD ())
|
||||
{
|
||||
|
||||
hasOrient = true;
|
||||
|
||||
orientationMatrix = dng_matrix_4by4 (0.0, 1.0, 0.0, 0.0,
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0) *
|
||||
orientationMatrix;
|
||||
|
||||
}
|
||||
|
||||
return hasOrient;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,197 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_orientation__
|
||||
#define __dng_orientation__
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#include "dng_matrix.h"
|
||||
#include "dng_types.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
class dng_orientation
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
// We internally use an orientation encoding ("Adobe") that is
|
||||
// different than the TIFF orientation encoding ("TIFF").
|
||||
|
||||
uint32 fAdobeOrientation;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kNormal = 0,
|
||||
kRotate90CW = 1,
|
||||
kRotate180 = 2,
|
||||
kRotate90CCW = 3,
|
||||
kMirror = 4,
|
||||
kMirror90CW = 5,
|
||||
kMirror180 = 6,
|
||||
kMirror90CCW = 7,
|
||||
kUnknown = 8
|
||||
};
|
||||
|
||||
dng_orientation ()
|
||||
|
||||
: fAdobeOrientation (kNormal)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
void SetAdobe (uint32 adobe)
|
||||
{
|
||||
fAdobeOrientation = adobe;
|
||||
}
|
||||
|
||||
uint32 GetAdobe () const
|
||||
{
|
||||
return fAdobeOrientation;
|
||||
}
|
||||
|
||||
void SetTIFF (uint32 tiff);
|
||||
|
||||
uint32 GetTIFF () const;
|
||||
|
||||
static dng_orientation AdobeToDNG (uint32 adobe)
|
||||
{
|
||||
|
||||
dng_orientation result;
|
||||
|
||||
result.SetAdobe (adobe);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static dng_orientation TIFFtoDNG (uint32 tiff)
|
||||
{
|
||||
|
||||
dng_orientation result;
|
||||
|
||||
result.SetTIFF (tiff);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static dng_orientation Normal ()
|
||||
{
|
||||
return AdobeToDNG (kNormal);
|
||||
}
|
||||
|
||||
static dng_orientation Rotate90CW ()
|
||||
{
|
||||
return AdobeToDNG (kRotate90CW);
|
||||
}
|
||||
|
||||
static dng_orientation Rotate180 ()
|
||||
{
|
||||
return AdobeToDNG (kRotate180);
|
||||
}
|
||||
|
||||
static dng_orientation Rotate90CCW ()
|
||||
{
|
||||
return AdobeToDNG (kRotate90CCW);
|
||||
}
|
||||
|
||||
static dng_orientation Mirror ()
|
||||
{
|
||||
return AdobeToDNG (kMirror);
|
||||
}
|
||||
|
||||
static dng_orientation Mirror90CW ()
|
||||
{
|
||||
return AdobeToDNG (kMirror90CW);
|
||||
}
|
||||
|
||||
static dng_orientation Mirror180 ()
|
||||
{
|
||||
return AdobeToDNG (kMirror180);
|
||||
}
|
||||
|
||||
static dng_orientation Mirror90CCW ()
|
||||
{
|
||||
return AdobeToDNG (kMirror90CCW);
|
||||
}
|
||||
|
||||
static dng_orientation Unknown ()
|
||||
{
|
||||
return AdobeToDNG (kUnknown);
|
||||
}
|
||||
|
||||
bool IsValid () const
|
||||
{
|
||||
return fAdobeOrientation < kUnknown;
|
||||
}
|
||||
|
||||
bool NotValid () const
|
||||
{
|
||||
return !IsValid ();
|
||||
}
|
||||
|
||||
bool FlipD () const;
|
||||
|
||||
bool FlipH () const;
|
||||
|
||||
bool FlipV () const;
|
||||
|
||||
bool operator== (const dng_orientation &b) const
|
||||
{
|
||||
return fAdobeOrientation == b.fAdobeOrientation;
|
||||
}
|
||||
|
||||
bool operator!= (const dng_orientation &b) const
|
||||
{
|
||||
return !(*this == b);
|
||||
}
|
||||
|
||||
dng_orientation operator- () const;
|
||||
|
||||
dng_orientation operator+ (const dng_orientation &b) const;
|
||||
|
||||
dng_orientation operator- (const dng_orientation &b) const
|
||||
{
|
||||
return (*this) + (-b);
|
||||
}
|
||||
|
||||
void operator+= (const dng_orientation &b)
|
||||
{
|
||||
*this = *this + b;
|
||||
}
|
||||
|
||||
void operator-= (const dng_orientation &b)
|
||||
{
|
||||
*this = *this - b;
|
||||
}
|
||||
|
||||
// If horizontalFirstRow is true, then the x (horizontal h) component
|
||||
// of the transform will be in the first row of the resulting matrix,
|
||||
// and the y (vertical v) component will be in the second row.
|
||||
//
|
||||
// If horizontalFirstRow is false, then the y (vertical v) component
|
||||
// of the transform will be in the first row of the resulting matrix,
|
||||
// and the x (horizontal h) component will be in the second row.
|
||||
|
||||
bool CalcForwardMatrix3by3 (dng_matrix &matrix,
|
||||
bool horizontalFirstRow) const;
|
||||
|
||||
bool CalcForwardMatrix4by4 (dng_matrix &matrix,
|
||||
bool horizontalFirstRow) const;
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,231 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_parse_utils__
|
||||
#define __dng_parse_utils__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_classes.h"
|
||||
#include "dng_flags.h"
|
||||
#include "dng_types.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_string.h"
|
||||
#include "dng_matrix.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGValidate
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char * LookupParentCode (uint32 parentCode);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char * LookupTagCode (uint32 parentCode,
|
||||
uint32 tagCode);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char * LookupTagType (uint32 tagType);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char * LookupNewSubFileType (uint32 key);
|
||||
|
||||
const char * LookupCompression (uint32 key);
|
||||
|
||||
const char * LookupPredictor (uint32 key);
|
||||
|
||||
const char * LookupSampleFormat (uint32 key);
|
||||
|
||||
const char * LookupPhotometricInterpretation (uint32 key);
|
||||
|
||||
const char * LookupOrientation (uint32 key);
|
||||
|
||||
const char * LookupResolutionUnit (uint32 key);
|
||||
|
||||
const char * LookupCFAColor (uint32 key);
|
||||
|
||||
const char * LookupSensingMethod (uint32 key);
|
||||
|
||||
const char * LookupExposureProgram (uint32 key);
|
||||
|
||||
const char * LookupMeteringMode (uint32 key);
|
||||
|
||||
const char * LookupLightSource (uint32 key);
|
||||
|
||||
const char * LookupColorSpace (uint32 key);
|
||||
|
||||
const char * LookupFileSource (uint32 key);
|
||||
|
||||
const char * LookupSceneType (uint32 key);
|
||||
|
||||
const char * LookupCustomRendered (uint32 key);
|
||||
|
||||
const char * LookupExposureMode (uint32 key);
|
||||
|
||||
const char * LookupWhiteBalance (uint32 key);
|
||||
|
||||
const char * LookupSceneCaptureType (uint32 key);
|
||||
|
||||
const char * LookupGainControl (uint32 key);
|
||||
|
||||
const char * LookupContrast (uint32 key);
|
||||
|
||||
const char * LookupSaturation (uint32 key);
|
||||
|
||||
const char * LookupSharpness (uint32 key);
|
||||
|
||||
const char * LookupSubjectDistanceRange (uint32 key);
|
||||
|
||||
const char * LookupComponent (uint32 key);
|
||||
|
||||
const char * LookupCFALayout (uint32 key);
|
||||
|
||||
const char * LookupMakerNoteSafety (uint32 key);
|
||||
|
||||
const char * LookupColorimetricReference (uint32 key);
|
||||
|
||||
const char * LookupPreviewColorSpace (uint32 key);
|
||||
|
||||
const char * LookupJPEGMarker (uint32 key);
|
||||
|
||||
const char * LookupSensitivityType (uint32 key);
|
||||
|
||||
const char * LookupDepthFormat (uint32 key);
|
||||
|
||||
const char * LookupDepthUnits (uint32 key);
|
||||
|
||||
const char * LookupDepthMeasureType (uint32 key);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void DumpHexAscii (dng_stream &stream,
|
||||
uint32 count);
|
||||
|
||||
void DumpHexAscii (const uint8 *buf,
|
||||
uint32 count);
|
||||
|
||||
void DumpXMP (dng_stream &stream,
|
||||
uint32 count);
|
||||
|
||||
void DumpString (const dng_string &s);
|
||||
|
||||
void DumpTagValues (dng_stream &stream,
|
||||
const char *entry_name,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
const char *tag_name = NULL);
|
||||
|
||||
void DumpMatrix (const dng_matrix &m);
|
||||
|
||||
void DumpVector (const dng_vector &v);
|
||||
|
||||
void DumpDateTime (const dng_date_time &dt);
|
||||
|
||||
void DumpExposureTime (real64 x);
|
||||
|
||||
void DumpFingerprint (const dng_fingerprint &p);
|
||||
|
||||
void DumpHueSatMap (dng_stream &stream,
|
||||
uint32 hues,
|
||||
uint32 sats,
|
||||
uint32 vals,
|
||||
bool skipSat0);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool CheckTagType (uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint16 validType0,
|
||||
uint16 validType1 = 0,
|
||||
uint16 validType2 = 0,
|
||||
uint16 validType3 = 0);
|
||||
|
||||
bool CheckTagCount (uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagCount,
|
||||
uint32 minCount,
|
||||
uint32 maxCount = 0);
|
||||
|
||||
bool CheckColorImage (uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 colorPlanes);
|
||||
|
||||
bool CheckMainIFD (uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 newSubFileType);
|
||||
|
||||
bool CheckRawIFD (uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 photometricInterpretation);
|
||||
|
||||
bool CheckCFA (uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 photometricInterpretation);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ParseStringTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagCount,
|
||||
dng_string &s,
|
||||
bool trimBlanks = true);
|
||||
|
||||
void ParseDualStringTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagCount,
|
||||
dng_string &s1,
|
||||
dng_string &s2);
|
||||
|
||||
void ParseEncodedStringTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagCount,
|
||||
dng_string &s);
|
||||
|
||||
bool ParseMatrixTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint32 rows,
|
||||
uint32 cols,
|
||||
dng_matrix &m);
|
||||
|
||||
bool ParseVectorTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
uint32 count,
|
||||
dng_vector &v);
|
||||
|
||||
bool ParseDateTimeTag (dng_stream &stream,
|
||||
uint32 parentCode,
|
||||
uint32 tagCode,
|
||||
uint32 tagType,
|
||||
uint32 tagCount,
|
||||
dng_date_time &dt);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,764 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Support for holding buffers of sample data.
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_pixel_buffer__
|
||||
#define __dng_pixel_buffer__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_rect.h"
|
||||
#include "dng_safe_arithmetic.h"
|
||||
#include "dng_tag_types.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// Compute best set of step values for a given source and destination area and stride.
|
||||
|
||||
void OptimizeOrder (const void *&sPtr,
|
||||
void *&dPtr,
|
||||
uint32 sPixelSize,
|
||||
uint32 dPixelSize,
|
||||
uint32 &count0,
|
||||
uint32 &count1,
|
||||
uint32 &count2,
|
||||
int32 &sStep0,
|
||||
int32 &sStep1,
|
||||
int32 &sStep2,
|
||||
int32 &dStep0,
|
||||
int32 &dStep1,
|
||||
int32 &dStep2);
|
||||
|
||||
void OptimizeOrder (const void *&sPtr,
|
||||
uint32 sPixelSize,
|
||||
uint32 &count0,
|
||||
uint32 &count1,
|
||||
uint32 &count2,
|
||||
int32 &sStep0,
|
||||
int32 &sStep1,
|
||||
int32 &sStep2);
|
||||
|
||||
void OptimizeOrder (void *&dPtr,
|
||||
uint32 dPixelSize,
|
||||
uint32 &count0,
|
||||
uint32 &count1,
|
||||
uint32 &count2,
|
||||
int32 &dStep0,
|
||||
int32 &dStep1,
|
||||
int32 &dStep2);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define qDebugPixelType 0
|
||||
|
||||
#if qDebugPixelType
|
||||
|
||||
#define ASSERT_PIXEL_TYPE(typeVal) CheckPixelType (typeVal)
|
||||
|
||||
#else
|
||||
|
||||
#define ASSERT_PIXEL_TYPE(typeVal) DNG_ASSERT (fPixelType == typeVal, "Pixel type access mismatch")
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/// \brief Holds a buffer of pixel data with "pixel geometry" metadata.
|
||||
///
|
||||
/// The pixel geometry describes the layout in terms of how many planes, rows and columns
|
||||
/// plus the steps (in bytes) between each column, row and plane.
|
||||
|
||||
class dng_pixel_buffer
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// Area this buffer holds.
|
||||
|
||||
dng_rect fArea;
|
||||
|
||||
// Range of planes this buffer holds.
|
||||
|
||||
uint32 fPlane;
|
||||
uint32 fPlanes;
|
||||
|
||||
// Steps between pixels.
|
||||
|
||||
int32 fRowStep;
|
||||
int32 fColStep;
|
||||
int32 fPlaneStep;
|
||||
|
||||
// Basic pixel type (TIFF tag type code).
|
||||
|
||||
uint32 fPixelType;
|
||||
|
||||
// Size of pixel type in bytes.
|
||||
|
||||
uint32 fPixelSize;
|
||||
|
||||
// Pointer to buffer's data.
|
||||
|
||||
void *fData;
|
||||
|
||||
// Do we have write-access to this data?
|
||||
|
||||
bool fDirty;
|
||||
|
||||
private:
|
||||
|
||||
void * InternalPixel (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
// TO DO: review this. do we set up buffers sometimes with "col" parameter
|
||||
// equal to 0, which would then cause this exception to throw?!
|
||||
|
||||
#if 0
|
||||
|
||||
// Ensure pixel to be accessed lies inside valid area.
|
||||
if (row < fArea.t || row >= fArea.b ||
|
||||
col < fArea.l || col >= fArea.r ||
|
||||
plane < fPlane || (plane - fPlane) >= fPlanes)
|
||||
{
|
||||
ThrowProgramError ("Out-of-range pixel access");
|
||||
}
|
||||
|
||||
// Compute offset of pixel.
|
||||
const int64 rowOffset = SafeInt64Mult(fRowStep,
|
||||
static_cast<int64> (row) - static_cast<int64> (fArea.t));
|
||||
const int64 colOffset = SafeInt64Mult(fColStep,
|
||||
static_cast<int64> (col) - static_cast<int64> (fArea.l));
|
||||
const int64 planeOffset = SafeInt64Mult(fPlaneStep,
|
||||
static_cast<int64> (plane - fPlane));
|
||||
const int64 offset = SafeInt64Mult(static_cast<int64>(fPixelSize),
|
||||
SafeInt64Add(SafeInt64Add(rowOffset, colOffset), planeOffset));
|
||||
|
||||
// Add offset to buffer base address.
|
||||
return static_cast<void *> (static_cast<uint8 *> (fData) + offset);
|
||||
|
||||
#else
|
||||
|
||||
#if qDNG64Bit
|
||||
|
||||
return (void *)
|
||||
(((uint8 *) fData) + (int64) fPixelSize *
|
||||
(fRowStep * (int64) (row - fArea.t) +
|
||||
fColStep * (int64) (col - fArea.l) +
|
||||
fPlaneStep * (int64) (plane - fPlane )));
|
||||
|
||||
#else
|
||||
|
||||
return (void *)
|
||||
(((uint8 *) fData) + (int32) fPixelSize *
|
||||
(fRowStep * (int32) (row - fArea.t) +
|
||||
fColStep * (int32) (col - fArea.l) +
|
||||
fPlaneStep * (int32) (plane - fPlane )));
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if qDebugPixelType
|
||||
|
||||
void CheckPixelType (uint32 pixelType) const;
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
dng_pixel_buffer ();
|
||||
|
||||
/// Note: This constructor is for internal use only and should not be
|
||||
/// considered part of the DNG SDK API.
|
||||
///
|
||||
/// Initialize the pixel buffer according to the given parameters (see
|
||||
/// below). May throw an error if arithmetic overflow occurs when
|
||||
/// computing the row, column or plane step, or if an invalid value
|
||||
/// was passed for planarConfiguration.
|
||||
///
|
||||
/// \param area Area covered by the pixel buffer
|
||||
/// \param plane Index of the first plane
|
||||
/// \param planes Number of planes
|
||||
/// \param pixelType Pixel data type (one of the values defined in
|
||||
/// dng_tag_types.h)
|
||||
/// \param planarConfiguration Layout of the pixel planes in memory: One
|
||||
/// of pcInterleaved, pcPlanar, or pcRowInterleaved (defined in
|
||||
/// dng_tag_values.h)
|
||||
/// \param data Pointer to the pixel data
|
||||
|
||||
dng_pixel_buffer (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
uint32 pixelType,
|
||||
uint32 planarConfiguration,
|
||||
void *data);
|
||||
|
||||
dng_pixel_buffer (const dng_pixel_buffer &buffer);
|
||||
|
||||
dng_pixel_buffer & operator= (const dng_pixel_buffer &buffer);
|
||||
|
||||
virtual ~dng_pixel_buffer ();
|
||||
|
||||
/// Get the range of pixel values.
|
||||
/// \retval Range of value a pixel can take. (Meaning [0, max] for unsigned case. Signed case is biased so [-32768, max - 32768].)
|
||||
|
||||
uint32 PixelRange () const;
|
||||
|
||||
/// Get extent of pixels in buffer
|
||||
/// \retval Rectangle giving valid extent of buffer.
|
||||
|
||||
const dng_rect & Area () const
|
||||
{
|
||||
return fArea;
|
||||
}
|
||||
|
||||
/// Number of planes of image data.
|
||||
/// \retval Number of planes held in buffer.
|
||||
|
||||
uint32 Planes () const
|
||||
{
|
||||
return fPlanes;
|
||||
}
|
||||
|
||||
/// Step, in pixels not bytes, between rows of data in buffer.
|
||||
/// \retval row step in pixels. May be negative.
|
||||
|
||||
int32 RowStep () const
|
||||
{
|
||||
return fRowStep;
|
||||
}
|
||||
|
||||
/// Step, in pixels not bytes, between planes of data in buffer.
|
||||
/// \retval plane step in pixels. May be negative.
|
||||
|
||||
int32 PlaneStep () const
|
||||
{
|
||||
return fPlaneStep;
|
||||
}
|
||||
|
||||
/// Get read-only untyped (void *) pointer to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as void *.
|
||||
|
||||
const void * ConstPixel (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
return InternalPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable untyped (void *) pointer to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as void *.
|
||||
|
||||
void * DirtyPixel (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fDirty, "Dirty access to const pixel buffer");
|
||||
|
||||
return InternalPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only uint8 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as uint8 *.
|
||||
|
||||
const uint8 * ConstPixel_uint8 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttByte);
|
||||
|
||||
return (const uint8 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
const uint8 * ConstPixel_uint8_overrideType (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
// No type check
|
||||
|
||||
return (const uint8 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable uint8 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as uint8 *.
|
||||
|
||||
uint8 * DirtyPixel_uint8 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttByte);
|
||||
|
||||
return (uint8 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
uint8 * DirtyPixel_uint8_overrideType (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
// No type check
|
||||
|
||||
return (uint8 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only int8 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as int8 *.
|
||||
|
||||
const int8 * ConstPixel_int8 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttSByte);
|
||||
|
||||
return (const int8 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable int8 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as int8 *.
|
||||
|
||||
int8 * DirtyPixel_int8 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttSByte);
|
||||
|
||||
return (int8 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only uint16 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as uint16 *.
|
||||
|
||||
const uint16 * ConstPixel_uint16 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttShort);
|
||||
|
||||
return (const uint16 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable uint16 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as uint16 *.
|
||||
|
||||
uint16 * DirtyPixel_uint16 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttShort);
|
||||
|
||||
return (uint16 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only int16 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as int16 *.
|
||||
|
||||
const int16 * ConstPixel_int16 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttSShort);
|
||||
|
||||
return (const int16 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable int16 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as int16 *.
|
||||
|
||||
int16 * DirtyPixel_int16 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttSShort);
|
||||
|
||||
return (int16 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only uint32 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as uint32 *.
|
||||
|
||||
const uint32 * ConstPixel_uint32 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttLong);
|
||||
|
||||
return (const uint32 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable uint32 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as uint32 *.
|
||||
|
||||
uint32 * DirtyPixel_uint32 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttLong);
|
||||
|
||||
return (uint32 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only int32 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as int32 *.
|
||||
|
||||
const int32 * ConstPixel_int32 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttSLong);
|
||||
|
||||
return (const int32 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable int32 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as int32 *.
|
||||
|
||||
int32 * DirtyPixel_int32 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttSLong);
|
||||
|
||||
return (int32 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get read-only real32 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as real32 *.
|
||||
|
||||
const real32 * ConstPixel_real32 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0) const
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttFloat);
|
||||
|
||||
return (const real32 *) ConstPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Get a writable real32 * to pixel data starting at a specific pixel in the buffer.
|
||||
/// \param row Start row for buffer pointer.
|
||||
/// \param col Start column for buffer pointer.
|
||||
/// \param plane Start plane for buffer pointer.
|
||||
/// \retval Pointer to pixel data as real32 *.
|
||||
|
||||
real32 * DirtyPixel_real32 (int32 row,
|
||||
int32 col,
|
||||
uint32 plane = 0)
|
||||
{
|
||||
|
||||
ASSERT_PIXEL_TYPE (ttFloat);
|
||||
|
||||
return (real32 *) DirtyPixel (row, col, plane);
|
||||
|
||||
}
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to a constant.
|
||||
/// \param area Rectangle of pixel buffer to set.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
/// \param value Constant value to set pixels to.
|
||||
|
||||
void SetConstant (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
uint32 value);
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to a constant unsigned 8-bit value.
|
||||
/// \param area Rectangle of pixel buffer to set.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
/// \param value Constant uint8 value to set pixels to.
|
||||
|
||||
void SetConstant_uint8 (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
uint8 value)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttByte, "Mismatched pixel type");
|
||||
|
||||
SetConstant (area, plane, planes, (uint32) value);
|
||||
|
||||
}
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to a constant unsigned 16-bit value.
|
||||
/// \param area Rectangle of pixel buffer to set.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
/// \param value Constant uint16 value to set pixels to.
|
||||
|
||||
void SetConstant_uint16 (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
uint16 value)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttShort, "Mismatched pixel type");
|
||||
|
||||
SetConstant (area, plane, planes, (uint32) value);
|
||||
|
||||
}
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to a constant signed 16-bit value.
|
||||
/// \param area Rectangle of pixel buffer to set.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
/// \param value Constant int16 value to set pixels to.
|
||||
|
||||
void SetConstant_int16 (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
int16 value)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttSShort, "Mismatched pixel type");
|
||||
|
||||
SetConstant (area, plane, planes, (uint32) (uint16) value);
|
||||
|
||||
}
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to a constant unsigned 32-bit value.
|
||||
/// \param area Rectangle of pixel buffer to set.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
/// \param value Constant uint32 value to set pixels to.
|
||||
|
||||
void SetConstant_uint32 (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
uint32 value)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttLong, "Mismatched pixel type");
|
||||
|
||||
SetConstant (area, plane, planes, value);
|
||||
|
||||
}
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to a constant real 32-bit value.
|
||||
/// \param area Rectangle of pixel buffer to set.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
/// \param value Constant real32 value to set pixels to.
|
||||
|
||||
void SetConstant_real32 (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes,
|
||||
real32 value)
|
||||
{
|
||||
|
||||
DNG_ASSERT (fPixelType == ttFloat, "Mismatched pixel type");
|
||||
|
||||
union
|
||||
{
|
||||
uint32 i;
|
||||
real32 f;
|
||||
} x;
|
||||
|
||||
x.f = value;
|
||||
|
||||
SetConstant (area, plane, planes, x.i);
|
||||
|
||||
}
|
||||
|
||||
/// Initialize a rectangular area of pixel buffer to zeros.
|
||||
/// \param area Rectangle of pixel buffer to zero.
|
||||
/// \param plane Plane to start filling on.
|
||||
/// \param planes Number of planes to fill.
|
||||
|
||||
void SetZero (const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes);
|
||||
|
||||
/// Copy image data from an area of one pixel buffer to same area of another.
|
||||
/// \param src Buffer to copy from.
|
||||
/// \param area Rectangle of pixel buffer to copy.
|
||||
/// \param srcPlane Plane to start copy in src.
|
||||
/// \param dstPlane Plane to start copy in dst.
|
||||
/// \param planes Number of planes to copy.
|
||||
|
||||
void CopyArea (const dng_pixel_buffer &src,
|
||||
const dng_rect &area,
|
||||
uint32 srcPlane,
|
||||
uint32 dstPlane,
|
||||
uint32 planes);
|
||||
|
||||
/// Copy image data from an area of one pixel buffer to same area of another.
|
||||
/// \param src Buffer to copy from.
|
||||
/// \param area Rectangle of pixel buffer to copy.
|
||||
/// \param plane Plane to start copy in src and this.
|
||||
/// \param planes Number of planes to copy.
|
||||
|
||||
void CopyArea (const dng_pixel_buffer &src,
|
||||
const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes)
|
||||
{
|
||||
|
||||
CopyArea (src, area, plane, plane, planes);
|
||||
|
||||
}
|
||||
|
||||
/// Calculate the offset phase of destination rectangle relative to source rectangle.
|
||||
/// Phase is based on a 0,0 origin and the notion of repeating srcArea across dstArea.
|
||||
/// It is the number of pixels into srcArea to start repeating from when tiling dstArea.
|
||||
/// \retval dng_point containing horizontal and vertical phase.
|
||||
|
||||
static dng_point RepeatPhase (const dng_rect &srcArea,
|
||||
const dng_rect &dstArea);
|
||||
|
||||
/// Repeat the image data in srcArea across dstArea.
|
||||
/// (Generally used for padding operations.)
|
||||
/// \param srcArea Area to repeat from.
|
||||
/// \param dstArea Area to fill with data from srcArea.
|
||||
|
||||
void RepeatArea (const dng_rect &srcArea,
|
||||
const dng_rect &dstArea);
|
||||
|
||||
/// Replicates a sub-area of a buffer to fill the entire buffer.
|
||||
|
||||
void RepeatSubArea (const dng_rect subArea,
|
||||
uint32 repeatV = 1,
|
||||
uint32 repeatH = 1);
|
||||
|
||||
/// Apply a right shift (C++ oerpator >>) to all pixel values. Only implemented for 16-bit (signed or unsigned) pixel buffers.
|
||||
/// \param shift Number of bits by which to right shift each pixel value.
|
||||
|
||||
void ShiftRight (uint32 shift);
|
||||
|
||||
/// Change metadata so pixels are iterated in opposite horizontal order.
|
||||
/// This operation does not require movement of actual pixel data.
|
||||
|
||||
void FlipH ();
|
||||
|
||||
/// Change metadata so pixels are iterated in opposite vertical order.
|
||||
/// This operation does not require movement of actual pixel data.
|
||||
|
||||
void FlipV ();
|
||||
|
||||
/// Change metadata so pixels are iterated in opposite plane order.
|
||||
/// This operation does not require movement of actual pixel data.
|
||||
|
||||
void FlipZ (); // Flip planes
|
||||
|
||||
/// Return true if the contents of an area of the pixel buffer area are the same as those of another.
|
||||
/// \param rhs Buffer to compare against.
|
||||
/// \param area Rectangle of pixel buffer to test.
|
||||
/// \param plane Plane to start comparing.
|
||||
/// \param planes Number of planes to compare.
|
||||
/// \retval bool true if areas are equal, false otherwise.
|
||||
|
||||
bool EqualArea (const dng_pixel_buffer &rhs,
|
||||
const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes) const;
|
||||
|
||||
/// Return the absolute value of the maximum difference between two pixel buffers. Used for comparison testing with tolerance
|
||||
/// \param rhs Buffer to compare against.
|
||||
/// \param area Rectangle of pixel buffer to test.
|
||||
/// \param plane Plane to start comparing.
|
||||
/// \param planes Number of planes to compare.
|
||||
/// \retval larges absolute value difference between the corresponding pixels each buffer across area.
|
||||
|
||||
real64 MaximumDifference (const dng_pixel_buffer &rhs,
|
||||
const dng_rect &area,
|
||||
uint32 plane,
|
||||
uint32 planes) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,15 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_point.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Currently all inlined.
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,313 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2006-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_point__
|
||||
#define __dng_point__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "dng_types.h"
|
||||
#include "dng_utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_point
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
int32 v;
|
||||
int32 h;
|
||||
|
||||
public:
|
||||
|
||||
dng_point ()
|
||||
: v (0)
|
||||
, h (0)
|
||||
{
|
||||
}
|
||||
|
||||
dng_point (int32 vv, int32 hh)
|
||||
: v (vv)
|
||||
, h (hh)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator== (const dng_point &pt) const
|
||||
{
|
||||
return (v == pt.v) &&
|
||||
(h == pt.h);
|
||||
}
|
||||
|
||||
bool operator!= (const dng_point &pt) const
|
||||
{
|
||||
return !(*this == pt);
|
||||
}
|
||||
|
||||
real64 Length () const
|
||||
{
|
||||
return hypot ((real64) v, (real64) h);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_point_real64
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
real64 v;
|
||||
real64 h;
|
||||
|
||||
public:
|
||||
|
||||
dng_point_real64 ()
|
||||
: v (0.0)
|
||||
, h (0.0)
|
||||
{
|
||||
}
|
||||
|
||||
dng_point_real64 (real64 vv, real64 hh)
|
||||
: v (vv)
|
||||
, h (hh)
|
||||
{
|
||||
}
|
||||
|
||||
dng_point_real64 (const dng_point &pt)
|
||||
: v ((real64) pt.v)
|
||||
, h ((real64) pt.h)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator== (const dng_point_real64 &pt) const
|
||||
{
|
||||
return (v == pt.v) &&
|
||||
(h == pt.h);
|
||||
}
|
||||
|
||||
bool operator!= (const dng_point_real64 &pt) const
|
||||
{
|
||||
return !(*this == pt);
|
||||
}
|
||||
|
||||
dng_point Round () const
|
||||
{
|
||||
return dng_point (Round_int32 (v),
|
||||
Round_int32 (h));
|
||||
}
|
||||
|
||||
real64 Length () const
|
||||
{
|
||||
return hypot (v, h);
|
||||
}
|
||||
|
||||
void Scale (real64 scale)
|
||||
{
|
||||
v *= scale;
|
||||
h *= scale;
|
||||
}
|
||||
|
||||
void Normalize ()
|
||||
{
|
||||
Scale (1.0 / Length ());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point operator+ (const dng_point &a,
|
||||
const dng_point &b)
|
||||
|
||||
|
||||
{
|
||||
|
||||
return dng_point (a.v + b.v,
|
||||
a.h + b.h);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point_real64 operator+ (const dng_point_real64 &a,
|
||||
const dng_point_real64 &b)
|
||||
|
||||
|
||||
{
|
||||
|
||||
return dng_point_real64 (a.v + b.v,
|
||||
a.h + b.h);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point operator- (const dng_point &a,
|
||||
const dng_point &b)
|
||||
|
||||
|
||||
{
|
||||
|
||||
return dng_point (a.v - b.v,
|
||||
a.h - b.h);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point_real64 operator- (const dng_point_real64 &a,
|
||||
const dng_point_real64 &b)
|
||||
|
||||
|
||||
{
|
||||
|
||||
return dng_point_real64 (a.v - b.v,
|
||||
a.h - b.h);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline real64 Distance (const dng_point_real64 &a,
|
||||
const dng_point_real64 &b)
|
||||
|
||||
|
||||
{
|
||||
|
||||
return (a - b).Length ();
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline real64 DistanceSquared (const dng_point_real64 &a,
|
||||
const dng_point_real64 &b)
|
||||
|
||||
|
||||
{
|
||||
|
||||
dng_point_real64 diff = a - b;
|
||||
|
||||
return (diff.v * diff.v) + (diff.h * diff.h);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Finds distance squared from point p to line segment from v to w.
|
||||
|
||||
inline real64 DistanceSquared (const dng_point_real64 &p,
|
||||
const dng_point_real64 &v,
|
||||
const dng_point_real64 &w)
|
||||
{
|
||||
|
||||
real64 len2 = DistanceSquared (v, w);
|
||||
|
||||
if (len2 == 0.0)
|
||||
return DistanceSquared (p, v);
|
||||
|
||||
real64 t = ((p.h - v.h) * (w.h - v.h) +
|
||||
(p.v - v.v) * (w.v - v.v)) / len2;
|
||||
|
||||
if (t <= 0.0)
|
||||
return DistanceSquared (p, v);
|
||||
|
||||
if (t >= 1.0)
|
||||
return DistanceSquared (p, w);
|
||||
|
||||
dng_point_real64 z;
|
||||
|
||||
z.h = v.h + t * (w.h - v.h);
|
||||
z.v = v.v + t * (w.v - v.v);
|
||||
|
||||
return DistanceSquared (p, z);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point Transpose (const dng_point &a)
|
||||
{
|
||||
|
||||
return dng_point (a.h, a.v);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point_real64 Transpose (const dng_point_real64 &a)
|
||||
{
|
||||
|
||||
return dng_point_real64 (a.h, a.v);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point_real64 Lerp (const dng_point_real64 &a,
|
||||
const dng_point_real64 &b,
|
||||
const real64 t)
|
||||
{
|
||||
|
||||
return dng_point_real64 (Lerp_real64 (a.v, b.v, t),
|
||||
Lerp_real64 (a.h, b.h, t));
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline real64 Dot (const dng_point_real64 &a,
|
||||
const dng_point_real64 &b)
|
||||
{
|
||||
|
||||
return (a.h * b.h) + (a.v * b.v);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point_real64 operator* (const real64 scale,
|
||||
const dng_point_real64 &pt)
|
||||
{
|
||||
|
||||
dng_point_real64 result = pt;
|
||||
|
||||
result.h *= scale;
|
||||
result.v *= scale;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point MakePerpendicular (const dng_point &pt)
|
||||
{
|
||||
|
||||
return dng_point (-pt.h, pt.v);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
inline dng_point_real64 MakePerpendicular (const dng_point_real64 &pt)
|
||||
{
|
||||
|
||||
return dng_point_real64 (-pt.h, pt.v);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,802 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2007-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_preview.h"
|
||||
|
||||
#include "dng_assertions.h"
|
||||
#include "dng_image.h"
|
||||
#include "dng_image_writer.h"
|
||||
#include "dng_memory.h"
|
||||
#include "dng_stream.h"
|
||||
#include "dng_tag_codes.h"
|
||||
#include "dng_tag_values.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_preview_tag_set: public dng_basic_tag_set
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
tag_string fApplicationNameTag;
|
||||
|
||||
tag_string fApplicationVersionTag;
|
||||
|
||||
tag_string fSettingsNameTag;
|
||||
|
||||
dng_fingerprint fSettingsDigest;
|
||||
|
||||
tag_uint8_ptr fSettingsDigestTag;
|
||||
|
||||
tag_uint32 fColorSpaceTag;
|
||||
|
||||
tag_string fDateTimeTag;
|
||||
|
||||
tag_real64 fRawToPreviewGainTag;
|
||||
|
||||
tag_uint32 fCacheVersionTag;
|
||||
|
||||
public:
|
||||
|
||||
dng_preview_tag_set (dng_tiff_directory &directory,
|
||||
const dng_preview &preview,
|
||||
const dng_ifd &ifd);
|
||||
|
||||
virtual ~dng_preview_tag_set ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_preview_tag_set::dng_preview_tag_set (dng_tiff_directory &directory,
|
||||
const dng_preview &preview,
|
||||
const dng_ifd &ifd)
|
||||
|
||||
: dng_basic_tag_set (directory, ifd)
|
||||
|
||||
, fApplicationNameTag (tcPreviewApplicationName,
|
||||
preview.fInfo.fApplicationName,
|
||||
false)
|
||||
|
||||
, fApplicationVersionTag (tcPreviewApplicationVersion,
|
||||
preview.fInfo.fApplicationVersion,
|
||||
false)
|
||||
|
||||
, fSettingsNameTag (tcPreviewSettingsName,
|
||||
preview.fInfo.fSettingsName,
|
||||
false)
|
||||
|
||||
, fSettingsDigest (preview.fInfo.fSettingsDigest)
|
||||
|
||||
, fSettingsDigestTag (tcPreviewSettingsDigest,
|
||||
fSettingsDigest.data,
|
||||
16)
|
||||
|
||||
, fColorSpaceTag (tcPreviewColorSpace,
|
||||
preview.fInfo.fColorSpace)
|
||||
|
||||
, fDateTimeTag (tcPreviewDateTime,
|
||||
preview.fInfo.fDateTime,
|
||||
true)
|
||||
|
||||
, fRawToPreviewGainTag (tcRawToPreviewGain,
|
||||
preview.fInfo.fRawToPreviewGain)
|
||||
|
||||
, fCacheVersionTag (tcCacheVersion,
|
||||
preview.fInfo.fCacheVersion)
|
||||
|
||||
{
|
||||
|
||||
if (preview.fInfo.fApplicationName.NotEmpty ())
|
||||
{
|
||||
|
||||
directory.Add (&fApplicationNameTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fApplicationVersion.NotEmpty ())
|
||||
{
|
||||
|
||||
directory.Add (&fApplicationVersionTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fSettingsName.NotEmpty ())
|
||||
{
|
||||
|
||||
directory.Add (&fSettingsNameTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fSettingsDigest.IsValid ())
|
||||
{
|
||||
|
||||
directory.Add (&fSettingsDigestTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fColorSpace != previewColorSpace_MaxEnum)
|
||||
{
|
||||
|
||||
directory.Add (&fColorSpaceTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fDateTime.NotEmpty ())
|
||||
{
|
||||
|
||||
directory.Add (&fDateTimeTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fRawToPreviewGain != 1.0)
|
||||
{
|
||||
|
||||
directory.Add (&fRawToPreviewGainTag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fInfo.fCacheVersion != 0)
|
||||
{
|
||||
|
||||
directory.Add (&fCacheVersionTag);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_preview_tag_set::~dng_preview_tag_set ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_preview::dng_preview ()
|
||||
|
||||
: fInfo ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_preview::~dng_preview ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_image_preview::dng_image_preview ()
|
||||
|
||||
: fImage ()
|
||||
, fIFD ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_image_preview::~dng_image_preview ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_basic_tag_set * dng_image_preview::AddTagSet (dng_tiff_directory &directory) const
|
||||
{
|
||||
|
||||
fIFD.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
|
||||
: sfAltPreviewImage;
|
||||
|
||||
fIFD.fImageWidth = fImage->Width ();
|
||||
fIFD.fImageLength = fImage->Height ();
|
||||
|
||||
fIFD.fSamplesPerPixel = fImage->Planes ();
|
||||
|
||||
fIFD.fPhotometricInterpretation = fIFD.fSamplesPerPixel == 1 ? piBlackIsZero
|
||||
: piRGB;
|
||||
|
||||
fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
|
||||
|
||||
for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
|
||||
{
|
||||
fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
|
||||
}
|
||||
|
||||
fIFD.SetSingleStrip ();
|
||||
|
||||
return new dng_preview_tag_set (directory, *this, fIFD);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_image_preview::WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const
|
||||
{
|
||||
|
||||
writer.WriteImage (host,
|
||||
fIFD,
|
||||
basic,
|
||||
stream,
|
||||
*fImage.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_jpeg_preview_tag_set: public dng_preview_tag_set
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
dng_urational fCoefficientsData [3];
|
||||
|
||||
tag_urational_ptr fCoefficientsTag;
|
||||
|
||||
uint16 fSubSamplingData [2];
|
||||
|
||||
tag_uint16_ptr fSubSamplingTag;
|
||||
|
||||
tag_uint16 fPositioningTag;
|
||||
|
||||
dng_urational fReferenceData [6];
|
||||
|
||||
tag_urational_ptr fReferenceTag;
|
||||
|
||||
public:
|
||||
|
||||
dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
|
||||
const dng_jpeg_preview &preview,
|
||||
const dng_ifd &ifd);
|
||||
|
||||
virtual ~dng_jpeg_preview_tag_set ();
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
dng_jpeg_preview_tag_set::dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
|
||||
const dng_jpeg_preview &preview,
|
||||
const dng_ifd &ifd)
|
||||
|
||||
: dng_preview_tag_set (directory, preview, ifd)
|
||||
|
||||
, fCoefficientsTag (tcYCbCrCoefficients, fCoefficientsData, 3)
|
||||
|
||||
, fSubSamplingTag (tcYCbCrSubSampling, fSubSamplingData, 2)
|
||||
|
||||
, fPositioningTag (tcYCbCrPositioning, preview.fYCbCrPositioning)
|
||||
|
||||
, fReferenceTag (tcReferenceBlackWhite, fReferenceData, 6)
|
||||
|
||||
{
|
||||
|
||||
if (preview.fPhotometricInterpretation == piYCbCr)
|
||||
{
|
||||
|
||||
fCoefficientsData [0] = dng_urational (299, 1000);
|
||||
fCoefficientsData [1] = dng_urational (587, 1000);
|
||||
fCoefficientsData [2] = dng_urational (114, 1000);
|
||||
|
||||
directory.Add (&fCoefficientsTag);
|
||||
|
||||
fSubSamplingData [0] = (uint16) preview.fYCbCrSubSampling.h;
|
||||
fSubSamplingData [1] = (uint16) preview.fYCbCrSubSampling.v;
|
||||
|
||||
directory.Add (&fSubSamplingTag);
|
||||
|
||||
directory.Add (&fPositioningTag);
|
||||
|
||||
fReferenceData [0] = dng_urational ( 0, 1);
|
||||
fReferenceData [1] = dng_urational (255, 1);
|
||||
fReferenceData [2] = dng_urational (128, 1);
|
||||
fReferenceData [3] = dng_urational (255, 1);
|
||||
fReferenceData [4] = dng_urational (128, 1);
|
||||
fReferenceData [5] = dng_urational (255, 1);
|
||||
|
||||
directory.Add (&fReferenceTag);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_jpeg_preview_tag_set::~dng_jpeg_preview_tag_set ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_jpeg_preview::dng_jpeg_preview ()
|
||||
|
||||
: fPreviewSize ()
|
||||
, fPhotometricInterpretation (piYCbCr)
|
||||
, fYCbCrSubSampling (1, 1)
|
||||
, fYCbCrPositioning (2)
|
||||
, fCompressedData ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_jpeg_preview::~dng_jpeg_preview ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_basic_tag_set * dng_jpeg_preview::AddTagSet (dng_tiff_directory &directory) const
|
||||
{
|
||||
|
||||
dng_ifd ifd;
|
||||
|
||||
ifd.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
|
||||
: sfAltPreviewImage;
|
||||
|
||||
ifd.fImageWidth = fPreviewSize.h;
|
||||
ifd.fImageLength = fPreviewSize.v;
|
||||
|
||||
ifd.fPhotometricInterpretation = fPhotometricInterpretation;
|
||||
|
||||
ifd.fBitsPerSample [0] = 8;
|
||||
ifd.fBitsPerSample [1] = 8;
|
||||
ifd.fBitsPerSample [2] = 8;
|
||||
|
||||
ifd.fSamplesPerPixel = (fPhotometricInterpretation == piBlackIsZero ? 1 : 3);
|
||||
|
||||
ifd.fCompression = ccJPEG;
|
||||
ifd.fPredictor = cpNullPredictor;
|
||||
|
||||
ifd.SetSingleStrip ();
|
||||
|
||||
return new dng_jpeg_preview_tag_set (directory, *this, ifd);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_jpeg_preview::WriteData (dng_host & /* host */,
|
||||
dng_image_writer & /* writer */,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const
|
||||
{
|
||||
|
||||
basic.SetTileOffset (0, (uint32) stream.Position ());
|
||||
|
||||
basic.SetTileByteCount (0, fCompressedData->LogicalSize ());
|
||||
|
||||
stream.Put (fCompressedData->Buffer (),
|
||||
fCompressedData->LogicalSize ());
|
||||
|
||||
if (fCompressedData->LogicalSize () & 1)
|
||||
{
|
||||
stream.Put_uint8 (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_jpeg_preview::SpoolAdobeThumbnail (dng_stream &stream) const
|
||||
{
|
||||
|
||||
DNG_ASSERT (fCompressedData.Get (),
|
||||
"SpoolAdobeThumbnail: no data");
|
||||
|
||||
DNG_ASSERT (fPhotometricInterpretation == piYCbCr,
|
||||
"SpoolAdobeThumbnail: Non-YCbCr");
|
||||
|
||||
uint32 compressedSize = fCompressedData->LogicalSize ();
|
||||
|
||||
stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
|
||||
stream.Put_uint16 (1036);
|
||||
stream.Put_uint16 (0);
|
||||
|
||||
stream.Put_uint32 (compressedSize + 28);
|
||||
|
||||
uint32 widthBytes = (fPreviewSize.h * 24 + 31) / 32 * 4;
|
||||
|
||||
stream.Put_uint32 (1);
|
||||
stream.Put_uint32 (fPreviewSize.h);
|
||||
stream.Put_uint32 (fPreviewSize.v);
|
||||
stream.Put_uint32 (widthBytes);
|
||||
stream.Put_uint32 (widthBytes * fPreviewSize.v);
|
||||
stream.Put_uint32 (compressedSize);
|
||||
stream.Put_uint16 (24);
|
||||
stream.Put_uint16 (1);
|
||||
|
||||
stream.Put (fCompressedData->Buffer (),
|
||||
compressedSize);
|
||||
|
||||
if (compressedSize & 1)
|
||||
{
|
||||
stream.Put_uint8 (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_raw_preview_tag_set: public dng_preview_tag_set
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
tag_data_ptr fOpcodeList2Tag;
|
||||
|
||||
tag_uint32_ptr fWhiteLevelTag;
|
||||
|
||||
uint32 fWhiteLevelData [kMaxColorPlanes];
|
||||
|
||||
tag_urational_ptr fBlackLevelTag;
|
||||
|
||||
dng_urational fBlackLevelData [kMaxColorPlanes];
|
||||
|
||||
public:
|
||||
|
||||
dng_raw_preview_tag_set (dng_tiff_directory &directory,
|
||||
const dng_raw_preview &preview,
|
||||
const dng_ifd &ifd);
|
||||
|
||||
virtual ~dng_raw_preview_tag_set ();
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_raw_preview_tag_set::dng_raw_preview_tag_set (dng_tiff_directory &directory,
|
||||
const dng_raw_preview &preview,
|
||||
const dng_ifd &ifd)
|
||||
|
||||
: dng_preview_tag_set (directory, preview, ifd)
|
||||
|
||||
, fOpcodeList2Tag (tcOpcodeList2,
|
||||
ttUndefined,
|
||||
0,
|
||||
NULL)
|
||||
|
||||
, fWhiteLevelTag (tcWhiteLevel,
|
||||
fWhiteLevelData,
|
||||
preview.fImage->Planes ())
|
||||
|
||||
, fBlackLevelTag (tcBlackLevel,
|
||||
fBlackLevelData,
|
||||
preview.fImage->Planes ())
|
||||
|
||||
{
|
||||
|
||||
if (preview.fOpcodeList2Data.Get ())
|
||||
{
|
||||
|
||||
fOpcodeList2Tag.SetData (preview.fOpcodeList2Data->Buffer ());
|
||||
fOpcodeList2Tag.SetCount (preview.fOpcodeList2Data->LogicalSize ());
|
||||
|
||||
directory.Add (&fOpcodeList2Tag);
|
||||
|
||||
}
|
||||
|
||||
if (preview.fImage->PixelType () == ttFloat)
|
||||
{
|
||||
|
||||
for (uint32 j = 0; j < kMaxColorPlanes; j++)
|
||||
{
|
||||
fWhiteLevelData [j] = 32768;
|
||||
}
|
||||
|
||||
directory.Add (&fWhiteLevelTag);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
bool nonZeroBlack = false;
|
||||
|
||||
for (uint32 j = 0; j < preview.fImage->Planes (); j++)
|
||||
{
|
||||
|
||||
fBlackLevelData [j].Set_real64 (preview.fBlackLevel [j], 1);
|
||||
|
||||
nonZeroBlack = nonZeroBlack || (preview.fBlackLevel [j] != 0.0);
|
||||
|
||||
}
|
||||
|
||||
if (nonZeroBlack)
|
||||
{
|
||||
|
||||
directory.Add (&fBlackLevelTag);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_raw_preview_tag_set::~dng_raw_preview_tag_set ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_raw_preview::dng_raw_preview ()
|
||||
|
||||
: fImage ()
|
||||
, fOpcodeList2Data ()
|
||||
, fCompressionQuality (-1)
|
||||
, fIFD ()
|
||||
|
||||
{
|
||||
|
||||
for (uint32 n = 0; n < kMaxSamplesPerPixel; n++)
|
||||
{
|
||||
fBlackLevel [n] = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_raw_preview::~dng_raw_preview ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_basic_tag_set * dng_raw_preview::AddTagSet (dng_tiff_directory &directory) const
|
||||
{
|
||||
|
||||
fIFD.fNewSubFileType = sfPreviewImage;
|
||||
|
||||
fIFD.fImageWidth = fImage->Width ();
|
||||
fIFD.fImageLength = fImage->Height ();
|
||||
|
||||
fIFD.fSamplesPerPixel = fImage->Planes ();
|
||||
|
||||
fIFD.fPhotometricInterpretation = piLinearRaw;
|
||||
|
||||
if (fImage->PixelType () == ttFloat)
|
||||
{
|
||||
|
||||
fIFD.fCompression = ccDeflate;
|
||||
|
||||
fIFD.fCompressionQuality = fCompressionQuality;
|
||||
|
||||
fIFD.fPredictor = cpFloatingPoint;
|
||||
|
||||
for (uint32 j = 0; j < fIFD.fSamplesPerPixel; j++)
|
||||
{
|
||||
fIFD.fBitsPerSample [j] = 16;
|
||||
fIFD.fSampleFormat [j] = sfFloatingPoint;
|
||||
}
|
||||
|
||||
fIFD.FindTileSize (512 * 1024);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
fIFD.fCompression = ccLossyJPEG;
|
||||
|
||||
fIFD.fCompressionQuality = fCompressionQuality;
|
||||
|
||||
fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
|
||||
|
||||
for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
|
||||
{
|
||||
fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
|
||||
}
|
||||
|
||||
fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
|
||||
|
||||
}
|
||||
|
||||
return new dng_raw_preview_tag_set (directory, *this, fIFD);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_raw_preview::WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const
|
||||
{
|
||||
|
||||
writer.WriteImage (host,
|
||||
fIFD,
|
||||
basic,
|
||||
stream,
|
||||
*fImage.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_mask_preview::dng_mask_preview ()
|
||||
|
||||
: fImage ()
|
||||
, fCompressionQuality (-1)
|
||||
, fIFD ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_mask_preview::~dng_mask_preview ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_basic_tag_set * dng_mask_preview::AddTagSet (dng_tiff_directory &directory) const
|
||||
{
|
||||
|
||||
fIFD.fNewSubFileType = sfPreviewMask;
|
||||
|
||||
fIFD.fImageWidth = fImage->Width ();
|
||||
fIFD.fImageLength = fImage->Height ();
|
||||
|
||||
fIFD.fSamplesPerPixel = 1;
|
||||
|
||||
fIFD.fPhotometricInterpretation = piTransparencyMask;
|
||||
|
||||
fIFD.fCompression = ccDeflate;
|
||||
fIFD.fPredictor = cpHorizontalDifference;
|
||||
|
||||
fIFD.fCompressionQuality = fCompressionQuality;
|
||||
|
||||
fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
|
||||
|
||||
fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
|
||||
|
||||
return new dng_basic_tag_set (directory, fIFD);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_mask_preview::WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const
|
||||
{
|
||||
|
||||
writer.WriteImage (host,
|
||||
fIFD,
|
||||
basic,
|
||||
stream,
|
||||
*fImage.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_depth_preview::dng_depth_preview ()
|
||||
|
||||
: fImage ()
|
||||
, fCompressionQuality (-1)
|
||||
, fFullResolution (false)
|
||||
, fIFD ()
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_depth_preview::~dng_depth_preview ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_basic_tag_set * dng_depth_preview::AddTagSet (dng_tiff_directory &directory) const
|
||||
{
|
||||
|
||||
fIFD.fNewSubFileType = fFullResolution ? sfDepthMap
|
||||
: sfPreviewDepthMap;
|
||||
|
||||
fIFD.fImageWidth = fImage->Width ();
|
||||
fIFD.fImageLength = fImage->Height ();
|
||||
|
||||
fIFD.fSamplesPerPixel = 1;
|
||||
|
||||
fIFD.fPhotometricInterpretation = piDepth;
|
||||
|
||||
fIFD.fCompression = ccDeflate;
|
||||
fIFD.fPredictor = cpHorizontalDifference;
|
||||
|
||||
fIFD.fCompressionQuality = fCompressionQuality;
|
||||
|
||||
fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
|
||||
|
||||
fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
|
||||
|
||||
return new dng_basic_tag_set (directory, fIFD);
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_depth_preview::WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const
|
||||
{
|
||||
|
||||
writer.WriteImage (host,
|
||||
fIFD,
|
||||
basic,
|
||||
stream,
|
||||
*fImage.Get ());
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_preview_list::dng_preview_list ()
|
||||
|
||||
: fCount (0)
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
dng_preview_list::~dng_preview_list ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void dng_preview_list::Append (AutoPtr<dng_preview> &preview)
|
||||
{
|
||||
|
||||
if (preview.Get ())
|
||||
{
|
||||
|
||||
DNG_ASSERT (fCount < kMaxDNGPreviews, "DNG preview list overflow");
|
||||
|
||||
if (fCount < kMaxDNGPreviews)
|
||||
{
|
||||
|
||||
fPreview [fCount++] . Reset (preview.Release ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -0,0 +1,241 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2007-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __dng_preview__
|
||||
#define __dng_preview__
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_auto_ptr.h"
|
||||
#include "dng_classes.h"
|
||||
#include "dng_ifd.h"
|
||||
#include "dng_opcode_list.h"
|
||||
#include "dng_point.h"
|
||||
#include "dng_sdk_limits.h"
|
||||
#include "dng_uncopyable.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_preview: private dng_uncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_preview_info fInfo;
|
||||
|
||||
protected:
|
||||
|
||||
dng_preview ();
|
||||
|
||||
public:
|
||||
|
||||
virtual ~dng_preview ();
|
||||
|
||||
virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const = 0;
|
||||
|
||||
virtual void WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const = 0;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_image_preview: public dng_preview
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
AutoPtr<dng_image> fImage;
|
||||
|
||||
private:
|
||||
|
||||
mutable dng_ifd fIFD;
|
||||
|
||||
public:
|
||||
|
||||
dng_image_preview ();
|
||||
|
||||
virtual ~dng_image_preview ();
|
||||
|
||||
virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
|
||||
|
||||
virtual void WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_jpeg_preview: public dng_preview
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
dng_point fPreviewSize;
|
||||
|
||||
uint16 fPhotometricInterpretation;
|
||||
|
||||
dng_point fYCbCrSubSampling;
|
||||
|
||||
uint16 fYCbCrPositioning;
|
||||
|
||||
AutoPtr<dng_memory_block> fCompressedData;
|
||||
|
||||
public:
|
||||
|
||||
dng_jpeg_preview ();
|
||||
|
||||
virtual ~dng_jpeg_preview ();
|
||||
|
||||
virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
|
||||
|
||||
virtual void WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const;
|
||||
|
||||
void SpoolAdobeThumbnail (dng_stream &stream) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_raw_preview: public dng_preview
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
AutoPtr<dng_image> fImage;
|
||||
|
||||
AutoPtr<dng_memory_block> fOpcodeList2Data;
|
||||
|
||||
real64 fBlackLevel [kMaxSamplesPerPixel];
|
||||
|
||||
int32 fCompressionQuality;
|
||||
|
||||
private:
|
||||
|
||||
mutable dng_ifd fIFD;
|
||||
|
||||
public:
|
||||
|
||||
dng_raw_preview ();
|
||||
|
||||
virtual ~dng_raw_preview ();
|
||||
|
||||
virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
|
||||
|
||||
virtual void WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_depth_preview: public dng_preview
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
AutoPtr<dng_image> fImage;
|
||||
|
||||
int32 fCompressionQuality;
|
||||
|
||||
bool fFullResolution;
|
||||
|
||||
private:
|
||||
|
||||
mutable dng_ifd fIFD;
|
||||
|
||||
public:
|
||||
|
||||
dng_depth_preview ();
|
||||
|
||||
virtual ~dng_depth_preview ();
|
||||
|
||||
virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
|
||||
|
||||
virtual void WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_mask_preview: public dng_preview
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
AutoPtr<dng_image> fImage;
|
||||
|
||||
int32 fCompressionQuality;
|
||||
|
||||
private:
|
||||
|
||||
mutable dng_ifd fIFD;
|
||||
|
||||
public:
|
||||
|
||||
dng_mask_preview ();
|
||||
|
||||
virtual ~dng_mask_preview ();
|
||||
|
||||
virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
|
||||
|
||||
virtual void WriteData (dng_host &host,
|
||||
dng_image_writer &writer,
|
||||
dng_basic_tag_set &basic,
|
||||
dng_stream &stream) const;
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class dng_preview_list
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
uint32 fCount;
|
||||
|
||||
AutoPtr<dng_preview> fPreview [kMaxDNGPreviews];
|
||||
|
||||
public:
|
||||
|
||||
dng_preview_list ();
|
||||
|
||||
~dng_preview_list ();
|
||||
|
||||
uint32 Count () const
|
||||
{
|
||||
return fCount;
|
||||
}
|
||||
|
||||
const dng_preview & Preview (uint32 index) const
|
||||
{
|
||||
return *(fPreview [index]);
|
||||
}
|
||||
|
||||
void Append (AutoPtr<dng_preview> &preview);
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,250 @@
|
||||
/*****************************************************************************/
|
||||
// Copyright 2002-2019 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef DNG_PTHREAD
|
||||
#define DNG_PTHREAD
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "dng_flags.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if qDNGThreadSafe
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if !qWinOS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Try generic POSIX compile */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define dng_pthread_disassociate()
|
||||
#define dng_pthread_terminate()
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#else
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if _MSC_VER >= 1600
|
||||
|
||||
// Get this included so ETIMEDOUT is predefined.
|
||||
#include <errno.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define DNG_ETIMEDOUT 60 /* Operation timed out */
|
||||
|
||||
struct dng_timespec {
|
||||
long tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
|
||||
|
||||
typedef unsigned long dng_pthread_t;
|
||||
|
||||
typedef struct dng_pthread_mutex_impl *dng_pthread_mutex_t;
|
||||
typedef struct dng_pthread_cond_impl *dng_pthread_cond_t;
|
||||
typedef unsigned long dng_pthread_key_t;
|
||||
|
||||
|
||||
#define DNG_PTHREAD_MUTEX_INITIALIZER ((struct dng_pthread_mutex_impl *)-1)
|
||||
#define DNG_PTHREAD_COND_INITIALIZER ((struct dng_pthread_cond_impl *)-1)
|
||||
|
||||
struct _dng_pthread_once_t {
|
||||
int inited;
|
||||
long semaphore;
|
||||
};
|
||||
|
||||
typedef struct _dng_pthread_once_t dng_pthread_once_t;
|
||||
#define DNG_PTHREAD_ONCE_INIT { 0, -1 }
|
||||
|
||||
#define dng_pthread_equal(t1, t2) ((t1) == (t2))
|
||||
|
||||
typedef struct dng_pthread_attr_impl *dng_pthread_attr_t;
|
||||
|
||||
int dng_pthread_attr_init(dng_pthread_attr_t *attr);
|
||||
int dng_pthread_attr_destroy(dng_pthread_attr_t *attr);
|
||||
|
||||
int dng_pthread_attr_setstacksize(dng_pthread_attr_t *attr, size_t stacksize);
|
||||
int dng_pthread_attr_getstacksize(const dng_pthread_attr_t *attr, size_t *stacksize);
|
||||
|
||||
int dng_pthread_create(dng_pthread_t *thread, const dng_pthread_attr_t * /* attrs */, void * (*func)(void *), void *arg);
|
||||
int dng_pthread_detach(dng_pthread_t thread);
|
||||
int dng_pthread_join(dng_pthread_t thread, void **result);
|
||||
dng_pthread_t dng_pthread_self();
|
||||
void dng_pthread_exit(void *result);
|
||||
|
||||
#define DNG_PTHREAD_MUTEX_RECURSIVE 0
|
||||
typedef unsigned long dng_pthread_mutexattr_t;
|
||||
|
||||
int dng_pthread_mutexattr_init(dng_pthread_mutexattr_t *mutexattr);
|
||||
int dng_pthread_mutexattr_settype(dng_pthread_mutexattr_t *mutexattr, int /*the options*/);
|
||||
|
||||
int dng_pthread_mutex_init(dng_pthread_mutex_t *mutex, void * /* attrs */);
|
||||
int dng_pthread_mutex_destroy(dng_pthread_mutex_t *mutex);
|
||||
int dng_pthread_mutex_lock(dng_pthread_mutex_t *mutex);
|
||||
int dng_pthread_mutex_unlock(dng_pthread_mutex_t *mutex);
|
||||
|
||||
int dng_pthread_cond_init(dng_pthread_cond_t *cond, void * /* attrs */);
|
||||
int dng_pthread_cond_destroy(dng_pthread_cond_t *cond);
|
||||
int dng_pthread_cond_wait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex);
|
||||
int dng_pthread_cond_timedwait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, struct dng_timespec *latest_time);
|
||||
int dng_pthread_cond_signal(dng_pthread_cond_t *cond);
|
||||
int dng_pthread_cond_broadcast(dng_pthread_cond_t *cond);
|
||||
|
||||
int dng_pthread_once(dng_pthread_once_t *once, void (*init_func)());
|
||||
|
||||
int dng_pthread_key_create(dng_pthread_key_t * key, void (*destructor) (void *));
|
||||
int dng_pthread_key_delete(dng_pthread_key_t key);
|
||||
int dng_pthread_setspecific(dng_pthread_key_t key, const void *value);
|
||||
void *dng_pthread_getspecific(dng_pthread_key_t key);
|
||||
|
||||
typedef struct dng_pthread_rwlock_impl *dng_pthread_rwlock_t;
|
||||
typedef void *pthread_rwlockattr1_t;
|
||||
|
||||
int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t * rwlock);
|
||||
int dng_pthread_rwlock_init(dng_pthread_rwlock_t * rwlock, const pthread_rwlockattr1_t * attrs);
|
||||
int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t * rwlock);
|
||||
int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t * rwlock);
|
||||
int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t * rwlock);
|
||||
int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t * rwlock);
|
||||
int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t * rwlock);
|
||||
|
||||
// dng_pthread may maintain per-thread global state. This routine frees that global state.
|
||||
// there is no need to call this for threads created by dng_pthread and one can call
|
||||
// dng_pthread routines of a thread after dng_pthread_disassociate as the global state will
|
||||
// be recreated as necessary. However dng_pthread_disassociate will need to be called again
|
||||
// and there is a slight performance cost. Do not call this routine while holding a mutex, etc.
|
||||
void dng_pthread_disassociate();
|
||||
|
||||
void dng_pthread_terminate();
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Map symbols back to plain pthread names. This whole mechanism is so the DNG pthreads library
|
||||
// symbols do not collide with another pthread emulation library
|
||||
// that may be in use in the same linked entity. However if that is the case, it would be far better
|
||||
// to have the DNG code use the same pthread library as the rest of the code.
|
||||
|
||||
//HERWIG#define pthread_t dng_pthread_t
|
||||
//HERWIG#define pthread_mutex_t dng_pthread_mutex_t
|
||||
//HERWIG#define pthread_cond_t dng_pthread_cond_t
|
||||
//HERWIG#define pthread_once_t dng_pthread_once_t
|
||||
//HERWIG#define pthread_key_t dng_pthread_key_t
|
||||
|
||||
#undef PTHREAD_MUTEX_INITIALIZER
|
||||
#define PTHREAD_MUTEX_INITIALIZER DNG_PTHREAD_MUTEX_INITIALIZER
|
||||
#undef PTHREAD_COND_INITIALIZER
|
||||
#define PTHREAD_COND_INITIALIZER DNG_PTHREAD_COND_INITIALIZER
|
||||
|
||||
#undef PTHREAD_ONCE_INIT
|
||||
#define PTHREAD_ONCE_INIT DNG_PTHREAD_ONCE_INIT
|
||||
|
||||
#if _MSC_VER < 1900
|
||||
#define timespec dng_timespec
|
||||
#endif
|
||||
|
||||
/* If it is defined on Windows, it probably has the wrong value... */
|
||||
#if defined(WIN32) || !defined(ETIMEDOUT)
|
||||
#undef ETIMEDOUT
|
||||
#define ETIMEDOUT DNG_ETIMEDOUT
|
||||
#endif
|
||||
|
||||
//HERWIG#define pthread_equal dng_pthread_equal
|
||||
|
||||
//HERWIG#define pthread_attr_t dng_pthread_attr_t
|
||||
|
||||
//HERWIG#define pthread_attr_init dng_pthread_attr_init
|
||||
//HERWIG#define pthread_attr_destroy dng_pthread_attr_destroy
|
||||
|
||||
//HERWIG#define pthread_attr_setstacksize dng_pthread_attr_setstacksize
|
||||
//HERWIG#define pthread_attr_getstacksize dng_pthread_attr_getstacksize
|
||||
|
||||
//HERWIG#define pthread_create dng_pthread_create
|
||||
//HERWIG#define pthread_detach dng_pthread_detach
|
||||
//HERWIG#define pthread_join dng_pthread_join
|
||||
//HERWIG#define pthread_self dng_pthread_self
|
||||
#define pthread_exit dng_pthread_exit
|
||||
|
||||
//HERWIG#define pthread_mutex_init dng_pthread_mutex_init
|
||||
//HERWIG#define pthread_mutex_destroy dng_pthread_mutex_destroy
|
||||
//HERWIG#define pthread_mutex_lock dng_pthread_mutex_lock
|
||||
//HERWIG#define pthread_mutex_unlock dng_pthread_mutex_unlock
|
||||
|
||||
//HERWIG#define pthread_cond_init dng_pthread_cond_init
|
||||
//HERWIG#define pthread_cond_destroy dng_pthread_cond_destroy
|
||||
//HERWIG#define pthread_cond_wait dng_pthread_cond_wait
|
||||
//HERWIG#define pthread_cond_timedwait dng_pthread_cond_timedwait
|
||||
//HERWIG#define pthread_cond_signal dng_pthread_cond_signal
|
||||
//HERWIG#define pthread_cond_broadcast dng_pthread_cond_broadcast
|
||||
|
||||
//HERWIG#define pthread_once dng_pthread_once
|
||||
|
||||
//HERWIG#define pthread_key_create dng_pthread_key_create
|
||||
//HERWIG#define pthread_key_delete dng_pthread_key_delete
|
||||
//HERWIG#define pthread_setspecific dng_pthread_setspecific
|
||||
//HERWIG#define pthread_getspecific dng_pthread_getspecific
|
||||
|
||||
//HERWIG#define pthread_rwlock_t dng_pthread_rwlock_t
|
||||
|
||||
//HERWIG#define pthread_rwlock_destroy dng_pthread_rwlock_destroy
|
||||
//HERWIG#define pthread_rwlock_init dng_pthread_rwlock_init
|
||||
//HERWIG#define pthread_rwlock_rdlock dng_pthread_rwlock_rdlock
|
||||
//HERWIG#define pthread_rwlock_tryrdlock dng_pthread_rwlock_tryrdlock
|
||||
//HERWIG#define pthread_rwlock_trywrlock dng_pthread_rwlock_trywrlock
|
||||
//HERWIG#define pthread_rwlock_unlock dng_pthread_rwlock_unlock
|
||||
//HERWIG#define pthread_rwlock_wrlock dng_pthread_rwlock_wrlock
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int dng_pthread_now (struct timespec *now);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif // qDNGThreadSafe
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue