예제 #1
0
void WriteLut3D(const std::string & filename, const float* lutdata, int edgeLen)
{
    if(!pystring::endswith(filename,".spi3d"))
    {
        std::ostringstream os;
        os << "Only .spi3d writing is currently supported. ";
        os << "As a work around, please write a .spi3d file, and then use ";
        os << "ociobakelut for transcoding.";
        throw Exception(os.str().c_str());
    }
    
    std::ofstream output;
    output.open(filename.c_str());
    if(!output.is_open())
    {
        std::ostringstream os;
        os <<  "Error opening " << filename << " for writing.";
        throw Exception(os.str().c_str());
    }
    
    output << "SPILUT 1.0\n";
    output << "3 3\n";
    output << edgeLen << " " << edgeLen << " " << edgeLen << "\n";
    
    int index = 0;
    for(int rindex=0; rindex<edgeLen; ++rindex)
    {
        for(int gindex=0; gindex<edgeLen; ++gindex)
        {
            for(int bindex=0; bindex<edgeLen; ++bindex)
            {
                index = GetLut3DIndex_B(rindex, gindex, bindex,
                                        edgeLen, edgeLen, edgeLen);
                
                output << rindex << " " << gindex << " " << bindex << " ";
                output << lutdata[index+0] << " ";
                output << lutdata[index+1] << " ";
                output << lutdata[index+2] << "\n";
            }
        }
    }
    
    output.close();
}
예제 #2
0
    void Lut3D_Tetrahedral(float* rgbaBuffer, long numPixels, const Lut3D & lut)
    {
        // Tetrahedral interoplation, as described by:
        // http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf
        // http://blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/
        // http://www.hpl.hp.com/techreports/98/HPL-98-95.html

        float maxIndex[3];
        float mInv[3];
        float b[3];
        float mInv_x_maxIndex[3];
        int lutSize[3];
        const float* startPos = &(lut.lut[0]);

        for(int i=0; i<3; ++i)
        {
            maxIndex[i] = (float) (lut.size[i] - 1);
            mInv[i] = 1.0f / (lut.from_max[i] - lut.from_min[i]);
            b[i] = lut.from_min[i];
            mInv_x_maxIndex[i] = (float) (mInv[i] * maxIndex[i]);

            lutSize[i] = lut.size[i];
        }

        for(long pixelIndex=0; pixelIndex<numPixels; ++pixelIndex)
        {

            if(isnan(rgbaBuffer[0]) || isnan(rgbaBuffer[1]) || isnan(rgbaBuffer[2]))
            {
                rgbaBuffer[0] = std::numeric_limits<float>::quiet_NaN();
                rgbaBuffer[1] = std::numeric_limits<float>::quiet_NaN();
                rgbaBuffer[2] = std::numeric_limits<float>::quiet_NaN();
            }
            else
            {
                float localIndex[3];
                int indexLow[3];
                int indexHigh[3];
                float delta[3];

                // Same index/delta calculation as linear interpolation
                localIndex[0] = std::max(std::min(mInv_x_maxIndex[0] * (rgbaBuffer[0] - b[0]), maxIndex[0]), 0.0f);
                localIndex[1] = std::max(std::min(mInv_x_maxIndex[1] * (rgbaBuffer[1] - b[1]), maxIndex[1]), 0.0f);
                localIndex[2] = std::max(std::min(mInv_x_maxIndex[2] * (rgbaBuffer[2] - b[2]), maxIndex[2]), 0.0f);

                indexLow[0] =  static_cast<int>(std::floor(localIndex[0]));
                indexLow[1] =  static_cast<int>(std::floor(localIndex[1]));
                indexLow[2] =  static_cast<int>(std::floor(localIndex[2]));

                indexHigh[0] =  static_cast<int>(std::ceil(localIndex[0]));
                indexHigh[1] =  static_cast<int>(std::ceil(localIndex[1]));
                indexHigh[2] =  static_cast<int>(std::ceil(localIndex[2]));

                delta[0] = localIndex[0] - static_cast<float>(indexLow[0]);
                delta[1] = localIndex[1] - static_cast<float>(indexLow[1]);
                delta[2] = localIndex[2] - static_cast<float>(indexLow[2]);

                // Rebind for consistency with Truelight paper
                float fx = delta[0];
                float fy = delta[1];
                float fz = delta[2];

                // Compute index into LUT for surrounding corners
                const int n000 = GetLut3DIndex_B(indexLow[0], indexLow[1], indexLow[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n100 = GetLut3DIndex_B(indexHigh[0], indexLow[1], indexLow[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n010 = GetLut3DIndex_B(indexLow[0], indexHigh[1], indexLow[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n001 = GetLut3DIndex_B(indexLow[0], indexLow[1], indexHigh[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n110 = GetLut3DIndex_B(indexHigh[0], indexHigh[1], indexLow[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n101 = GetLut3DIndex_B(indexHigh[0], indexLow[1], indexHigh[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n011 = GetLut3DIndex_B(indexLow[0], indexHigh[1], indexHigh[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);
                const int n111 = GetLut3DIndex_B(indexHigh[0], indexHigh[1], indexHigh[2],
                                                 lutSize[0], lutSize[1], lutSize[2]);

                if (fx > fy) {
                    if (fy > fz) {
                       rgbaBuffer[0] =
                           (1-fx)  * startPos[n000] +
                           (fx-fy) * startPos[n100] +
                           (fy-fz) * startPos[n110] +
                           (fz)    * startPos[n111];

                       rgbaBuffer[1] =
                           (1-fx)  * startPos[n000+1] +
                           (fx-fy) * startPos[n100+1] +
                           (fy-fz) * startPos[n110+1] +
                           (fz)    * startPos[n111+1];

                       rgbaBuffer[2] =
                           (1-fx)  * startPos[n000+2] +
                           (fx-fy) * startPos[n100+2] +
                           (fy-fz) * startPos[n110+2] +
                           (fz)    * startPos[n111+2];
                    }
                    else if (fx > fz)
                    {
                        rgbaBuffer[0] =
                            (1-fx)  * startPos[n000] +
                            (fx-fz) * startPos[n100] +
                            (fz-fy) * startPos[n101] +
                            (fy)    * startPos[n111];

                        rgbaBuffer[1] =
                            (1-fx)  * startPos[n000+1] +
                            (fx-fz) * startPos[n100+1] +
                            (fz-fy) * startPos[n101+1] +
                            (fy)    * startPos[n111+1];

                        rgbaBuffer[2] =
                            (1-fx)  * startPos[n000+2] +
                            (fx-fz) * startPos[n100+2] +
                            (fz-fy) * startPos[n101+2] +
                            (fy)    * startPos[n111+2];
                    }
                    else
                    {
                        rgbaBuffer[0] =
                            (1-fz)  * startPos[n000] +
                            (fz-fx) * startPos[n001] +
                            (fx-fy) * startPos[n101] +
                            (fy)    * startPos[n111];

                        rgbaBuffer[1] =
                            (1-fz)  * startPos[n000+1] +
                            (fz-fx) * startPos[n001+1] +
                            (fx-fy) * startPos[n101+1] +
                            (fy)    * startPos[n111+1];

                        rgbaBuffer[2] =
                            (1-fz)  * startPos[n000+2] +
                            (fz-fx) * startPos[n001+2] +
                            (fx-fy) * startPos[n101+2] +
                            (fy)    * startPos[n111+2];
                    }
                }
                else
                {
                    if (fz > fy)
                    {
                        rgbaBuffer[0] =
                            (1-fz)  * startPos[n000] +
                            (fz-fy) * startPos[n001] +
                            (fy-fx) * startPos[n011] +
                            (fx)    * startPos[n111];

                        rgbaBuffer[1] =
                            (1-fz)  * startPos[n000+1] +
                            (fz-fy) * startPos[n001+1] +
                            (fy-fx) * startPos[n011+1] +
                            (fx)    * startPos[n111+1];

                        rgbaBuffer[2] =
                            (1-fz)  * startPos[n000+2] +
                            (fz-fy) * startPos[n001+2] +
                            (fy-fx) * startPos[n011+2] +
                            (fx)    * startPos[n111+2];
                    }
                    else if (fz > fx)
                    {
                        rgbaBuffer[0] =
                            (1-fy)  * startPos[n000] +
                            (fy-fz) * startPos[n010] +
                            (fz-fx) * startPos[n011] +
                            (fx)    * startPos[n111];

                        rgbaBuffer[1] =
                            (1-fy)  * startPos[n000+1] +
                            (fy-fz) * startPos[n010+1] +
                            (fz-fx) * startPos[n011+1] +
                            (fx)    * startPos[n111+1];

                        rgbaBuffer[2] =
                            (1-fy)  * startPos[n000+2] +
                            (fy-fz) * startPos[n010+2] +
                            (fz-fx) * startPos[n011+2] +
                            (fx)    * startPos[n111+2];
                    }
                    else
                    {
                        rgbaBuffer[0] =
                            (1-fy)  * startPos[n000] +
                            (fy-fx) * startPos[n010] +
                            (fx-fz) * startPos[n110] +
                            (fz)    * startPos[n111];

                        rgbaBuffer[1] =
                            (1-fy)  * startPos[n000+1] +
                            (fy-fx) * startPos[n010+1] +
                            (fx-fz) * startPos[n110+1] +
                            (fz)    * startPos[n111+1];

                        rgbaBuffer[2] =
                            (1-fy)  * startPos[n000+2] +
                            (fy-fx) * startPos[n010+2] +
                            (fx-fz) * startPos[n110+2] +
                            (fz)    * startPos[n111+2];
                    }
                }
            } // !isnan
            
            rgbaBuffer += 4;
        }
    }