| /*****************************************************************************/ |
| // 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; |
| |
| } |
| |
| } |
| |
| } |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |