From ab987e10f154f5536bb8fd936ae0966e909fa969 Mon Sep 17 00:00:00 2001 From: luxagraf Date: Thu, 15 Jun 2023 15:58:59 -0500 Subject: added all my scripts --- gpr/source/lib/dng_sdk/dng_linearization_info.cpp | 1517 +++++++++++++++++++++ 1 file changed, 1517 insertions(+) create mode 100644 gpr/source/lib/dng_sdk/dng_linearization_info.cpp (limited to 'gpr/source/lib/dng_sdk/dng_linearization_info.cpp') diff --git a/gpr/source/lib/dng_sdk/dng_linearization_info.cpp b/gpr/source/lib/dng_sdk/dng_linearization_info.cpp new file mode 100644 index 0000000..1c1309b --- /dev/null +++ b/gpr/source/lib/dng_sdk/dng_linearization_info.cpp @@ -0,0 +1,1517 @@ +/*****************************************************************************/ +// Copyright 2006-2011 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_linearization_info.cpp#1 $ */ +/* $DateTime: 2012/05/30 13:28:51 $ */ +/* $Change: 832332 $ */ +/* $Author: tknoll $ */ + +/*****************************************************************************/ + +#include "dng_linearization_info.h" + +#include "dng_area_task.h" +#include "dng_exceptions.h" +#include "dng_host.h" +#include "dng_image.h" +#include "dng_info.h" +#include "dng_negative.h" +#include "dng_pixel_buffer.h" +#include "dng_tag_types.h" +#include "dng_tile_iterator.h" +#include "dng_utils.h" + +/*****************************************************************************/ + +class dng_linearize_plane + { + + private: + + const dng_image & fSrcImage; + dng_image & fDstImage; + + uint32 fPlane; + + dng_rect fActiveArea; + + uint32 fSrcPixelType; + uint32 fDstPixelType; + + bool fReal32; + + real32 fScale; + + AutoPtr fScale_buffer; + + uint32 fBlack_2D_rows; + uint32 fBlack_2D_cols; + + AutoPtr fBlack_2D_buffer; + + uint32 fBlack_1D_rows; + + AutoPtr fBlack_1D_buffer; + + public: + + dng_linearize_plane (dng_host &host, + dng_linearization_info &info, + const dng_image &srcImage, + dng_image &dstImage, + uint32 plane); + + ~dng_linearize_plane (); + + void Process (const dng_rect &tile); + + }; + +/*****************************************************************************/ + +dng_linearize_plane::dng_linearize_plane (dng_host &host, + dng_linearization_info &info, + const dng_image &srcImage, + dng_image &dstImage, + uint32 plane) + + : fSrcImage (srcImage) + , fDstImage (dstImage) + , fPlane (plane) + , fActiveArea (info.fActiveArea) + , fSrcPixelType (srcImage.PixelType ()) + , fDstPixelType (dstImage.PixelType ()) + , fReal32 (false) + , fScale (0.0f) + , fScale_buffer () + , fBlack_2D_rows (0) + , fBlack_2D_cols (0) + , fBlack_2D_buffer () + , fBlack_1D_rows (0) + , fBlack_1D_buffer () + + { + + uint32 j; + uint32 k; + + // Make sure the source pixel type is supported. + + if (fSrcPixelType != ttByte && + fSrcPixelType != ttShort && + fSrcPixelType != ttLong && + fSrcPixelType != ttFloat) + { + + DNG_REPORT ("Unsupported source pixel type"); + + ThrowProgramError (); + + } + + if (fDstPixelType != ttShort && + fDstPixelType != ttFloat) + { + + DNG_REPORT ("Unsupported destination pixel type"); + + ThrowProgramError (); + + } + + if (fSrcPixelType == ttFloat && + fDstPixelType != ttFloat) + { + + DNG_REPORT ("Cannot convert floating point stage1 to non-floating stage2"); + + ThrowProgramError (); + + } + + // Are we using floating point math? + + fReal32 = (fSrcPixelType == ttLong || + fDstPixelType == ttFloat); + + // Find the scale for this plane. + + real64 maxBlack = info.MaxBlackLevel (plane); + + real64 minRange = info.fWhiteLevel [plane] - maxBlack; + + if (minRange <= 0.0) + { + ThrowBadFormat (); + } + + real64 scale = 1.0 / minRange; + + fScale = (real32) scale; + + // Calculate two-dimensional black pattern, if any. + + if (info.fBlackDeltaH.Get ()) + { + + fBlack_2D_rows = info.fBlackLevelRepeatRows; + fBlack_2D_cols = info.fActiveArea.W (); + + } + + else if (info.fBlackLevelRepeatCols > 1) + { + + fBlack_2D_rows = info.fBlackLevelRepeatRows; + fBlack_2D_cols = info.fBlackLevelRepeatCols; + + } + + if (fBlack_2D_rows) + { + + fBlack_2D_buffer.Reset (host.Allocate (fBlack_2D_rows * fBlack_2D_cols * 4)); + + for (j = 0; j < fBlack_2D_rows; j++) + { + + for (k = 0; k < fBlack_2D_cols; k++) + { + + real64 x = info.fBlackLevel [j] + [k % info.fBlackLevelRepeatCols] + [plane]; + + if (info.fBlackDeltaH.Get ()) + { + + x += info.fBlackDeltaH->Buffer_real64 () [k]; + + } + + x *= scale; + + uint32 index = j * fBlack_2D_cols + k; + + if (fReal32) + { + + fBlack_2D_buffer->Buffer_real32 () [index] = (real32) x; + + } + + else + { + + x *= 0x0FFFF * 256.0; + + int32 y = Round_int32 (x); + + fBlack_2D_buffer->Buffer_int32 () [index] = y; + + } + + } + + } + + } + + // Calculate one-dimensional (per row) black pattern, if any. + + if (info.fBlackDeltaV.Get ()) + { + + fBlack_1D_rows = info.fActiveArea.H (); + + } + + else if (fBlack_2D_rows == 0 && + (info.fBlackLevelRepeatRows > 1 || fSrcPixelType != ttShort)) + { + + fBlack_1D_rows = info.fBlackLevelRepeatRows; + + } + + if (fBlack_1D_rows) + { + + fBlack_1D_buffer.Reset (host.Allocate (fBlack_1D_rows * 4)); + + bool allZero = true; + + for (j = 0; j < fBlack_1D_rows; j++) + { + + real64 x = 0.0; + + if (fBlack_2D_rows == 0) + { + + x = info.fBlackLevel [j % info.fBlackLevelRepeatRows] + [0] + [plane]; + + } + + if (info.fBlackDeltaV.Get ()) + { + + x += info.fBlackDeltaV->Buffer_real64 () [j]; + + } + + allZero = allZero && (x == 0.0); + + x *= scale; + + if (fReal32) + { + + fBlack_1D_buffer->Buffer_real32 () [j] = (real32) x; + + } + + else + { + + x *= 0x0FFFF * 256.0; + + int32 y = Round_int32 (x); + + fBlack_1D_buffer->Buffer_int32 () [j] = y; + + } + + } + + if (allZero) + { + + fBlack_1D_rows = 0; + + fBlack_1D_buffer.Reset (); + + } + + } + + // Calculate scale table, if any. + + if (fSrcPixelType != ttLong && + fSrcPixelType != ttFloat) + { + + // Find linearization table, if any. + + uint16 *lut = NULL; + + uint32 lutEntries = 0; + + if (info.fLinearizationTable.Get ()) + { + + lut = info.fLinearizationTable->Buffer_uint16 (); + + lutEntries = info.fLinearizationTable->LogicalSize () >> 1; + + } + + // If the black level does not vary from pixel to pixel, then + // the entire process can be a single LUT. + + if (fBlack_1D_rows == 0 && + fBlack_2D_rows == 0) + { + + fScale_buffer.Reset (host.Allocate (0x10000 * + TagTypeSize (fDstPixelType))); + + for (j = 0; j < 0x10000; j++) + { + + uint32 x = j; + + // Apply linearization table, if any. + + if (lut) + { + + x = Min_uint32 (x, lutEntries - 1); + + x = lut [x]; + + } + + // Subtract constant black level. + + real64 y = x - info.fBlackLevel [0] [0] [plane]; + + // Apply scale. + + y *= scale; + + // We can burn in the clipping also. + + y = Pin_real64 (0.0, y, 1.0); + + // Store output value in table. + + if (fDstPixelType == ttShort) + { + + uint16 z = (uint16) Round_uint32 (y * 0x0FFFF); + + fScale_buffer->Buffer_uint16 () [j] = z; + + } + + else + { + + fScale_buffer->Buffer_real32 () [j] = (real32) y; + + } + + } + + } + + // Else we only do the scaling operation in the scale table. + + else + { + + fScale_buffer.Reset (host.Allocate (0x10000 * 4)); + + for (j = 0; j < 0x10000; j++) + { + + uint32 x = j; + + // Apply linearization table, if any. + + if (lut) + { + + x = Min_uint32 (x, lutEntries - 1); + + x = lut [x]; + + } + + // Apply scale. + + real64 y = x * scale; + + // Store output value in table. + + if (fReal32) + { + + fScale_buffer->Buffer_real32 () [j] = (real32) y; + + } + + else + { + + int32 z = Round_int32 (y * 0x0FFFF * 256.0); + + fScale_buffer->Buffer_int32 () [j] = z; + + } + + } + + } + + } + + } + +/*****************************************************************************/ + +dng_linearize_plane::~dng_linearize_plane () + { + + } + +/*****************************************************************************/ + +void dng_linearize_plane::Process (const dng_rect &srcTile) + { + + // Process tile. + + dng_rect dstTile = srcTile - fActiveArea.TL (); + + dng_const_tile_buffer srcBuffer (fSrcImage, srcTile); + dng_dirty_tile_buffer dstBuffer (fDstImage, dstTile); + + int32 sStep = srcBuffer.fColStep; + int32 dStep = dstBuffer.fColStep; + + uint32 count = srcTile.W (); + + uint32 dstCol = dstTile.l; + + uint32 rows = srcTile.H (); + + for (uint32 row = 0; row < rows; row++) + { + + uint32 dstRow = dstTile.t + row; + + const void *sPtr = srcBuffer.ConstPixel (srcTile.t + row, + srcTile.l, + fPlane); + + void *dPtr = dstBuffer.DirtyPixel (dstRow, + dstCol, + fPlane); + + // Floating point source case. + + if (fSrcPixelType == ttFloat) + { + + real32 scale = fScale; + + const real32 *srcPtr = (const real32 *) sPtr; + + real32 *dstPtr = (real32 *) dPtr; + + // Optimize scale only case, which is the most common. + + if (fBlack_1D_rows == 0 && + fBlack_2D_cols == 0) + { + + for (uint32 j = 0; j < count; j++) + { + + *dstPtr = (*srcPtr) * scale; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + else + { + + real32 b1 = 0.0f; + + if (fBlack_1D_rows) + { + b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows]; + } + + const real32 *b2 = NULL; + + uint32 b2_count = fBlack_2D_cols; + uint32 b2_phase = 0; + + if (b2_count) + { + + b2 = fBlack_2D_buffer->Buffer_real32 () + + b2_count * (dstRow % fBlack_2D_rows); + + b2_phase = dstCol % b2_count; + + } + + for (uint32 j = 0; j < count; j++) + { + + real32 x = (*srcPtr) * scale - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + *dstPtr = x; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + } + + // Simple LUT case. + + else if (fBlack_1D_rows == 0 && + fBlack_2D_rows == 0 && fSrcPixelType != ttLong) + { + + if (fDstPixelType == ttShort) + { + + const uint16 *lut = fScale_buffer->Buffer_uint16 (); + + uint16 *dstPtr = (uint16 *) dPtr; + + if (fSrcPixelType == ttByte) + { + + const uint8 *srcPtr = (const uint8 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + *dstPtr = lut [*srcPtr]; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + else + { + + const uint16 *srcPtr = (const uint16 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + *dstPtr = lut [*srcPtr]; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + } + + else + { + + const real32 *lut = fScale_buffer->Buffer_real32 (); + + real32 *dstPtr = (real32 *) dPtr; + + if (fSrcPixelType == ttByte) + { + + const uint8 *srcPtr = (const uint8 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + *dstPtr = lut [*srcPtr]; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + else + { + + const uint16 *srcPtr = (const uint16 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + *dstPtr = lut [*srcPtr]; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + } + + } + + // Integer math case. + + else if (!fReal32) + { + + const int32 *lut = fScale_buffer->Buffer_int32 (); + + int32 b1 = 0; + + if (fBlack_1D_rows) + { + b1 = fBlack_1D_buffer->Buffer_int32 () [dstRow % fBlack_1D_rows]; + } + + const int32 *b2 = NULL; + + uint32 b2_count = fBlack_2D_cols; + uint32 b2_phase = 0; + + if (b2_count) + { + + b2 = fBlack_2D_buffer->Buffer_int32 () + + b2_count * (dstRow % fBlack_2D_rows); + + b2_phase = dstCol % b2_count; + + } + + uint16 *dstPtr = (uint16 *) dPtr; + + b1 -= 128; // Rounding for 8 bit shift + + if (fSrcPixelType == ttByte) + { + + const uint8 *srcPtr = (const uint8 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + int32 x = lut [*srcPtr] - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + x >>= 8; + + *dstPtr = Pin_uint16 (x); + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + else + { + + const uint16 *srcPtr = (const uint16 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + int32 x = lut [*srcPtr] - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + x >>= 8; + + *dstPtr = Pin_uint16 (x); + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + } + + // Floating point math cases. + + else + { + + real32 b1 = 0.0f; + + if (fBlack_1D_rows) + { + b1 = fBlack_1D_buffer->Buffer_real32 () [dstRow % fBlack_1D_rows]; + } + + const real32 *b2 = NULL; + + uint32 b2_count = fBlack_2D_cols; + uint32 b2_phase = 0; + + if (b2_count) + { + + b2 = fBlack_2D_buffer->Buffer_real32 () + + b2_count * (dstRow % fBlack_2D_rows); + + b2_phase = dstCol % b2_count; + + } + + // Case 1: uint8/uint16 -> real32 + + if (fSrcPixelType != ttLong) + { + + const real32 *lut = fScale_buffer->Buffer_real32 (); + + real32 *dstPtr = (real32 *) dPtr; + + if (fSrcPixelType == ttByte) + { + + const uint8 *srcPtr = (const uint8 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + real32 x = lut [*srcPtr] - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + x = Pin_real32 (0.0f, x, 1.0f); + + *dstPtr = x; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + else + { + + const uint16 *srcPtr = (const uint16 *) sPtr; + + for (uint32 j = 0; j < count; j++) + { + + real32 x = lut [*srcPtr] - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + x = Pin_real32 (0.0f, x, 1.0f); + + *dstPtr = x; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + } + + // Otherwise source is uint32 + + else + { + + real32 scale = fScale; + + const uint32 *srcPtr = (const uint32 *) sPtr; + + // Case 2: uint32 -> real32 + + if (fDstPixelType == ttFloat) + { + + real32 *dstPtr = (real32 *) dPtr; + + for (uint32 j = 0; j < count; j++) + { + + real32 x = ((real32) *srcPtr) * scale - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + x = Pin_real32 (0.0f, x, 1.0f); + + *dstPtr = x; + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + // Case 3: uint32 -> uint16 + + else + { + + uint16 *dstPtr = (uint16 *) dPtr; + + real32 dstScale = (real32) 0x0FFFF; + + for (uint32 j = 0; j < count; j++) + { + + real32 x = ((real32) *srcPtr) * scale - b1; + + if (b2_count) + { + + x -= b2 [b2_phase]; + + if (++b2_phase == b2_count) + { + b2_phase = 0; + } + + } + + x = Pin_real32 (0.0f, x, 1.0f); + + *dstPtr = (uint16) (x * dstScale + 0.5f); + + srcPtr += sStep; + dstPtr += dStep; + + } + + } + + } + + } + + } + + } + +/*****************************************************************************/ + +class dng_linearize_image: public dng_area_task + { + + private: + + const dng_image & fSrcImage; + dng_image & fDstImage; + + dng_rect fActiveArea; + + AutoPtr fPlaneTask [kMaxColorPlanes]; + + public: + + dng_linearize_image (dng_host &host, + dng_linearization_info &info, + const dng_image &srcImage, + dng_image &dstImage); + + virtual ~dng_linearize_image (); + + virtual dng_rect RepeatingTile1 () const; + + virtual dng_rect RepeatingTile2 () const; + + virtual void Process (uint32 threadIndex, + const dng_rect &tile, + dng_abort_sniffer *sniffer); + + }; + +/*****************************************************************************/ + +dng_linearize_image::dng_linearize_image (dng_host &host, + dng_linearization_info &info, + const dng_image &srcImage, + dng_image &dstImage) + + : fSrcImage (srcImage) + , fDstImage (dstImage) + , fActiveArea (info.fActiveArea) + + { + + // Build linearization table for each plane. + + for (uint32 plane = 0; plane < srcImage.Planes (); plane++) + { + + fPlaneTask [plane].Reset (new dng_linearize_plane (host, + info, + srcImage, + dstImage, + plane)); + + } + + // Adjust maximum tile size. + + fMaxTileSize = dng_point (1024, 1024); + + } + +/*****************************************************************************/ + +dng_linearize_image::~dng_linearize_image () + { + + } + +/*****************************************************************************/ + +dng_rect dng_linearize_image::RepeatingTile1 () const + { + + return fSrcImage.RepeatingTile (); + + } + +/*****************************************************************************/ + +dng_rect dng_linearize_image::RepeatingTile2 () const + { + + return fDstImage.RepeatingTile () + fActiveArea.TL (); + + } + +/*****************************************************************************/ + +void dng_linearize_image::Process (uint32 /* threadIndex */, + const dng_rect &srcTile, + dng_abort_sniffer * /* sniffer */) + { + + // Process each plane. + + for (uint32 plane = 0; plane < fSrcImage.Planes (); plane++) + { + + fPlaneTask [plane]->Process (srcTile); + + } + + } + +/*****************************************************************************/ + +dng_linearization_info::dng_linearization_info () + + : fActiveArea () + , fMaskedAreaCount (0) + , fLinearizationTable () + , fBlackLevelRepeatRows (1) + , fBlackLevelRepeatCols (1) + , fBlackDeltaH () + , fBlackDeltaV () + , fBlackDenom (256) + + { + + uint32 j; + uint32 k; + uint32 n; + + for (j = 0; j < kMaxBlackPattern; j++) + for (k = 0; k < kMaxBlackPattern; k++) + for (n = 0; n < kMaxSamplesPerPixel; n++) + { + fBlackLevel [j] [k] [n] = 0.0; + } + + for (n = 0; n < kMaxSamplesPerPixel; n++) + { + fWhiteLevel [n] = 65535.0; + } + + } + +/*****************************************************************************/ + +dng_linearization_info::~dng_linearization_info () + { + + } + +/*****************************************************************************/ + +void dng_linearization_info::RoundBlacks () + { + + uint32 j; + uint32 k; + uint32 n; + + real64 maxAbs = 0.0; + + for (j = 0; j < fBlackLevelRepeatRows; j++) + for (k = 0; k < fBlackLevelRepeatCols; k++) + for (n = 0; n < kMaxSamplesPerPixel; n++) + { + + maxAbs = Max_real64 (maxAbs, + Abs_real64 (fBlackLevel [j] [k] [n])); + + } + + uint32 count = RowBlackCount (); + + for (j = 0; j < count; j++) + { + + maxAbs = Max_real64 (maxAbs, + Abs_real64 (fBlackDeltaV->Buffer_real64 () [j])); + + } + + count = ColumnBlackCount (); + + for (j = 0; j < count; j++) + { + + maxAbs = Max_real64 (maxAbs, + Abs_real64 (fBlackDeltaH->Buffer_real64 () [j])); + + + } + + fBlackDenom = 256; + + while (fBlackDenom > 1 && (maxAbs * fBlackDenom) >= 30000.0 * 65536.0) + { + fBlackDenom >>= 1; + } + + for (j = 0; j < fBlackLevelRepeatRows; j++) + for (k = 0; k < fBlackLevelRepeatCols; k++) + for (n = 0; n < kMaxSamplesPerPixel; n++) + { + + fBlackLevel [j] [k] [n] = BlackLevel (j, k, n).As_real64 (); + + } + + count = RowBlackCount (); + + for (j = 0; j < count; j++) + { + + fBlackDeltaV->Buffer_real64 () [j] = RowBlack (j).As_real64 (); + + } + + count = ColumnBlackCount (); + + for (j = 0; j < count; j++) + { + + fBlackDeltaH->Buffer_real64 () [j] = ColumnBlack (j).As_real64 (); + + } + + } + +/*****************************************************************************/ + +void dng_linearization_info::Parse (dng_host &host, + dng_stream &stream, + dng_info &info) + { + + uint32 j; + uint32 k; + uint32 n; + + // Find main image IFD. + + dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get (); + + // Copy active area. + + fActiveArea = rawIFD.fActiveArea; + + // Copy masked areas. + + fMaskedAreaCount = rawIFD.fMaskedAreaCount; + + for (j = 0; j < fMaskedAreaCount; j++) + { + fMaskedArea [j] = rawIFD.fMaskedArea [j]; + } + + // Read linearization LUT. + + if (rawIFD.fLinearizationTableCount) + { + + uint32 size = rawIFD.fLinearizationTableCount * (uint32) sizeof (uint16); + + fLinearizationTable.Reset (host.Allocate (size)); + + uint16 *table = fLinearizationTable->Buffer_uint16 (); + + stream.SetReadPosition (rawIFD.fLinearizationTableOffset); + + for (j = 0; j < rawIFD.fLinearizationTableCount; j++) + { + table [j] = stream.Get_uint16 (); + } + + } + + // Copy black level pattern. + + fBlackLevelRepeatRows = rawIFD.fBlackLevelRepeatRows; + fBlackLevelRepeatCols = rawIFD.fBlackLevelRepeatCols; + + for (j = 0; j < kMaxBlackPattern; j++) + for (k = 0; k < kMaxBlackPattern; k++) + for (n = 0; n < kMaxSamplesPerPixel; n++) + { + fBlackLevel [j] [k] [n] = rawIFD.fBlackLevel [j] [k] [n]; + } + + // Read BlackDeltaH. + + if (rawIFD.fBlackLevelDeltaHCount) + { + + uint32 size = rawIFD.fBlackLevelDeltaHCount * (uint32) sizeof (real64); + + fBlackDeltaH.Reset (host.Allocate (size)); + + real64 *blacks = fBlackDeltaH->Buffer_real64 (); + + stream.SetReadPosition (rawIFD.fBlackLevelDeltaHOffset); + + for (j = 0; j < rawIFD.fBlackLevelDeltaHCount; j++) + { + blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaHType); + } + + } + + // Read BlackDeltaV. + + if (rawIFD.fBlackLevelDeltaVCount) + { + + uint32 size = rawIFD.fBlackLevelDeltaVCount * (uint32) sizeof (real64); + + fBlackDeltaV.Reset (host.Allocate (size)); + + real64 *blacks = fBlackDeltaV->Buffer_real64 (); + + stream.SetReadPosition (rawIFD.fBlackLevelDeltaVOffset); + + for (j = 0; j < rawIFD.fBlackLevelDeltaVCount; j++) + { + blacks [j] = stream.TagValue_real64 (rawIFD.fBlackLevelDeltaVType); + } + + } + + // Copy white level. + + for (n = 0; n < kMaxSamplesPerPixel; n++) + { + fWhiteLevel [n] = rawIFD.fWhiteLevel [n]; + } + + // Round off black levels. + + RoundBlacks (); + + } + +/*****************************************************************************/ + +void dng_linearization_info::PostParse (dng_host & /* host */, + dng_negative &negative) + { + + if (fActiveArea.IsEmpty ()) + { + + fActiveArea = negative.Stage1Image ()->Bounds (); + + } + + } + +/*****************************************************************************/ + +real64 dng_linearization_info::MaxBlackLevel (uint32 plane) const + { + + uint32 j; + uint32 k; + + // Find maximum value of fBlackDeltaH for each phase of black pattern. + + real64 maxDeltaH [kMaxBlackPattern]; + + for (j = 0; j < fBlackLevelRepeatCols; j++) + { + maxDeltaH [j] = 0.0; + } + + if (fBlackDeltaH.Get ()) + { + + real64 *table = fBlackDeltaH->Buffer_real64 (); + + uint32 entries = fBlackDeltaH->LogicalSize () / (uint32) sizeof (table [0]); + + for (j = 0; j < entries; j++) + { + + real64 &entry = maxDeltaH [j % fBlackLevelRepeatCols]; + + if (j < fBlackLevelRepeatCols) + { + entry = table [j]; + } + else + { + entry = Max_real64 (entry, table [j]); + } + + } + + } + + // Find maximum value of fBlackDeltaV for each phase of black pattern. + + real64 maxDeltaV [kMaxBlackPattern]; + + for (j = 0; j < fBlackLevelRepeatRows; j++) + { + maxDeltaV [j] = 0.0; + } + + if (fBlackDeltaV.Get ()) + { + + real64 *table = fBlackDeltaV->Buffer_real64 (); + + uint32 entries = fBlackDeltaV->LogicalSize () / (uint32) sizeof (table [0]); + + for (j = 0; j < entries; j++) + { + + real64 &entry = maxDeltaV [j % fBlackLevelRepeatRows]; + + if (j < fBlackLevelRepeatRows) + { + entry = table [j]; + } + else + { + entry = Max_real64 (entry, table [j]); + } + + } + + } + + // Now scan the pattern and find the maximum value after row and column + // deltas. + + real64 maxBlack = 0.0; + + for (j = 0; j < fBlackLevelRepeatRows; j++) + { + + for (k = 0; k < fBlackLevelRepeatCols; k++) + { + + real64 black = fBlackLevel [j] [k] [plane]; + + black += maxDeltaH [k]; + black += maxDeltaV [j]; + + if (j == 0 && k == 0) + { + maxBlack = black; + } + else + { + maxBlack = Max_real64 (maxBlack, black); + } + + } + + } + + return maxBlack; + + } + +/*****************************************************************************/ + +void dng_linearization_info::Linearize (dng_host &host, + const dng_image &srcImage, + dng_image &dstImage) + { + + dng_linearize_image processor (host, + *this, + srcImage, + dstImage); + + host.PerformAreaTask (processor, + fActiveArea); + + } + +/*****************************************************************************/ + +dng_urational dng_linearization_info::BlackLevel (uint32 row, + uint32 col, + uint32 plane) const + { + + dng_urational r; + + r.Set_real64 (fBlackLevel [row] [col] [plane], fBlackDenom); + + return r; + + } + +/*****************************************************************************/ + +uint32 dng_linearization_info::RowBlackCount () const + { + + if (fBlackDeltaV.Get ()) + { + + return fBlackDeltaV->LogicalSize () >> 3; + + } + + return 0; + + } + +/*****************************************************************************/ + +dng_srational dng_linearization_info::RowBlack (uint32 row) const + { + + if (fBlackDeltaV.Get ()) + { + + dng_srational r; + + r.Set_real64 (fBlackDeltaV->Buffer_real64 () [row], fBlackDenom); + + return r; + + } + + return dng_srational (0, 1); + + } + +/*****************************************************************************/ + +uint32 dng_linearization_info::ColumnBlackCount () const + { + + if (fBlackDeltaH.Get ()) + { + + return fBlackDeltaH->LogicalSize () >> 3; + + } + + return 0; + + } + +/*****************************************************************************/ + +dng_srational dng_linearization_info::ColumnBlack (uint32 col) const + { + + if (fBlackDeltaH.Get ()) + { + + dng_srational r; + + r.Set_real64 (fBlackDeltaH->Buffer_real64 () [col], fBlackDenom); + + return r; + + } + + return dng_srational (0, 1); + + } + +/*****************************************************************************/ -- cgit v1.2.3-70-g09d2