Author: post
Date: 2013-04-01 19:53:25 +0200 (Mon, 01 Apr 2013)
New Revision: 532
Modified:
RawSpeed/DngDecoder.cpp
RawSpeed/DngOpcodes.cpp
RawSpeed/DngOpcodes.h
RawSpeed/RawDecoder.cpp
RawSpeed/RawDecoder.h
Log:
Implement bad pixel mapping DNG Opcodes.
Modified: RawSpeed/DngDecoder.cpp
===================================================================
--- RawSpeed/DngDecoder.cpp 2013-03-25 20:57:33 UTC (rev 531)
+++ RawSpeed/DngDecoder.cpp 2013-04-01 17:53:25 UTC (rev 532)
@@ -379,6 +379,21 @@
if (mRaw->dim.area() <= 0)
ThrowRDE("DNG Decoder: No image left after crop");
+ // Apply stage 1 opcodes
+ if (applyStage1DngOpcodes) {
+ if (raw->hasEntry(OPCODELIST1))
+ {
+ // Apply stage 1 codes
+ try{
+ DngOpcodes codes(raw->getEntry(OPCODELIST1));
+ mRaw = codes.applyOpCodes(mRaw);
+ } catch (RawDecoderException &e) {
+ // We push back errors from the opcode parser, since the image may
still be usable
+ mRaw->setError(e.what());
+ }
+ }
+ }
+
// Linearization
if (raw->hasEntry(LINEARIZATIONTABLE)) {
const ushort16* intable =
raw->getEntry(LINEARIZATIONTABLE)->getShortArray();
Modified: RawSpeed/DngOpcodes.cpp
===================================================================
--- RawSpeed/DngOpcodes.cpp 2013-03-25 20:57:33 UTC (rev 531)
+++ RawSpeed/DngOpcodes.cpp 2013-04-01 17:53:25 UTC (rev 532)
@@ -35,12 +35,18 @@
for (uint32 i = 0; i < opcode_count; i++) {
uint32 code = getULong(&data[bytes_used]);
//uint32 version = getULong(&data[bytes_used+4]);
- //uint32 flags = getULong(&data[bytes_used+8]);
+ uint32 flags = getULong(&data[bytes_used+8]);
uint32 expected_size = getULong(&data[bytes_used+12]);
bytes_used += 16;
uint32 opcode_used = 0;
switch (code)
{
+ case 4:
+ mOpcodes.push_back(new OpcodeFixBadPixelsConstant(&data[bytes_used],
entry_size - bytes_used, &opcode_used));
+ break;
+ case 5:
+ mOpcodes.push_back(new OpcodeFixBadPixelsList(&data[bytes_used],
entry_size - bytes_used, &opcode_used));
+ break;
case 6:
mOpcodes.push_back(new OpcodeTrimBounds(&data[bytes_used], entry_size
- bytes_used, &opcode_used));
break;
@@ -63,7 +69,9 @@
mOpcodes.push_back(new OpcodeScalePerCol(&data[bytes_used], entry_size
- bytes_used, &opcode_used));
break;
default:
- ThrowRDE("DngOpcodes: Unsupported Opcode: %d", code);
+ // Throw Error if not marked as optional
+ if (!(flags & 1))
+ ThrowRDE("DngOpcodes: Unsupported Opcode: %d", code);
}
if (opcode_used != expected_size)
ThrowRDE("DngOpcodes: Inconsistent length of opcode");
@@ -101,6 +109,92 @@
return img;
}
+/***************** OpcodeFixBadPixelsConstant ****************/
+
+OpcodeFixBadPixelsConstant::OpcodeFixBadPixelsConstant(const uchar8*
parameters, int param_max_bytes, uint32 *bytes_used )
+{
+ if (param_max_bytes < 8)
+ ThrowRDE("OpcodeFixBadPixelsConstant: Not enough data to read parameters,
only %d bytes left.", param_max_bytes);
+ mValue = getLong(¶meters[0]);
+ // Bayer Phase not used
+ *bytes_used = 8;
+ mFlags = MultiThreaded;
+}
+
+RawImage& OpcodeFixBadPixelsConstant::createOutput( RawImage &in )
+{
+ // These limitations are present within the DNG SDK as well.
+ if (in->getDataType() != TYPE_USHORT16)
+ ThrowRDE("OpcodeFixBadPixelsConstant: Only 16 bit images supported");
+
+ if (in->getCpp() > 1)
+ ThrowRDE("OpcodeFixBadPixelsConstant: This operation is only supported
with 1 component");
+
+ return in;
+}
+
+void OpcodeFixBadPixelsConstant::apply( RawImage &in, RawImage &out, int
startY, int endY )
+{
+ vector<uint32> bad_pos;
+ for (int y = startY; y < endY; y ++) {
+ ushort16* src = (ushort16*)out->getData(0, y);
+ for (int x = 0; x < in->dim.x; x++) {
+ if (src[x]== mValue) {
+ bad_pos.push_back(((uint32)x | (uint32)y<<16));
+ }
+ }
+ }
+ if (!bad_pos.empty()) {
+ pthread_mutex_lock(&out->mBadPixelMutex);
+ out->mBadPixelPositions.insert(out->mBadPixelPositions.end(),
bad_pos.begin(), bad_pos.end());
+ pthread_mutex_unlock(&out->mBadPixelMutex);
+ }
+
+}
+
+/***************** OpcodeFixBadPixelsList ****************/
+
+OpcodeFixBadPixelsList::OpcodeFixBadPixelsList( const uchar8* parameters, int
param_max_bytes, uint32 *bytes_used )
+{
+ if (param_max_bytes < 12)
+ ThrowRDE("OpcodeFixBadPixelsList: Not enough data to read parameters, only
%d bytes left.", param_max_bytes);
+ // Skip phase - we don't care
+ int BadPointCount = getLong(¶meters[4]);
+ int BadRectCount = getLong(¶meters[8]);
+ bytes_used[0] = 12;
+ if (12 + BadPointCount * 8 + BadRectCount * 16 > param_max_bytes)
+ ThrowRDE("OpcodeFixBadPixelsList: Ran out parameter space, only %d bytes
left.", param_max_bytes);
+
+ // Read points
+ for (int i = 0; i < BadPointCount; i++) {
+ uint32 BadPointRow = (uint32)getLong(¶meters[bytes_used[0]]);
+ uint32 BadPointCol = (uint32)getLong(¶meters[bytes_used[0]+4]);
+ bytes_used[0] += 8;
+ bad_pos.push_back(BadPointRow | (BadPointCol << 16));
+ }
+
+ // Read rects
+ for (int i = 0; i < BadRectCount; i++) {
+ uint32 BadRectTop = (uint32)getLong(¶meters[bytes_used[0]]);
+ uint32 BadRectLeft = (uint32)getLong(¶meters[bytes_used[0]+4]);
+ uint32 BadRectBottom = (uint32)getLong(¶meters[bytes_used[0]]);
+ uint32 BadRectRight = (uint32)getLong(¶meters[bytes_used[0]+4]);
+ bytes_used[0] += 16;
+ if (BadRectTop < BadRectBottom && BadRectLeft < BadRectRight) {
+ for (uint32 y = BadRectLeft; y <= BadRectRight; y++) {
+ for (uint32 x = BadRectTop; x <= BadRectBottom; x++) {
+ bad_pos.push_back(x | (y << 16));
+ }
+ }
+ }
+ }
+}
+
+void OpcodeFixBadPixelsList::apply( RawImage &in, RawImage &out, int startY,
int endY )
+{
+ out->mBadPixelPositions.insert(out->mBadPixelPositions.end(),
bad_pos.begin(), bad_pos.end());
+}
+
/***************** OpcodeTrimBounds ****************/
OpcodeTrimBounds::OpcodeTrimBounds(const uchar8* parameters, int
param_max_bytes, uint32 *bytes_used )
@@ -592,4 +686,5 @@
}
}
+
} // namespace RawSpeed
Modified: RawSpeed/DngOpcodes.h
===================================================================
--- RawSpeed/DngOpcodes.h 2013-03-25 20:57:33 UTC (rev 531)
+++ RawSpeed/DngOpcodes.h 2013-04-01 17:53:25 UTC (rev 532)
@@ -100,6 +100,29 @@
}
};
+class OpcodeFixBadPixelsConstant: public DngOpcode
+{
+public:
+ OpcodeFixBadPixelsConstant(const uchar8* parameters, int param_max_bytes,
uint32 *bytes_used);
+ virtual ~OpcodeFixBadPixelsConstant(void) {};
+ virtual RawImage& createOutput( RawImage &in );
+ virtual void apply(RawImage &in, RawImage &out, int startY, int endY);
+private:
+ int mValue;
+};
+
+
+class OpcodeFixBadPixelsList: public DngOpcode
+{
+public:
+ OpcodeFixBadPixelsList(const uchar8* parameters, int param_max_bytes, uint32
*bytes_used);
+ virtual ~OpcodeFixBadPixelsList(void) {};
+ virtual void apply(RawImage &in, RawImage &out, int startY, int endY);
+private:
+ vector<uint32> bad_pos;
+};
+
+
class OpcodeTrimBounds: public DngOpcode
{
public:
@@ -111,7 +134,6 @@
};
-
class OpcodeMapTable: public DngOpcode
{
public:
Modified: RawSpeed/RawDecoder.cpp
===================================================================
--- RawSpeed/RawDecoder.cpp 2013-03-25 20:57:33 UTC (rev 531)
+++ RawSpeed/RawDecoder.cpp 2013-04-01 17:53:25 UTC (rev 532)
@@ -28,6 +28,7 @@
decoderVersion = 0;
failOnUnknown = FALSE;
interpolateBadPixels = TRUE;
+ applyStage1DngOpcodes = TRUE;
}
RawDecoder::~RawDecoder(void) {
Modified: RawSpeed/RawDecoder.h
===================================================================
--- RawSpeed/RawDecoder.h 2013-03-25 20:57:33 UTC (rev 531)
+++ RawSpeed/RawDecoder.h 2013-04-01 17:53:25 UTC (rev 532)
@@ -97,6 +97,10 @@
/* If you disable this parameter, no bad pixel interpolation will be done */
bool interpolateBadPixels;
+ /* Apply stage 1 DNG opcodes. */
+ /* This usually maps out bad pixels, etc */
+ bool applyStage1DngOpcodes;
+
protected:
/* Attempt to decode the image */
/* A RawDecoderException will be thrown if the image cannot be decoded, */
_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit