Author: post
Date: 2013-03-25 16:39:12 +0100 (Mon, 25 Mar 2013)
New Revision: 528

Modified:
   RawSpeed/RawDecoder.cpp
   RawSpeed/RawDecoder.h
   RawSpeed/RawImage.cpp
   RawSpeed/RawImage.h
   RawSpeed/RawImageDataFloat.cpp
   RawSpeed/RawImageDataU16.cpp
   RawSpeed/Rw2Decoder.cpp
   RawSpeed/Rw2Decoder.h
Log:
Move bad pixel interpolation in to a generic setting, and make it possible to 
have bad pixels that doesn't depend on the value of the pixel.
Make a 4-way interpolation where bad pixels bordering the current bad pixel is 
skipped, and the distance to the found pixel is used.
Bad pixel interpolation can be disabled by setting 
RawDecoder.interpolateBadPixels = false;

Modified: RawSpeed/RawDecoder.cpp
===================================================================
--- RawSpeed/RawDecoder.cpp     2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/RawDecoder.cpp     2013-03-25 15:39:12 UTC (rev 528)
@@ -27,6 +27,7 @@
        RawDecoder::RawDecoder(FileMap* file) : mRaw(RawImage::create()), 
mFile(file) {
   decoderVersion = 0;
   failOnUnknown = FALSE;
+  interpolateBadPixels = TRUE;
 }
 
 RawDecoder::~RawDecoder(void) {
@@ -261,7 +262,7 @@
 void *RawDecoderDecodeThread(void *_this) {
   RawDecoderThread* me = (RawDecoderThread*)_this;
   try {
-    me->parent->decodeThreaded(me);
+      me->parent->decodeThreaded(me);
   } catch (RawDecoderException &ex) {
     me->parent->mRaw->setError(ex.what());
   } catch (IOException &ex) {
@@ -310,7 +311,10 @@
 RawSpeed::RawImage RawDecoder::decodeRaw()
 {
   try {
-    return decodeRawInternal();
+    RawImage raw = decodeRawInternal();
+    if (interpolateBadPixels)
+      raw->fixBadPixels();
+    return raw;
   } catch (TiffParserException &e) {
     ThrowRDE("%s", e.what());
   } catch (FileIOException &e) {

Modified: RawSpeed/RawDecoder.h
===================================================================
--- RawSpeed/RawDecoder.h       2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/RawDecoder.h       2013-03-25 15:39:12 UTC (rev 528)
@@ -93,6 +93,10 @@
   /* DNGs are always attempted to be decoded, so this variable has no effect 
on DNGs */
   bool failOnUnknown;
 
+  /* Set how to handle bad pixels. */
+  /* If you disable this parameter, no bad pixel interpolation will be done */
+  bool interpolateBadPixels;
+
 protected:
   /* Attempt to decode the image */
   /* A RawDecoderException will be thrown if the image cannot be decoded, */

Modified: RawSpeed/RawImage.cpp
===================================================================
--- RawSpeed/RawImage.cpp       2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/RawImage.cpp       2013-03-25 15:39:12 UTC (rev 528)
@@ -37,7 +37,9 @@
   pthread_mutex_init(&mymutex, NULL);
   subsampling.x = subsampling.y = 1;
   isoSpeed = 0;
+  mBadPixelMap = NULL;
   pthread_mutex_init(&errMutex, NULL);
+  pthread_mutex_init(&mBadPixelMutex, NULL);
 }
 
 RawImageData::RawImageData(iPoint2D _dim, uint32 _bpc, uint32 _cpp) :
@@ -48,23 +50,24 @@
   blackLevelSeparate[0] = blackLevelSeparate[1] = blackLevelSeparate[2] = 
blackLevelSeparate[3] = -1;
   subsampling.x = subsampling.y = 1;
   isoSpeed = 0;
+  mBadPixelMap = NULL;
   createData();
   pthread_mutex_init(&mymutex, NULL);
   pthread_mutex_init(&errMutex, NULL);
+  pthread_mutex_init(&mBadPixelMutex, NULL);
 }
 
 RawImageData::~RawImageData(void) {
   _ASSERTE(dataRefCount == 0);
-  if (data)
-    _aligned_free(data);
-  data = 0;
   mOffset = iPoint2D(0, 0);
   pthread_mutex_destroy(&mymutex);
   pthread_mutex_destroy(&errMutex);
+  pthread_mutex_destroy(&mBadPixelMutex);
   for (uint32 i = 0 ; i < errors.size(); i++) {
     free((void*)errors[i]);
   }
   errors.clear();
+  destroyData();
 }
 
 
@@ -85,7 +88,10 @@
 void RawImageData::destroyData() {
   if (data)
     _aligned_free(data);
+  if (mBadPixelMap)
+    _aligned_free(mBadPixelMap);
   data = 0;
+  mBadPixelMap = 0;
 }
 
 void RawImageData::setCpp(uint32 val) {
@@ -164,6 +170,17 @@
   pthread_mutex_unlock(&errMutex);
 }
 
+void RawImageData::createBadPixelMap()
+{
+  if (!isAllocated())
+    ThrowRDE("RawImageData::createBadPixelMap: (internal) Bad pixel map cannot 
be allocated before image.");
+  mBadPixelMapPitch = (((uncropped_dim.x / 8) + 15) / 16) * 16;
+  mBadPixelMap = (uchar8*)_aligned_malloc(mBadPixelMapPitch * uncropped_dim.y, 
16);
+  memset(mBadPixelMap, 0, mBadPixelMapPitch * uncropped_dim.y);
+  if (!mBadPixelMap)
+    ThrowRDE("RawImageData::createData: Memory Allocation failed.");
+}
+
 RawImage::RawImage(RawImageData* p) : p_(p) {
   pthread_mutex_lock(&p_->mymutex);
   ++p_->dataRefCount;
@@ -186,6 +203,123 @@
   pthread_mutex_unlock(&p_->mymutex);
 }
 
+
+void RawImageData::transferBadPixelsToMap()
+{
+  if (mBadPixelPositions.empty())
+    return;
+
+  if (!mBadPixelMap)
+    createBadPixelMap();
+
+  for (vector<uint32>::iterator i=mBadPixelPositions.begin(); i != 
mBadPixelPositions.end(); i++) {
+    uint32 pos = *i;
+    uint32 pos_x = pos&0xffff;
+    uint32 pos_y = pos>>16;
+    mBadPixelMap[mBadPixelMapPitch * pos_y + (pos_x >> 3)] |= 1 << (pos_x&7);
+  }
+  mBadPixelPositions.clear();
+}
+
+void RawImageData::fixBadPixels()
+{
+#if !defined (EMULATE_DCRAW_BAD_PIXELS)
+
+  /* Transfer if not already done */
+  transferBadPixelsToMap();
+
+#if 0 // For testing purposes
+  if (!mBadPixelMap)
+    createBadPixelMap();
+  for (int y = 400; y < 700; y++){
+    for (int x = 1200; x < 1700; x++) {
+      mBadPixelMap[mBadPixelMapPitch * y + (x >> 3)] |= 1 << (x&7);
+    }
+  }
+#endif
+
+  /* Process bad pixels, if any */
+  if (mBadPixelMap)
+    startWorker(RawImageWorker::FIX_BAD_PIXELS, false);
+
+  return;
+
+#else  // EMULATE_DCRAW_BAD_PIXELS - not recommended, testing purposes only
+
+  for (vector<uint32>::iterator i=mBadPixelPositions.begin(); i != 
mBadPixelPositions.end(); i++) {
+    uint32 pos = *i;
+    uint32 pos_x = pos&0xffff;
+    uint32 pos_y = pos>>16;
+    uint32 total = 0;
+    uint32 div = 0;
+    // 0 side covered by unsignedness.
+    for (uint32 r=pos_x-2; r<=pos_x+2 && r<(uint32)uncropped_dim.x; r+=2) {
+      for (uint32 c=pos_y-2; c<=pos_y+2 && c<(uint32)uncropped_dim.y; c+=2) {
+        ushort16* pix = (ushort16*)getDataUncropped(r,c);
+        if (*pix) {
+          total += *pix;
+          div++;
+        }
+      }
+    }
+    ushort16* pix = (ushort16*)getDataUncropped(pos_x,pos_y);
+    if (div) {
+      pix[0] = total / div;
+    }
+  }
+#endif
+
+}
+
+void RawImageData::startWorker(RawImageWorker::RawImageWorkerTask task, bool 
cropped )
+{
+  int height = cropped ? dim.y : uncropped_dim.y;
+
+  int threads = getThreadCount(); 
+  if (threads <= 1) {
+    RawImageWorker worker(this, task, 0, height);
+    worker.performTask();
+    return;
+  }
+
+  RawImageWorker **workers = new RawImageWorker*[threads];
+  int y_offset = 0;
+  int y_per_thread = (height + threads - 1) / threads;
+
+  for (int i = 0; i < threads; i++) {
+    int y_end = MIN(y_offset + y_per_thread, height);
+    workers[i] = new RawImageWorker(this, task, y_offset, y_end);
+    workers[i]->startThread();
+    y_offset = y_end;
+  }
+  for (int i = 0; i < threads; i++) {
+    workers[i]->waitForThread();
+    delete workers[i];
+  }
+  delete[] workers;
+}
+
+void RawImageData::fixBadPixelsThread( int start_y, int end_y )
+{
+  int gw = (uncropped_dim.x + 15) / 32;
+  for (int y = start_y; y < end_y; y++) {
+    uint32* bad_map = (uint32*)&mBadPixelMap[y*mBadPixelMapPitch];
+    for (int x = 0 ; x < gw; x++) {
+      // Test if there is a bad pixel within these 32 pixels
+      if (bad_map[x] != 0) {
+        uchar8 *bad = (uchar8*)&bad_map[x];
+        // Go through each pixel
+        for (int i = 0; i < 4; i++) {
+          for (int j = 0; j < 8; j++) {
+            if (1 == ((bad[i]>>j) & 1))
+              fixBadPixel(x*32+i*8+j, y, 0);
+          }
+        }
+      }
+    }
+  }
+}
+
 RawImageData* RawImage::operator->() {
   return p_;
 }
@@ -204,7 +338,7 @@
 
 void *RawImageWorkerThread(void *_this) {
   RawImageWorker* me = (RawImageWorker*)_this;
-  me->_performTask();
+  me->performTask();
   pthread_exit(NULL);
   return 0;
 }
@@ -215,7 +349,6 @@
   start_y = _start_y;
   end_y = _end_y;
   task = _task;
-  startThread();
 }
 
 void RawImageWorker::startThread()
@@ -233,14 +366,17 @@
   pthread_join(threadid, &status);
 }
 
-void RawImageWorker::_performTask()
+void RawImageWorker::performTask()
 {
   try {
     switch(task)
     {
-    case TASK_SCALE_VALUES:
+    case SCALE_VALUES:
       data->scaleValues(start_y, end_y);
       break;
+    case FIX_BAD_PIXELS:
+      data->fixBadPixelsThread(start_y, end_y);
+      break;
     default:
       _ASSERTE(false);
     }
@@ -254,4 +390,5 @@
 }
 
 
+
 } // namespace RawSpeed

Modified: RawSpeed/RawImage.h
===================================================================
--- RawSpeed/RawImage.h 2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/RawImage.h 2013-03-25 15:39:12 UTC (rev 528)
@@ -29,9 +29,24 @@
 namespace RawSpeed {
 
 class RawImage;
-class RawImageWorker;
+class RawImageData;
 typedef enum {TYPE_USHORT16, TYPE_FLOAT32} RawImageType;
 
+class RawImageWorker {
+public:
+  typedef enum {SCALE_VALUES, FIX_BAD_PIXELS} RawImageWorkerTask;
+  RawImageWorker(RawImageData *img, RawImageWorkerTask task, int start_y, int 
end_y);
+  void startThread();
+  void waitForThread();
+  void performTask();
+protected:
+  pthread_t threadid;
+  RawImageData* data;
+  RawImageWorkerTask task;
+  int start_y;
+  int end_y;
+};
+
 class RawImageData
 {
   friend class RawImageWorker;
@@ -51,7 +66,11 @@
   iPoint2D getCropOffset();
   virtual void scaleBlackWhite() = 0;
   virtual void calculateBlackAreas() = 0;
+  virtual void transferBadPixelsToMap();
+  virtual void fixBadPixels();
+
   bool isAllocated() {return !!data;}
+  void createBadPixelMap();
   iPoint2D dim;
   uint32 pitch;
   bool isCFA;
@@ -68,12 +87,21 @@
   vector<const char*> errors;
   pthread_mutex_t errMutex;   // Mutex for above
   void setError(const char* err);
+  /* Vector containing the positions of bad pixels */
+  /* Format is x | (y << 16), so maximum pixel position is 65535 */
+  vector<uint32> mBadPixelPositions;    // Positions of zeroes that must be 
interpolated
+  pthread_mutex_t mBadPixelMutex;   // Mutex for above, must be used if more 
than 1 thread is accessing vector
+  uchar8 *mBadPixelMap;
+  uint32 mBadPixelMapPitch;
 
 protected:
   RawImageType dataType;
   RawImageData(void);
   RawImageData(iPoint2D dim, uint32 bpp, uint32 cpp=1);
   virtual void scaleValues(int start_y, int end_y) = 0;
+  virtual void fixBadPixel( uint32 x, uint32 y, int component = 0) = 0;
+  void fixBadPixelsThread(int start_y, int end_y);
+  void startWorker(RawImageWorker::RawImageWorkerTask task, bool cropped );
   uint32 dataRefCount;
   uchar8* data;
   uint32 cpp;      // Components per pixel
@@ -92,6 +120,8 @@
 
 protected:
   virtual void scaleValues(int start_y, int end_y);
+  virtual void fixBadPixel( uint32 x, uint32 y, int component = 0);
+
   RawImageDataU16(void);
   RawImageDataU16(iPoint2D dim, uint32 cpp=1);
   friend class RawImage;
@@ -105,26 +135,12 @@
 
 protected:
   virtual void scaleValues(int start_y, int end_y);
+  virtual void fixBadPixel( uint32 x, uint32 y, int component = 0);
   RawImageDataFloat(void);
   RawImageDataFloat(iPoint2D dim, uint32 cpp=1);
   friend class RawImage;
 };
 
-class RawImageWorker {
-public:
-  typedef enum {TASK_SCALE_VALUES} RawImageWorkerTask;
-  RawImageWorker(RawImageData *img, RawImageWorkerTask task, int start_y, int 
end_y);
-  void waitForThread();
-  void _performTask();
-protected:
-  void startThread();
-  pthread_t threadid;
-  RawImageData* data;
-  RawImageWorkerTask task;
-  int start_y;
-  int end_y;
-};
-
  class RawImage {
  public:
    static RawImage create(RawImageType type = TYPE_USHORT16);

Modified: RawSpeed/RawImageDataFloat.cpp
===================================================================
--- RawSpeed/RawImageDataFloat.cpp      2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/RawImageDataFloat.cpp      2013-03-25 15:39:12 UTC (rev 528)
@@ -127,27 +127,9 @@
     if (blackLevelSeparate[0] < 0)
       calculateBlackAreas();
 
-    int threads = getThreadCount(); 
-    if (threads <= 1)
-      scaleValues(0, dim.y);
-    else {
-      RawImageWorker **workers = new RawImageWorker*[threads];
-      int y_offset = 0;
-      int y_per_thread = (dim.y + threads - 1) / threads;
+    startWorker(RawImageWorker::SCALE_VALUES, true);
+}
 
-      for (int i = 0; i < threads; i++) {
-        int y_end = MIN(y_offset + y_per_thread, dim.y);
-        workers[i] = new RawImageWorker(this, 
RawImageWorker::TASK_SCALE_VALUES, y_offset, y_end);
-        y_offset = y_end;
-      }
-      for (int i = 0; i < threads; i++) {
-        workers[i]->waitForThread();
-        delete workers[i];
-      }
-      delete[] workers;
-    }
-  }
-
 #if 0 // _MSC_VER > 1399 || defined(__SSE2__)
 
   void RawImageDataFloat::scaleValues(int start_y, int end_y) {
@@ -288,4 +270,96 @@
 
 #endif
 
+  /* This performs a 4 way interpolated pixel */
+  /* The value is interpolated from the 4 closest valid pixels in */
+  /* the horizontal and vertical direction. Pixels found further away */
+  /* are weighed less */
+
+void RawImageDataFloat::fixBadPixel( uint32 x, uint32 y, int component )
+{
+  float values[4];
+  float dist[4];
+  float weight[4];
+
+  values[0] = values[1] = values[2] = values[3] = -1;
+  dist[0] = dist[1] = dist[2] = dist[3] = 0;
+  uchar8* bad_line = &mBadPixelMap[y*mBadPixelMapPitch];
+
+  // Find pixel to the left
+  int x_find = (int)x - 2;
+  int curr = 0;
+  while (x_find >= 0 && values[curr] < 0) {
+    if (0 == ((bad_line[x_find>>3] >> (x_find&7)) & 1)) {
+      values[curr] = ((float*)getData(x_find, y))[component];
+      dist[curr] = float((int)x-x_find);
+    }
+    x_find-=2;
+  }
+  // Find pixel to the right
+  x_find = (int)x + 2;
+  curr = 1;
+  while (x_find < uncropped_dim.x && values[curr] < 0) {
+    if (0 == ((bad_line[x_find>>3] >> (x_find&7)) & 1)) {
+      values[curr] = ((float*)getData(x_find, y))[component];
+      dist[curr] = float(x_find-(int)x);
+    }
+    x_find+=2;
+  }
+
+  bad_line = &mBadPixelMap[x>>3];
+  // Find pixel upwards
+  int y_find = (int)y - 2;
+  curr = 2;
+  while (y_find >= 0 && values[curr] < 0) {
+    if (0 == ((bad_line[y_find*mBadPixelMapPitch] >> (x&7)) & 1)) {
+      values[curr] = ((float*)getData(x, y_find))[component];
+      dist[curr] = float((int)y-y_find);
+    }
+    y_find-=2;
+  }
+  // Find pixel downwards
+  y_find = (int)y + 2;
+  curr = 3;
+  while (y_find < uncropped_dim.y && values[curr] < 0) {
+    if (0 == ((bad_line[y_find*mBadPixelMapPitch] >> (x&7)) & 1)) {
+      values[curr] = ((float*)getData(x, y_find))[component];
+      dist[curr] = float(y_find-(int)y);
+    }
+    y_find+=2;
+  }
+  // Find x weights
+  float total_dist_x = dist[0] + dist[1];
+
+  float total_div = 0.000001f;
+  if (total_dist_x) {
+    weight[0] = dist[0] > 0.0f ? (total_dist_x - dist[0]) / total_dist_x : 0;
+    weight[1] = 1.0f - weight[0];
+    total_div += 1;
+  }
+
+  // Find y weights
+  float total_dist_y = dist[2] + dist[3];
+  if (total_dist_y) {
+    weight[2] = dist[2] > 0.0f ? (total_dist_x - dist[2]) / total_dist_y : 0;
+    weight[3] = 1.0f - weight[2];
+    total_div += 1;
+  }
+
+
+  float total_pixel = 0;
+  for (int i = 0; i < 4; i++)
+    if (values[i] >= 0)
+      total_pixel += values[i] * dist[i];
+
+  total_pixel /= total_div;
+  float* pix = (float*)getDataUncropped(x, y);
+  pix[component] = total_pixel;
+
+  /* Process other pixels - could be done inline, since we have the weights */
+  if (cpp > 1 && component == 0)
+    for (int i = 1; i < (int)cpp; i++)
+      fixBadPixel(x,y,i);
+
+}
+
 } // namespace RawSpeed

Modified: RawSpeed/RawImageDataU16.cpp
===================================================================
--- RawSpeed/RawImageDataU16.cpp        2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/RawImageDataU16.cpp        2013-03-25 15:39:12 UTC (rev 528)
@@ -133,7 +133,7 @@
       blackLevel = b;
     if (whitePoint >= 65536)
       whitePoint = m;
-    printf("ISO:%d, Estimated black:%d, Estimated white: %d\n", isoSpeed, 
blackLevel, whitePoint);
+    printf("Rawspeed, ISO:%d, Estimated black:%d, Estimated white: %d\n", 
isoSpeed, blackLevel, whitePoint);
   }
 
   /* Skip, if not needed */
@@ -146,26 +146,7 @@
 
 //  printf("ISO:%d, black[0]:%d, white: %d\n", isoSpeed, 
blackLevelSeparate[0], whitePoint);
 //  printf("black[1]:%d, black[2]:%d, black[3]:%d\n", blackLevelSeparate[1], 
blackLevelSeparate[2], blackLevelSeparate[3]);
-
-  int threads = getThreadCount(); 
-  if (threads <= 1)
-    scaleValues(0, dim.y);
-  else {
-    RawImageWorker **workers = new RawImageWorker*[threads];
-    int y_offset = 0;
-    int y_per_thread = (dim.y + threads - 1) / threads;
-
-    for (int i = 0; i < threads; i++) {
-      int y_end = MIN(y_offset + y_per_thread, dim.y);
-      workers[i] = new RawImageWorker(this, RawImageWorker::TASK_SCALE_VALUES, 
y_offset, y_end);
-      y_offset = y_end;
-    }
-    for (int i = 0; i < threads; i++) {
-      workers[i]->waitForThread();
-      delete workers[i];
-    }
-    delete[] workers;
-  }
+  startWorker(RawImageWorker::SCALE_VALUES, true);
 }
 
 #if _MSC_VER > 1399 || defined(__SSE2__)
@@ -351,4 +332,96 @@
 
 #endif
 
+/* This performs a 4 way interpolated pixel */
+/* The value is interpolated from the 4 closest valid pixels in */
+/* the horizontal and vertical direction. Pixels found further away */
+/* are weighed less */
+
+void RawImageDataU16::fixBadPixel( uint32 x, uint32 y, int component )
+{
+  int values[4];
+  int dist[4];
+  int weight[4];
+
+  values[0] = values[1] = values[2] = values[3] = -1;
+  dist[0] = dist[1] = dist[2] = dist[3] = 0;
+  uchar8* bad_line = &mBadPixelMap[y*mBadPixelMapPitch];
+  int step = isCFA ? 2 : 1;
+
+  // Find pixel to the left
+  int x_find = (int)x - step;
+  int curr = 0;
+  while (x_find >= 0 && values[curr] < 0) {
+    if (0 == ((bad_line[x_find>>3] >> (x_find&7)) & 1)) {
+      values[curr] = ((ushort16*)getData(x_find, y))[component];
+      dist[curr] = (int)x-x_find;
+    }
+    x_find -= step;
+  }
+  // Find pixel to the right
+  x_find = (int)x + step;
+  curr = 1;
+  while (x_find < uncropped_dim.x && values[curr] < 0) {
+    if (0 == ((bad_line[x_find>>3] >> (x_find&7)) & 1)) {
+      values[curr] = ((ushort16*)getData(x_find, y))[component];
+      dist[curr] = x_find-(int)x;
+    }
+    x_find += step;
+  }
+
+  bad_line = &mBadPixelMap[x>>3];
+  // Find pixel upwards
+  int y_find = (int)y - step;
+  curr = 2;
+  while (y_find >= 0 && values[curr] < 0) {
+    if (0 == ((bad_line[y_find*mBadPixelMapPitch] >> (x&7)) & 1)) {
+      values[curr] = ((ushort16*)getData(x, y_find))[component];
+      dist[curr] = (int)y-y_find;
+    }
+    y_find -= step;
+  }
+  // Find pixel downwards
+  y_find = (int)y + step;
+  curr = 3;
+  while (y_find < uncropped_dim.y && values[curr] < 0) {
+    if (0 == ((bad_line[y_find*mBadPixelMapPitch] >> (x&7)) & 1)) {
+      values[curr] = ((ushort16*)getData(x, y_find))[component];
+      dist[curr] = y_find-(int)y;
+    }
+    y_find += step;
+  }
+
+  // Find x weights
+  int total_dist_x = dist[0] + dist[1];
+
+  int total_shifts = 7;
+  if (total_dist_x) {
+    weight[0] = dist[0] ? (total_dist_x - dist[0]) * 256 / total_dist_x : 0;
+    weight[1] = 256 - weight[0];
+    total_shifts++;
+  }
+
+  // Find y weights
+  int total_dist_y = dist[2] + dist[3];
+  if (total_dist_y) {
+    weight[2] = dist[2] ? (total_dist_x - dist[2]) * 256 / total_dist_y : 0;
+    weight[3] = 256-weight[2];
+    total_shifts++;
+  }
+
+  int total_pixel = 0;
+  for (int i = 0; i < 4; i++)
+    if (values[i] >= 0)
+      total_pixel += values[i] * weight[i];
+
+  total_pixel >>= total_shifts;
+  ushort16* pix = (ushort16*)getDataUncropped(x, y);
+  pix[component] = clampbits(total_pixel, 16);
+
+  /* Process other pixels - could be done inline, since we have the weights */
+  if (cpp > 1 && component == 0)
+    for (int i = 1; i < (int)cpp; i++)
+      fixBadPixel(x,y,i);
+}
+
 } // namespace RawSpeed

Modified: RawSpeed/Rw2Decoder.cpp
===================================================================
--- RawSpeed/Rw2Decoder.cpp     2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/Rw2Decoder.cpp     2013-03-25 15:39:12 UTC (rev 528)
@@ -102,38 +102,7 @@
 }
 
 void Rw2Decoder::DecodeRw2() {
-  pthread_mutex_init(&zeroMutex, NULL);
   startThreads();
-  pthread_mutex_destroy(&zeroMutex);
-  // Interpolate over zeroes.
-  int pitch = (int)mRaw->pitch;
-
-  for (vector<uint32>::iterator i=zero_pos.begin(); i != zero_pos.end(); i++) {
-    uint32 pos = *i;
-    uint32 pos_x = pos&0xffff;
-    uint32 pos_y = pos>>16;
-    ushort16* pix = (ushort16*)mRaw->getData(pos_x, pos_y);
-    uint32 total = 0;
-    uint32 div = 0;
-    if (pos_x > 1 && 0 != pix[-2]) {
-      total += pix[-2];
-      div++;
-    }
-    if (pos_x < (uint32)mRaw->dim.x-2 && 0 != pix[2]) {
-      total += pix[2];
-      div++;
-    }
-    if (pos_y > 1 && 0 != pix[-pitch]) {
-      total += pix[-pitch];  // Note: 2 lines above, since pitch is in bytes 
and pix in shorts this cancels out.
-      div++;
-    }
-    if (pos_y < (uint32)mRaw->dim.y-2 && 0 != pix[mRaw->pitch]) {
-      total += pix[mRaw->pitch];  // Note: 2 lines below, since pitch is in 
bytes and pix in shorts this cancels out.
-      div++;
-    }
-    if (div)
-      pix[0] = total / div;
-  }
 }
 
 void Rw2Decoder::decodeThreaded(RawDecoderThread * t) {
@@ -204,10 +173,9 @@
     }
   }
   if (zero_is_bad && !zero_pos.empty()) {
-    Rw2Decoder* rw2_dec = (Rw2Decoder*)t->parent;
-    pthread_mutex_lock(&zeroMutex);
-    rw2_dec->zero_pos.insert(rw2_dec->zero_pos.end(), zero_pos.begin(), 
zero_pos.end());
-    pthread_mutex_unlock(&zeroMutex);
+    pthread_mutex_lock(&mRaw->mBadPixelMutex);
+    mRaw->mBadPixelPositions.insert(mRaw->mBadPixelPositions.end(), 
zero_pos.begin(), zero_pos.end());
+    pthread_mutex_unlock(&mRaw->mBadPixelMutex);
   }
 }
 

Modified: RawSpeed/Rw2Decoder.h
===================================================================
--- RawSpeed/Rw2Decoder.h       2013-03-20 19:37:34 UTC (rev 527)
+++ RawSpeed/Rw2Decoder.h       2013-03-25 15:39:12 UTC (rev 528)
@@ -58,8 +58,6 @@
   std::string guessMode();
   ByteStream* input_start;
   uint32 load_flags;
-  vector<uint32> zero_pos;    // Positions of zeroes that must be interpolated
-  pthread_mutex_t zeroMutex;   // Mutex for above
 };
 
 } // namespace RawSpeed


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

Reply via email to