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.
1912 lines
33 KiB
1912 lines
33 KiB
/*****************************************************************************/
|
|
// Copyright 2006-2008 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_pixel_buffer.cpp#1 $ */
|
|
/* $DateTime: 2012/05/30 13:28:51 $ */
|
|
/* $Change: 832332 $ */
|
|
/* $Author: tknoll $ */
|
|
|
|
/*****************************************************************************/
|
|
|
|
#include "dng_pixel_buffer.h"
|
|
|
|
#include "dng_bottlenecks.h"
|
|
#include "dng_exceptions.h"
|
|
#include "dng_flags.h"
|
|
#include "dng_safe_arithmetic.h"
|
|
#include "dng_tag_types.h"
|
|
#include "dng_tag_values.h"
|
|
#include "dng_utils.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
namespace {
|
|
|
|
bool SafeUint32ToInt32Mult(uint32 arg1, uint32 arg2, int32 *result) {
|
|
uint32 uint32_result;
|
|
return SafeUint32Mult(arg1, arg2, &uint32_result) &&
|
|
ConvertUint32ToInt32(uint32_result, result);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
/*****************************************************************************/
|
|
|
|
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)
|
|
{
|
|
|
|
uint32 step0;
|
|
uint32 step1;
|
|
uint32 step2;
|
|
|
|
// Optimize the order for the data that is most spread out.
|
|
|
|
uint32 sRange = Abs_int32 (sStep0) * (count0 - 1) +
|
|
Abs_int32 (sStep1) * (count1 - 1) +
|
|
Abs_int32 (sStep2) * (count2 - 1);
|
|
|
|
uint32 dRange = Abs_int32 (dStep0) * (count0 - 1) +
|
|
Abs_int32 (dStep1) * (count1 - 1) +
|
|
Abs_int32 (dStep2) * (count2 - 1);
|
|
|
|
if (dRange >= sRange)
|
|
{
|
|
|
|
if (dStep0 < 0)
|
|
{
|
|
|
|
sPtr = (const void *)
|
|
(((const uint8 *) sPtr) + (int32)(count0 - 1) * sStep0 * (int32)sPixelSize);
|
|
|
|
dPtr = (void *)
|
|
(((uint8 *) dPtr) + (int32)(count0 - 1) * dStep0 * (int32)dPixelSize);
|
|
|
|
sStep0 = -sStep0;
|
|
dStep0 = -dStep0;
|
|
|
|
}
|
|
|
|
if (dStep1 < 0)
|
|
{
|
|
|
|
sPtr = (const void *)
|
|
(((const uint8 *) sPtr) + (int32)(count1 - 1) * sStep1 * (int32)sPixelSize);
|
|
|
|
dPtr = (void *)
|
|
(((uint8 *) dPtr) + (int32)(count1 - 1) * dStep1 * (int32)dPixelSize);
|
|
|
|
sStep1 = -sStep1;
|
|
dStep1 = -dStep1;
|
|
|
|
}
|
|
|
|
if (dStep2 < 0)
|
|
{
|
|
|
|
sPtr = (const void *)
|
|
(((const uint8 *) sPtr) + (int32)(count2 - 1) * sStep2 * (int32)sPixelSize);
|
|
|
|
dPtr = (void *)
|
|
(((uint8 *) dPtr) + (int32)(count2 - 1) * dStep2 * (int32)dPixelSize);
|
|
|
|
sStep2 = -sStep2;
|
|
dStep2 = -dStep2;
|
|
|
|
}
|
|
|
|
step0 = (uint32) dStep0;
|
|
step1 = (uint32) dStep1;
|
|
step2 = (uint32) dStep2;
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
if (sStep0 < 0)
|
|
{
|
|
|
|
sPtr = (const void *)
|
|
(((const uint8 *) sPtr) + (int32)(count0 - 1) * sStep0 * (int32)sPixelSize);
|
|
|
|
dPtr = (void *)
|
|
(((uint8 *) dPtr) + (int32)(count0 - 1) * dStep0 * (int32)dPixelSize);
|
|
|
|
sStep0 = -sStep0;
|
|
dStep0 = -dStep0;
|
|
|
|
}
|
|
|
|
if (sStep1 < 0)
|
|
{
|
|
|
|
sPtr = (const void *)
|
|
(((const uint8 *) sPtr) + (int32)(count1 - 1) * sStep1 * (int32)sPixelSize);
|
|
|
|
dPtr = (void *)
|
|
(((uint8 *) dPtr) + (int32)(count1 - 1) * dStep1 * (int32)dPixelSize);
|
|
|
|
sStep1 = -sStep1;
|
|
dStep1 = -dStep1;
|
|
|
|
}
|
|
|
|
if (sStep2 < 0)
|
|
{
|
|
|
|
sPtr = (const void *)
|
|
(((const uint8 *) sPtr) + (int32)(count2 - 1) * sStep2 * (int32)sPixelSize);
|
|
|
|
dPtr = (void *)
|
|
(((uint8 *) dPtr) + (int32)(count2 - 1) * dStep2 * (int32)dPixelSize);
|
|
|
|
sStep2 = -sStep2;
|
|
dStep2 = -dStep2;
|
|
|
|
}
|
|
|
|
step0 = (uint32) sStep0;
|
|
step1 = (uint32) sStep1;
|
|
step2 = (uint32) sStep2;
|
|
|
|
}
|
|
|
|
if (count0 == 1) step0 = 0xFFFFFFFF;
|
|
if (count1 == 1) step1 = 0xFFFFFFFF;
|
|
if (count2 == 1) step2 = 0xFFFFFFFF;
|
|
|
|
uint32 index0;
|
|
uint32 index1;
|
|
uint32 index2;
|
|
|
|
if (step0 >= step1)
|
|
{
|
|
|
|
if (step1 >= step2)
|
|
{
|
|
index0 = 0;
|
|
index1 = 1;
|
|
index2 = 2;
|
|
}
|
|
|
|
else if (step2 >= step0)
|
|
{
|
|
index0 = 2;
|
|
index1 = 0;
|
|
index2 = 1;
|
|
}
|
|
|
|
else
|
|
{
|
|
index0 = 0;
|
|
index1 = 2;
|
|
index2 = 1;
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
if (step0 >= step2)
|
|
{
|
|
index0 = 1;
|
|
index1 = 0;
|
|
index2 = 2;
|
|
}
|
|
|
|
else if (step2 >= step1)
|
|
{
|
|
index0 = 2;
|
|
index1 = 1;
|
|
index2 = 0;
|
|
}
|
|
|
|
else
|
|
{
|
|
index0 = 1;
|
|
index1 = 2;
|
|
index2 = 0;
|
|
}
|
|
|
|
}
|
|
|
|
uint32 count [3];
|
|
|
|
count [0] = count0;
|
|
count [1] = count1;
|
|
count [2] = count2;
|
|
|
|
count0 = count [index0];
|
|
count1 = count [index1];
|
|
count2 = count [index2];
|
|
|
|
int32 step [3];
|
|
|
|
step [0] = sStep0;
|
|
step [1] = sStep1;
|
|
step [2] = sStep2;
|
|
|
|
sStep0 = step [index0];
|
|
sStep1 = step [index1];
|
|
sStep2 = step [index2];
|
|
|
|
step [0] = dStep0;
|
|
step [1] = dStep1;
|
|
step [2] = dStep2;
|
|
|
|
dStep0 = step [index0];
|
|
dStep1 = step [index1];
|
|
dStep2 = step [index2];
|
|
|
|
if (sStep0 == ((int32) count1) * sStep1 &&
|
|
dStep0 == ((int32) count1) * dStep1)
|
|
{
|
|
count1 *= count0;
|
|
count0 = 1;
|
|
}
|
|
|
|
if (sStep1 == ((int32) count2) * sStep2 &&
|
|
dStep1 == ((int32) count2) * dStep2)
|
|
{
|
|
count2 *= count1;
|
|
count1 = 1;
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void OptimizeOrder (const void *&sPtr,
|
|
uint32 sPixelSize,
|
|
uint32 &count0,
|
|
uint32 &count1,
|
|
uint32 &count2,
|
|
int32 &sStep0,
|
|
int32 &sStep1,
|
|
int32 &sStep2)
|
|
{
|
|
|
|
void *dPtr = NULL;
|
|
|
|
int32 dStep0 = sStep0;
|
|
int32 dStep1 = sStep1;
|
|
int32 dStep2 = sStep2;
|
|
|
|
OptimizeOrder (sPtr,
|
|
dPtr,
|
|
sPixelSize,
|
|
sPixelSize,
|
|
count0,
|
|
count1,
|
|
count2,
|
|
sStep0,
|
|
sStep1,
|
|
sStep2,
|
|
dStep0,
|
|
dStep1,
|
|
dStep2);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void OptimizeOrder (void *&dPtr,
|
|
uint32 dPixelSize,
|
|
uint32 &count0,
|
|
uint32 &count1,
|
|
uint32 &count2,
|
|
int32 &dStep0,
|
|
int32 &dStep1,
|
|
int32 &dStep2)
|
|
{
|
|
|
|
const void *sPtr = NULL;
|
|
|
|
int32 sStep0 = dStep0;
|
|
int32 sStep1 = dStep1;
|
|
int32 sStep2 = dStep2;
|
|
|
|
OptimizeOrder (sPtr,
|
|
dPtr,
|
|
dPixelSize,
|
|
dPixelSize,
|
|
count0,
|
|
count1,
|
|
count2,
|
|
sStep0,
|
|
sStep1,
|
|
sStep2,
|
|
dStep0,
|
|
dStep1,
|
|
dStep2);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_pixel_buffer::dng_pixel_buffer ()
|
|
|
|
: fArea ()
|
|
, fPlane (0)
|
|
, fPlanes (1)
|
|
, fRowStep (1)
|
|
, fColStep (1)
|
|
, fPlaneStep (1)
|
|
, fPixelType (ttUndefined)
|
|
, fPixelSize (0)
|
|
, fData (NULL)
|
|
, fDirty (true)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_pixel_buffer::dng_pixel_buffer (const dng_rect &area,
|
|
uint32 plane,
|
|
uint32 planes,
|
|
uint32 pixelType,
|
|
uint32 planarConfiguration,
|
|
void *data)
|
|
|
|
: fArea (area)
|
|
, fPlane (plane)
|
|
, fPlanes (planes)
|
|
, fRowStep (0)
|
|
, fColStep (0)
|
|
, fPlaneStep (0)
|
|
, fPixelType (pixelType)
|
|
, fPixelSize (TagTypeSize(pixelType))
|
|
, fData (data)
|
|
, fDirty (true)
|
|
|
|
{
|
|
|
|
const char *overflowMessage = "Arithmetic overflow in pixel buffer setup";
|
|
|
|
// Initialize fRowStep, fColStep and fPlaneStep according to the desired
|
|
// pixel layout.
|
|
switch (planarConfiguration)
|
|
{
|
|
case pcInterleaved:
|
|
fPlaneStep = 1;
|
|
if (!ConvertUint32ToInt32 (fPlanes, &fColStep) ||
|
|
!SafeUint32ToInt32Mult (fArea.W(), fPlanes, &fRowStep))
|
|
{
|
|
ThrowMemoryFull (overflowMessage);
|
|
}
|
|
break;
|
|
case pcPlanar:
|
|
fColStep = 1;
|
|
// Even though we've hardened dng_rect::W() to guarantee that it
|
|
// will never return a result that's out of range for an int32,
|
|
// we still protect the conversion for defense in depth.
|
|
if (!ConvertUint32ToInt32 (fArea.W(), &fRowStep) ||
|
|
!SafeUint32ToInt32Mult (fArea.H(), fArea.W(), &fPlaneStep))
|
|
{
|
|
ThrowMemoryFull (overflowMessage);
|
|
}
|
|
break;
|
|
case pcRowInterleaved:
|
|
case pcRowInterleavedAlign16:
|
|
{
|
|
fColStep = 1;
|
|
uint32 planeStepUint32;
|
|
if (planarConfiguration == pcRowInterleaved)
|
|
{
|
|
planeStepUint32 = fArea.W();
|
|
}
|
|
else
|
|
{
|
|
if (!RoundUpForPixelSize (fArea.W(), fPixelSize,
|
|
&planeStepUint32))
|
|
{
|
|
ThrowMemoryFull (overflowMessage);
|
|
}
|
|
}
|
|
if (!ConvertUint32ToInt32 (planeStepUint32, &fPlaneStep) ||
|
|
!SafeUint32ToInt32Mult (planeStepUint32, fPlanes, &fRowStep))
|
|
{
|
|
ThrowMemoryFull (overflowMessage);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ThrowProgramError ("Invalid value for 'planarConfiguration'");
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_pixel_buffer::dng_pixel_buffer (const dng_pixel_buffer &buffer)
|
|
|
|
: fArea (buffer.fArea)
|
|
, fPlane (buffer.fPlane)
|
|
, fPlanes (buffer.fPlanes)
|
|
, fRowStep (buffer.fRowStep)
|
|
, fColStep (buffer.fColStep)
|
|
, fPlaneStep (buffer.fPlaneStep)
|
|
, fPixelType (buffer.fPixelType)
|
|
, fPixelSize (buffer.fPixelSize)
|
|
, fData (buffer.fData)
|
|
, fDirty (buffer.fDirty)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_pixel_buffer & dng_pixel_buffer::operator= (const dng_pixel_buffer &buffer)
|
|
{
|
|
|
|
fArea = buffer.fArea;
|
|
fPlane = buffer.fPlane;
|
|
fPlanes = buffer.fPlanes;
|
|
fRowStep = buffer.fRowStep;
|
|
fColStep = buffer.fColStep;
|
|
fPlaneStep = buffer.fPlaneStep;
|
|
fPixelType = buffer.fPixelType;
|
|
fPixelSize = buffer.fPixelSize;
|
|
fPixelType = buffer.fPixelType;
|
|
fData = buffer.fData;
|
|
fDirty = buffer.fDirty;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_pixel_buffer::~dng_pixel_buffer ()
|
|
{
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
#if qDebugPixelType
|
|
|
|
void dng_pixel_buffer::CheckPixelType (uint32 pixelType) const
|
|
{
|
|
|
|
if (fPixelType != pixelType)
|
|
{
|
|
|
|
DNG_REPORT ("Pixel type access mismatch");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
uint32 dng_pixel_buffer::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;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::SetConstant (const dng_rect &area,
|
|
uint32 plane,
|
|
uint32 planes,
|
|
uint32 value)
|
|
{
|
|
|
|
uint32 rows = area.H ();
|
|
uint32 cols = area.W ();
|
|
|
|
void *dPtr = DirtyPixel (area.t,
|
|
area.l,
|
|
plane);
|
|
|
|
int32 dRowStep = fRowStep;
|
|
int32 dColStep = fColStep;
|
|
int32 dPlaneStep = fPlaneStep;
|
|
|
|
OptimizeOrder (dPtr,
|
|
fPixelSize,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
switch (fPixelSize)
|
|
{
|
|
|
|
case 1:
|
|
{
|
|
|
|
if (rows == 1 && cols == 1 && dPlaneStep == 1 && value == 0)
|
|
{
|
|
|
|
DoZeroBytes (dPtr, planes);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
DoSetArea8 ((uint8 *) dPtr,
|
|
(uint8) value,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
|
|
if (rows == 1 && cols == 1 && dPlaneStep == 1 && value == 0)
|
|
{
|
|
|
|
DoZeroBytes (dPtr, planes << 1);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
DoSetArea16 ((uint16 *) dPtr,
|
|
(uint16) value,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
|
|
if (rows == 1 && cols == 1 && dPlaneStep == 1 && value == 0)
|
|
{
|
|
|
|
DoZeroBytes (dPtr, planes << 2);
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
DoSetArea32 ((uint32 *) dPtr,
|
|
value,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::SetZero (const dng_rect &area,
|
|
uint32 plane,
|
|
uint32 planes)
|
|
{
|
|
|
|
uint32 value = 0;
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttByte:
|
|
case ttShort:
|
|
case ttLong:
|
|
case ttFloat:
|
|
{
|
|
break;
|
|
}
|
|
|
|
case ttSShort:
|
|
{
|
|
value = 0x8000;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetConstant (area,
|
|
plane,
|
|
planes,
|
|
value);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::CopyArea (const dng_pixel_buffer &src,
|
|
const dng_rect &area,
|
|
uint32 srcPlane,
|
|
uint32 dstPlane,
|
|
uint32 planes)
|
|
{
|
|
|
|
uint32 rows = area.H ();
|
|
uint32 cols = area.W ();
|
|
|
|
const void *sPtr = src.ConstPixel (area.t,
|
|
area.l,
|
|
srcPlane);
|
|
|
|
void *dPtr = DirtyPixel (area.t,
|
|
area.l,
|
|
dstPlane);
|
|
|
|
int32 sRowStep = src.fRowStep;
|
|
int32 sColStep = src.fColStep;
|
|
int32 sPlaneStep = src.fPlaneStep;
|
|
|
|
int32 dRowStep = fRowStep;
|
|
int32 dColStep = fColStep;
|
|
int32 dPlaneStep = fPlaneStep;
|
|
|
|
OptimizeOrder (sPtr,
|
|
dPtr,
|
|
src.fPixelSize,
|
|
fPixelSize,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
if (fPixelType == src.fPixelType)
|
|
{
|
|
|
|
if (rows == 1 && cols == 1 && sPlaneStep == 1 && dPlaneStep == 1)
|
|
{
|
|
|
|
DoCopyBytes (sPtr,
|
|
dPtr,
|
|
planes * fPixelSize);
|
|
|
|
}
|
|
|
|
else switch (fPixelSize)
|
|
{
|
|
|
|
case 1:
|
|
{
|
|
|
|
DoCopyArea8 ((const uint8 *) sPtr,
|
|
(uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
|
|
DoCopyArea16 ((const uint16 *) sPtr,
|
|
(uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
|
|
DoCopyArea32 ((const uint32 *) sPtr,
|
|
(uint32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (src.fPixelType == ttByte)
|
|
{
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttShort:
|
|
{
|
|
|
|
DoCopyArea8_16 ((const uint8 *) sPtr,
|
|
(uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttSShort:
|
|
{
|
|
|
|
DoCopyArea8_S16 ((const uint8 *) sPtr,
|
|
(int16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttLong:
|
|
{
|
|
|
|
DoCopyArea8_32 ((const uint8 *) sPtr,
|
|
(uint32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttFloat:
|
|
{
|
|
|
|
DoCopyArea8_R32 ((const uint8 *) sPtr,
|
|
(real32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
src.PixelRange ());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (src.fPixelType == ttShort)
|
|
{
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttByte:
|
|
{
|
|
|
|
DoCopyArea8 (((const uint8 *) sPtr) + (qDNGBigEndian ? 1 : 0),
|
|
(uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep << 1,
|
|
sColStep << 1,
|
|
sPlaneStep << 1,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttSShort:
|
|
{
|
|
|
|
DoCopyArea16_S16 ((const uint16 *) sPtr,
|
|
(int16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttLong:
|
|
{
|
|
|
|
DoCopyArea16_32 ((const uint16 *) sPtr,
|
|
(uint32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttFloat:
|
|
{
|
|
|
|
DoCopyArea16_R32 ((const uint16 *) sPtr,
|
|
(real32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
src.PixelRange ());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (src.fPixelType == ttSShort)
|
|
{
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttByte:
|
|
{
|
|
|
|
DoCopyArea8 (((const uint8 *) sPtr) + (qDNGBigEndian ? 1 : 0),
|
|
(uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep << 1,
|
|
sColStep << 1,
|
|
sPlaneStep << 1,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttShort:
|
|
{
|
|
|
|
// Moving between signed 16 bit values and unsigned 16
|
|
// bit values just requires toggling the sign bit. So
|
|
// we can use the "backwards" bottleneck.
|
|
|
|
DoCopyArea16_S16 ((const uint16 *) sPtr,
|
|
(int16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttFloat:
|
|
{
|
|
|
|
DoCopyAreaS16_R32 ((const int16 *) sPtr,
|
|
(real32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
src.PixelRange ());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (src.fPixelType == ttLong)
|
|
{
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttByte:
|
|
{
|
|
|
|
DoCopyArea8 (((const uint8 *) sPtr) + (qDNGBigEndian ? 3 : 0),
|
|
(uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep << 2,
|
|
sColStep << 2,
|
|
sPlaneStep << 2,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttShort:
|
|
{
|
|
|
|
DoCopyArea16 (((const uint16 *) sPtr) + (qDNGBigEndian ? 1 : 0),
|
|
(uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep << 1,
|
|
sColStep << 1,
|
|
sPlaneStep << 1,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (src.fPixelType == ttFloat)
|
|
{
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttByte:
|
|
{
|
|
|
|
DoCopyAreaR32_8 ((const real32 *) sPtr,
|
|
(uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
PixelRange ());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttShort:
|
|
{
|
|
|
|
DoCopyAreaR32_16 ((const real32 *) sPtr,
|
|
(uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
PixelRange ());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ttSShort:
|
|
{
|
|
|
|
DoCopyAreaR32_S16 ((const real32 *) sPtr,
|
|
(int16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
PixelRange ());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
dng_point dng_pixel_buffer::RepeatPhase (const dng_rect &srcArea,
|
|
const dng_rect &dstArea)
|
|
{
|
|
|
|
int32 repeatV = srcArea.H ();
|
|
int32 repeatH = srcArea.W ();
|
|
|
|
int32 phaseV;
|
|
int32 phaseH;
|
|
|
|
if (srcArea.t >= dstArea.t)
|
|
{
|
|
phaseV = (repeatV - ((srcArea.t - dstArea.t) % repeatV)) % repeatV;
|
|
}
|
|
else
|
|
{
|
|
phaseV = (dstArea.t - srcArea.t) % repeatV;
|
|
}
|
|
|
|
if (srcArea.l >= dstArea.l)
|
|
{
|
|
phaseH = (repeatH - ((srcArea.l - dstArea.l) % repeatH)) % repeatH;
|
|
}
|
|
else
|
|
{
|
|
phaseH = (dstArea.l - srcArea.l) % repeatH;
|
|
}
|
|
|
|
return dng_point (phaseV, phaseH);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::RepeatArea (const dng_rect &srcArea,
|
|
const dng_rect &dstArea)
|
|
{
|
|
|
|
dng_point repeat = srcArea.Size ();
|
|
|
|
dng_point phase = RepeatPhase (srcArea,
|
|
dstArea);
|
|
|
|
const void *sPtr = ConstPixel (srcArea.t,
|
|
srcArea.l,
|
|
fPlane);
|
|
|
|
void *dPtr = DirtyPixel (dstArea.t,
|
|
dstArea.l,
|
|
fPlane);
|
|
|
|
uint32 rows = dstArea.H ();
|
|
uint32 cols = dstArea.W ();
|
|
|
|
switch (fPixelSize)
|
|
{
|
|
|
|
case 1:
|
|
{
|
|
|
|
DoRepeatArea8 ((const uint8 *) sPtr,
|
|
(uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
fPlanes,
|
|
fRowStep,
|
|
fColStep,
|
|
fPlaneStep,
|
|
repeat.v,
|
|
repeat.h,
|
|
phase.v,
|
|
phase.h);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
|
|
DoRepeatArea16 ((const uint16 *) sPtr,
|
|
(uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
fPlanes,
|
|
fRowStep,
|
|
fColStep,
|
|
fPlaneStep,
|
|
repeat.v,
|
|
repeat.h,
|
|
phase.v,
|
|
phase.h);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
|
|
DoRepeatArea32 ((const uint32 *) sPtr,
|
|
(uint32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
fPlanes,
|
|
fRowStep,
|
|
fColStep,
|
|
fPlaneStep,
|
|
repeat.v,
|
|
repeat.h,
|
|
phase.v,
|
|
phase.h);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::RepeatSubArea (const dng_rect subArea,
|
|
uint32 repeatV,
|
|
uint32 repeatH)
|
|
{
|
|
|
|
if (fArea.t < subArea.t)
|
|
{
|
|
|
|
RepeatArea (dng_rect (subArea.t , fArea.l,
|
|
subArea.t + repeatV, fArea.r),
|
|
dng_rect (fArea.t , fArea.l,
|
|
subArea.t , fArea.r));
|
|
|
|
}
|
|
|
|
if (fArea.b > subArea.b)
|
|
{
|
|
|
|
RepeatArea (dng_rect (subArea.b - repeatV, fArea.l,
|
|
subArea.b , fArea.r),
|
|
dng_rect (subArea.b , fArea.l,
|
|
fArea.b , fArea.r));
|
|
|
|
}
|
|
|
|
if (fArea.l < subArea.l)
|
|
{
|
|
|
|
RepeatArea (dng_rect (fArea.t, subArea.l ,
|
|
fArea.b, subArea.l + repeatH),
|
|
dng_rect (fArea.t, fArea.l ,
|
|
fArea.b, subArea.l ));
|
|
|
|
}
|
|
|
|
if (fArea.r > subArea.r)
|
|
{
|
|
|
|
RepeatArea (dng_rect (fArea.t, subArea.r - repeatH,
|
|
fArea.b, subArea.r ),
|
|
dng_rect (fArea.t, subArea.r ,
|
|
fArea.b, fArea.r ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::ShiftRight (uint32 shift)
|
|
{
|
|
|
|
if (fPixelType != ttShort)
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
}
|
|
|
|
uint32 rows = fArea.H ();
|
|
uint32 cols = fArea.W ();
|
|
|
|
uint32 planes = fPlanes;
|
|
|
|
void *dPtr = DirtyPixel (fArea.t,
|
|
fArea.l,
|
|
fPlane);
|
|
|
|
const void *sPtr = dPtr;
|
|
|
|
int32 sRowStep = fRowStep;
|
|
int32 sColStep = fColStep;
|
|
int32 sPlaneStep = fPlaneStep;
|
|
|
|
int32 dRowStep = fRowStep;
|
|
int32 dColStep = fColStep;
|
|
int32 dPlaneStep = fPlaneStep;
|
|
|
|
OptimizeOrder (sPtr,
|
|
dPtr,
|
|
fPixelSize,
|
|
fPixelSize,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
DoShiftRight16 ((uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep,
|
|
shift);
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::FlipH ()
|
|
{
|
|
|
|
fData = InternalPixel (fArea.t, fArea.r - 1);
|
|
|
|
fColStep = -fColStep;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::FlipV ()
|
|
{
|
|
|
|
fData = InternalPixel (fArea.b - 1, fArea.l);
|
|
|
|
fRowStep = -fRowStep;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void dng_pixel_buffer::FlipZ ()
|
|
{
|
|
|
|
fData = InternalPixel (fArea.t, fArea.l, fPlanes - 1);
|
|
|
|
fPlaneStep = -fPlaneStep;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
bool dng_pixel_buffer::EqualArea (const dng_pixel_buffer &src,
|
|
const dng_rect &area,
|
|
uint32 plane,
|
|
uint32 planes) const
|
|
{
|
|
|
|
uint32 rows = area.H ();
|
|
uint32 cols = area.W ();
|
|
|
|
const void *sPtr = src.ConstPixel (area.t,
|
|
area.l,
|
|
plane);
|
|
|
|
const void *dPtr = ConstPixel (area.t,
|
|
area.l,
|
|
plane);
|
|
|
|
int32 sRowStep = src.fRowStep;
|
|
int32 sColStep = src.fColStep;
|
|
int32 sPlaneStep = src.fPlaneStep;
|
|
|
|
int32 dRowStep = fRowStep;
|
|
int32 dColStep = fColStep;
|
|
int32 dPlaneStep = fPlaneStep;
|
|
|
|
if (fPixelType == src.fPixelType)
|
|
{
|
|
|
|
if (rows == 1 && cols == 1 && sPlaneStep == 1 && dPlaneStep == 1)
|
|
{
|
|
|
|
return DoEqualBytes (sPtr,
|
|
dPtr,
|
|
planes * fPixelSize);
|
|
|
|
}
|
|
|
|
else switch (fPixelSize)
|
|
{
|
|
|
|
case 1:
|
|
{
|
|
|
|
return DoEqualArea8 ((const uint8 *) sPtr,
|
|
(const uint8 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
|
|
return DoEqualArea16 ((const uint16 *) sPtr,
|
|
(const uint16 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
|
|
return DoEqualArea32 ((const uint32 *) sPtr,
|
|
(const uint32 *) dPtr,
|
|
rows,
|
|
cols,
|
|
planes,
|
|
sRowStep,
|
|
sColStep,
|
|
sPlaneStep,
|
|
dRowStep,
|
|
dColStep,
|
|
dPlaneStep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
namespace
|
|
{
|
|
|
|
template <typename T>
|
|
real64 MaxDiff (const T *src1,
|
|
int32 s1RowStep,
|
|
int32 s1PlaneStep,
|
|
const T *src2,
|
|
int32 s2RowStep,
|
|
int32 s2PlaneStep,
|
|
uint32 rows,
|
|
uint32 cols,
|
|
uint32 planes)
|
|
{
|
|
|
|
real64 result = 0.0;
|
|
|
|
for (uint32 plane = 0; plane < planes; plane++)
|
|
{
|
|
|
|
const T *src1Save = src1;
|
|
const T *src2Save = src2;
|
|
|
|
for (uint32 row = 0; row < rows; row++)
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col++)
|
|
{
|
|
real64 diff = fabs ((real64)src1 [col] - src2 [col]);
|
|
|
|
if (diff > result)
|
|
result = diff;
|
|
|
|
}
|
|
|
|
src1 += s1RowStep;
|
|
src2 += s2RowStep;
|
|
|
|
}
|
|
|
|
src1 = src1Save + s1PlaneStep;
|
|
src2 = src2Save + s2PlaneStep;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
template <typename T>
|
|
real64 MaxDiff (const T *src1,
|
|
int32 s1ColStep,
|
|
int32 s1RowStep,
|
|
int32 s1PlaneStep,
|
|
const T *src2,
|
|
int32 s2ColStep,
|
|
int32 s2RowStep,
|
|
int32 s2PlaneStep,
|
|
uint32 rows,
|
|
uint32 cols,
|
|
uint32 planes)
|
|
{
|
|
|
|
if (s1ColStep == s2ColStep &&
|
|
s1ColStep == 1)
|
|
return MaxDiff (src1,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
src2,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
real64 result = 0.0;
|
|
|
|
for (uint32 plane = 0; plane < planes; plane++)
|
|
{
|
|
|
|
const T *src1Save = src1;
|
|
const T *src2Save = src2;
|
|
|
|
for (uint32 row = 0; row < rows; row++)
|
|
{
|
|
|
|
for (uint32 col = 0; col < cols; col++)
|
|
{
|
|
real64 diff = fabs ((real64)src1 [col * s1ColStep] - src2 [col * s2ColStep]);
|
|
|
|
if (diff > result)
|
|
result = diff;
|
|
|
|
}
|
|
|
|
src1 += s1RowStep;
|
|
src2 += s2RowStep;
|
|
|
|
}
|
|
|
|
src1 = src1Save + s1PlaneStep;
|
|
src2 = src2Save + s2PlaneStep;
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
}
|
|
|
|
real64 dng_pixel_buffer::MaximumDifference (const dng_pixel_buffer &rhs,
|
|
const dng_rect &area,
|
|
uint32 plane,
|
|
uint32 planes) const
|
|
{
|
|
|
|
uint32 rows = area.H ();
|
|
uint32 cols = area.W ();
|
|
|
|
const void *s1Ptr = rhs.ConstPixel (area.t,
|
|
area.l,
|
|
plane);
|
|
|
|
const void *s2Ptr = ConstPixel (area.t,
|
|
area.l,
|
|
plane);
|
|
|
|
int32 s1RowStep = rhs.fRowStep;
|
|
int32 s1ColStep = rhs.fColStep;
|
|
int32 s1PlaneStep = rhs.fPlaneStep;
|
|
|
|
int32 s2RowStep = fRowStep;
|
|
int32 s2ColStep = fColStep;
|
|
int32 s2PlaneStep = fPlaneStep;
|
|
|
|
if (fPixelType == rhs.fPixelType)
|
|
{
|
|
|
|
switch (fPixelType)
|
|
{
|
|
|
|
case ttByte:
|
|
return MaxDiff ((const uint8 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const uint8 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttShort:
|
|
return MaxDiff ((const uint16 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const uint16 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttLong:
|
|
return MaxDiff ((const uint32 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const uint32 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttSByte:
|
|
return MaxDiff ((const int8 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const int8 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttSShort:
|
|
return MaxDiff ((const int16 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const int16 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttSLong:
|
|
return MaxDiff ((const int32 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const int32 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttFloat:
|
|
return MaxDiff ((const real32 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const real32 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
case ttDouble:
|
|
return MaxDiff ((const real64 *)s1Ptr,
|
|
s1ColStep,
|
|
s1RowStep,
|
|
s1PlaneStep,
|
|
(const real64 *)s2Ptr,
|
|
s2ColStep,
|
|
s2RowStep,
|
|
s2PlaneStep,
|
|
rows,
|
|
cols,
|
|
planes);
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
{
|
|
|
|
ThrowNotYetImplemented ();
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
ThrowProgramError ("attempt to difference pixel buffers of different formats.");
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|