@@ -41,26 +41,32 @@ static bool isfinite( float arg )
41
41
42
42
43
43
44
+ /* Size threshold for using parallel loops (256x256 pixels)
45
+ */
46
+ #define PARALLEL_THRESHOLD 65536
47
+
48
+
44
49
/* D65 temp 6504.
45
50
*/
46
51
#define D65_X0 95.0470
47
52
#define D65_Y0 100.0
48
53
#define D65_Z0 108.8827
49
54
50
- /* Size threshold for using parallel loops (256x256 pixels)
51
- */
52
- #define PARALLEL_THRESHOLD 65536
53
-
54
-
55
- /* XYZ to sRGB conversion matrix
55
+ /* D65 XYZ <-> sRGB conversion matrices
56
56
*/
57
57
static const float XYZ_sRGB[3 ][3 ] = { { 3.2406255 , -1.537208 , -0.4986286 },
58
58
{-0.9689307 , 1.8757561 , 0.0415175 },
59
59
{ 0.0557101 , -0.2040211 , 1.0569959 } };
60
60
61
+ static const float sRGB_XYZ [3 ][3 ] = { { 0.4124564 , 0.3575761 , 0.1804375 },
62
+ { 0.2126729 , 0.7151522 , 0.0721750 },
63
+ { 0.0193339 , 0.1191920 , 0.9503041 } };
64
+
65
+
61
66
using namespace std ;
62
67
63
68
69
+
64
70
// Normalization function
65
71
void Transform::normalize ( RawTile& in, const vector<float >& max, const vector<float >& min ) {
66
72
@@ -158,7 +164,7 @@ void Transform::normalize( RawTile& in, const vector<float>& max, const vector<f
158
164
in.data = normdata;
159
165
in.bpc = 32 ;
160
166
in.sampleType = SampleType::FLOATINGPOINT;
161
- in.dataLength = ( uint32_t ) np * (in. bpc / 8 ) ;
167
+ in.dataLength = np << 2 ;
162
168
in.capacity = in.dataLength ;
163
169
164
170
}
@@ -304,6 +310,65 @@ void Transform::LAB2sRGB( const float *in, float *out ){
304
310
305
311
306
312
313
+ // Convert a single pixel from normalized sRGB to CIELAB
314
+ void Transform::sRGB2LAB ( const float *in, float *out ){
315
+
316
+ float R,G,B;
317
+ float X,Y,Z;
318
+ float L,a,b;
319
+
320
+ R = in[0 ];
321
+ G = in[1 ];
322
+ B = in[2 ];
323
+
324
+ // Linearize
325
+ if ( R <= 0.04045 ) R /= 12.92 ;
326
+ else R = powf ( ( (R+0.055 ) / 1.055 ), 2.4 );
327
+
328
+ if ( G <= 0.04045 ) G /= 12.92 ;
329
+ else G = powf ( ( (G+0.055 ) / 1.055 ), 2.4 );
330
+
331
+ if ( B <= 0.04045 ) B /= 12.92 ;
332
+ else B = powf ( ( (B+0.055 ) / 1.055 ), 2.4 );
333
+
334
+ // Linear RGB needs to be scaled to 100
335
+ R += 100.0 ;
336
+ G *= 100.0 ;
337
+ B *= 100.0 ;
338
+
339
+ // Convert from linear RGB to XYZ
340
+ X = (R * sRGB_XYZ [0 ][0 ]) + (G * sRGB_XYZ [0 ][1 ]) + (B * sRGB_XYZ [0 ][2 ]);
341
+ Y = (R * sRGB_XYZ [1 ][0 ]) + (G * sRGB_XYZ [1 ][1 ]) + (B * sRGB_XYZ [1 ][2 ]);
342
+ Z = (R * sRGB_XYZ [2 ][0 ]) + (G * sRGB_XYZ [2 ][1 ]) + (B * sRGB_XYZ [2 ][2 ]);
343
+
344
+ // Scale XYZ by illuminant
345
+ X /= D65_X0;
346
+ Y /= D65_Y0;
347
+ Z /= D65_Z0;
348
+
349
+ // Convert from XYZ to CIELAB
350
+ if ( X > 0.008856452 ) X = cbrtf (X);
351
+ else X = ( 7.787037037 * X ) + 0.137931034 ;
352
+
353
+ if ( Y > 0.008856452 ) Y = cbrtf (Y);
354
+ else Y = ( 7.787037037 * Y ) + 0.137931034 ;
355
+
356
+ if ( Z > 0.008856452 ) Z = cbrtf (Z);
357
+ else Z = ( 7.787037037 * Z ) + 0.137931034 ;
358
+
359
+
360
+ L = ( 116.0 * Y ) - 16.0 ;
361
+ a = 500.0 * ( X - Y );
362
+ b = 200.0 * ( Y - Z );
363
+
364
+ // Return our CIELAB values
365
+ out[0 ] = L;
366
+ out[1 ] = a;
367
+ out[2 ] = b;
368
+ }
369
+
370
+
371
+
307
372
// Convert whole image from CIELAB to sRGB. Input data can be in 8 bit, 16 bit or floating point form
308
373
void Transform::LAB2sRGB ( RawTile& in ){
309
374
@@ -355,7 +420,7 @@ void Transform::LAB2sRGB( RawTile& in ){
355
420
}
356
421
357
422
// Perform color conversion on this pixel
358
- LAB2sRGB ( & cielab[ 0 ], & rgb[ 0 ] );
423
+ LAB2sRGB ( cielab, rgb );
359
424
360
425
output[n] = rgb[0 ];
361
426
output[n+1 ] = rgb[1 ];
@@ -376,6 +441,36 @@ void Transform::LAB2sRGB( RawTile& in ){
376
441
377
442
378
443
444
+ // Convert whole image from sRGB to CIELAB - input should be normalized and in floating point format
445
+ void Transform::sRGB2LAB ( RawTile& in ){
446
+
447
+ uint32_t np = (uint32_t ) in.width * in.height * in.channels ;
448
+
449
+ // Parallelize code using OpenMP
450
+ #if defined(__ICC) || defined(__INTEL_COMPILER)
451
+ #pragma ivdep
452
+ #elif defined(_OPENMP)
453
+ #pragma omp parallel for
454
+ #endif
455
+ for ( uint32_t n=0 ; n<np; n+=in.channels ){
456
+
457
+ float rgb[3 ];
458
+ float cielab[3 ];
459
+
460
+ rgb[0 ] = ((float *)in.data )[n];
461
+ rgb[1 ] = ((float *)in.data )[n+1 ];
462
+ rgb[2 ] = ((float *)in.data )[n+2 ];
463
+
464
+ sRGB2LAB ( rgb, cielab );
465
+
466
+ ((float *)in.data )[n] = cielab[0 ];
467
+ ((float *)in.data )[n+1 ] = cielab[1 ];
468
+ ((float *)in.data )[n+2 ] = cielab[2 ];
469
+ }
470
+ }
471
+
472
+
473
+
379
474
// Colormap function
380
475
// Based on the routine colormap.cpp in Imagin Raytracer by Olivier Ferrand
381
476
// http://www.imagin-raytracer.org
0 commit comments