Author: post
Date: 2013-06-01 14:53:54 +0200 (Sat, 01 Jun 2013)
New Revision: 548

Modified:
   RawSpeed/SrwDecoder.cpp
   RawSpeed/SrwDecoder.h
Log:
Add support for compressed Samsung images.

Modified: RawSpeed/SrwDecoder.cpp
===================================================================
--- RawSpeed/SrwDecoder.cpp     2013-06-01 11:38:04 UTC (rev 547)
+++ RawSpeed/SrwDecoder.cpp     2013-06-01 12:53:54 UTC (rev 548)
@@ -1,6 +1,8 @@
 #include "StdAfx.h"
 #include "SrwDecoder.h"
 #include "TiffParserOlympus.h"
+#include "ByteStreamSwap.h"
+
 #if defined(__unix__) || defined(__APPLE__) 
 #include <stdlib.h>
 #endif
@@ -30,7 +32,7 @@
 
 SrwDecoder::SrwDecoder(TiffIFD *rootIFD, FileMap* file):
 RawDecoder(file), mRootIFD(rootIFD) {
-  decoderVersion = 2;
+  decoderVersion = 3;
 }
 
 SrwDecoder::~SrwDecoder(void) {
@@ -65,17 +67,117 @@
 
   if (32770 == compression)
   {
-    bool bit_order = (bits == 12);  // Default guess
-    map<string,string>::iterator msb_hint = hints.find("msb_override");
-    if (msb_hint != hints.end())
-      bit_order = (0 == (msb_hint->second).compare("true"));
-    this->decodeUncompressed(raw, bit_order ? BitOrder_Jpeg : BitOrder_Plain);
-    return mRaw;
+    if (!raw->hasEntry ((TiffTag)40976)) {
+      bool bit_order = (bits == 12);  // Default guess
+      map<string,string>::iterator msb_hint = hints.find("msb_override");
+      if (msb_hint != hints.end())
+        bit_order = (0 == (msb_hint->second).compare("true"));
+      this->decodeUncompressed(raw, bit_order ? BitOrder_Jpeg : 
BitOrder_Plain);
+      return mRaw;
+    } else {
+      uint32 nslices = raw->getEntry(STRIPOFFSETS)->count;
+      if (nslices != 1)
+        ThrowRDE("Srw Decoder: Only one slice supported, found %u", nslices);
+      try {
+        decodeCompressed(raw);
+      } catch (RawDecoderException& e) {
+        mRaw->setError(e.what());
+      }
+      return mRaw;
+    }
   }
   ThrowRDE("Srw Decoder: Unsupported compression");
   return mRaw;
 }
+// Decoder for compressed srw files (NX300 and later)
+void SrwDecoder::decodeCompressed( TiffIFD* raw )
+{
+  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
+  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
+  mRaw->dim = iPoint2D(width, height);
+  mRaw->createData();
+  const uint32 offset = raw->getEntry(STRIPOFFSETS)->getInt();
+  const uint32 count = raw->getEntry(STRIPBYTECOUNTS)->getInt();
+  uint32 compressed_offset = raw->getEntry((TiffTag)40976)->getInt();
+  ByteStream *b;
+  if (getHostEndianness() == little)
+    b = new ByteStream(mFile->getData(0), mFile->getSize());
+  else
+    b = new ByteStreamSwap(mFile->getData(0), mFile->getSize());
+  b->setAbsoluteOffset(compressed_offset);
 
+  for (uint32 y = 0; y < height; y++) {
+    uint32 line_offset = offset + b->getInt();
+    if (line_offset >= mFile->getSize())
+      ThrowRDE("Srw decoder: Offset outside image file, file probably 
truncated.");
+    int len[4];
+    for (int i = 0; i < 4; i++)
+      len[i] = y < 2 ? 7 : 4;
+    BitPumpMSB32 bits(mFile->getData(line_offset),mFile->getSize() - 
line_offset);
+    int op[4];
+    ushort16* img = (ushort16*)mRaw->getData(0, y);
+    ushort16* img_up = (ushort16*)mRaw->getData(0, max(0, (int)y - 1));
+    ushort16* img_up2 = (ushort16*)mRaw->getData(0, max(0, (int)y - 2));
+    // Image is arranged in groups of 16 pixels horizontally
+    for (uint32 x = 0; x < width; x += 16) {
+      bool dir = !!bits.getBit();
+      for (int i = 0; i < 4; i++)
+        op[i] = bits.getBits(2);
+      for (int i = 0; i < 4; i++) {
+        switch (op[i]) {
+          case 3: len[i] = bits.getBits(4);
+            break;
+          case 2: len[i]--;
+            break;
+          case 1: len[i]++;
+        }
+        if (len[i] < 0)
+          ThrowRDE("Srw Decompressor: Bit length less than 0.");
+        if (len[i] > 16)
+          ThrowRDE("Srw Decompressor: Bit Length more than 16.");
+      }
+      if (dir) {
+        // Upward prediction
+        // First we decode even pixels
+        for (int c = 0; c < 16; c += 2) {
+          int b = len[(c >> 3)];
+          int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
+          img[c] = adj + img_up[c];
+        }
+        // Now we decode odd pixels
+        // Why on earth upward prediction only looks up 1 line above
+        // is beyond me, it will hurt compression a deal.
+        for (int c = 1; c < 16; c += 2) {
+          int b = len[2 | (c >> 3)];
+          int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
+          img[c] = adj + img_up2[c];
+        }
+      } else {
+        // Left to right prediction
+        // First we decode even pixels
+        int pred_left = x ? img[-2] : 128;
+        for (int c = 0; c < 16; c += 2) {
+          int b = len[(c >> 3)];
+          int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
+          img[c] = adj + pred_left;
+        }
+        // Now we decode odd pixels
+        pred_left = x ? img[-1] : 128;
+        for (int c = 1; c < 16; c += 2) {
+          int b = len[2 | (c >> 3)];
+          int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
+          img[c] = adj + pred_left;
+        }
+      }
+      bits.checkPos();
+      img += 16;
+      img_up += 16;
+      img_up2 += 16;
+    }
+  }
+}
+
+
 void SrwDecoder::checkSupportInternal(CameraMetaData *meta) {
   vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);
   if (data.empty())
@@ -126,7 +228,7 @@
         mRaw->cfa.setColorAt(iPoint2D(x, y), c2);
       }
     }
-    printf("Camera CFA: %s\n", mRaw->cfa.asString().c_str());
+    //printf("Camera CFA: %s\n", mRaw->cfa.asString().c_str());
   }
 
   int iso = 0;
@@ -136,4 +238,5 @@
   setMetaData(meta, make, model, "", iso);
 }
 
+
 } // namespace RawSpeed

Modified: RawSpeed/SrwDecoder.h
===================================================================
--- RawSpeed/SrwDecoder.h       2013-06-01 11:38:04 UTC (rev 547)
+++ RawSpeed/SrwDecoder.h       2013-06-01 12:53:54 UTC (rev 548)
@@ -40,6 +40,7 @@
   virtual void decodeMetaDataInternal(CameraMetaData *meta);
   virtual void checkSupportInternal(CameraMetaData *meta);
 private:
+  void SrwDecoder::decodeCompressed( TiffIFD* raw);
   TiffIFD *mRootIFD;
 };
 


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to