Author: post
Date: 2011-03-19 20:23:21 +0100 (Sat, 19 Mar 2011)
New Revision: 347

Added:
   RawSpeed/RawImageDataFloat.cpp
   RawSpeed/RawImageDataU16.cpp
Modified:
   RawSpeed/ArwDecoder.cpp
   RawSpeed/Cr2Decoder.cpp
   RawSpeed/DngDecoder.cpp
   RawSpeed/LJpegPlain.cpp
   RawSpeed/NefDecoder.cpp
   RawSpeed/OrfDecoder.cpp
   RawSpeed/PefDecoder.cpp
   RawSpeed/RawDecoder.cpp
   RawSpeed/RawImage.cpp
   RawSpeed/RawImage.h
   RawSpeed/RawSpeed.vcproj
   RawSpeed/Rw2Decoder.cpp
Log:
Split RawImageData into separate classes, to prepare to have different data 
type. Right now only Unsigned 16 bit is used. (Note: Makefiles must include the 
new files)

Modified: RawSpeed/ArwDecoder.cpp
===================================================================
--- RawSpeed/ArwDecoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/ArwDecoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -70,7 +70,6 @@
     height += 8;
 
   mRaw->dim = iPoint2D(width, height);
-  mRaw->bpp = 2;
   mRaw->createData();
 
   const ushort16* c = raw->getEntry(SONY_CURVE)->getShortArray();

Modified: RawSpeed/Cr2Decoder.cpp
===================================================================
--- RawSpeed/Cr2Decoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/Cr2Decoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -77,7 +77,6 @@
     ThrowRDE("CR2 Decoder: No Slices found.");
   }
 
-  mRaw->bpp = 2;
   mRaw->dim = iPoint2D(slices[0].w, completeH);
 
   if (raw->hasEntry((TiffTag)0xc6c5)) {

Modified: RawSpeed/DngDecoder.cpp
===================================================================
--- RawSpeed/DngDecoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/DngDecoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -83,7 +83,6 @@
   try {
     mRaw->dim.x = raw->getEntry(IMAGEWIDTH)->getInt();
     mRaw->dim.y = raw->getEntry(IMAGELENGTH)->getInt();
-    mRaw->bpp = 2;
   } catch (TiffParserException) {
     ThrowRDE("DNG Decoder: Could not read basic image information.");
   }

Modified: RawSpeed/LJpegPlain.cpp
===================================================================
--- RawSpeed/LJpegPlain.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/LJpegPlain.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -163,7 +163,7 @@
     slice_width[i] = slicesW[i] / pixGroup / maxSuperH; // This is a guess, 
but works for sRaw1+2.
 
   for (slice = 0; slice < slices; slice++) {
-    offset[slice] = ((t_x + offX) * mRaw->bpp + ((offY + t_y) * mRaw->pitch)) 
| (t_s << 28);
+    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * 
mRaw->pitch)) | (t_s << 28);
     _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
     t_y += maxSuperV;
     if (t_y >= (frame.h - skipY)) {
@@ -300,7 +300,7 @@
     slice_width[i] = slicesW[i] / COMPS;
 
   for (slice = 0; slice < slices; slice++) {
-    offset[slice] = ((t_x + offX) * mRaw->bpp + ((offY + t_y) * mRaw->pitch)) 
| (t_s << 28);
+    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * 
mRaw->pitch)) | (t_s << 28);
     _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
     t_y += 2;
     if (t_y >= (frame.h - skipY)) {
@@ -426,7 +426,7 @@
     slice_width[i] = slicesW[i] / 2;
 
   for (slice = 0; slice < slices; slice++) {
-    offset[slice] = ((t_x + offX) * mRaw->bpp + ((offY + t_y) * mRaw->pitch)) 
| (t_s << 28);
+    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * 
mRaw->pitch)) | (t_s << 28);
     _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
     t_y ++;
     if (t_y >= (frame.h - skipY)) {
@@ -527,7 +527,7 @@
   uint32 slice = 0;
   uint32 cw = (frame.w - skipX);
   for (slice = 0; slice < slices; slice++) {
-    offset[slice] = ((t_x + offX) * mRaw->bpp + ((offY + t_y) * mRaw->pitch)) 
| (t_s << 28);
+    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * 
mRaw->pitch)) | (t_s << 28);
     _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
     t_y++;
     if (t_y == (frame.h - skipY)) {
@@ -615,7 +615,7 @@
   uint32 t_s = 0;
   uint32 slice = 0;
   for (slice = 0; slice < slices; slice++) {
-    offset[slice] = ((t_x + offX) * mRaw->bpp + ((offY + t_y) * mRaw->pitch)) 
| (t_s << 28);
+    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * 
mRaw->pitch)) | (t_s << 28);
     _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
     t_y++;
     if (t_y == (frame.h - skipY)) {
@@ -711,7 +711,7 @@
   uint32 t_s = 0;
   uint32 slice = 0;
   for (slice = 0; slice < slices; slice++) {
-    offset[slice] = ((t_x + offX) * mRaw->bpp + ((offY + t_y) * mRaw->pitch)) 
| (t_s << 28);
+    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * 
mRaw->pitch)) | (t_s << 28);
     _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
     t_y++;
     if (t_y == (frame.h - skipY)) {

Modified: RawSpeed/NefDecoder.cpp
===================================================================
--- RawSpeed/NefDecoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/NefDecoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -83,7 +83,6 @@
   uint32 bitPerPixel = raw->getEntry(BITSPERSAMPLE)->getInt();
 
   mRaw->dim = iPoint2D(width, height);
-  mRaw->bpp = 2;
   mRaw->createData();
 
   data = mRootIFD->getIFDsWithTag(MAKERNOTE);
@@ -177,7 +176,6 @@
     ThrowRDE("NEF Decoder: No valid slices found. File probably truncated.");
 
   mRaw->dim = iPoint2D(width, offY);
-  mRaw->bpp = 2;
   mRaw->createData();
   if (bitPerPixel == 14 && width*slices[0].h*2 == slices[0].count)
     bitPerPixel = 16; // D3

Modified: RawSpeed/OrfDecoder.cpp
===================================================================
--- RawSpeed/OrfDecoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/OrfDecoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -63,7 +63,6 @@
     ThrowRDE("ORF Decoder: Truncated file");
 
   mRaw->dim = iPoint2D(width, height);
-  mRaw->bpp = 2;
   mRaw->createData();
 
   data = mRootIFD->getIFDsWithTag(MAKERNOTE);

Modified: RawSpeed/PefDecoder.cpp
===================================================================
--- RawSpeed/PefDecoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/PefDecoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -66,7 +66,6 @@
   uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
 
   mRaw->dim = iPoint2D(width, height);
-  mRaw->bpp = 2;
   mRaw->createData();
   try {
     PentaxDecompressor l(mFile, mRaw);

Modified: RawSpeed/RawDecoder.cpp
===================================================================
--- RawSpeed/RawDecoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/RawDecoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -66,7 +66,6 @@
     ThrowRDE("RAW Decoder: No valid slices found. File probably truncated.");
 
   mRaw->dim = iPoint2D(width, offY);
-  mRaw->bpp = 2;
   mRaw->createData();
   mRaw->whitePoint = (1<<bitPerPixel)-1;
 
@@ -136,7 +135,7 @@
 
     if (bitPerPixel == 16 && getHostEndianness() == little)  {
       BitBlt(&data[offset.x*sizeof(ushort16)*cpp+y*outPitch], outPitch,
-             input.getData(), inputPitch, w*mRaw->bpp, h - y);
+             input.getData(), inputPitch, w*mRaw->getBpp(), h - y);
       return;
     }
     if (bitPerPixel == 12 && (int)w == inputPitch * 8 / 12 && 
getHostEndianness() == little)  {

Modified: RawSpeed/RawImage.cpp
===================================================================
--- RawSpeed/RawImage.cpp       2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/RawImage.cpp       2011-03-19 19:23:21 UTC (rev 347)
@@ -148,254 +148,7 @@
   dim = new_size;
 }
 
-void RawImageData::calculateBlackAreas() {
-  int* histogram = (int*)malloc(4*65536*sizeof(int));
-  memset(histogram, 0, 4*65536*sizeof(int));
-  int totalpixels = 0;
 
-  for (uint32 i = 0; i < blackAreas.size(); i++) {
-    BlackArea area = blackAreas[i];
-
-    /* Make sure area sizes are multiple of two, 
-       so we have the same amount of pixels for each CFA group */
-    area.size = area.size - (area.size&1);
-
-    /* Process horizontal area */
-    if (!area.isVertical) {
-      if ((int)area.offset+(int)area.size > uncropped_dim.y)
-        ThrowRDE("RawImageData::calculateBlackAreas: Offset + size is larger 
than height of image");
-      for (uint32 y = area.offset; y < area.offset+area.size; y++) {
-        ushort16 *pixel = (ushort16*)getDataUncropped(mOffset.x, y);
-        int* localhist = &histogram[(y&1)*(65536*2)];
-        for (int x = mOffset.x; x < dim.x+mOffset.x; x++) {
-          localhist[((x&1)<<16) + *pixel]++;
-        }
-      }
-      totalpixels += area.size * dim.x;
-    }
-
-    /* Process vertical area */
-    if (area.isVertical) {
-      if ((int)area.offset+(int)area.size > uncropped_dim.x)
-        ThrowRDE("RawImageData::calculateBlackAreas: Offset + size is larger 
than width of image");
-      for (int y = mOffset.y; y < dim.y+mOffset.y; y++) {
-        ushort16 *pixel = (ushort16*)getDataUncropped(area.offset, y);
-        int* localhist = &histogram[(y&1)*(65536*2)];
-        for (uint32 x = area.offset; x < area.size+area.offset; x++) {
-          localhist[((x&1)<<16) + *pixel]++;
-        }
-      }
-      totalpixels += area.size * dim.y;
-    }
-  }
-
-  if (!totalpixels) {
-    for (int i = 0 ; i < 4; i++)
-      blackLevelSeparate[i] = blackLevel;
-    return;
-  }
-
-  /* Calculate median value of black areas for each component */
-  /* Adjust the number of total pixels so it is the same as the median of each 
histogram */
-  totalpixels /= 4*2;
-
-  for (int i = 0 ; i < 4; i++) {
-    int* localhist = &histogram[i*65536];
-    int acc_pixels = localhist[0];
-    int pixel_value = 0;
-    while (acc_pixels <= totalpixels && pixel_value < 65535) {
-      pixel_value++;
-      acc_pixels += localhist[pixel_value];
-    }
-    blackLevelSeparate[i] = pixel_value;
-  }
-  free(histogram);
-}
-
-void RawImageData::scaleBlackWhite() {
-  const int skipBorder = 150;
-  int gw = (dim.x - skipBorder) * cpp;
-  if ((blackAreas.empty() && blackLevelSeparate[0] < 0 && blackLevel < 0) || 
whitePoint == 65536) {  // Estimate
-    int b = 65536;
-    int m = 0;
-    for (int row = skipBorder*cpp;row < (dim.y - skipBorder);row++) {
-      ushort16 *pixel = (ushort16*)getData(skipBorder, row);
-      for (int col = skipBorder ; col < gw ; col++) {
-        b = MIN(*pixel, b);
-        m = MAX(*pixel, m);
-        pixel++;
-      }
-    }
-    if (blackLevel < 0)
-      blackLevel = b;
-    if (whitePoint == 65536)
-      whitePoint = m;
-    printf("Estimated black:%d, Estimated white: %d\n", blackLevel, 
whitePoint);
-  }
-
-  /* If filter has not set separate blacklevel, compute or fetch it */
-  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;
-
-    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 _MSC_VER > 1399 || defined(__SSE2__)
-
-void RawImageData::scaleValues(int start_y, int end_y) {
-  bool use_sse2;
-#ifdef _MSC_VER 
-  int info[4];
-  __cpuid(info, 1);
-  use_sse2 = !!(info[3]&(1 << 26));
-#else
-  use_sse2 = TRUE;
-#endif
-
-  float app_scale = 65535.0f / (whitePoint - blackLevelSeparate[0]);
-  // Check SSE2
-  if (use_sse2 && app_scale < 63) {
-
-    __m128i sseround;
-    __m128i ssesub2;
-    __m128i ssesign;
-    uint32* sub_mul = (uint32*)_aligned_malloc(16*4*2, 16);
-    uint32 gw = pitch / 16;
-    // 10 bit fraction
-    uint32 mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[mOffset.x&1]));  
-    mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[(mOffset.x+1)&1])))<<16;
-    uint32 b = blackLevelSeparate[mOffset.x&1] | 
(blackLevelSeparate[(mOffset.x+1)&1]<<16);
-
-    for (int i = 0; i< 4; i++) {
-      sub_mul[i] = b;     // Subtract even lines
-      sub_mul[4+i] = mul;   // Multiply even lines
-    }
-
-    mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[2+(mOffset.x&1)]));
-    mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[2+((mOffset.x+1)&1)])))<<16;
-    b = blackLevelSeparate[2+(mOffset.x&1)] | 
(blackLevelSeparate[2+((mOffset.x+1)&1)]<<16);
-
-    for (int i = 0; i< 4; i++) {
-      sub_mul[8+i] = b;   // Subtract odd lines
-      sub_mul[12+i] = mul;  // Multiply odd lines
-    }
-
-    sseround = _mm_set_epi32(512, 512, 512, 512);
-    ssesub2 = _mm_set_epi32(32768, 32768, 32768, 32768);
-    ssesign = _mm_set_epi32(0x80008000, 0x80008000, 0x80008000, 0x80008000);
-
-    for (int y = start_y; y < end_y; y++) {
-      __m128i* pixel = (__m128i*) & data[(mOffset.y+y)*pitch];
-      __m128i ssescale, ssesub;
-      if (((y+mOffset.y)&1) == 0) { 
-        ssesub = _mm_load_si128((__m128i*)&sub_mul[0]);
-        ssescale = _mm_load_si128((__m128i*)&sub_mul[4]);
-      } else {
-        ssesub = _mm_load_si128((__m128i*)&sub_mul[8]);
-        ssescale = _mm_load_si128((__m128i*)&sub_mul[12]);
-      }
-
-      for (uint32 x = 0 ; x < gw; x++) {
-        __m128i pix_high;
-        __m128i temp;
-        _mm_prefetch((char*)(pixel+1), _MM_HINT_T0);
-        __m128i pix_low = _mm_load_si128(pixel);
-        // Subtract black
-        pix_low = _mm_subs_epu16(pix_low, ssesub);
-        // Multiply the two unsigned shorts and combine it to 32 bit result
-        pix_high = _mm_mulhi_epu16(pix_low, ssescale);
-        temp = _mm_mullo_epi16(pix_low, ssescale);
-        pix_low = _mm_unpacklo_epi16(temp, pix_high);
-        pix_high = _mm_unpackhi_epi16(temp, pix_high);
-        // Add rounder
-        pix_low = _mm_add_epi32(pix_low, sseround);
-        pix_high = _mm_add_epi32(pix_high, sseround);
-        // Shift down
-        pix_low = _mm_srai_epi32(pix_low, 10);
-        pix_high = _mm_srai_epi32(pix_high, 10);
-        // Subtract to avoid clipping
-        pix_low = _mm_sub_epi32(pix_low, ssesub2);
-        pix_high = _mm_sub_epi32(pix_high, ssesub2);
-        // Pack
-        pix_low = _mm_packs_epi32(pix_low, pix_high);
-        // Shift sign off
-        pix_low = _mm_xor_si128(pix_low, ssesign);
-        _mm_store_si128(pixel, pix_low);
-        pixel++;
-      }
-    }
-    _aligned_free(sub_mul);
-  } else {
-    // Not SSE2
-    int gw = dim.x * cpp;
-    int mul[4];
-    int sub[4];
-    for (int i = 0; i < 4; i++) {
-      int v = i;
-      if ((mOffset.x&1) != 0)
-        v ^= 1;
-      if ((mOffset.y&1) != 0)
-        v ^= 2;
-      mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[v]));
-      sub[i] = blackLevelSeparate[v];
-    }
-    for (int y = start_y; y < end_y; y++) {
-      ushort16 *pixel = (ushort16*)getData(0, y);
-      int *mul_local = &mul[2*(y&1)];
-      int *sub_local = &sub[2*(y&1)];
-      for (int x = 0 ; x < gw; x++) {
-        pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 
8192) >> 14, 16);
-      }
-    }
-  }
-}
-
-#else
-
-void RawImageData::scaleValues(int start_y, int end_y) {
-  int gw = dim.x * cpp;
-  int mul[4];
-  int sub[4];
-  for (int i = 0; i < 4; i++) {
-    int v = i;
-    if ((mOffset.x&1) != 0)
-      v ^= 1;
-    if ((mOffset.y&1) != 0)
-      v ^= 2;
-    mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[v]));
-    sub[i] = blackLevelSeparate[v];
-  }
-  for (int y = start_y; y < end_y; y++) {
-    ushort16 *pixel = (ushort16*)getData(0, y);
-    int *mul_local = &mul[2*(y&1)];
-    int *sub_local = &sub[2*(y&1)];
-    for (int x = 0 ; x < gw; x++) {
-      pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 
8192) >> 14, 16);
-    }
-  }
-}
-
-#endif
-
-
 RawImage::RawImage(RawImageData* p) : p_(p) {
   pthread_mutex_lock(&p_->mymutex);
   ++p_->dataRefCount;

Modified: RawSpeed/RawImage.h
===================================================================
--- RawSpeed/RawImage.h 2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/RawImage.h 2011-03-19 19:23:21 UTC (rev 347)
@@ -28,26 +28,29 @@
 
 class RawImage;
 class RawImageWorker;
+typedef enum {TYPE_USHORT16, TYPE_FLOAT32} RawImageType;
 
 class RawImageData
 {
   friend class RawImageWorker;
 public:
   virtual ~RawImageData(void);
-  iPoint2D dim;
-  uint32 bpp;      // Bytes per pixel.
   uint32 getCpp() const { return cpp; }
+  uint32 getBpp() const { return bpp; }
   void setCpp(uint32 val);
-  uint32 pitch;
   virtual void createData();
   virtual void destroyData();
+  RawSpeed::RawImageType DataType() const { return dataType; }
   uchar8* getData();
   uchar8* getData(uint32 x, uint32 y);    // Not super fast, but safe. Don't 
use per pixel.
   uchar8* getDataUncropped(uint32 x, uint32 y);
   virtual void subFrame( iPoint2D offset, iPoint2D new_size );
   iPoint2D getUncroppedDim();
   iPoint2D getCropOffset();
-  void scaleBlackWhite();
+  virtual void scaleBlackWhite() = 0;
+  bool isAllocated() {return !!data;}
+  iPoint2D dim;
+  uint32 pitch;
   bool isCFA;
   ColorFilterArray cfa;
   int blackLevel;
@@ -55,21 +58,48 @@
   int whitePoint;
   vector<BlackArea> blackAreas;
   iPoint2D subsampling;
-  bool isAllocated() {return !!data;}
-  void scaleValues(int start_y, int end_y);
 protected:
+  RawImageType dataType;
   RawImageData(void);
   RawImageData(iPoint2D dim, uint32 bpp, uint32 cpp=1);
-  void calculateBlackAreas();
+  virtual void calculateBlackAreas() = 0;
+  virtual void scaleValues(int start_y, int end_y) = 0;
   uint32 dataRefCount;
   uchar8* data;
   uint32 cpp;      // Components per pixel
+  uint32 bpp;      // Bytes per pixel.
   friend class RawImage;
   pthread_mutex_t mymutex;
   iPoint2D mOffset;
   iPoint2D uncropped_dim;
 };
 
+class RawImageDataU16 : public RawImageData
+{
+public:
+  virtual void scaleBlackWhite();
+
+protected:
+  virtual void calculateBlackAreas();
+  virtual void scaleValues(int start_y, int end_y);
+  RawImageDataU16(void);
+  RawImageDataU16(iPoint2D dim, uint32 cpp=1);
+  friend class RawImage;
+};
+
+class RawImageDataFloat : public RawImageData
+{
+public:
+  virtual void scaleBlackWhite();
+
+protected:
+  virtual void calculateBlackAreas();
+  virtual void scaleValues(int start_y, int end_y);
+  RawImageDataFloat(void);
+  RawImageDataFloat(iPoint2D dim, uint32 cpp=1);
+  friend class RawImage;
+};
+
 class RawImageWorker {
 public:
   typedef enum {TASK_SCALE_VALUES} RawImageWorkerTask;
@@ -87,8 +117,8 @@
 
  class RawImage {
  public:
-   static RawImage create();
-   static RawImage create(iPoint2D dim, uint32 bytesPerComponent, uint32 
componentsPerPixel = 1);
+   static RawImage create(RawImageType type = TYPE_USHORT16);
+   static RawImage create(iPoint2D dim, RawImageType type = TYPE_USHORT16, 
uint32 componentsPerPixel = 1);
    RawImageData* operator-> ();
    RawImageData& operator* ();
    RawImage(RawImageData* p);  // p must not be NULL
@@ -100,8 +130,28 @@
    RawImageData* p_;    // p_ is never NULL
  };
 
-inline RawImage RawImage::create()  { return new RawImageData(); }
-inline RawImage RawImage::create(iPoint2D dim, uint32 bytesPerPixel, uint32 
componentsPerPixel)
-{ return new RawImageData(dim, bytesPerPixel, componentsPerPixel); }
+inline RawImage RawImage::create(RawImageType type)  { 
+  switch (type)
+  {
+    case TYPE_USHORT16:
+      return new RawImageDataU16();
+    case TYPE_FLOAT32:
+      return new RawImageDataFloat();
+    default:
+      printf("RawImage::create: Unknown Image type!\n");
+  }
+  return NULL; 
+}
 
+inline RawImage RawImage::create(iPoint2D dim, RawImageType type, uint32 
componentsPerPixel)
+{   
+  switch (type) {
+    case TYPE_USHORT16:
+      return new RawImageDataU16(dim, componentsPerPixel);
+    default:
+      printf("RawImage::create: Unknown Image type!\n");
+  }
+  return NULL; 
+}
+
 } // namespace RawSpeed

Added: RawSpeed/RawImageDataFloat.cpp
===================================================================
--- RawSpeed/RawImageDataFloat.cpp                              (rev 0)
+++ RawSpeed/RawImageDataFloat.cpp      2011-03-19 19:23:21 UTC (rev 347)
@@ -0,0 +1,288 @@
+#include "StdAfx.h"
+#include "RawImage.h"
+#include "RawDecoder.h"  // For exceptions
+/*
+RawSpeed - RAW file decoder.
+
+Copyright (C) 2009 Klaus Post
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+http://www.klauspost.com
+*/
+#if defined(__SSE2__)
+#include <emmintrin.h>
+#endif
+
+namespace RawSpeed {
+
+  RawImageDataFloat::RawImageDataFloat(void) {
+    bpp = 4;
+    dataType = TYPE_FLOAT32;
+  }
+
+  RawImageDataFloat::RawImageDataFloat(iPoint2D _dim, uint32 _cpp) :
+  RawImageData(_dim, 4, _cpp)
+  {
+    dataType = TYPE_FLOAT32;
+  }
+
+
+  void RawImageDataFloat::calculateBlackAreas() {
+    float accPixels[4] = {0,0,0,0};
+    int totalpixels = 0;
+
+    for (uint32 i = 0; i < blackAreas.size(); i++) {
+      BlackArea area = blackAreas[i];
+
+      /* Make sure area sizes are multiple of two, 
+      so we have the same amount of pixels for each CFA group */
+      area.size = area.size - (area.size&1);
+
+      /* Process horizontal area */
+      if (!area.isVertical) {
+        if ((int)area.offset+(int)area.size > uncropped_dim.y)
+          ThrowRDE("RawImageData::calculateBlackAreas: Offset + size is larger 
than height of image");
+        for (uint32 y = area.offset; y < area.offset+area.size; y++) {
+          float *pixel = (float*)getDataUncropped(mOffset.x, y);
+          for (int x = mOffset.x; x < dim.x+mOffset.x; x++) {
+            accPixels[((y&1)<<1)|(x&1)] += *pixel++;
+          }
+        }
+        totalpixels += area.size * dim.x;
+      }
+
+      /* Process vertical area */
+      if (area.isVertical) {
+        if ((int)area.offset+(int)area.size > uncropped_dim.x)
+          ThrowRDE("RawImageData::calculateBlackAreas: Offset + size is larger 
than width of image");
+        for (int y = mOffset.y; y < dim.y+mOffset.y; y++) {
+          float *pixel = (float*)getDataUncropped(area.offset, y);
+          for (uint32 x = area.offset; x < area.size+area.offset; x++) {
+            accPixels[((y&1)<<1)|(x&1)] += *pixel++;
+          }
+        }
+        totalpixels += area.size * dim.y;
+      }
+    }
+
+    if (!totalpixels) {
+      for (int i = 0 ; i < 4; i++)
+        blackLevelSeparate[i] = blackLevel;
+      return;
+    }
+
+    /* Calculate median value of black areas for each component */
+    /* Adjust the number of total pixels so it is the same as the median of 
each histogram */
+    totalpixels /= 4;
+
+    for (int i = 0 ; i < 4; i++) {
+      blackLevelSeparate[i] = (int)(65535.0f * accPixels[i]/totalpixels);
+    }
+
+    /* If this is not a CFA image, we do not use separate blacklevels, use 
average */
+    if (!isCFA) {
+      int total = 0;
+      for (int i = 0 ; i < 4; i++)
+        total+=blackLevelSeparate[i];
+      for (int i = 0 ; i < 4; i++)
+        blackLevelSeparate[i] = (total+2)>>2;
+    }
+  }
+
+  void RawImageDataFloat::scaleBlackWhite() {
+    const int skipBorder = 150;
+    int gw = (dim.x - skipBorder) * cpp;
+    if ((blackAreas.empty() && blackLevelSeparate[0] < 0 && blackLevel < 0) || 
whitePoint == 65536) {  // Estimate
+      float b = 100000000;
+      float m = -10000000;
+      for (int row = skipBorder*cpp;row < (dim.y - skipBorder);row++) {
+        float *pixel = (float*)getData(skipBorder, row);
+        for (int col = skipBorder ; col < gw ; col++) {
+          b = MIN(*pixel, b);
+          m = MAX(*pixel, m);
+          pixel++;
+        }
+      }
+      if (blackLevel < 0)
+        blackLevel = (int)b;
+      if (whitePoint == 65536)
+        whitePoint = (int)m;
+      printf("Estimated black:%d, Estimated white: %d\n", blackLevel, 
whitePoint);
+    }
+
+    /* If filter has not set separate blacklevel, compute or fetch it */
+    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;
+
+      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) {
+    bool use_sse2;
+#ifdef _MSC_VER 
+    int info[4];
+    __cpuid(info, 1);
+    use_sse2 = !!(info[3]&(1 << 26));
+#else
+    use_sse2 = TRUE;
+#endif
+
+    float app_scale = 65535.0f / (whitePoint - blackLevelSeparate[0]);
+    // Check SSE2
+    if (use_sse2 && app_scale < 63) {
+
+      __m128i sseround;
+      __m128i ssesub2;
+      __m128i ssesign;
+      uint32* sub_mul = (uint32*)_aligned_malloc(16*4*2, 16);
+      uint32 gw = pitch / 16;
+      // 10 bit fraction
+      uint32 mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[mOffset.x&1]));  
+      mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[(mOffset.x+1)&1])))<<16;
+      uint32 b = blackLevelSeparate[mOffset.x&1] | 
(blackLevelSeparate[(mOffset.x+1)&1]<<16);
+
+      for (int i = 0; i< 4; i++) {
+        sub_mul[i] = b;     // Subtract even lines
+        sub_mul[4+i] = mul;   // Multiply even lines
+      }
+
+      mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[2+(mOffset.x&1)]));
+      mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[2+((mOffset.x+1)&1)])))<<16;
+      b = blackLevelSeparate[2+(mOffset.x&1)] | 
(blackLevelSeparate[2+((mOffset.x+1)&1)]<<16);
+
+      for (int i = 0; i< 4; i++) {
+        sub_mul[8+i] = b;   // Subtract odd lines
+        sub_mul[12+i] = mul;  // Multiply odd lines
+      }
+
+      sseround = _mm_set_epi32(512, 512, 512, 512);
+      ssesub2 = _mm_set_epi32(32768, 32768, 32768, 32768);
+      ssesign = _mm_set_epi32(0x80008000, 0x80008000, 0x80008000, 0x80008000);
+
+      for (int y = start_y; y < end_y; y++) {
+        __m128i* pixel = (__m128i*) & data[(mOffset.y+y)*pitch];
+        __m128i ssescale, ssesub;
+        if (((y+mOffset.y)&1) == 0) { 
+          ssesub = _mm_load_si128((__m128i*)&sub_mul[0]);
+          ssescale = _mm_load_si128((__m128i*)&sub_mul[4]);
+        } else {
+          ssesub = _mm_load_si128((__m128i*)&sub_mul[8]);
+          ssescale = _mm_load_si128((__m128i*)&sub_mul[12]);
+        }
+
+        for (uint32 x = 0 ; x < gw; x++) {
+          __m128i pix_high;
+          __m128i temp;
+          _mm_prefetch((char*)(pixel+1), _MM_HINT_T0);
+          __m128i pix_low = _mm_load_si128(pixel);
+          // Subtract black
+          pix_low = _mm_subs_epu16(pix_low, ssesub);
+          // Multiply the two unsigned shorts and combine it to 32 bit result
+          pix_high = _mm_mulhi_epu16(pix_low, ssescale);
+          temp = _mm_mullo_epi16(pix_low, ssescale);
+          pix_low = _mm_unpacklo_epi16(temp, pix_high);
+          pix_high = _mm_unpackhi_epi16(temp, pix_high);
+          // Add rounder
+          pix_low = _mm_add_epi32(pix_low, sseround);
+          pix_high = _mm_add_epi32(pix_high, sseround);
+          // Shift down
+          pix_low = _mm_srai_epi32(pix_low, 10);
+          pix_high = _mm_srai_epi32(pix_high, 10);
+          // Subtract to avoid clipping
+          pix_low = _mm_sub_epi32(pix_low, ssesub2);
+          pix_high = _mm_sub_epi32(pix_high, ssesub2);
+          // Pack
+          pix_low = _mm_packs_epi32(pix_low, pix_high);
+          // Shift sign off
+          pix_low = _mm_xor_si128(pix_low, ssesign);
+          _mm_store_si128(pixel, pix_low);
+          pixel++;
+        }
+      }
+      _aligned_free(sub_mul);
+    } else {
+      // Not SSE2
+      int gw = dim.x * cpp;
+      int mul[4];
+      int sub[4];
+      for (int i = 0; i < 4; i++) {
+        int v = i;
+        if ((mOffset.x&1) != 0)
+          v ^= 1;
+        if ((mOffset.y&1) != 0)
+          v ^= 2;
+        mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[v]));
+        sub[i] = blackLevelSeparate[v];
+      }
+      for (int y = start_y; y < end_y; y++) {
+        ushort16 *pixel = (ushort16*)getData(0, y);
+        int *mul_local = &mul[2*(y&1)];
+        int *sub_local = &sub[2*(y&1)];
+        for (int x = 0 ; x < gw; x++) {
+          pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 
8192) >> 14, 16);
+        }
+      }
+    }
+  }
+
+#else
+
+  void RawImageDataFloat::scaleValues(int start_y, int end_y) {
+    int gw = dim.x * cpp;
+    float mul[4];
+    float sub[4];
+    for (int i = 0; i < 4; i++) {
+      int v = i;
+      if ((mOffset.x&1) != 0)
+        v ^= 1;
+      if ((mOffset.y&1) != 0)
+        v ^= 2;
+      mul[i] = 65535.0f / (float)(whitePoint - blackLevelSeparate[v]);
+      sub[i] = (float)blackLevelSeparate[v];
+    }
+    for (int y = start_y; y < end_y; y++) {
+      float *pixel = (float*)getData(0, y);
+      float *mul_local = &mul[2*(y&1)];
+      float *sub_local = &sub[2*(y&1)];
+      for (int x = 0 ; x < gw; x++) {
+        pixel[x] = (pixel[x] - sub_local[x&1]) * mul_local[x&1];
+      }
+    }
+  }
+
+#endif
+
+} // namespace RawSpeed

Added: RawSpeed/RawImageDataU16.cpp
===================================================================
--- RawSpeed/RawImageDataU16.cpp                                (rev 0)
+++ RawSpeed/RawImageDataU16.cpp        2011-03-19 19:23:21 UTC (rev 347)
@@ -0,0 +1,298 @@
+#include "StdAfx.h"
+#include "RawImage.h"
+#include "RawDecoder.h"  // For exceptions
+/*
+    RawSpeed - RAW file decoder.
+
+    Copyright (C) 2009 Klaus Post
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
USA
+
+    http://www.klauspost.com
+*/
+#if defined(__SSE2__)
+#include <emmintrin.h>
+#endif
+
+namespace RawSpeed {
+
+RawImageDataU16::RawImageDataU16(void)
+{
+  bpp = 2;
+}
+
+RawImageDataU16::RawImageDataU16(iPoint2D _dim, uint32 _cpp) :
+RawImageData(_dim, 2, _cpp)
+{
+}
+
+
+void RawImageDataU16::calculateBlackAreas() {
+  int* histogram = (int*)malloc(4*65536*sizeof(int));
+  memset(histogram, 0, 4*65536*sizeof(int));
+  int totalpixels = 0;
+
+  for (uint32 i = 0; i < blackAreas.size(); i++) {
+    BlackArea area = blackAreas[i];
+
+    /* Make sure area sizes are multiple of two, 
+       so we have the same amount of pixels for each CFA group */
+    area.size = area.size - (area.size&1);
+
+    /* Process horizontal area */
+    if (!area.isVertical) {
+      if ((int)area.offset+(int)area.size > uncropped_dim.y)
+        ThrowRDE("RawImageData::calculateBlackAreas: Offset + size is larger 
than height of image");
+      for (uint32 y = area.offset; y < area.offset+area.size; y++) {
+        ushort16 *pixel = (ushort16*)getDataUncropped(mOffset.x, y);
+        int* localhist = &histogram[(y&1)*(65536*2)];
+        for (int x = mOffset.x; x < dim.x+mOffset.x; x++) {
+          localhist[((x&1)<<16) + *pixel]++;
+        }
+      }
+      totalpixels += area.size * dim.x;
+    }
+
+    /* Process vertical area */
+    if (area.isVertical) {
+      if ((int)area.offset+(int)area.size > uncropped_dim.x)
+        ThrowRDE("RawImageData::calculateBlackAreas: Offset + size is larger 
than width of image");
+      for (int y = mOffset.y; y < dim.y+mOffset.y; y++) {
+        ushort16 *pixel = (ushort16*)getDataUncropped(area.offset, y);
+        int* localhist = &histogram[(y&1)*(65536*2)];
+        for (uint32 x = area.offset; x < area.size+area.offset; x++) {
+          localhist[((x&1)<<16) + *pixel]++;
+        }
+      }
+      totalpixels += area.size * dim.y;
+    }
+  }
+
+  if (!totalpixels) {
+    for (int i = 0 ; i < 4; i++)
+      blackLevelSeparate[i] = blackLevel;
+    return;
+  }
+
+  /* Calculate median value of black areas for each component */
+  /* Adjust the number of total pixels so it is the same as the median of each 
histogram */
+  totalpixels /= 4*2;
+
+  for (int i = 0 ; i < 4; i++) {
+    int* localhist = &histogram[i*65536];
+    int acc_pixels = localhist[0];
+    int pixel_value = 0;
+    while (acc_pixels <= totalpixels && pixel_value < 65535) {
+      pixel_value++;
+      acc_pixels += localhist[pixel_value];
+    }
+    blackLevelSeparate[i] = pixel_value;
+  }
+
+  /* If this is not a CFA image, we do not use separate blacklevels, use 
average */
+  if (!isCFA) {
+    int total = 0;
+    for (int i = 0 ; i < 4; i++)
+      total+=blackLevelSeparate[i];
+    for (int i = 0 ; i < 4; i++)
+      blackLevelSeparate[i] = (total+2)>>2;
+  }
+  free(histogram);
+}
+
+void RawImageDataU16::scaleBlackWhite() {
+  const int skipBorder = 150;
+  int gw = (dim.x - skipBorder) * cpp;
+  if ((blackAreas.empty() && blackLevelSeparate[0] < 0 && blackLevel < 0) || 
whitePoint == 65536) {  // Estimate
+    int b = 65536;
+    int m = 0;
+    for (int row = skipBorder*cpp;row < (dim.y - skipBorder);row++) {
+      ushort16 *pixel = (ushort16*)getData(skipBorder, row);
+      for (int col = skipBorder ; col < gw ; col++) {
+        b = MIN(*pixel, b);
+        m = MAX(*pixel, m);
+        pixel++;
+      }
+    }
+    if (blackLevel < 0)
+      blackLevel = b;
+    if (whitePoint == 65536)
+      whitePoint = m;
+    printf("Estimated black:%d, Estimated white: %d\n", blackLevel, 
whitePoint);
+  }
+
+  /* If filter has not set separate blacklevel, compute or fetch it */
+  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;
+
+    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 _MSC_VER > 1399 || defined(__SSE2__)
+
+void RawImageDataU16::scaleValues(int start_y, int end_y) {
+  bool use_sse2;
+#ifdef _MSC_VER 
+  int info[4];
+  __cpuid(info, 1);
+  use_sse2 = !!(info[3]&(1 << 26));
+#else
+  use_sse2 = TRUE;
+#endif
+
+  float app_scale = 65535.0f / (whitePoint - blackLevelSeparate[0]);
+  // Check SSE2
+  if (use_sse2 && app_scale < 63) {
+
+    __m128i sseround;
+    __m128i ssesub2;
+    __m128i ssesign;
+    uint32* sub_mul = (uint32*)_aligned_malloc(16*4*2, 16);
+    uint32 gw = pitch / 16;
+    // 10 bit fraction
+    uint32 mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[mOffset.x&1]));  
+    mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[(mOffset.x+1)&1])))<<16;
+    uint32 b = blackLevelSeparate[mOffset.x&1] | 
(blackLevelSeparate[(mOffset.x+1)&1]<<16);
+
+    for (int i = 0; i< 4; i++) {
+      sub_mul[i] = b;     // Subtract even lines
+      sub_mul[4+i] = mul;   // Multiply even lines
+    }
+
+    mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[2+(mOffset.x&1)]));
+    mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[2+((mOffset.x+1)&1)])))<<16;
+    b = blackLevelSeparate[2+(mOffset.x&1)] | 
(blackLevelSeparate[2+((mOffset.x+1)&1)]<<16);
+
+    for (int i = 0; i< 4; i++) {
+      sub_mul[8+i] = b;   // Subtract odd lines
+      sub_mul[12+i] = mul;  // Multiply odd lines
+    }
+
+    sseround = _mm_set_epi32(512, 512, 512, 512);
+    ssesub2 = _mm_set_epi32(32768, 32768, 32768, 32768);
+    ssesign = _mm_set_epi32(0x80008000, 0x80008000, 0x80008000, 0x80008000);
+
+    for (int y = start_y; y < end_y; y++) {
+      __m128i* pixel = (__m128i*) & data[(mOffset.y+y)*pitch];
+      __m128i ssescale, ssesub;
+      if (((y+mOffset.y)&1) == 0) { 
+        ssesub = _mm_load_si128((__m128i*)&sub_mul[0]);
+        ssescale = _mm_load_si128((__m128i*)&sub_mul[4]);
+      } else {
+        ssesub = _mm_load_si128((__m128i*)&sub_mul[8]);
+        ssescale = _mm_load_si128((__m128i*)&sub_mul[12]);
+      }
+
+      for (uint32 x = 0 ; x < gw; x++) {
+        __m128i pix_high;
+        __m128i temp;
+        _mm_prefetch((char*)(pixel+1), _MM_HINT_T0);
+        __m128i pix_low = _mm_load_si128(pixel);
+        // Subtract black
+        pix_low = _mm_subs_epu16(pix_low, ssesub);
+        // Multiply the two unsigned shorts and combine it to 32 bit result
+        pix_high = _mm_mulhi_epu16(pix_low, ssescale);
+        temp = _mm_mullo_epi16(pix_low, ssescale);
+        pix_low = _mm_unpacklo_epi16(temp, pix_high);
+        pix_high = _mm_unpackhi_epi16(temp, pix_high);
+        // Add rounder
+        pix_low = _mm_add_epi32(pix_low, sseround);
+        pix_high = _mm_add_epi32(pix_high, sseround);
+        // Shift down
+        pix_low = _mm_srai_epi32(pix_low, 10);
+        pix_high = _mm_srai_epi32(pix_high, 10);
+        // Subtract to avoid clipping
+        pix_low = _mm_sub_epi32(pix_low, ssesub2);
+        pix_high = _mm_sub_epi32(pix_high, ssesub2);
+        // Pack
+        pix_low = _mm_packs_epi32(pix_low, pix_high);
+        // Shift sign off
+        pix_low = _mm_xor_si128(pix_low, ssesign);
+        _mm_store_si128(pixel, pix_low);
+        pixel++;
+      }
+    }
+    _aligned_free(sub_mul);
+  } else {
+    // Not SSE2
+    int gw = dim.x * cpp;
+    int mul[4];
+    int sub[4];
+    for (int i = 0; i < 4; i++) {
+      int v = i;
+      if ((mOffset.x&1) != 0)
+        v ^= 1;
+      if ((mOffset.y&1) != 0)
+        v ^= 2;
+      mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[v]));
+      sub[i] = blackLevelSeparate[v];
+    }
+    for (int y = start_y; y < end_y; y++) {
+      ushort16 *pixel = (ushort16*)getData(0, y);
+      int *mul_local = &mul[2*(y&1)];
+      int *sub_local = &sub[2*(y&1)];
+      for (int x = 0 ; x < gw; x++) {
+        pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 
8192) >> 14, 16);
+      }
+    }
+  }
+}
+
+#else
+
+void RawImageDataU16::scaleValues(int start_y, int end_y) {
+  int gw = dim.x * cpp;
+  int mul[4];
+  int sub[4];
+  for (int i = 0; i < 4; i++) {
+    int v = i;
+    if ((mOffset.x&1) != 0)
+      v ^= 1;
+    if ((mOffset.y&1) != 0)
+      v ^= 2;
+    mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - 
blackLevelSeparate[v]));
+    sub[i] = blackLevelSeparate[v];
+  }
+  for (int y = start_y; y < end_y; y++) {
+    ushort16 *pixel = (ushort16*)getData(0, y);
+    int *mul_local = &mul[2*(y&1)];
+    int *sub_local = &sub[2*(y&1)];
+    for (int x = 0 ; x < gw; x++) {
+      pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 
8192) >> 14, 16);
+    }
+  }
+}
+
+#endif
+
+} // namespace RawSpeed

Modified: RawSpeed/RawSpeed.vcproj
===================================================================
--- RawSpeed/RawSpeed.vcproj    2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/RawSpeed.vcproj    2011-03-19 19:23:21 UTC (rev 347)
@@ -190,10 +190,6 @@
                        
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
                        >
                        <File
-                               RelativePath=".\RawImage.cpp"
-                               >
-                       </File>
-                       <File
                                RelativePath=".\RawSpeed.cpp"
                                >
                        </File>
@@ -389,6 +385,22 @@
                                        >
                                </File>
                        </Filter>
+                       <Filter
+                               Name="RawImage"
+                               >
+                               <File
+                                       RelativePath=".\RawImage.cpp"
+                                       >
+                               </File>
+                               <File
+                                       RelativePath=".\RawImageDataFloat.cpp"
+                                       >
+                               </File>
+                               <File
+                                       RelativePath=".\RawImageDataU16.cpp"
+                                       >
+                               </File>
+                       </Filter>
                </Filter>
                <Filter
                        Name="Header Files"

Modified: RawSpeed/Rw2Decoder.cpp
===================================================================
--- RawSpeed/Rw2Decoder.cpp     2011-03-19 17:20:28 UTC (rev 346)
+++ RawSpeed/Rw2Decoder.cpp     2011-03-19 19:23:21 UTC (rev 347)
@@ -51,8 +51,6 @@
   uint32 height = raw->getEntry((TiffTag)3)->getShort();
   uint32 width = raw->getEntry((TiffTag)2)->getShort();
 
-  mRaw->bpp = 2;
-
   if (isOldPanasonic) {
     ThrowRDE("Cannot decoder old-style Panasonic RAW files");
     TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);


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

Reply via email to