Author: post
Date: 2012-12-09 11:19:39 +0100 (Sun, 09 Dec 2012)
New Revision: 501
Modified:
RawSpeed/RawImageDataU16.cpp
Log:
Add random information when scaling up images below camera precision. Each
pixel is added a random value +-(upscale / 2). Effectively this makes sure that
pixel values below the sensor resolution/camera compression model is random.
Simply said, when upscaling 12 to 16 bits, this means the last 4 bits are
random instead of simply 0. This should avoid banding and similar artifacts on
heavy processed images.
Modified: RawSpeed/RawImageDataU16.cpp
===================================================================
--- RawSpeed/RawImageDataU16.cpp 2012-12-06 14:14:32 UTC (rev 500)
+++ RawSpeed/RawImageDataU16.cpp 2012-12-09 10:19:39 UTC (rev 501)
@@ -180,13 +180,25 @@
use_sse2 = TRUE;
#endif
- float app_scale = 65535.0f / (whitePoint - blackLevelSeparate[0]);
+ int depth_values = whitePoint - blackLevelSeparate[0];
+ float app_scale = 65535.0f / depth_values;
+
+ // Scale in 30.2 fp
+ int full_scale_fp = (int)(app_scale * 4.0f);
+ // Half Scale in 18.14 fp
+ int half_scale_fp = (int)(app_scale * 4095.0f);
+
// Check SSE2
if (use_sse2 && app_scale < 63) {
__m128i sseround;
__m128i ssesub2;
__m128i ssesign;
+ __m128i rand_mul;
+ __m128i rand_mask;
+ __m128i sse_full_scale_fp;
+ __m128i sse_half_scale_fp;
+
uint32* sub_mul = (uint32*)_aligned_malloc(16*4*2, 16);
if (!sub_mul)
ThrowRDE("Out of memory, failed to allocate 128 bytes");
@@ -213,8 +225,14 @@
sseround = _mm_set_epi32(512, 512, 512, 512);
ssesub2 = _mm_set_epi32(32768, 32768, 32768, 32768);
ssesign = _mm_set_epi32(0x80008000, 0x80008000, 0x80008000, 0x80008000);
+ sse_full_scale_fp = _mm_set1_epi32(full_scale_fp|(full_scale_fp<<16));
+ sse_half_scale_fp = _mm_set1_epi32(half_scale_fp >> 4);
+ rand_mul = _mm_set1_epi32(0x4d9f1d32);
+ rand_mask = _mm_set1_epi32(0x00ff00ff); // 8 random bits
+
for (int y = start_y; y < end_y; y++) {
+ __m128i sserandom = _mm_set_epi32(dim.x*1676+y*18000,
dim.x*2342+y*34311, dim.x*4272+y*12123, dim.x*1234+y*23464);
__m128i* pixel = (__m128i*) & data[(mOffset.y+y)*pitch];
__m128i ssescale, ssesub;
if (((y+mOffset.y)&1) == 0) {
@@ -240,6 +258,18 @@
// Add rounder
pix_low = _mm_add_epi32(pix_low, sseround);
pix_high = _mm_add_epi32(pix_high, sseround);
+
+ sserandom = _mm_xor_si128(_mm_mulhi_epi16(sserandom, rand_mul),
_mm_mullo_epi16(sserandom, rand_mul));
+ __m128i rand_masked = _mm_and_si128(sserandom, rand_mask); // Get 8
random bits
+ rand_masked = _mm_mullo_epi16(rand_masked, sse_full_scale_fp);
+
+ __m128i zero = _mm_setzero_si128();
+ __m128i rand_lo = _mm_sub_epi32(sse_half_scale_fp,
_mm_unpacklo_epi16(rand_masked,zero));
+ __m128i rand_hi = _mm_sub_epi32(sse_half_scale_fp,
_mm_unpackhi_epi16(rand_masked,zero));
+
+ pix_low = _mm_add_epi32(pix_low, rand_lo);
+ pix_high = _mm_add_epi32(pix_high, rand_hi);
+
// Shift down
pix_low = _mm_srai_epi32(pix_low, 10);
pix_high = _mm_srai_epi32(pix_high, 10);
@@ -270,11 +300,14 @@
sub[i] = blackLevelSeparate[v];
}
for (int y = start_y; y < end_y; y++) {
+ int v = dim.x + y * 36969;
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);
+ v = 18000 *(v & 65535) + (v >> 16);
+ int rand = half_scale_fp - (full_scale_fp * (v&2047));
+ pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] +
8192 + rand) >> 14, 16);
}
}
}
@@ -286,6 +319,14 @@
int gw = dim.x * cpp;
int mul[4];
int sub[4];
+ int depth_values = whitePoint - blackLevelSeparate[0];
+ float app_scale = 65535.0f / depth_values;
+
+ // Scale in 30.2 fp
+ int full_scale_fp = (int)(app_scale * 4.0f);
+ // Half Scale in 18.14 fp
+ int half_scale_fp = (int)(app_scale * 4095.0f);
+
for (int i = 0; i < 4; i++) {
int v = i;
if ((mOffset.x&1) != 0)
@@ -296,11 +337,14 @@
sub[i] = blackLevelSeparate[v];
}
for (int y = start_y; y < end_y; y++) {
+ int v = dim.x + y * 36969;
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);
+ v = 18000 *(v & 65535) + (v >> 16);
+ int rand = half_scale_fp - (full_scale_fp * (v&2047));
+ pixel[x] = clampbits(((pixel[x] - sub_local[x&1]) * mul_local[x&1] +
8192 + rand) >> 14, 16);
}
}
}
_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit