Esempio n. 1
0
 void Processor::Impl::getGpuLut3D(float* lut3d, const GpuShaderDesc & shaderDesc) const
 {
     if(!lut3d) return;
     
     AutoMutex lock(m_resultsCacheMutex);
     
     if(m_lastShaderDesc != shaderDesc.getCacheID())
     {
         m_lastShaderDesc = shaderDesc.getCacheID();
         m_shader = "";
         m_shaderCacheID = "";
         m_lut3D.clear();
         m_lut3DCacheID = "";
     }
     
     int lut3DEdgeLen = shaderDesc.getLut3DEdgeLen();
     int lut3DNumPixels = lut3DEdgeLen*lut3DEdgeLen*lut3DEdgeLen;
     
     // Can we write the entire shader using only shader text?
     // If so, the lut3D is not needed so clear it.
     // This is preferable to identity, as it lets people notice if
     // it's accidentally being used.
     if(m_gpuOpsCpuLatticeProcess.empty())
     {
         memset(lut3d, 0, sizeof(float) * 3 * lut3DNumPixels);
         return;
     }
     
     if(m_lut3D.empty())
     {
         // Allocate 3dlut image, RGBA
         m_lut3D.resize(lut3DNumPixels*4);
         GenerateIdentityLut3D(&m_lut3D[0], lut3DEdgeLen, 4);
         
         // Apply the lattice ops to it
         for(int i=0; i<(int)m_gpuOpsCpuLatticeProcess.size(); ++i)
         {
             m_gpuOpsCpuLatticeProcess[i]->apply(&m_lut3D[0], lut3DNumPixels);
         }
         
         // Convert the RGBA image to an RGB image, in place.
         // Of course, this only works because we're doing it from left to right
         // so old pixels are read before they're written over
         // TODO: is this bad for memory access patterns?
         //       see if this is faster with a 2nd temp float array
         
         for(int i=1; i<lut3DNumPixels; ++i) // skip the 1st pixel, it's ok.
         {
             m_lut3D[3*i+0] = m_lut3D[4*i+0];
             m_lut3D[3*i+1] = m_lut3D[4*i+1];
             m_lut3D[3*i+2] = m_lut3D[4*i+2];
         }
     }
     
     // Copy to the destination
     memcpy(lut3d, &m_lut3D[0], sizeof(float) * 3 * lut3DNumPixels);
 }
Esempio n. 2
0
void Generate(int cubesize, int maxwidth,
              const std::string & outputfile,
              const std::string & configfile,
              const std::string & incolorspace,
              const std::string & outcolorspace)
{
    int width = 0;
    int height = 0;
    int numchannels = 3;
    GetLutImageSize(width, height, cubesize, maxwidth);
    
    std::vector<float> img;
    img.resize(width*height*numchannels, 0);
    
    GenerateIdentityLut3D(&img[0], cubesize, numchannels, LUT3DORDER_FAST_RED);
    
    if(!incolorspace.empty() || !outcolorspace.empty())
    {
        OCIO::ConstConfigRcPtr config = OCIO::Config::Create();
        if(!configfile.empty())
        {
            config = OCIO::Config::CreateFromFile(configfile.c_str());
        }
        else if(getenv("OCIO"))
        {
            config = OCIO::Config::CreateFromEnv();
        }
        else
        {
            std::ostringstream os;
            os << "You must specify an ocio configuration ";
            os << "(either with --config or $OCIO).";
            throw Exception(os.str().c_str());
        }
        
        OCIO::ConstProcessorRcPtr processor = 
            config->getProcessor(incolorspace.c_str(), outcolorspace.c_str());
       
        OCIO::PackedImageDesc imgdesc(&img[0], width, height, 3);
        processor->apply(imgdesc);
    }

    OIIO::ImageOutput* f = OIIO::ImageOutput::create(outputfile);
    if(!f)
    {
        throw Exception( "Could not create output image.");
    }
    
    OIIO::ImageSpec spec(width, height, numchannels, OIIO::TypeDesc::TypeFloat);
    
    // TODO: If DPX, force 16-bit output?
    f->open(outputfile, spec);
    f->write_image(OIIO::TypeDesc::FLOAT, &img[0]);
    f->close();
    delete f;
}
 void LocalFileFormat::Write(const Baker & baker,
                             const std::string & formatName,
                             std::ostream & ostream) const
 {
     
     static const int DEFAULT_CUBE_SIZE = 32;
     
     if(formatName != "iridas_cube")
     {
         std::ostringstream os;
         os << "Unknown cube format name, '";
         os << formatName << "'.";
         throw Exception(os.str().c_str());
     }
     
     ConstConfigRcPtr config = baker.getConfig();
     
     int cubeSize = baker.getCubeSize();
     if(cubeSize==-1) cubeSize = DEFAULT_CUBE_SIZE;
     cubeSize = std::max(2, cubeSize); // smallest cube is 2x2x2
     
     std::vector<float> cubeData;
     cubeData.resize(cubeSize*cubeSize*cubeSize*3);
     GenerateIdentityLut3D(&cubeData[0], cubeSize, 3, LUT3DORDER_FAST_RED);
     PackedImageDesc cubeImg(&cubeData[0], cubeSize*cubeSize*cubeSize, 1, 3);
     
     // Apply our conversion from the input space to the output space.
     ConstProcessorRcPtr inputToTarget;
     std::string looks = baker.getLooks();
     if(!looks.empty())
     {
         LookTransformRcPtr transform = LookTransform::Create();
         transform->setLooks(looks.c_str());
         transform->setSrc(baker.getInputSpace());
         transform->setDst(baker.getTargetSpace());
         inputToTarget = config->getProcessor(transform, TRANSFORM_DIR_FORWARD);
     }
     else
     {
         inputToTarget = config->getProcessor(baker.getInputSpace(), baker.getTargetSpace());
     }
     inputToTarget->apply(cubeImg);
     
     if(baker.getMetadata() != NULL)
     {
         std::string metadata = baker.getMetadata();
         std::vector<std::string> metadatavec;
         pystring::split(pystring::strip(metadata), metadatavec, "\n");
         if(metadatavec.size() > 0)
         {
             for(size_t i = 0; i < metadatavec.size(); ++i)
             {
                 ostream << "# " << metadatavec[i] << "\n";
             }
             ostream << "\n";
         }
     }
     ostream << "LUT_3D_SIZE " << cubeSize << "\n";
     if(cubeSize < 2)
     {
         throw Exception("Internal cube size exception");
     }
     
     // Set to a fixed 6 decimal precision
     ostream.setf(std::ios::fixed, std::ios::floatfield);
     ostream.precision(6);
     for(int i=0; i<cubeSize*cubeSize*cubeSize; ++i)
     {
         ostream << cubeData[3*i+0] << " "
                 << cubeData[3*i+1] << " "
                 << cubeData[3*i+2] << "\n";
     }
 }