You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1599 lines
32 KiB
1599 lines
32 KiB
/*****************************************************************************/
|
|
// Copyright 2008-2009 Adobe Systems Incorporated
|
|
// All Rights Reserved.
|
|
//
|
|
// NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
// accordance with the terms of the Adobe license agreement accompanying it.
|
|
/*****************************************************************************/
|
|
|
|
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_misc_opcodes.cpp#1 $ */
|
|
/* $DateTime: 2012/05/30 13:28:51 $ */
|
|
/* $Change: 832332 $ */
|
|
/* $Author: tknoll $ */
|
|
|
|
/*****************************************************************************/
|
|
|
|
#include "dng_misc_opcodes.h"
|
|
|
|
#include "dng_bottlenecks.h"
|
|
#include "dng_exceptions.h"
|
|
#include "dng_globals.h"
|
|
#include "dng_host.h"
|
|
#include "dng_image.h"
|
|
#include "dng_rect.h"
|
|
#include "dng_safe_arithmetic.h"
|
|
#include "dng_stream.h"
|
|
#include "dng_tag_values.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_TrimBounds::dng_opcode_TrimBounds (const dng_rect &bounds)
|
|
|
|
: dng_opcode (dngOpcode_TrimBounds,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fBounds (bounds)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_TrimBounds::dng_opcode_TrimBounds (dng_stream &stream)
|
|
|
|
: dng_opcode (dngOpcode_TrimBounds,
|
|
stream,
|
|
"TrimBounds")
|
|
|
|
, fBounds ()
|
|
|
|
{
|
|
|
|
if (stream.Get_uint32 () != 16)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
fBounds.t = stream.Get_int32 ();
|
|
fBounds.l = stream.Get_int32 ();
|
|
fBounds.b = stream.Get_int32 ();
|
|
fBounds.r = stream.Get_int32 ();
|
|
|
|
if (fBounds.IsEmpty ())
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("Bounds: t=%d, l=%d, b=%d, r=%d\n",
|
|
(int) fBounds.t,
|
|
(int) fBounds.l,
|
|
(int) fBounds.b,
|
|
(int) fBounds.r);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_TrimBounds::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
stream.Put_uint32 (16);
|
|
|
|
stream.Put_int32 (fBounds.t);
|
|
stream.Put_int32 (fBounds.l);
|
|
stream.Put_int32 (fBounds.b);
|
|
stream.Put_int32 (fBounds.r);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_TrimBounds::Apply (dng_host & /* host */,
|
|
dng_negative & /* negative */,
|
|
AutoPtr<dng_image> &image)
|
|
{
|
|
|
|
if (fBounds.IsEmpty () || (fBounds & image->Bounds ()) != fBounds)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
image->Trim (fBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_area_spec::GetData (dng_stream &stream)
|
|
{
|
|
|
|
fArea.t = stream.Get_int32 ();
|
|
fArea.l = stream.Get_int32 ();
|
|
fArea.b = stream.Get_int32 ();
|
|
fArea.r = stream.Get_int32 ();
|
|
|
|
fPlane = stream.Get_uint32 ();
|
|
fPlanes = stream.Get_uint32 ();
|
|
|
|
fRowPitch = stream.Get_uint32 ();
|
|
fColPitch = stream.Get_uint32 ();
|
|
|
|
if (fPlanes < 1)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (fRowPitch < 1 || fColPitch < 1)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (fArea.IsEmpty ())
|
|
{
|
|
if (fRowPitch != 1 || fColPitch != 1)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
int32 width = 0;
|
|
int32 height = 0;
|
|
if (!SafeInt32Sub (fArea.b, fArea.t, &height) ||
|
|
!SafeInt32Sub (fArea.r, fArea.l, &width) ||
|
|
fRowPitch > static_cast<uint32>(height) ||
|
|
fColPitch > static_cast<uint32>(width))
|
|
{
|
|
ThrowBadFormat();
|
|
}
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("AreaSpec: t=%d, l=%d, b=%d, r=%d, p=%u:%u, rp=%u, cp=%u\n",
|
|
(int) fArea.t,
|
|
(int) fArea.l,
|
|
(int) fArea.b,
|
|
(int) fArea.r,
|
|
(unsigned) fPlane,
|
|
(unsigned) fPlanes,
|
|
(unsigned) fRowPitch,
|
|
(unsigned) fColPitch);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_area_spec::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
stream.Put_int32 (fArea.t);
|
|
stream.Put_int32 (fArea.l);
|
|
stream.Put_int32 (fArea.b);
|
|
stream.Put_int32 (fArea.r);
|
|
|
|
stream.Put_uint32 (fPlane);
|
|
stream.Put_uint32 (fPlanes);
|
|
|
|
stream.Put_uint32 (fRowPitch);
|
|
stream.Put_uint32 (fColPitch);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_area_spec::Overlap (const dng_rect &tile) const
|
|
{
|
|
|
|
// Special case - if the fArea is empty, then dng_area_spec covers
|
|
// the entire image, no matter how large it is.
|
|
|
|
if (fArea.IsEmpty ())
|
|
{
|
|
return tile;
|
|
}
|
|
|
|
dng_rect overlap = fArea & tile;
|
|
|
|
if (overlap.NotEmpty ())
|
|
{
|
|
|
|
overlap.t = fArea.t + ConvertUint32ToInt32(
|
|
RoundUpUint32ToMultiple(static_cast<uint32>(overlap.t - fArea.t),
|
|
fRowPitch));
|
|
overlap.l = fArea.l + ConvertUint32ToInt32(
|
|
RoundUpUint32ToMultiple(static_cast<uint32>(overlap.l - fArea.l),
|
|
fColPitch));
|
|
|
|
if (overlap.NotEmpty ())
|
|
{
|
|
|
|
overlap.b = overlap.t + ((overlap.H () - 1) / fRowPitch) * fRowPitch + 1;
|
|
overlap.r = overlap.l + ((overlap.W () - 1) / fColPitch) * fColPitch + 1;
|
|
|
|
return overlap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dng_rect ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_MapTable::dng_opcode_MapTable (dng_host &host,
|
|
const dng_area_spec &areaSpec,
|
|
const uint16 *table,
|
|
uint32 count)
|
|
|
|
: dng_inplace_opcode (dngOpcode_MapTable,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fAreaSpec (areaSpec)
|
|
, fTable ()
|
|
, fCount (count)
|
|
|
|
{
|
|
|
|
if (count == 0 || count > 0x10000)
|
|
{
|
|
ThrowProgramError ();
|
|
}
|
|
|
|
fTable.Reset (host.Allocate (0x10000 * sizeof (uint16)));
|
|
|
|
DoCopyBytes (table,
|
|
fTable->Buffer (),
|
|
count * (uint32) sizeof (uint16));
|
|
|
|
ReplicateLastEntry ();
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_MapTable::dng_opcode_MapTable (dng_host &host,
|
|
dng_stream &stream)
|
|
|
|
: dng_inplace_opcode (dngOpcode_MapTable,
|
|
stream,
|
|
"MapTable")
|
|
|
|
, fAreaSpec ()
|
|
, fTable ()
|
|
, fCount (0)
|
|
|
|
{
|
|
|
|
uint32 dataSize = stream.Get_uint32 ();
|
|
|
|
fAreaSpec.GetData (stream);
|
|
|
|
fCount = stream.Get_uint32 ();
|
|
|
|
uint32 requiredSize = SafeUint32Mult(fCount, 2);
|
|
requiredSize = SafeUint32Add(requiredSize, dng_area_spec::kDataSize);
|
|
requiredSize = SafeUint32Add(requiredSize, 4);
|
|
if (dataSize != requiredSize)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (fCount == 0 || fCount > 0x10000)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
fTable.Reset (host.Allocate (0x10000 * sizeof (uint16)));
|
|
|
|
uint16 *table = fTable->Buffer_uint16 ();
|
|
|
|
for (uint32 index = 0; index < fCount; index++)
|
|
{
|
|
table [index] = stream.Get_uint16 ();
|
|
}
|
|
|
|
ReplicateLastEntry ();
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("Count: %u\n", (unsigned) fCount);
|
|
|
|
for (uint32 j = 0; j < fCount && j < gDumpLineLimit; j++)
|
|
{
|
|
printf (" Table [%5u] = %5u\n", (unsigned) j, (unsigned) table [j]);
|
|
}
|
|
|
|
if (fCount > gDumpLineLimit)
|
|
{
|
|
printf (" ... %u table entries skipped\n", (unsigned) (fCount - gDumpLineLimit));
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_MapTable::ReplicateLastEntry ()
|
|
{
|
|
|
|
uint16 *table = fTable->Buffer_uint16 ();
|
|
|
|
uint16 lastEntry = table [fCount];
|
|
|
|
for (uint32 index = fCount; index < 0x10000; index++)
|
|
{
|
|
table [index] = lastEntry;
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_MapTable::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
stream.Put_uint32 (dng_area_spec::kDataSize + 4 + fCount * 2);
|
|
|
|
fAreaSpec.PutData (stream);
|
|
|
|
stream.Put_uint32 (fCount);
|
|
|
|
uint16 *table = fTable->Buffer_uint16 ();
|
|
|
|
for (uint32 index = 0; index < fCount; index++)
|
|
{
|
|
stream.Put_uint16 (table [index]);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_opcode_MapTable::BufferPixelType (uint32 /* imagePixelType */)
|
|
{
|
|
|
|
return ttShort;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_opcode_MapTable::ModifiedBounds (const dng_rect &imageBounds)
|
|
{
|
|
|
|
return fAreaSpec.Overlap (imageBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_MapTable::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 ())
|
|
{
|
|
|
|
for (uint32 plane = fAreaSpec.Plane ();
|
|
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
|
plane < buffer.Planes ();
|
|
plane++)
|
|
{
|
|
|
|
DoMapArea16 (buffer.DirtyPixel_uint16 (overlap.t, overlap.l, plane),
|
|
1,
|
|
(overlap.H () + fAreaSpec.RowPitch () - 1) / fAreaSpec.RowPitch (),
|
|
(overlap.W () + fAreaSpec.ColPitch () - 1) / fAreaSpec.ColPitch (),
|
|
0,
|
|
fAreaSpec.RowPitch () * buffer.RowStep (),
|
|
fAreaSpec.ColPitch (),
|
|
fTable->Buffer_uint16 ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (const dng_area_spec &areaSpec,
|
|
uint32 degree,
|
|
const real64 *coefficient)
|
|
|
|
: dng_inplace_opcode (dngOpcode_MapPolynomial,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fAreaSpec (areaSpec)
|
|
, fDegree (degree)
|
|
|
|
{
|
|
|
|
for (uint32 j = 0; j <= kMaxDegree; j++)
|
|
{
|
|
|
|
if (j <= fDegree)
|
|
{
|
|
fCoefficient [j] = coefficient [j];
|
|
}
|
|
|
|
else
|
|
{
|
|
fCoefficient [j] = 0.0;
|
|
}
|
|
|
|
}
|
|
|
|
// Reduce degree if possible.
|
|
|
|
while (fDegree > 0 && fCoefficient [fDegree] == 0.0)
|
|
{
|
|
fDegree--;
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (dng_stream &stream)
|
|
|
|
: dng_inplace_opcode (dngOpcode_MapPolynomial,
|
|
stream,
|
|
"MapPolynomial")
|
|
|
|
, fAreaSpec ()
|
|
, fDegree (0)
|
|
|
|
{
|
|
|
|
uint32 dataSize = stream.Get_uint32 ();
|
|
|
|
fAreaSpec.GetData (stream);
|
|
|
|
fDegree = stream.Get_uint32 ();
|
|
|
|
if (fDegree > kMaxDegree)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (dataSize != dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
for (uint32 j = 0; j <= kMaxDegree; j++)
|
|
{
|
|
|
|
if (j <= fDegree)
|
|
{
|
|
fCoefficient [j] = stream.Get_real64 ();
|
|
}
|
|
else
|
|
{
|
|
fCoefficient [j] = 0.0;
|
|
}
|
|
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
for (uint32 k = 0; k <= fDegree; k++)
|
|
{
|
|
printf (" Coefficient [%u] = %f\n", (unsigned) k, fCoefficient [k]);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_MapPolynomial::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
stream.Put_uint32 (dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8);
|
|
|
|
fAreaSpec.PutData (stream);
|
|
|
|
stream.Put_uint32 (fDegree);
|
|
|
|
for (uint32 j = 0; j <= fDegree; j++)
|
|
{
|
|
stream.Put_real64 (fCoefficient [j]);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_opcode_MapPolynomial::BufferPixelType (uint32 imagePixelType)
|
|
{
|
|
|
|
// If we are operating on the stage 1 image, then we need
|
|
// to adjust the coefficients to convert from the image
|
|
// values to the 32-bit floating point values that this
|
|
// opcode operates on.
|
|
|
|
// If we are operating on the stage 2 or 3 image, the logical
|
|
// range of the image is already 0.0 to 1.0, so we don't
|
|
// need to adjust the values.
|
|
|
|
real64 scale32 = 1.0;
|
|
|
|
if (Stage () == 1)
|
|
{
|
|
|
|
switch (imagePixelType)
|
|
{
|
|
|
|
case ttFloat:
|
|
break;
|
|
|
|
case ttShort:
|
|
{
|
|
scale32 = (real64) 0xFFFF;
|
|
break;
|
|
}
|
|
|
|
case ttLong:
|
|
{
|
|
scale32 = (real64) 0xFFFFFFFF;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
ThrowBadFormat ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
real64 factor32 = 1.0 / scale32;
|
|
|
|
for (uint32 j = 0; j <= kMaxDegree; j++)
|
|
{
|
|
|
|
fCoefficient32 [j] = ConvertDoubleToFloat(fCoefficient [j] * factor32);
|
|
|
|
factor32 *= scale32;
|
|
|
|
}
|
|
|
|
return ttFloat;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_opcode_MapPolynomial::ModifiedBounds (const dng_rect &imageBounds)
|
|
{
|
|
|
|
return fAreaSpec.Overlap (imageBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_MapPolynomial::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 ())
|
|
{
|
|
|
|
uint32 cols = overlap.W ();
|
|
|
|
uint32 colPitch = fAreaSpec.ColPitch ();
|
|
|
|
for (uint32 plane = fAreaSpec.Plane ();
|
|
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
|
plane < buffer.Planes ();
|
|
plane++)
|
|
{
|
|
|
|
for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
|
|
{
|
|
|
|
real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
|
|
|
|
switch (fDegree)
|
|
{
|
|
|
|
case 0:
|
|
{
|
|
|
|
real32 y = Pin_real32 (0.0f,
|
|
fCoefficient32 [0],
|
|
1.0f);
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
dPtr [col] = y;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
|
|
real32 c0 = fCoefficient32 [0];
|
|
real32 c1 = fCoefficient32 [1];
|
|
|
|
if (c0 == 0.0f)
|
|
{
|
|
|
|
if (c1 > 0.0f)
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = c1 * x;
|
|
|
|
dPtr [col] = Min_real32 (y, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
dPtr [col] = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = c0 +
|
|
c1 * x;
|
|
|
|
dPtr [col] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = fCoefficient32 [0] + x *
|
|
(fCoefficient32 [1] + x *
|
|
(fCoefficient32 [2]));
|
|
|
|
dPtr [col] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = fCoefficient32 [0] + x *
|
|
(fCoefficient32 [1] + x *
|
|
(fCoefficient32 [2] + x *
|
|
(fCoefficient32 [3])));
|
|
|
|
dPtr [col] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = fCoefficient32 [0] + x *
|
|
(fCoefficient32 [1] + x *
|
|
(fCoefficient32 [2] + x *
|
|
(fCoefficient32 [3] + x *
|
|
(fCoefficient32 [4]))));
|
|
|
|
dPtr [col] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = fCoefficient32 [0];
|
|
|
|
real32 xx = x;
|
|
|
|
for (uint32 j = 1; j <= fDegree; j++)
|
|
{
|
|
|
|
y += fCoefficient32 [j] * xx;
|
|
|
|
xx *= x;
|
|
|
|
}
|
|
|
|
dPtr [col] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_DeltaPerRow::dng_opcode_DeltaPerRow (const dng_area_spec &areaSpec,
|
|
AutoPtr<dng_memory_block> &table)
|
|
|
|
: dng_inplace_opcode (dngOpcode_DeltaPerRow,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fAreaSpec (areaSpec)
|
|
, fTable ()
|
|
, fScale (1.0f)
|
|
|
|
{
|
|
|
|
fTable.Reset (table.Release ());
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_DeltaPerRow::dng_opcode_DeltaPerRow (dng_host &host,
|
|
dng_stream &stream)
|
|
|
|
: dng_inplace_opcode (dngOpcode_DeltaPerRow,
|
|
stream,
|
|
"DeltaPerRow")
|
|
|
|
, fAreaSpec ()
|
|
, fTable ()
|
|
, fScale (1.0f)
|
|
|
|
{
|
|
|
|
uint32 dataSize = stream.Get_uint32 ();
|
|
|
|
fAreaSpec.GetData (stream);
|
|
|
|
uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().H (),
|
|
fAreaSpec.RowPitch ());
|
|
|
|
if (deltas != stream.Get_uint32 ())
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (dataSize != dng_area_spec::kDataSize + 4 + deltas * 4)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
fTable.Reset (host.Allocate (SafeUint32Mult (deltas,
|
|
static_cast<uint32> (sizeof (real32)))));
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < deltas; j++)
|
|
{
|
|
table [j] = stream.Get_real32 ();
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("Count: %u\n", (unsigned) deltas);
|
|
|
|
for (uint32 k = 0; k < deltas && k < gDumpLineLimit; k++)
|
|
{
|
|
printf (" Delta [%u] = %f\n", (unsigned) k, table [k]);
|
|
}
|
|
|
|
if (deltas > gDumpLineLimit)
|
|
{
|
|
printf (" ... %u deltas skipped\n", (unsigned) (deltas - gDumpLineLimit));
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_DeltaPerRow::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().H (),
|
|
fAreaSpec.RowPitch ());
|
|
|
|
stream.Put_uint32 (dng_area_spec::kDataSize + 4 + deltas * 4);
|
|
|
|
fAreaSpec.PutData (stream);
|
|
|
|
stream.Put_uint32 (deltas);
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < deltas; j++)
|
|
{
|
|
stream.Put_real32 (table [j]);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_opcode_DeltaPerRow::BufferPixelType (uint32 imagePixelType)
|
|
{
|
|
|
|
real64 scale32 = 1.0;
|
|
|
|
switch (imagePixelType)
|
|
{
|
|
|
|
case ttFloat:
|
|
break;
|
|
|
|
case ttShort:
|
|
{
|
|
scale32 = (real64) 0xFFFF;
|
|
break;
|
|
}
|
|
|
|
case ttLong:
|
|
{
|
|
scale32 = (real64) 0xFFFFFFFF;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
ThrowBadFormat ();
|
|
|
|
}
|
|
|
|
fScale = (real32) (1.0 / scale32);
|
|
|
|
return ttFloat;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_opcode_DeltaPerRow::ModifiedBounds (const dng_rect &imageBounds)
|
|
{
|
|
|
|
return fAreaSpec.Overlap (imageBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_DeltaPerRow::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 ())
|
|
{
|
|
|
|
uint32 cols = overlap.W ();
|
|
|
|
uint32 colPitch = fAreaSpec.ColPitch ();
|
|
|
|
for (uint32 plane = fAreaSpec.Plane ();
|
|
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
|
plane < buffer.Planes ();
|
|
plane++)
|
|
{
|
|
|
|
const real32 *table = fTable->Buffer_real32 () +
|
|
((overlap.t - fAreaSpec.Area ().t) /
|
|
fAreaSpec.RowPitch ());
|
|
|
|
for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
|
|
{
|
|
|
|
real32 rowDelta = *(table++) * fScale;
|
|
|
|
real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = x + rowDelta;
|
|
|
|
dPtr [col] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_DeltaPerColumn::dng_opcode_DeltaPerColumn (const dng_area_spec &areaSpec,
|
|
AutoPtr<dng_memory_block> &table)
|
|
|
|
: dng_inplace_opcode (dngOpcode_DeltaPerColumn,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fAreaSpec (areaSpec)
|
|
, fTable ()
|
|
, fScale (1.0f)
|
|
|
|
{
|
|
|
|
fTable.Reset (table.Release ());
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_DeltaPerColumn::dng_opcode_DeltaPerColumn (dng_host &host,
|
|
dng_stream &stream)
|
|
|
|
: dng_inplace_opcode (dngOpcode_DeltaPerColumn,
|
|
stream,
|
|
"DeltaPerColumn")
|
|
|
|
, fAreaSpec ()
|
|
, fTable ()
|
|
, fScale (1.0f)
|
|
|
|
{
|
|
|
|
uint32 dataSize = stream.Get_uint32 ();
|
|
|
|
fAreaSpec.GetData (stream);
|
|
|
|
uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().W (),
|
|
fAreaSpec.ColPitch ());
|
|
|
|
if (deltas != stream.Get_uint32 ())
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (dataSize != dng_area_spec::kDataSize + 4 + deltas * 4)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
fTable.Reset (host.Allocate (SafeUint32Mult (deltas,
|
|
static_cast<uint32> (sizeof (real32)))));
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < deltas; j++)
|
|
{
|
|
table [j] = stream.Get_real32 ();
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("Count: %u\n", (unsigned) deltas);
|
|
|
|
for (uint32 k = 0; k < deltas && k < gDumpLineLimit; k++)
|
|
{
|
|
printf (" Delta [%u] = %f\n", (unsigned) k, table [k]);
|
|
}
|
|
|
|
if (deltas > gDumpLineLimit)
|
|
{
|
|
printf (" ... %u deltas skipped\n", (unsigned) (deltas - gDumpLineLimit));
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_DeltaPerColumn::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
uint32 deltas = SafeUint32DivideUp (fAreaSpec.Area ().W (),
|
|
fAreaSpec.ColPitch ());
|
|
|
|
stream.Put_uint32 (dng_area_spec::kDataSize + 4 + deltas * 4);
|
|
|
|
fAreaSpec.PutData (stream);
|
|
|
|
stream.Put_uint32 (deltas);
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < deltas; j++)
|
|
{
|
|
stream.Put_real32 (table [j]);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_opcode_DeltaPerColumn::BufferPixelType (uint32 imagePixelType)
|
|
{
|
|
|
|
real64 scale32 = 1.0;
|
|
|
|
switch (imagePixelType)
|
|
{
|
|
|
|
case ttFloat:
|
|
break;
|
|
|
|
case ttShort:
|
|
{
|
|
scale32 = (real64) 0xFFFF;
|
|
break;
|
|
}
|
|
|
|
case ttLong:
|
|
{
|
|
scale32 = (real64) 0xFFFFFFFF;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
ThrowBadFormat ();
|
|
|
|
}
|
|
|
|
fScale = (real32) (1.0 / scale32);
|
|
|
|
return ttFloat;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_opcode_DeltaPerColumn::ModifiedBounds (const dng_rect &imageBounds)
|
|
{
|
|
|
|
return fAreaSpec.Overlap (imageBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_DeltaPerColumn::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 ())
|
|
{
|
|
|
|
uint32 rows = (overlap.H () + fAreaSpec.RowPitch () - 1) /
|
|
fAreaSpec.RowPitch ();
|
|
|
|
int32 rowStep = buffer.RowStep () * fAreaSpec.RowPitch ();
|
|
|
|
for (uint32 plane = fAreaSpec.Plane ();
|
|
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
|
plane < buffer.Planes ();
|
|
plane++)
|
|
{
|
|
|
|
const real32 *table = fTable->Buffer_real32 () +
|
|
((overlap.l - fAreaSpec.Area ().l) /
|
|
fAreaSpec.ColPitch ());
|
|
|
|
for (int32 col = overlap.l; col < overlap.r; col += fAreaSpec.ColPitch ())
|
|
{
|
|
|
|
real32 colDelta = *(table++) * fScale;
|
|
|
|
real32 *dPtr = buffer.DirtyPixel_real32 (overlap.t, col, plane);
|
|
|
|
for (uint32 row = 0; row < rows; row++)
|
|
{
|
|
|
|
real32 x = dPtr [0];
|
|
|
|
real32 y = x + colDelta;
|
|
|
|
dPtr [0] = Pin_real32 (0.0f, y, 1.0f);
|
|
|
|
dPtr += rowStep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_ScalePerRow::dng_opcode_ScalePerRow (const dng_area_spec &areaSpec,
|
|
AutoPtr<dng_memory_block> &table)
|
|
|
|
: dng_inplace_opcode (dngOpcode_ScalePerRow,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fAreaSpec (areaSpec)
|
|
, fTable ()
|
|
|
|
{
|
|
|
|
fTable.Reset (table.Release ());
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_ScalePerRow::dng_opcode_ScalePerRow (dng_host &host,
|
|
dng_stream &stream)
|
|
|
|
: dng_inplace_opcode (dngOpcode_ScalePerRow,
|
|
stream,
|
|
"ScalePerRow")
|
|
|
|
, fAreaSpec ()
|
|
, fTable ()
|
|
|
|
{
|
|
|
|
uint32 dataSize = stream.Get_uint32 ();
|
|
|
|
fAreaSpec.GetData (stream);
|
|
|
|
uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().H (),
|
|
fAreaSpec.RowPitch ());
|
|
|
|
if (scales != stream.Get_uint32 ())
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (dataSize != dng_area_spec::kDataSize + 4 + scales * 4)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
fTable.Reset (host.Allocate (SafeUint32Mult (scales,
|
|
static_cast<uint32> (sizeof (real32)))));
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < scales; j++)
|
|
{
|
|
table [j] = stream.Get_real32 ();
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("Count: %u\n", (unsigned) scales);
|
|
|
|
for (uint32 k = 0; k < scales && k < gDumpLineLimit; k++)
|
|
{
|
|
printf (" Scale [%u] = %f\n", (unsigned) k, table [k]);
|
|
}
|
|
|
|
if (scales > gDumpLineLimit)
|
|
{
|
|
printf (" ... %u scales skipped\n", (unsigned) (scales - gDumpLineLimit));
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_ScalePerRow::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().H (),
|
|
fAreaSpec.RowPitch ());
|
|
|
|
stream.Put_uint32 (dng_area_spec::kDataSize + 4 + scales * 4);
|
|
|
|
fAreaSpec.PutData (stream);
|
|
|
|
stream.Put_uint32 (scales);
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < scales; j++)
|
|
{
|
|
stream.Put_real32 (table [j]);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_opcode_ScalePerRow::BufferPixelType (uint32 /* imagePixelType */)
|
|
{
|
|
|
|
return ttFloat;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_opcode_ScalePerRow::ModifiedBounds (const dng_rect &imageBounds)
|
|
{
|
|
|
|
return fAreaSpec.Overlap (imageBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_ScalePerRow::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 ())
|
|
{
|
|
|
|
uint32 cols = overlap.W ();
|
|
|
|
uint32 colPitch = fAreaSpec.ColPitch ();
|
|
|
|
for (uint32 plane = fAreaSpec.Plane ();
|
|
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
|
plane < buffer.Planes ();
|
|
plane++)
|
|
{
|
|
|
|
const real32 *table = fTable->Buffer_real32 () +
|
|
((overlap.t - fAreaSpec.Area ().t) /
|
|
fAreaSpec.RowPitch ());
|
|
|
|
for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
|
|
{
|
|
|
|
real32 rowScale = *(table++);
|
|
|
|
real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
|
|
|
|
for (uint32 col = 0; col < cols; col += colPitch)
|
|
{
|
|
|
|
real32 x = dPtr [col];
|
|
|
|
real32 y = x * rowScale;
|
|
|
|
dPtr [col] = Min_real32 (y, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_ScalePerColumn::dng_opcode_ScalePerColumn (const dng_area_spec &areaSpec,
|
|
AutoPtr<dng_memory_block> &table)
|
|
|
|
: dng_inplace_opcode (dngOpcode_ScalePerColumn,
|
|
dngVersion_1_3_0_0,
|
|
kFlag_None)
|
|
|
|
, fAreaSpec (areaSpec)
|
|
, fTable ()
|
|
|
|
{
|
|
|
|
fTable.Reset (table.Release ());
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_opcode_ScalePerColumn::dng_opcode_ScalePerColumn (dng_host &host,
|
|
dng_stream &stream)
|
|
|
|
: dng_inplace_opcode (dngOpcode_ScalePerColumn,
|
|
stream,
|
|
"ScalePerColumn")
|
|
|
|
, fAreaSpec ()
|
|
, fTable ()
|
|
|
|
{
|
|
|
|
uint32 dataSize = stream.Get_uint32 ();
|
|
|
|
fAreaSpec.GetData (stream);
|
|
|
|
uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().W (),
|
|
fAreaSpec.ColPitch());
|
|
|
|
if (scales != stream.Get_uint32 ())
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
if (dataSize != dng_area_spec::kDataSize + 4 + scales * 4)
|
|
{
|
|
ThrowBadFormat ();
|
|
}
|
|
|
|
fTable.Reset (host.Allocate (SafeUint32Mult (scales,
|
|
static_cast<uint32> (sizeof (real32)))));
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < scales; j++)
|
|
{
|
|
table [j] = stream.Get_real32 ();
|
|
}
|
|
|
|
#if qDNGValidate
|
|
|
|
if (gVerbose)
|
|
{
|
|
|
|
printf ("Count: %u\n", (unsigned) scales);
|
|
|
|
for (uint32 k = 0; k < scales && k < gDumpLineLimit; k++)
|
|
{
|
|
printf (" Scale [%u] = %f\n", (unsigned) k, table [k]);
|
|
}
|
|
|
|
if (scales > gDumpLineLimit)
|
|
{
|
|
printf (" ... %u deltas skipped\n", (unsigned) (scales - gDumpLineLimit));
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_ScalePerColumn::PutData (dng_stream &stream) const
|
|
{
|
|
|
|
uint32 scales = SafeUint32DivideUp (fAreaSpec.Area ().W (),
|
|
fAreaSpec.ColPitch ());
|
|
|
|
stream.Put_uint32 (dng_area_spec::kDataSize + 4 + scales * 4);
|
|
|
|
fAreaSpec.PutData (stream);
|
|
|
|
stream.Put_uint32 (scales);
|
|
|
|
real32 *table = fTable->Buffer_real32 ();
|
|
|
|
for (uint32 j = 0; j < scales; j++)
|
|
{
|
|
stream.Put_real32 (table [j]);
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_opcode_ScalePerColumn::BufferPixelType (uint32 /* imagePixelType */)
|
|
{
|
|
|
|
return ttFloat;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_rect dng_opcode_ScalePerColumn::ModifiedBounds (const dng_rect &imageBounds)
|
|
{
|
|
|
|
return fAreaSpec.Overlap (imageBounds);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_opcode_ScalePerColumn::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 ())
|
|
{
|
|
|
|
uint32 rows = (overlap.H () + fAreaSpec.RowPitch () - 1) /
|
|
fAreaSpec.RowPitch ();
|
|
|
|
int32 rowStep = buffer.RowStep () * fAreaSpec.RowPitch ();
|
|
|
|
for (uint32 plane = fAreaSpec.Plane ();
|
|
plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
|
|
plane < buffer.Planes ();
|
|
plane++)
|
|
{
|
|
|
|
const real32 *table = fTable->Buffer_real32 () +
|
|
((overlap.l - fAreaSpec.Area ().l) /
|
|
fAreaSpec.ColPitch ());
|
|
|
|
for (int32 col = overlap.l; col < overlap.r; col += fAreaSpec.ColPitch ())
|
|
{
|
|
|
|
real32 colScale = *(table++);
|
|
|
|
real32 *dPtr = buffer.DirtyPixel_real32 (overlap.t, col, plane);
|
|
|
|
for (uint32 row = 0; row < rows; row++)
|
|
{
|
|
|
|
real32 x = dPtr [0];
|
|
|
|
real32 y = x * colScale;
|
|
|
|
dPtr [0] = Min_real32 (y, 1.0f);
|
|
|
|
dPtr += rowStep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|