~ubuntu-branches/ubuntu/saucy/darktable/saucy

« back to all changes in this revision

Viewing changes to src/rawspeed/RawSpeed/RawImage.cpp

  • Committer: Bazaar Package Importer
  • Author(s): David Bremner
  • Date: 2011-07-12 09:36:46 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110712093646-yp9dbxan44dmw15h
Tags: 0.9-1
* New upstream release.
* Remove all patches now upstream; only patch for
  -Wno-error=unused-but-set-variable remains.
* Bump Standards-Version to 3.9.2 (no changes)

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
namespace RawSpeed {
30
30
 
31
31
RawImageData::RawImageData(void):
32
 
    dim(0, 0), bpp(0), isCFA(true),
 
32
    dim(0, 0), isCFA(true),
33
33
    blackLevel(-1), whitePoint(65536),
34
 
    dataRefCount(0), data(0), cpp(1) {
 
34
    dataRefCount(0), data(0), cpp(1), bpp(0),
 
35
    uncropped_dim(0, 0) {
 
36
  blackLevelSeparate[0] = blackLevelSeparate[1] = blackLevelSeparate[2] = blackLevelSeparate[3] = -1;
35
37
  pthread_mutex_init(&mymutex, NULL);
36
38
  subsampling.x = subsampling.y = 1;
37
39
}
38
40
 
39
41
RawImageData::RawImageData(iPoint2D _dim, uint32 _bpc, uint32 _cpp) :
40
 
    dim(_dim), bpp(_bpc),
 
42
    dim(_dim),
41
43
    blackLevel(-1), whitePoint(65536),
42
 
    dataRefCount(0), data(0), cpp(cpp) {
 
44
    dataRefCount(0), data(0), cpp(cpp), bpp(_bpc),
 
45
    uncropped_dim(0, 0) {
 
46
  blackLevelSeparate[0] = blackLevelSeparate[1] = blackLevelSeparate[2] = blackLevelSeparate[3] = -1;
43
47
  subsampling.x = subsampling.y = 1;
44
48
  createData();
45
49
  pthread_mutex_init(&mymutex, NULL);
66
70
  data = (uchar8*)_aligned_malloc(pitch * dim.y, 16);
67
71
  if (!data)
68
72
    ThrowRDE("RawImageData::createData: Memory Allocation failed.");
 
73
  uncropped_dim = dim;
69
74
}
70
75
 
71
76
void RawImageData::destroyData() {
107
112
}
108
113
 
109
114
uchar8* RawImageData::getDataUncropped(uint32 x, uint32 y) {
110
 
  if ((int)x >= dim.x+mOffset.x)
 
115
  if ((int)x >= uncropped_dim.x)
111
116
    ThrowRDE("RawImageData::getDataUncropped - X Position outside image requested.");
112
 
  if ((int)y >= dim.y+mOffset.y) {
 
117
  if ((int)y >= uncropped_dim.y) {
113
118
    ThrowRDE("RawImageData::getDataUncropped - Y Position outside image requested.");
114
119
  }
115
120
 
119
124
  return &data[y*pitch+x*bpp];
120
125
}
121
126
 
 
127
iPoint2D RawImageData::getUncroppedDim()
 
128
{
 
129
  return uncropped_dim;
 
130
}
 
131
 
 
132
iPoint2D RawImageData::getCropOffset()
 
133
{
 
134
  return mOffset;
 
135
}
 
136
 
122
137
void RawImageData::subFrame(iPoint2D offset, iPoint2D new_size) {
123
138
  if (!new_size.isThisInside(dim - offset)) {
124
139
    printf("WARNING: RawImageData::subFrame - Attempted to create new subframe larger than original size. Crop skipped.\n");
133
148
  dim = new_size;
134
149
}
135
150
 
136
 
void RawImageData::calculateBlackAreas() {
137
 
  int* histogram = (int*)malloc(4*65536*sizeof(int));
138
 
  memset(histogram, 0, 4*65536*sizeof(int));
139
 
  int totalpixels = 0;
140
 
 
141
 
  for (uint32 i = 0; i < blackAreas.size(); i++) {
142
 
    BlackArea area = blackAreas[i];
143
 
    /* Process horizontal area */
144
 
    if (!area.isVertical) {
145
 
      for (uint32 y = area.offset; y < area.offset+area.size; y++) {
146
 
        ushort16 *pixel = (ushort16*)getDataUncropped(mOffset.x, y);
147
 
        int* localhist = &histogram[(y&1)*(65536*2)];
148
 
        for (int x = mOffset.x; x < dim.x; x++) {
149
 
          localhist[((x&1)<<16) + *pixel]++;
150
 
        }
151
 
      }
152
 
      totalpixels += area.size * dim.x;
153
 
    }
154
 
 
155
 
    /* Process vertical area */
156
 
    if (area.isVertical) {
157
 
      for (int y = mOffset.y; y < dim.y; y++) {
158
 
        ushort16 *pixel = (ushort16*)getDataUncropped(area.offset, y);
159
 
        int* localhist = &histogram[(y&1)*(65536*2)];
160
 
        for (uint32 x = area.offset; x < area.size; x++) {
161
 
          localhist[((x&1)<<16) + *pixel]++;
162
 
        }
163
 
      }
164
 
    }
165
 
    totalpixels += area.size * dim.y;
166
 
  }
167
 
 
168
 
  if (!totalpixels) {
169
 
    for (int i = 0 ; i < 4; i++)
170
 
      blackLevelSeparate[i] = blackLevel;
171
 
    return;
172
 
  }
173
 
 
174
 
  /* Calculate median value of black areas for each component */
175
 
  /* Adjust the number of total pixels so it is the same as the median of each histogram */
176
 
  totalpixels /= 4*2;
177
 
 
178
 
  for (int i = 0 ; i < 4; i++) {
179
 
    int* localhist = &histogram[i*65536];
180
 
    int acc_pixels = localhist[0];
181
 
    int pixel_value = 0;
182
 
    while (acc_pixels <= totalpixels && pixel_value < 65535) {
183
 
      pixel_value++;
184
 
      acc_pixels += localhist[pixel_value];
185
 
    }
186
 
    blackLevelSeparate[i] = pixel_value;
187
 
  }
188
 
  free(histogram);
189
 
}
190
 
 
191
 
void RawImageData::scaleBlackWhite() {
192
 
  const int skipBorder = 150;
193
 
  int gw = (dim.x - skipBorder) * cpp;
194
 
  if (blackLevel < 0 || whitePoint == 65536) {  // Estimate
195
 
    int b = 65536;
196
 
    int m = 0;
197
 
    for (int row = skipBorder*cpp;row < (dim.y - skipBorder);row++) {
198
 
      ushort16 *pixel = (ushort16*)getData(skipBorder, row);
199
 
      for (int col = skipBorder ; col < gw ; col++) {
200
 
        b = MIN(*pixel, b);
201
 
        m = MAX(*pixel, m);
202
 
        pixel++;
203
 
      }
204
 
    }
205
 
    if (blackLevel < 0)
206
 
      blackLevel = b;
207
 
    if (whitePoint == 65536)
208
 
      whitePoint = m;
209
 
    printf("Estimated black:%d, Estimated white: %d\n", blackLevel, whitePoint);
210
 
  }
211
 
 
212
 
  calculateBlackAreas();
213
 
  scaleValues();
214
 
}
215
 
 
216
 
#if _MSC_VER > 1399 || defined(__SSE2__)
217
 
 
218
 
void RawImageData::scaleValues() {
219
 
  bool use_sse2;
220
 
#ifdef _MSC_VER 
221
 
  int info[4];
222
 
  __cpuid(info, 1);
223
 
  use_sse2 = !!(info[3]&(1 << 26));
224
 
#else
225
 
  use_sse2 = TRUE;
226
 
#endif
227
 
 
228
 
  // Check SSE2
229
 
  if (use_sse2) {
230
 
 
231
 
    __m128i sseround;
232
 
    __m128i ssesub2;
233
 
    __m128i ssesign;
234
 
    uint32* sub_mul = (uint32*)_aligned_malloc(16*4*2, 16);
235
 
    uint32 gw = pitch / 16;
236
 
    // 10 bit fraction
237
 
    uint32 mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - blackLevelSeparate[mOffset.x&1]));  
238
 
    mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - blackLevelSeparate[(mOffset.x+1)&1])))<<16;
239
 
    uint32 b = blackLevelSeparate[mOffset.x&1] | (blackLevelSeparate[(mOffset.x+1)&1]<<16);
240
 
 
241
 
    for (int i = 0; i< 4; i++) {
242
 
      sub_mul[i] = b;     // Subtract even lines
243
 
      sub_mul[4+i] = mul;   // Multiply even lines
244
 
    }
245
 
 
246
 
    mul = (int)(1024.0f * 65535.0f / (float)(whitePoint - blackLevelSeparate[2+(mOffset.x&1)]));
247
 
    mul |= ((int)(1024.0f * 65535.0f / (float)(whitePoint - blackLevelSeparate[2+((mOffset.x+1)&1)])))<<16;
248
 
    b = blackLevelSeparate[2+(mOffset.x&1)] | (blackLevelSeparate[2+((mOffset.x+1)&1)]<<16);
249
 
 
250
 
    for (int i = 0; i< 4; i++) {
251
 
      sub_mul[8+i] = b;   // Subtract odd lines
252
 
      sub_mul[12+i] = mul;  // Multiply odd lines
253
 
    }
254
 
 
255
 
    sseround = _mm_set_epi32(512, 512, 512, 512);
256
 
    ssesub2 = _mm_set_epi32(32768, 32768, 32768, 32768);
257
 
    ssesign = _mm_set_epi32(0x80008000, 0x80008000, 0x80008000, 0x80008000);
258
 
 
259
 
    for (int y = 0; y < dim.y; y++) {
260
 
      __m128i* pixel = (__m128i*) & data[(mOffset.y+y)*pitch];
261
 
      __m128i ssescale, ssesub;
262
 
      if (((y+mOffset.y)&1) == 0) { 
263
 
        ssesub = _mm_load_si128((__m128i*)&sub_mul[0]);
264
 
        ssescale = _mm_load_si128((__m128i*)&sub_mul[4]);
265
 
      } else {
266
 
        ssesub = _mm_load_si128((__m128i*)&sub_mul[8]);
267
 
        ssescale = _mm_load_si128((__m128i*)&sub_mul[12]);
268
 
      }
269
 
 
270
 
      for (uint32 x = 0 ; x < gw; x++) {
271
 
        __m128i pix_high;
272
 
        __m128i temp;
273
 
        __m128i pix_low = _mm_load_si128(pixel);
274
 
        // Subtract black
275
 
        pix_low = _mm_subs_epu16(pix_low, ssesub);
276
 
        // Multiply the two unsigned shorts and combine it to 32 bit result
277
 
        pix_high = _mm_mulhi_epu16(pix_low, ssescale);
278
 
        temp = _mm_mullo_epi16(pix_low, ssescale);
279
 
        pix_low = _mm_unpacklo_epi16(temp, pix_high);
280
 
        pix_high = _mm_unpackhi_epi16(temp, pix_high);
281
 
        // Add rounder
282
 
        pix_low = _mm_add_epi32(pix_low, sseround);
283
 
        pix_high = _mm_add_epi32(pix_high, sseround);
284
 
        // Shift down
285
 
        pix_low = _mm_srai_epi32(pix_low, 10);
286
 
        pix_high = _mm_srai_epi32(pix_high, 10);
287
 
        // Subtract to avoid clipping
288
 
        pix_low = _mm_sub_epi32(pix_low, ssesub2);
289
 
        pix_high = _mm_sub_epi32(pix_high, ssesub2);
290
 
        // Pack
291
 
        pix_low = _mm_packs_epi32(pix_low, pix_high);
292
 
        // Shift sign off
293
 
        pix_low = _mm_xor_si128(pix_low, ssesign);
294
 
        _mm_store_si128(pixel, pix_low);
295
 
        pixel++;
296
 
      }
297
 
    }
298
 
    _aligned_free(sub_mul);
299
 
  } else {
300
 
    // Not SSE2
301
 
    int gw = dim.x * cpp;
302
 
    int mul[4];
303
 
    int sub[4];
304
 
    for (int i = 0; i < 4; i++) {
305
 
      int v = i;
306
 
      if ((mOffset.x&1) != 0)
307
 
        v ^= 1;
308
 
      if ((mOffset.y&1) != 0)
309
 
        v ^= 2;
310
 
      mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - blackLevelSeparate[v]));
311
 
      sub[i] = blackLevelSeparate[v];
312
 
    }
313
 
    for (int y = 0; y < dim.y; y++) {
314
 
      ushort16 *pixel = (ushort16*)getData(0, y);
315
 
      int *mul_local = &mul[2*(y&1)];
316
 
      int *sub_local = &sub[2*(y&1)];
317
 
      for (int x = 0 ; x < gw; x++) {
318
 
        pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 8192) >> 14, 16);
319
 
      }
320
 
    }
321
 
  }
322
 
}
323
 
 
324
 
#else
325
 
 
326
 
void RawImageData::scaleValues() {
327
 
  int gw = dim.x * cpp;
328
 
  int mul[4];
329
 
  int sub[4];
330
 
  for (int i = 0; i < 4; i++) {
331
 
    int v = i;
332
 
    if ((mOffset.x&1) != 0)
333
 
      v ^= 1;
334
 
    if ((mOffset.y&1) != 0)
335
 
      v ^= 2;
336
 
    mul[i] = (int)(16384.0f * 65535.0f / (float)(whitePoint - blackLevelSeparate[v]));
337
 
    sub[i] = blackLevelSeparate[v];
338
 
  }
339
 
  for (int y = 0; y < dim.y; y++) {
340
 
    ushort16 *pixel = (ushort16*)getData(0, y);
341
 
    int *mul_local = &mul[2*(y&1)];
342
 
    int *sub_local = &sub[2*(y&1)];
343
 
    for (int x = 0 ; x < gw; x++) {
344
 
      pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] + 8192) >> 14, 16);
345
 
    }
346
 
  }
347
 
}
348
 
 
349
 
#endif
350
 
 
351
151
 
352
152
RawImage::RawImage(RawImageData* p) : p_(p) {
353
153
  pthread_mutex_lock(&p_->mymutex);
387
187
  return *this;
388
188
}
389
189
 
 
190
void *RawImageWorkerThread(void *_this) {
 
191
  RawImageWorker* me = (RawImageWorker*)_this;
 
192
  me->_performTask();
 
193
  pthread_exit(NULL);
 
194
  return 0;
 
195
}
 
196
 
 
197
RawImageWorker::RawImageWorker( RawImageData *_img, RawImageWorkerTask _task, int _start_y, int _end_y )
 
198
{
 
199
  data = _img;
 
200
  start_y = _start_y;
 
201
  end_y = _end_y;
 
202
  task = _task;
 
203
  startThread();
 
204
}
 
205
 
 
206
void RawImageWorker::startThread()
 
207
{
 
208
  /* Initialize and set thread detached attribute */
 
209
  pthread_attr_t attr;
 
210
  pthread_attr_init(&attr);
 
211
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 
212
  pthread_create(&threadid, &attr, RawImageWorkerThread, this);
 
213
}
 
214
 
 
215
void RawImageWorker::waitForThread()
 
216
 
217
  void *status;
 
218
  pthread_join(threadid, &status);
 
219
}
 
220
 
 
221
void RawImageWorker::_performTask()
 
222
{
 
223
  switch(task)
 
224
  {
 
225
    case TASK_SCALE_VALUES:
 
226
      data->scaleValues(start_y, end_y);
 
227
      break;
 
228
    default:
 
229
      _ASSERTE(false);
 
230
  }
 
231
}
 
232
 
 
233
 
390
234
} // namespace RawSpeed