Blame IlmImf/dwaLookups.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2009-2014 DreamWorks Animation LLC. 
Packit Service 6754ca
//
Packit Service 6754ca
// All rights reserved.
Packit Service 6754ca
//
Packit Service 6754ca
// Redistribution and use in source and binary forms, with or without
Packit Service 6754ca
// modification, are permitted provided that the following conditions are
Packit Service 6754ca
// met:
Packit Service 6754ca
// *       Redistributions of source code must retain the above copyright
Packit Service 6754ca
// notice, this list of conditions and the following disclaimer.
Packit Service 6754ca
// *       Redistributions in binary form must reproduce the above
Packit Service 6754ca
// copyright notice, this list of conditions and the following disclaimer
Packit Service 6754ca
// in the documentation and/or other materials provided with the
Packit Service 6754ca
// distribution.
Packit Service 6754ca
// *       Neither the name of DreamWorks Animation nor the names of
Packit Service 6754ca
// its contributors may be used to endorse or promote products derived
Packit Service 6754ca
// from this software without specific prior written permission.
Packit Service 6754ca
//
Packit Service 6754ca
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 6754ca
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 6754ca
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 6754ca
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 6754ca
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 6754ca
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 6754ca
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 6754ca
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 6754ca
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 6754ca
//
Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// A program to generate various acceleration lookup tables 
Packit Service 6754ca
// for Imf::DwaCompressor
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
#include <cstddef>
Packit Service 6754ca
#include <stdio.h>
Packit Service 6754ca
#include <stdlib.h>
Packit Service 6754ca
#include <math.h>
Packit Service 6754ca
#include <vector>
Packit Service 6754ca
Packit Service 6754ca
#include <OpenEXRConfig.h>
Packit Service 6754ca
Packit Service 6754ca
#ifdef OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN
Packit Service 6754ca
#include <unistd.h>
Packit Service 6754ca
#endif
Packit Service 6754ca
Packit Service 6754ca
#include <half.h>
Packit Service 6754ca
#include <IlmThread.h>
Packit Service 6754ca
#include <IlmThreadSemaphore.h>
Packit Service 6754ca
#include <ImfIO.h>
Packit Service 6754ca
#include <ImfXdr.h>
Packit Service 6754ca
#include "ImfNamespace.h"
Packit Service 6754ca
Packit Service 6754ca
using namespace OPENEXR_IMF_NAMESPACE;
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
    class LutHeaderWorker
Packit Service 6754ca
    {
Packit Service 6754ca
        public:
Packit Service 6754ca
            class Runner : public IlmThread::Thread
Packit Service 6754ca
            {
Packit Service 6754ca
                public:
Packit Service 6754ca
                    Runner(LutHeaderWorker &worker, bool output):
Packit Service 6754ca
                        IlmThread::Thread(),
Packit Service 6754ca
                        _worker(worker),
Packit Service 6754ca
                        _output(output)
Packit Service 6754ca
                    {
Packit Service 6754ca
                        start();
Packit Service 6754ca
                    }
Packit Service 6754ca
Packit Service 6754ca
                    virtual ~Runner()
Packit Service 6754ca
                    {
Packit Service 6754ca
                        _semaphore.wait();
Packit Service 6754ca
                    }
Packit Service 6754ca
Packit Service 6754ca
                    virtual void run()
Packit Service 6754ca
                    {
Packit Service 6754ca
                        _semaphore.post();
Packit Service 6754ca
                        _worker.run(_output);
Packit Service 6754ca
                    }
Packit Service 6754ca
Packit Service 6754ca
                private:
Packit Service 6754ca
                    LutHeaderWorker     &_worker;
Packit Service 6754ca
                    bool                 _output;
Packit Service 6754ca
                    IlmThread::Semaphore _semaphore;
Packit Service 6754ca
Packit Service 6754ca
            }; // class LutHeaderWorker::Runner
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
            LutHeaderWorker(size_t startValue,
Packit Service 6754ca
                            size_t endValue):
Packit Service 6754ca
                _lastCandidateCount(0),
Packit Service 6754ca
                _startValue(startValue),
Packit Service 6754ca
                _endValue(endValue),
Packit Service 6754ca
                _numElements(0),
Packit Service 6754ca
                _offset(new size_t[numValues()]),
Packit Service 6754ca
                _elements(new unsigned short[1024*1024*2])
Packit Service 6754ca
            {
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            ~LutHeaderWorker()
Packit Service 6754ca
            {
Packit Service 6754ca
                delete[] _offset;
Packit Service 6754ca
                delete[] _elements;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            size_t lastCandidateCount() const
Packit Service 6754ca
            {
Packit Service 6754ca
                return _lastCandidateCount;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            size_t numValues() const 
Packit Service 6754ca
            {
Packit Service 6754ca
                return _endValue - _startValue;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            size_t numElements() const
Packit Service 6754ca
            {
Packit Service 6754ca
                return _numElements;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            const size_t* offset() const
Packit Service 6754ca
            {
Packit Service 6754ca
                return _offset;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            const unsigned short* elements() const
Packit Service 6754ca
            {
Packit Service 6754ca
                return _elements;
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
            void run(bool outputProgress)
Packit Service 6754ca
            {
Packit Service 6754ca
                half candidate[16];
Packit Service 6754ca
                int  candidateCount = 0;
Packit Service 6754ca
Packit Service 6754ca
                for (size_t input=_startValue; input<_endValue; ++input) {
Packit Service 6754ca
Packit Service 6754ca
                    if (outputProgress) {
Packit Service 6754ca
#ifdef __GNUC__
Packit Service 6754ca
                        if (input % 100 == 0) {
Packit Service 6754ca
                            fprintf(stderr, 
Packit Service 6754ca
                            " Building acceleration for DwaCompressor, %.2f %%      %c",
Packit Service 6754ca
                                          100.*(float)input/(float)numValues(), 13);
Packit Service 6754ca
                        }
Packit Service 6754ca
#else
Packit Service 6754ca
                        if (input % 1000 == 0) {
Packit Service 6754ca
                            fprintf(stderr, 
Packit Service 6754ca
                            " Building acceleration for DwaCompressor, %.2f %%\n",
Packit Service 6754ca
                                          100.*(float)input/(float)numValues());
Packit Service 6754ca
                        }
Packit Service 6754ca
#endif
Packit Service 6754ca
                    } 
Packit Service 6754ca
Packit Service 6754ca
                    
Packit Service 6754ca
                    int  numSetBits = countSetBits(input);
Packit Service 6754ca
                    half inputHalf, closestHalf;
Packit Service 6754ca
Packit Service 6754ca
                    inputHalf.setBits(input);
Packit Service 6754ca
Packit Service 6754ca
                    _offset[input - _startValue] = _numElements;
Packit Service 6754ca
Packit Service 6754ca
                    // Gather candidates
Packit Service 6754ca
                    candidateCount = 0;
Packit Service 6754ca
                    for (int targetNumSetBits=numSetBits-1; targetNumSetBits>=0;
Packit Service 6754ca
                                                           --targetNumSetBits) {
Packit Service 6754ca
                        bool valueFound = false;
Packit Service 6754ca
Packit Service 6754ca
                        for (int i=0; i<65536; ++i) {
Packit Service 6754ca
                            if (countSetBits(i) != targetNumSetBits) continue;
Packit Service 6754ca
Packit Service 6754ca
                            if (!valueFound) {
Packit Service 6754ca
                                closestHalf.setBits(i);
Packit Service 6754ca
                                valueFound = true;
Packit Service 6754ca
                            } else {
Packit Service 6754ca
                                half tmpHalf;
Packit Service 6754ca
Packit Service 6754ca
                                tmpHalf.setBits(i);
Packit Service 6754ca
Packit Service 6754ca
                                if (fabs((float)inputHalf - (float)tmpHalf) < 
Packit Service 6754ca
                                    fabs((float)inputHalf - (float)closestHalf)) {
Packit Service 6754ca
                                    closestHalf = tmpHalf;
Packit Service 6754ca
                                }
Packit Service 6754ca
                            }
Packit Service 6754ca
                        }
Packit Service 6754ca
Packit Service 6754ca
                        if (valueFound == false) {
Packit Service 6754ca
                            fprintf(stderr, "bork bork bork!\n");
Packit Service 6754ca
                        }       
Packit Service 6754ca
Packit Service 6754ca
                        candidate[candidateCount] = closestHalf;
Packit Service 6754ca
                        candidateCount++;
Packit Service 6754ca
                    }
Packit Service 6754ca
Packit Service 6754ca
                    // Sort candidates by increasing number of bits set
Packit Service 6754ca
                    for (int i=0; i
Packit Service 6754ca
                        for (int j=i+1; j
Packit Service 6754ca
Packit Service 6754ca
                            int   iCnt = countSetBits(candidate[i].bits());
Packit Service 6754ca
                            int   jCnt = countSetBits(candidate[j].bits());
Packit Service 6754ca
Packit Service 6754ca
                            if (jCnt < iCnt) {
Packit Service 6754ca
                                half tmp     = candidate[i];
Packit Service 6754ca
                                candidate[i] = candidate[j];
Packit Service 6754ca
                                candidate[j] = tmp;
Packit Service 6754ca
                            }
Packit Service 6754ca
                        }
Packit Service 6754ca
                    }
Packit Service 6754ca
Packit Service 6754ca
                    // Copy candidates to the data buffer;
Packit Service 6754ca
                    for (int i=0; i
Packit Service 6754ca
                        _elements[_numElements] = candidate[i].bits();
Packit Service 6754ca
                        _numElements++;
Packit Service 6754ca
                    }
Packit Service 6754ca
Packit Service 6754ca
                    if (input == _endValue-1) {
Packit Service 6754ca
                        _lastCandidateCount = candidateCount;
Packit Service 6754ca
                    }
Packit Service 6754ca
                }
Packit Service 6754ca
            }
Packit Service 6754ca
            
Packit Service 6754ca
Packit Service 6754ca
        private:
Packit Service 6754ca
            size_t          _lastCandidateCount;
Packit Service 6754ca
            size_t          _startValue;
Packit Service 6754ca
            size_t          _endValue;
Packit Service 6754ca
            size_t          _numElements;
Packit Service 6754ca
            size_t         *_offset;
Packit Service 6754ca
            unsigned short *_elements;
Packit Service 6754ca
Packit Service 6754ca
            //
Packit Service 6754ca
            // Precomputing the bit count runs faster than using
Packit Service 6754ca
            // the builtin instruction, at least in one case..
Packit Service 6754ca
            //
Packit Service 6754ca
            // Precomputing 8-bits is no slower than 16-bits,
Packit Service 6754ca
            // and saves a fair bit of overhead..
Packit Service 6754ca
            //
Packit Service 6754ca
            int countSetBits(unsigned short src)
Packit Service 6754ca
            {
Packit Service 6754ca
                static const unsigned short numBitsSet[256] =
Packit Service 6754ca
                {
Packit Service 6754ca
                    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
Packit Service 6754ca
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit Service 6754ca
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit Service 6754ca
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit Service 6754ca
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit Service 6754ca
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit Service 6754ca
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit Service 6754ca
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit Service 6754ca
                    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
Packit Service 6754ca
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit Service 6754ca
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit Service 6754ca
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit Service 6754ca
                    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
Packit Service 6754ca
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit Service 6754ca
                    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
Packit Service 6754ca
                    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
Packit Service 6754ca
                };
Packit Service 6754ca
Packit Service 6754ca
                return numBitsSet[src & 0xff] + numBitsSet[src >> 8];
Packit Service 6754ca
            }
Packit Service 6754ca
Packit Service 6754ca
    }; // class LutHeaderWorker
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// Generate a no-op LUT, to cut down in conditional branches
Packit Service 6754ca
//
Packit Service 6754ca
void
Packit Service 6754ca
generateNoop()
Packit Service 6754ca
{
Packit Service 6754ca
    printf("const unsigned short dwaCompressorNoOp[] = \n");
Packit Service 6754ca
    printf("{");
Packit Service 6754ca
    for (int i=0; i<65536; ++i) {
Packit Service 6754ca
Packit Service 6754ca
        if (i % 8 == 0) {
Packit Service 6754ca
            printf("\n    ");
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        unsigned short dst;
Packit Service 6754ca
        char *tmp = (char *)(&dst);
Packit Service 6754ca
Packit Service 6754ca
        unsigned short src = (unsigned short)i;
Packit Service 6754ca
        Xdr::write <CharPtrIO> (tmp,  src);
Packit Service 6754ca
Packit Service 6754ca
        printf("0x%04x, ", dst);
Packit Service 6754ca
    }
Packit Service 6754ca
    printf("\n};\n");
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// Nonlinearly encode luminance. For values below 1.0, we want
Packit Service 6754ca
// to use a gamma 2.2 function to match what is fairly common
Packit Service 6754ca
// for storing output referred. However, > 1, gamma functions blow up,
Packit Service 6754ca
// and log functions are much better behaved. We could use a log 
Packit Service 6754ca
// function everywhere, but it tends to over-sample dark 
Packit Service 6754ca
// regions and undersample the brighter regions, when 
Packit Service 6754ca
// compared to the way real devices reproduce values.
Packit Service 6754ca
//
Packit Service 6754ca
// So, above 1, use a log function which is a smooth blend
Packit Service 6754ca
// into the gamma function. 
Packit Service 6754ca
//
Packit Service 6754ca
//  Nonlinear(linear) = 
Packit Service 6754ca
//
Packit Service 6754ca
//    linear^(1./2.2)             / linear <= 1.0
Packit Service 6754ca
//                               |
Packit Service 6754ca
//    ln(linear)/ln(e^2.2) + 1    \ otherwise
Packit Service 6754ca
//
Packit Service 6754ca
//
Packit Service 6754ca
// toNonlinear[] needs to take in XDR format half float values,
Packit Service 6754ca
// and output NATIVE format float. 
Packit Service 6754ca
//
Packit Service 6754ca
// toLinear[] does the opposite - takes in NATIVE half and 
Packit Service 6754ca
// outputs XDR half values.
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
generateToLinear()
Packit Service 6754ca
{
Packit Service 6754ca
    unsigned short toLinear[65536];
Packit Service 6754ca
Packit Service 6754ca
    toLinear[0] = 0;
Packit Service 6754ca
Packit Service 6754ca
    for (int i=1; i<65536; ++i) {
Packit Service 6754ca
        half  h;
Packit Service 6754ca
        float sign    = 1;
Packit Service 6754ca
        float logBase = pow(2.7182818, 2.2);
Packit Service 6754ca
Packit Service 6754ca
        // map  NaN and inf to 0
Packit Service 6754ca
        if ((i & 0x7c00) == 0x7c00) {
Packit Service 6754ca
            toLinear[i]    = 0;
Packit Service 6754ca
            continue;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // _toLinear - assume i is NATIVE, but our output needs
Packit Service 6754ca
        //             to get flipped to XDR
Packit Service 6754ca
        //
Packit Service 6754ca
        h.setBits(i);
Packit Service 6754ca
        sign = 1;
Packit Service 6754ca
        if ((float)h < 0) {
Packit Service 6754ca
            sign = -1;
Packit Service 6754ca
        } 
Packit Service 6754ca
Packit Service 6754ca
        if ( fabs( (float)h) <= 1.0 ) {
Packit Service 6754ca
            h  = (half)(sign * pow((float)fabs((float)h), 2.2f));
Packit Service 6754ca
        } else {
Packit Service 6754ca
            h  = (half)(sign * pow(logBase, (float)(fabs((float)h) - 1.0)));
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        {
Packit Service 6754ca
            char *tmp = (char *)(&toLinear[i]);
Packit Service 6754ca
Packit Service 6754ca
            Xdr::write <CharPtrIO> ( tmp,  h.bits());
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
    
Packit Service 6754ca
    printf("const unsigned short dwaCompressorToLinear[] = \n");
Packit Service 6754ca
    printf("{");
Packit Service 6754ca
    for (int i=0; i<65536; ++i) {
Packit Service 6754ca
        if (i % 8 == 0) {
Packit Service 6754ca
            printf("\n    ");
Packit Service 6754ca
        }
Packit Service 6754ca
        printf("0x%04x, ", toLinear[i]);
Packit Service 6754ca
    }
Packit Service 6754ca
    printf("\n};\n");
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
generateToNonlinear()
Packit Service 6754ca
{
Packit Service 6754ca
    unsigned short toNonlinear[65536];
Packit Service 6754ca
Packit Service 6754ca
    toNonlinear[0] = 0;
Packit Service 6754ca
Packit Service 6754ca
    for (int i=1; i<65536; ++i) {
Packit Service 6754ca
        unsigned short usNative, usXdr;
Packit Service 6754ca
        half  h;
Packit Service 6754ca
        float sign    = 1;
Packit Service 6754ca
        float logBase = pow(2.7182818, 2.2);
Packit Service 6754ca
Packit Service 6754ca
        usXdr           = i;
Packit Service 6754ca
Packit Service 6754ca
        {
Packit Service 6754ca
            const char *tmp = (char *)(&usXdr);
Packit Service 6754ca
Packit Service 6754ca
            Xdr::read<CharPtrIO>(tmp, usNative);
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        // map  NaN and inf to 0
Packit Service 6754ca
        if ((usNative & 0x7c00) == 0x7c00) {
Packit Service 6754ca
            toNonlinear[i] = 0;
Packit Service 6754ca
            continue;
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // toNonlinear - assume i is XDR
Packit Service 6754ca
        //
Packit Service 6754ca
        h.setBits(usNative);
Packit Service 6754ca
        sign = 1;
Packit Service 6754ca
        if ((float)h < 0) {
Packit Service 6754ca
            sign = -1;
Packit Service 6754ca
        } 
Packit Service 6754ca
Packit Service 6754ca
        if ( fabs( (float)h ) <= 1.0) {
Packit Service 6754ca
            h = (half)(sign * pow(fabs((float)h), 1.f/2.2f));
Packit Service 6754ca
        } else {
Packit Service 6754ca
            h = (half)(sign * ( log(fabs((float)h)) / log(logBase) + 1.0) );
Packit Service 6754ca
        }
Packit Service 6754ca
        toNonlinear[i] = h.bits();
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    printf("const unsigned short dwaCompressorToNonlinear[] = \n");
Packit Service 6754ca
    printf("{");
Packit Service 6754ca
    for (int i=0; i<65536; ++i) {
Packit Service 6754ca
        if (i % 8 == 0) {
Packit Service 6754ca
            printf("\n    ");
Packit Service 6754ca
        }
Packit Service 6754ca
        printf("0x%04x, ", toNonlinear[i]);
Packit Service 6754ca
    }
Packit Service 6754ca
    printf("\n};\n");
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// Attempt to get available CPUs in a somewhat portable way. 
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
cpuCount()
Packit Service 6754ca
{
Packit Service 6754ca
    if (!IlmThread::supportsThreads()) return 1;
Packit Service 6754ca
Packit Service 6754ca
    int cpuCount = 1;
Packit Service 6754ca
Packit Service 6754ca
#if defined (OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN)
Packit Service 6754ca
Packit Service 6754ca
    cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
Packit Service 6754ca
Packit Service 6754ca
#elif defined (_WIN32)
Packit Service 6754ca
Packit Service 6754ca
    SYSTEM_INFO sysinfo;
Packit Service 6754ca
    GetSystemInfo( &sysinfo );
Packit Service 6754ca
    cpuCount = sysinfo.dwNumberOfProcessors;
Packit Service 6754ca
Packit Service 6754ca
#endif
Packit Service 6754ca
Packit Service 6754ca
    if (cpuCount < 1) cpuCount = 1;
Packit Service 6754ca
    return cpuCount;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
//
Packit Service 6754ca
// Generate acceleration luts for the quantization.
Packit Service 6754ca
//
Packit Service 6754ca
// For each possible input value, we want to find the closest numbers
Packit Service 6754ca
// which have one fewer bits set than before. 
Packit Service 6754ca
//
Packit Service 6754ca
// This gives us num_bits(input)-1 values per input. If we alloc
Packit Service 6754ca
// space for everything, that's like a 2MB table. We can do better
Packit Service 6754ca
// by compressing all the values to be contigious and using offset
Packit Service 6754ca
// pointers.
Packit Service 6754ca
//
Packit Service 6754ca
// After we've found the candidates with fewer bits set, sort them
Packit Service 6754ca
// based on increasing numbers of bits set. This way, on quantize(),
Packit Service 6754ca
// we can scan through the list and halt once we find the first
Packit Service 6754ca
// candidate within the error range. For small values that can 
Packit Service 6754ca
// be quantized to 0, 0 is the first value tested and the search
Packit Service 6754ca
// can exit fairly quickly.
Packit Service 6754ca
//
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
generateLutHeader()
Packit Service 6754ca
{
Packit Service 6754ca
    std::vector<LutHeaderWorker*> workers;
Packit Service 6754ca
Packit Service 6754ca
    size_t numWorkers     = cpuCount();
Packit Service 6754ca
    size_t workerInterval = 65536 / numWorkers;
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i=0; i
Packit Service 6754ca
        if (i != numWorkers-1) {
Packit Service 6754ca
            workers.push_back( new LutHeaderWorker( i   *workerInterval, 
Packit Service 6754ca
                                                   (i+1)*workerInterval) );
Packit Service 6754ca
        } else {
Packit Service 6754ca
            workers.push_back( new LutHeaderWorker(i*workerInterval, 65536) );
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    if (IlmThread::supportsThreads()) {
Packit Service 6754ca
        std::vector<LutHeaderWorker::Runner*> runners;
Packit Service 6754ca
        for (size_t i=0; i
Packit Service 6754ca
            runners.push_back( new LutHeaderWorker::Runner(*workers[i], (i==0)) );
Packit Service 6754ca
        }
Packit Service 6754ca
Packit Service 6754ca
        for (size_t i=0; i
Packit Service 6754ca
            delete runners[i];
Packit Service 6754ca
        }
Packit Service 6754ca
    } else {
Packit Service 6754ca
        for (size_t i=0; i
Packit Service 6754ca
            workers[i]->run(i == 0);
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    printf("static unsigned int closestDataOffset[] = {\n");
Packit Service 6754ca
    int offsetIdx  = 0;
Packit Service 6754ca
    int offsetPrev = 0;
Packit Service 6754ca
    for (size_t i=0; i
Packit Service 6754ca
        for (size_t value=0; value<workers[i]->numValues(); ++value) {
Packit Service 6754ca
            if (offsetIdx % 8 == 0) {
Packit Service 6754ca
                printf("    ");
Packit Service 6754ca
            }
Packit Service 6754ca
            printf("%6lu, ", workers[i]->offset()[value] + offsetPrev);
Packit Service 6754ca
            if (offsetIdx % 8 == 7) {
Packit Service 6754ca
                printf("\n");
Packit Service 6754ca
            }
Packit Service 6754ca
            offsetIdx++;
Packit Service 6754ca
        }
Packit Service 6754ca
        offsetPrev += workers[i]->offset()[workers[i]->numValues()-1] + 
Packit Service 6754ca
                      workers[i]->lastCandidateCount();
Packit Service 6754ca
    }
Packit Service 6754ca
    printf("};\n\n\n");
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    printf("static unsigned short closestData[] = {\n");
Packit Service 6754ca
    int elementIdx = 0;
Packit Service 6754ca
    for (size_t i=0; i
Packit Service 6754ca
        for (size_t element=0; element<workers[i]->numElements(); ++element) {
Packit Service 6754ca
            if (elementIdx % 8 == 0) {
Packit Service 6754ca
                printf("    ");
Packit Service 6754ca
            }
Packit Service 6754ca
            printf("%5d, ", workers[i]->elements()[element]);
Packit Service 6754ca
            if (elementIdx % 8 == 7) {
Packit Service 6754ca
                printf("\n");
Packit Service 6754ca
            }
Packit Service 6754ca
            elementIdx++;
Packit Service 6754ca
        }    
Packit Service 6754ca
    }
Packit Service 6754ca
    printf("};\n\n\n");
Packit Service 6754ca
Packit Service 6754ca
    for (size_t i=0; i
Packit Service 6754ca
        delete workers[i];
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
main(int argc, char **argv)
Packit Service 6754ca
{
Packit Service 6754ca
    printf("#include <cstddef>\n");
Packit Service 6754ca
    printf("\n\n\n");
Packit Service 6754ca
Packit Service 6754ca
    generateNoop();
Packit Service 6754ca
Packit Service 6754ca
    printf("\n\n\n");
Packit Service 6754ca
Packit Service 6754ca
    generateToLinear();
Packit Service 6754ca
Packit Service 6754ca
    printf("\n\n\n");
Packit Service 6754ca
Packit Service 6754ca
    generateToNonlinear();
Packit Service 6754ca
Packit Service 6754ca
    printf("\n\n\n");
Packit Service 6754ca
Packit Service 6754ca
    generateLutHeader();
Packit Service 6754ca
Packit Service 6754ca
    return 0;
Packit Service 6754ca
}