~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/3rdparty/openexr/IlmImf/ImfRgbaYca.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//////////////////////////////////////////////////////////////////////////////
 
2
//
 
3
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
 
4
// Entertainment Company Ltd.  Portions contributed and copyright held by
 
5
// others as indicated.  All rights reserved.
 
6
//
 
7
// Redistribution and use in source and binary forms, with or without
 
8
// modification, are permitted provided that the following conditions are
 
9
// met:
 
10
//
 
11
//     * Redistributions of source code must retain the above
 
12
//       copyright notice, this list of conditions and the following
 
13
//       disclaimer.
 
14
//
 
15
//     * Redistributions in binary form must reproduce the above
 
16
//       copyright notice, this list of conditions and the following
 
17
//       disclaimer in the documentation and/or other materials provided with
 
18
//       the distribution.
 
19
//
 
20
//     * Neither the name of Industrial Light & Magic nor the names of
 
21
//       any other contributors to this software may be used to endorse or
 
22
//       promote products derived from this software without specific prior
 
23
//       written permission.
 
24
//
 
25
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 
26
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
27
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
28
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
29
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
30
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
31
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
32
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 
33
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
34
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
35
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
36
//
 
37
//////////////////////////////////////////////////////////////////////////////
 
38
 
 
39
//-----------------------------------------------------------------------------
 
40
//
 
41
//      Conversion between RGBA and YCA data.
 
42
//
 
43
//-----------------------------------------------------------------------------
 
44
 
 
45
#include <ImfRgbaYca.h>
 
46
#include <assert.h>
 
47
#include <algorithm>
 
48
 
 
49
using namespace Imath;
 
50
using namespace std;
 
51
 
 
52
namespace Imf {
 
53
namespace RgbaYca {
 
54
 
 
55
 
 
56
V3f
 
57
computeYw (const Chromaticities &cr)
 
58
{
 
59
    M44f m = RGBtoXYZ (cr, 1);
 
60
    return V3f (m[0][1], m[1][1], m[2][1]) / (m[0][1] + m[1][1] + m[2][1]);
 
61
}
 
62
 
 
63
 
 
64
void
 
65
RGBAtoYCA (const V3f &yw,
 
66
       int n,
 
67
       bool aIsValid,
 
68
       const Rgba rgbaIn[/*n*/],
 
69
       Rgba ycaOut[/*n*/])
 
70
{
 
71
    for (int i = 0; i < n; ++i)
 
72
    {
 
73
    Rgba in = rgbaIn[i];
 
74
    Rgba &out = ycaOut[i];
 
75
 
 
76
    //
 
77
    // Conversion to YCA and subsequent chroma subsampling
 
78
    // work only if R, G and B are finite and non-negative.
 
79
    //
 
80
 
 
81
    if (!in.r.isFinite() || in.r < 0)
 
82
        in.r = 0;
 
83
 
 
84
    if (!in.g.isFinite() || in.g < 0)
 
85
        in.g = 0;
 
86
 
 
87
    if (!in.b.isFinite() || in.b < 0)
 
88
        in.b = 0;
 
89
 
 
90
    if (in.r == in.g && in.g == in.b)
 
91
    {
 
92
        //
 
93
        // Special case -- R, G and B are equal. To avoid rounding
 
94
        // errors, we explicitly set the output luminance channel
 
95
        // to G, and the chroma channels to 0.
 
96
        //
 
97
        // The special cases here and in YCAtoRGBA() ensure that
 
98
        // converting black-and white images from RGBA to YCA and
 
99
        // back is lossless.
 
100
        //
 
101
 
 
102
        out.r = 0;
 
103
        out.g = in.g;
 
104
        out.b = 0;
 
105
    }
 
106
    else
 
107
    {
 
108
        out.g = in.r * yw.x + in.g * yw.y + in.b * yw.z;
 
109
 
 
110
        float Y = out.g;
 
111
 
 
112
        if (abs (in.r - Y) < HALF_MAX * Y)
 
113
        out.r = (in.r - Y) / Y;
 
114
        else
 
115
        out.r = 0;
 
116
 
 
117
        if (abs (in.b - Y) < HALF_MAX * Y)
 
118
        out.b = (in.b - Y) / Y;
 
119
        else
 
120
        out.b = 0;
 
121
    }
 
122
 
 
123
    if (aIsValid)
 
124
        out.a = in.a;
 
125
    else
 
126
        out.a = 1;
 
127
    }
 
128
}
 
129
 
 
130
 
 
131
void
 
132
decimateChromaHoriz (int n,
 
133
             const Rgba ycaIn[/*n+N-1*/],
 
134
             Rgba ycaOut[/*n*/])
 
135
{
 
136
    #ifdef DEBUG
 
137
    assert (ycaIn != ycaOut);
 
138
    #endif
 
139
 
 
140
    int begin = N2;
 
141
    int end = begin + n;
 
142
 
 
143
    for (int i = begin, j = 0; i < end; ++i, ++j)
 
144
    {
 
145
    if ((j & 1) == 0)
 
146
    {
 
147
        ycaOut[j].r = ycaIn[i - 13].r *  0.001064f +
 
148
              ycaIn[i - 11].r * -0.003771f +
 
149
              ycaIn[i -  9].r *  0.009801f +
 
150
              ycaIn[i -  7].r * -0.021586f +
 
151
              ycaIn[i -  5].r *  0.043978f +
 
152
              ycaIn[i -  3].r * -0.093067f +
 
153
              ycaIn[i -  1].r *  0.313659f +
 
154
              ycaIn[i     ].r *  0.499846f +
 
155
              ycaIn[i +  1].r *  0.313659f +
 
156
              ycaIn[i +  3].r * -0.093067f +
 
157
              ycaIn[i +  5].r *  0.043978f +
 
158
              ycaIn[i +  7].r * -0.021586f +
 
159
              ycaIn[i +  9].r *  0.009801f +
 
160
              ycaIn[i + 11].r * -0.003771f +
 
161
              ycaIn[i + 13].r *  0.001064f;
 
162
 
 
163
        ycaOut[j].b = ycaIn[i - 13].b *  0.001064f +
 
164
              ycaIn[i - 11].b * -0.003771f +
 
165
              ycaIn[i -  9].b *  0.009801f +
 
166
              ycaIn[i -  7].b * -0.021586f +
 
167
              ycaIn[i -  5].b *  0.043978f +
 
168
              ycaIn[i -  3].b * -0.093067f +
 
169
              ycaIn[i -  1].b *  0.313659f +
 
170
              ycaIn[i     ].b *  0.499846f +
 
171
              ycaIn[i +  1].b *  0.313659f +
 
172
              ycaIn[i +  3].b * -0.093067f +
 
173
              ycaIn[i +  5].b *  0.043978f +
 
174
              ycaIn[i +  7].b * -0.021586f +
 
175
              ycaIn[i +  9].b *  0.009801f +
 
176
              ycaIn[i + 11].b * -0.003771f +
 
177
              ycaIn[i + 13].b *  0.001064f;
 
178
    }
 
179
 
 
180
    ycaOut[j].g = ycaIn[i].g;
 
181
    ycaOut[j].a = ycaIn[i].a;
 
182
    }
 
183
}
 
184
 
 
185
 
 
186
void
 
187
decimateChromaVert (int n,
 
188
            const Rgba * const ycaIn[N],
 
189
            Rgba ycaOut[/*n*/])
 
190
{
 
191
    for (int i = 0; i < n; ++i)
 
192
    {
 
193
    if ((i & 1) == 0)
 
194
    {
 
195
        ycaOut[i].r = ycaIn[ 0][i].r *  0.001064f +
 
196
              ycaIn[ 2][i].r * -0.003771f +
 
197
              ycaIn[ 4][i].r *  0.009801f +
 
198
              ycaIn[ 6][i].r * -0.021586f +
 
199
              ycaIn[ 8][i].r *  0.043978f +
 
200
              ycaIn[10][i].r * -0.093067f +
 
201
              ycaIn[12][i].r *  0.313659f +
 
202
              ycaIn[13][i].r *  0.499846f +
 
203
              ycaIn[14][i].r *  0.313659f +
 
204
              ycaIn[16][i].r * -0.093067f +
 
205
              ycaIn[18][i].r *  0.043978f +
 
206
              ycaIn[20][i].r * -0.021586f +
 
207
              ycaIn[22][i].r *  0.009801f +
 
208
              ycaIn[24][i].r * -0.003771f +
 
209
              ycaIn[26][i].r *  0.001064f;
 
210
 
 
211
        ycaOut[i].b = ycaIn[ 0][i].b *  0.001064f +
 
212
              ycaIn[ 2][i].b * -0.003771f +
 
213
              ycaIn[ 4][i].b *  0.009801f +
 
214
              ycaIn[ 6][i].b * -0.021586f +
 
215
              ycaIn[ 8][i].b *  0.043978f +
 
216
              ycaIn[10][i].b * -0.093067f +
 
217
              ycaIn[12][i].b *  0.313659f +
 
218
              ycaIn[13][i].b *  0.499846f +
 
219
              ycaIn[14][i].b *  0.313659f +
 
220
              ycaIn[16][i].b * -0.093067f +
 
221
              ycaIn[18][i].b *  0.043978f +
 
222
              ycaIn[20][i].b * -0.021586f +
 
223
              ycaIn[22][i].b *  0.009801f +
 
224
              ycaIn[24][i].b * -0.003771f +
 
225
              ycaIn[26][i].b *  0.001064f;
 
226
    }
 
227
 
 
228
    ycaOut[i].g = ycaIn[13][i].g;
 
229
    ycaOut[i].a = ycaIn[13][i].a;
 
230
    }
 
231
}
 
232
 
 
233
 
 
234
void
 
235
roundYCA (int n,
 
236
      unsigned int roundY,
 
237
      unsigned int roundC,
 
238
      const Rgba ycaIn[/*n*/],
 
239
      Rgba ycaOut[/*n*/])
 
240
{
 
241
    for (int i = 0; i < n; ++i)
 
242
    {
 
243
    ycaOut[i].g = ycaIn[i].g.round (roundY);
 
244
    ycaOut[i].a = ycaIn[i].a;
 
245
 
 
246
    if ((i & 1) == 0)
 
247
    {
 
248
        ycaOut[i].r = ycaIn[i].r.round (roundC);
 
249
        ycaOut[i].b = ycaIn[i].b.round (roundC);
 
250
    }
 
251
    }
 
252
}
 
253
 
 
254
 
 
255
void
 
256
reconstructChromaHoriz (int n,
 
257
            const Rgba ycaIn[/*n+N-1*/],
 
258
            Rgba ycaOut[/*n*/])
 
259
{
 
260
    #ifdef DEBUG
 
261
    assert (ycaIn != ycaOut);
 
262
    #endif
 
263
 
 
264
    int begin = N2;
 
265
    int end = begin + n;
 
266
 
 
267
    for (int i = begin, j = 0; i < end; ++i, ++j)
 
268
    {
 
269
    if (j & 1)
 
270
    {
 
271
        ycaOut[j].r = ycaIn[i - 13].r *  0.002128f +
 
272
              ycaIn[i - 11].r * -0.007540f +
 
273
              ycaIn[i -  9].r *  0.019597f +
 
274
              ycaIn[i -  7].r * -0.043159f +
 
275
              ycaIn[i -  5].r *  0.087929f +
 
276
              ycaIn[i -  3].r * -0.186077f +
 
277
              ycaIn[i -  1].r *  0.627123f +
 
278
              ycaIn[i +  1].r *  0.627123f +
 
279
              ycaIn[i +  3].r * -0.186077f +
 
280
              ycaIn[i +  5].r *  0.087929f +
 
281
              ycaIn[i +  7].r * -0.043159f +
 
282
              ycaIn[i +  9].r *  0.019597f +
 
283
              ycaIn[i + 11].r * -0.007540f +
 
284
              ycaIn[i + 13].r *  0.002128f;
 
285
 
 
286
        ycaOut[j].b = ycaIn[i - 13].b *  0.002128f +
 
287
              ycaIn[i - 11].b * -0.007540f +
 
288
              ycaIn[i -  9].b *  0.019597f +
 
289
              ycaIn[i -  7].b * -0.043159f +
 
290
              ycaIn[i -  5].b *  0.087929f +
 
291
              ycaIn[i -  3].b * -0.186077f +
 
292
              ycaIn[i -  1].b *  0.627123f +
 
293
              ycaIn[i +  1].b *  0.627123f +
 
294
              ycaIn[i +  3].b * -0.186077f +
 
295
              ycaIn[i +  5].b *  0.087929f +
 
296
              ycaIn[i +  7].b * -0.043159f +
 
297
              ycaIn[i +  9].b *  0.019597f +
 
298
              ycaIn[i + 11].b * -0.007540f +
 
299
              ycaIn[i + 13].b *  0.002128f;
 
300
    }
 
301
    else
 
302
    {
 
303
        ycaOut[j].r = ycaIn[i].r;
 
304
        ycaOut[j].b = ycaIn[i].b;
 
305
    }
 
306
 
 
307
    ycaOut[j].g = ycaIn[i].g;
 
308
    ycaOut[j].a = ycaIn[i].a;
 
309
    }
 
310
}
 
311
 
 
312
 
 
313
void
 
314
reconstructChromaVert (int n,
 
315
               const Rgba * const ycaIn[N],
 
316
               Rgba ycaOut[/*n*/])
 
317
{
 
318
    for (int i = 0; i < n; ++i)
 
319
    {
 
320
    ycaOut[i].r = ycaIn[ 0][i].r *  0.002128f +
 
321
              ycaIn[ 2][i].r * -0.007540f +
 
322
              ycaIn[ 4][i].r *  0.019597f +
 
323
              ycaIn[ 6][i].r * -0.043159f +
 
324
              ycaIn[ 8][i].r *  0.087929f +
 
325
              ycaIn[10][i].r * -0.186077f +
 
326
              ycaIn[12][i].r *  0.627123f +
 
327
              ycaIn[14][i].r *  0.627123f +
 
328
              ycaIn[16][i].r * -0.186077f +
 
329
              ycaIn[18][i].r *  0.087929f +
 
330
              ycaIn[20][i].r * -0.043159f +
 
331
              ycaIn[22][i].r *  0.019597f +
 
332
              ycaIn[24][i].r * -0.007540f +
 
333
              ycaIn[26][i].r *  0.002128f;
 
334
 
 
335
    ycaOut[i].b = ycaIn[ 0][i].b *  0.002128f +
 
336
              ycaIn[ 2][i].b * -0.007540f +
 
337
              ycaIn[ 4][i].b *  0.019597f +
 
338
              ycaIn[ 6][i].b * -0.043159f +
 
339
              ycaIn[ 8][i].b *  0.087929f +
 
340
              ycaIn[10][i].b * -0.186077f +
 
341
              ycaIn[12][i].b *  0.627123f +
 
342
              ycaIn[14][i].b *  0.627123f +
 
343
              ycaIn[16][i].b * -0.186077f +
 
344
              ycaIn[18][i].b *  0.087929f +
 
345
              ycaIn[20][i].b * -0.043159f +
 
346
              ycaIn[22][i].b *  0.019597f +
 
347
              ycaIn[24][i].b * -0.007540f +
 
348
              ycaIn[26][i].b *  0.002128f;
 
349
 
 
350
    ycaOut[i].g = ycaIn[13][i].g;
 
351
    ycaOut[i].a = ycaIn[13][i].a;
 
352
    }
 
353
}
 
354
 
 
355
 
 
356
void
 
357
YCAtoRGBA (const Imath::V3f &yw,
 
358
       int n,
 
359
       const Rgba ycaIn[/*n*/],
 
360
       Rgba rgbaOut[/*n*/])
 
361
{
 
362
    for (int i = 0; i < n; ++i)
 
363
    {
 
364
    const Rgba &in = ycaIn[i];
 
365
    Rgba &out = rgbaOut[i];
 
366
 
 
367
    if (in.r == 0 && in.b == 0)
 
368
    {
 
369
        //
 
370
        // Special case -- both chroma channels are 0.  To avoid
 
371
        // rounding errors, we explicitly set the output R, G and B
 
372
        // channels equal to the input luminance.
 
373
        //
 
374
        // The special cases here and in RGBAtoYCA() ensure that
 
375
        // converting black-and white images from RGBA to YCA and
 
376
        // back is lossless.
 
377
        //
 
378
 
 
379
        out.r = in.g;
 
380
        out.g = in.g;
 
381
        out.b = in.g;
 
382
        out.a = in.a;
 
383
    }
 
384
    else
 
385
    {
 
386
        float Y =  in.g;
 
387
        float r = (in.r + 1) * Y;
 
388
        float b = (in.b + 1) * Y;
 
389
        float g = (Y - r * yw.x - b * yw.z) / yw.y;
 
390
 
 
391
        out.r = r;
 
392
        out.g = g;
 
393
        out.b = b;
 
394
        out.a = in.a;
 
395
    }
 
396
    }
 
397
}
 
398
 
 
399
 
 
400
namespace {
 
401
 
 
402
inline float
 
403
saturation (const Rgba &in)
 
404
{
 
405
    float rgbMax = max (in.r, max (in.g, in.b));
 
406
    float rgbMin = min (in.r, min (in.g, in.b));
 
407
 
 
408
    if (rgbMax > 0)
 
409
    return 1 - rgbMin / rgbMax;
 
410
    else
 
411
    return 0;
 
412
}
 
413
 
 
414
 
 
415
void
 
416
desaturate (const Rgba &in, float f, const V3f &yw, Rgba &out)
 
417
{
 
418
    float rgbMax = max (in.r, max (in.g, in.b));
 
419
 
 
420
    out.r = max (float (rgbMax - (rgbMax - in.r) * f), 0.0f);
 
421
    out.g = max (float (rgbMax - (rgbMax - in.g) * f), 0.0f);
 
422
    out.b = max (float (rgbMax - (rgbMax - in.b) * f), 0.0f);
 
423
    out.a = in.a;
 
424
 
 
425
    float Yin  = in.r  * yw.x + in.g  * yw.y + in.b  * yw.z;
 
426
    float Yout = out.r * yw.x + out.g * yw.y + out.b * yw.z;
 
427
 
 
428
    if (Yout > 0)
 
429
    {
 
430
    out.r *= Yin / Yout;
 
431
    out.g *= Yin / Yout;
 
432
    out.b *= Yin / Yout;
 
433
    }
 
434
}
 
435
 
 
436
} // namespace
 
437
 
 
438
 
 
439
void
 
440
fixSaturation (const Imath::V3f &yw,
 
441
           int n,
 
442
           const Rgba * const rgbaIn[3],
 
443
           Rgba rgbaOut[/*n*/])
 
444
{
 
445
    float neighborA2 = saturation (rgbaIn[0][0]);
 
446
    float neighborA1 = neighborA2;
 
447
 
 
448
    float neighborB2 = saturation (rgbaIn[2][0]);
 
449
    float neighborB1 = neighborB2;
 
450
 
 
451
    for (int i = 0; i < n; ++i)
 
452
    {
 
453
    float neighborA0 = neighborA1;
 
454
    neighborA1 = neighborA2;
 
455
 
 
456
    float neighborB0 = neighborB1;
 
457
    neighborB1 = neighborB2;
 
458
 
 
459
    if (i < n - 1)
 
460
    {
 
461
        neighborA2 = saturation (rgbaIn[0][i + 1]);
 
462
        neighborB2 = saturation (rgbaIn[2][i + 1]);
 
463
    }
 
464
 
 
465
    //
 
466
    // A0       A1       A2
 
467
    //      rgbaOut[i]
 
468
    // B0       B1       B2
 
469
    //
 
470
 
 
471
    float sMean = min (1.0f, 0.25f * (neighborA0 + neighborA2 +
 
472
                      neighborB0 + neighborB2));
 
473
 
 
474
    const Rgba &in  = rgbaIn[1][i];
 
475
    Rgba &out = rgbaOut[i];
 
476
 
 
477
    float s = saturation (in);
 
478
 
 
479
    if (s > sMean)
 
480
    {
 
481
        float sMax = min (1.0f, 1 - (1 - sMean) * 0.25f);
 
482
 
 
483
        if (s > sMax)
 
484
        {
 
485
        desaturate (in, sMax / s, yw, out);
 
486
        continue;
 
487
        }
 
488
    }
 
489
 
 
490
    out = in;
 
491
    }
 
492
}
 
493
 
 
494
} // namespace RgbaYca
 
495
} // namespace Imf