Beispiel #1
0
ColorProcessor*
ColorConfig::createLookTransform (string_view looks,
                                  string_view inputColorSpace,
                                  string_view outputColorSpace,
                                  bool inverse,
                                  string_view context_key,
                                  string_view context_val) const
{
#ifdef USE_OCIO
    // Ask OCIO to make a Processor that can handle the requested
    // transformation.
    if (getImpl()->config_) {
        OCIO::ConstConfigRcPtr config = getImpl()->config_;
        OCIO::LookTransformRcPtr transform = OCIO::LookTransform::Create();
        transform->setLooks (looks.c_str());
        OCIO::TransformDirection dir;
        if (inverse) {
            // The TRANSFORM_DIR_INVERSE applies an inverse for the
            // end-to-end transform, which would otherwise do dst->inv
            // look -> src.  This is an unintuitive result for the
            // artist (who would expect in, out to remain unchanged), so
            // we account for that here by flipping src/dst
            transform->setSrc (outputColorSpace.c_str());
            transform->setDst (inputColorSpace.c_str());
            dir = OCIO::TRANSFORM_DIR_INVERSE;
        } else { // forward
            transform->setSrc (inputColorSpace.c_str());
            transform->setDst (outputColorSpace.c_str());
            dir = OCIO::TRANSFORM_DIR_FORWARD;
        }
        OCIO::ConstContextRcPtr context = config->getCurrentContext();
        if (context_key.size() && context_val.size()) {
            OCIO::ContextRcPtr ctx = context->createEditableCopy();
            ctx->setStringVar (context_key.c_str(), context_val.c_str());
            context = ctx;
        }

        OCIO::ConstProcessorRcPtr p;
        try {
            // Get the processor corresponding to this transform.
            p = getImpl()->config_->getProcessor (context, transform, dir);
        }
        catch(OCIO::Exception &e) {
            getImpl()->error_ = e.what();
            return NULL;
        }
        catch(...) {
            getImpl()->error_ = "An unknown error occurred in OpenColorIO, getProcessor";
            return NULL;
        }
    
        getImpl()->error_ = "";
        return new ColorProcessor_OCIO(p);
    }
#endif

    return NULL;    // if we get this far, we've failed
}
Beispiel #2
0
int main (int argc, const char* argv[])
{
    
    bool help = false;
    int cubesize = -1;
    int shapersize = -1; // cubsize^2
    std::string format;
    std::string inputconfig;
    std::string inputspace;
    std::string shaperspace;
    std::string looks;
    std::string outputspace;
    bool usestdout = false;
    bool verbose = false;
    
    int whitepointtemp = 6505;
    std::string displayicc;
    std::string description;
    std::string copyright = "No copyright. Use freely.";
    
    // What are the allowed baker output formats?
    std::ostringstream formats;
    formats << "the LUT format to bake: ";
    for(int i=0; i<OCIO::Baker::getNumFormats(); ++i)
    {
        if(i!=0) formats << ", ";
        formats << OCIO::Baker::getFormatNameByIndex(i);
        formats << " (." << OCIO::Baker::getFormatExtensionByIndex(i) << ")";
    }
    formats << ", icc (.icc)";
    
    std::string formatstr = formats.str();
    
    std::string dummystr;
    float dummyf1, dummyf2, dummyf3;
    
    ArgParse ap;
    ap.options("ociobakelut -- create a new LUT or ICC profile from an OCIO config or LUT file(s)\n\n"
               "usage:  ociobakelut [options] <OUTPUTFILE.LUT>\n\n"
               "example:  ociobakelut --inputspace lg10 --outputspace srgb8 --format flame lg_to_srgb.3dl\n"
               "example:  ociobakelut --lut filmlut.3dl --lut calibration.3dl --format flame display.3dl\n"
               "example:  ociobakelut --cccid 0 --lut cdlgrade.ccc --lut calibration.3dl --format flame graded_display.3dl\n"
               "example:  ociobakelut --lut look.3dl --offset 0.01 -0.02 0.03 --lut display.3dl --format flame display_with_look.3dl\n"
               "example:  ociobakelut --inputspace lg10 --outputspace srgb8 --format icc ~/Library/ColorSync/Profiles/test.icc\n"
               "example:  ociobakelut --lut filmlut.3dl --lut calibration.3dl --format icc ~/Library/ColorSync/Profiles/test.icc\n\n",
               "%*", parse_end_args, "",
               "<SEPARATOR>", "Using Existing OCIO Configurations",
               "--inputspace %s", &inputspace, "Input OCIO ColorSpace (or Role)",
               "--outputspace %s", &outputspace, "Output OCIO ColorSpace (or Role)",
               "--shaperspace %s", &shaperspace, "the OCIO ColorSpace or Role, for the shaper",
               "--looks %s", &looks, "the OCIO looks to apply",
               "--iconfig %s", &inputconfig, "Input .ocio configuration file (default: $OCIO)\n",
               "<SEPARATOR>", "Config-Free LUT Baking",
               "<SEPARATOR>", "    (all options can be specified multiple times, each is applied in order)",
               "--cccid %s", &dummystr, "Specify a CCCId for any following LUTs",
               "--lut %s", &dummystr, "Specify a LUT (forward direction)",
               "--invlut %s", &dummystr, "Specify a LUT (inverse direction)",
               "--slope %f %f %f", &dummyf1, &dummyf2, &dummyf3, "slope",
               "--offset %f %f %f", &dummyf1, &dummyf2, &dummyf3, "offset (float)",
               "--offset10 %f %f %f", &dummyf1, &dummyf2, &dummyf3, "offset (10-bit)",
               "--power %f %f %f", &dummyf1, &dummyf2, &dummyf3, "power",
               "--sat %f", &dummyf1, "saturation (ASC-CDL luma coefficients)\n",
               "<SEPARATOR>", "Baking Options",
               "--format %s", &format, formatstr.c_str(),
               "--shapersize %d", &shapersize, "size of the shaper (default: format specific)",
               "--cubesize %d", &cubesize, "size of the cube (default: format specific)",
               "--stdout", &usestdout, "Write to stdout (rather than file)",
               "--v", &verbose, "Verbose",
               "--help", &help, "Print help message\n",
               "<SEPARATOR>", "ICC Options",
               //"--cubesize %d", &cubesize, "size of the ICC CLUT cube (default: 32)",
               "--whitepoint %d", &whitepointtemp, "whitepoint for the profile (default: 6505)",
               "--displayicc %s", &displayicc , "an ICC profile which matches the OCIO profiles target display",
               "--description %s", &description , "a meaningful description, this will show up in UI like photoshop (defaults to \"filename.icc\")",
               "--copyright %s", &copyright , "a copyright field (default: \"No copyright. Use freely.\"\n",
               // TODO: add --metadata option
               NULL);
    
    if (ap.parse(argc, argv) < 0)
    {
        std::cout << ap.geterror() << std::endl;
        ap.usage();
        std::cout << "\n";
        return 1;
    }
    
    if (help || (argc == 1 ))
    {
        ap.usage();
        std::cout << "\n";
        return 1;
    }
    
    // If we're printing to stdout, disable verbose printouts
    if(usestdout)
    {
        verbose = false;
    }
    
    // Create the OCIO processor for the specified transform.
    OCIO::ConstConfigRcPtr config;
    
    
    OCIO::GroupTransformRcPtr groupTransform;
    
    try
    {
        groupTransform = parse_luts(argc, argv);
    }
    catch(const OCIO::Exception & e)
    {
        std::cerr << "\nERROR: " << e.what() << std::endl;
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    catch(...)
    {
        std::cerr << "\nERROR: An unknown error occurred in parse_luts" << std::endl;
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    
    if(!groupTransform)
    {
        std::cerr << "\nERROR: parse_luts returned null transform" << std::endl;
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    
    // If --luts have been specified, synthesize a new (temporary) configuration
    // with the transformation embedded in a colorspace.
    if(!groupTransform->empty())
    {
        if(!inputspace.empty())
        {
            std::cerr << "\nERROR: --inputspace is not allowed when using --lut\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        if(!outputspace.empty())
        {
            std::cerr << "\nERROR: --outputspace is not allowed when using --lut\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        if(!looks.empty())
        {
            std::cerr << "\nERROR: --looks is not allowed when using --lut\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        if(!shaperspace.empty())
        {
            std::cerr << "\nERROR: --shaperspace is not allowed when using --lut\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        
        OCIO::ConfigRcPtr editableConfig = OCIO::Config::Create();
        
        OCIO::ColorSpaceRcPtr inputColorSpace = OCIO::ColorSpace::Create();
        inputspace = "RawInput";
        inputColorSpace->setName(inputspace.c_str());
        editableConfig->addColorSpace(inputColorSpace);
        
        OCIO::ColorSpaceRcPtr outputColorSpace = OCIO::ColorSpace::Create();
        outputspace = "ProcessedOutput";
        outputColorSpace->setName(outputspace.c_str());
        
        outputColorSpace->setTransform(groupTransform,
            OCIO::COLORSPACE_DIR_FROM_REFERENCE);
        
        if(verbose)
        {
            std::cout << "[OpenColorIO DEBUG]: Specified Transform:";
            std::cout << *groupTransform;
            std::cout << "\n";
        }
        
        editableConfig->addColorSpace(outputColorSpace);
        config = editableConfig;
    }
    else
    {
    
        if(inputspace.empty())
        {
            std::cerr << "\nERROR: You must specify the --inputspace.\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        
        if(outputspace.empty())
        {
            std::cerr << "\nERROR: You must specify the --outputspace.\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        
        if(format.empty())
        {
            std::cerr << "\nERROR: You must specify the LUT format using --format.\n\n";
            std::cerr << "See --help for more info." << std::endl;
            return 1;
        }
        
        if(!inputconfig.empty())
        {
            if(!usestdout && verbose)
                std::cout << "[OpenColorIO INFO]: Loading " << inputconfig << std::endl;
            config = OCIO::Config::CreateFromFile(inputconfig.c_str());
        }
        else if(getenv("OCIO"))
        {
            if(!usestdout && verbose)
                std::cout << "[OpenColorIO INFO]: Loading $OCIO " << getenv("OCIO") << std::endl;
            config = OCIO::Config::CreateFromEnv();
        }
        else
        {
            std::cerr << "ERROR: You must specify an input OCIO configuration ";
            std::cerr << "(either with --iconfig or $OCIO).\n\n";
            ap.usage ();
            return 1;
        }
    }
    
    if(outputfile.empty() && !usestdout)
    {
        std::cerr << "\nERROR: You must specify the outputfile or --stdout.\n\n";
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    
    try
    {
        if(format == "icc")
        {
            if(description.empty())
            {
                description = outputfile;
                if(verbose)
                    std::cout << "[OpenColorIO INFO]: \"--description\" set to default value of filename.icc: " << outputfile << "" << std::endl;
            }
            
            if(usestdout)
            {
                std::cerr << "\nERROR: --stdout not supported when writing ICC profiles.\n\n";
                std::cerr << "See --help for more info." << std::endl;
                return 1;
            }
            
            if(outputfile.empty())
            {
                std::cerr << "ERROR: you need to specify a output ICC path\n";
                std::cerr << "See --help for more info." << std::endl;
                return 1;
            }
            
            if(cubesize<2) cubesize = 32; // default

            OCIO::ConstProcessorRcPtr processor;
            if (!looks.empty())
            {
                OCIO::LookTransformRcPtr transform =
                    OCIO::LookTransform::Create();
                transform->setLooks(looks.c_str());
                transform->setSrc(inputspace.c_str());
                transform->setDst(outputspace.c_str());
                processor = config->getProcessor(transform,
                    OCIO::TRANSFORM_DIR_FORWARD);
            }
            else
            {
                processor = config->getProcessor(inputspace.c_str(),
                    outputspace.c_str());
            }
            
            SaveICCProfileToFile(outputfile,
                                 processor,
                                 cubesize,
                                 whitepointtemp,
                                 displayicc,
                                 description,
                                 copyright,
                                 verbose);
        }
        else
        {
        
            OCIO::BakerRcPtr baker = OCIO::Baker::Create();
            
            // setup the baker for our LUT type
            baker->setConfig(config);
            baker->setFormat(format.c_str());
            baker->setInputSpace(inputspace.c_str());
            baker->setShaperSpace(shaperspace.c_str());
            baker->setLooks(looks.c_str());
            baker->setTargetSpace(outputspace.c_str());
            if(shapersize!=-1) baker->setShaperSize(shapersize);
            if(cubesize!=-1) baker->setCubeSize(cubesize);
            
            // output LUT
            std::ostringstream output;
            
            if(!usestdout && verbose)
                std::cout << "[OpenColorIO INFO]: Baking '" << format << "' LUT" << std::endl;
            
            if(usestdout)
            {
                baker->bake(std::cout);
            }
            else
            {
                std::ofstream f(outputfile.c_str());
                baker->bake(f);
                if(verbose)
                    std::cout << "[OpenColorIO INFO]: Wrote '" << outputfile << "'" << std::endl;
            }
        }
    }
    catch(OCIO::Exception & exception)
    {
        std::cerr << "OCIO Error: " << exception.what() << std::endl;
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    catch (std::exception& exception)
    {
        std::cerr << "Error: " << exception.what() << "\n";
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    catch(...)
    {
        std::cerr << "Unknown OCIO error encountered." << std::endl;
        std::cerr << "See --help for more info." << std::endl;
        return 1;
    }
    
    return 0;
}
void OCIOLookTransform::_validate(bool for_real)
{
    if(!m_hasColorSpaces)
    {
        error("No colorspaces available for input and/or output.");
        return;
    }

    int inputColorSpaceCount = static_cast<int>(m_inputColorSpaceCstrNames.size()) - 1;
    if(m_inputColorSpaceIndex < 0 || m_inputColorSpaceIndex >= inputColorSpaceCount)
    {
        std::ostringstream err;
        err << "Input colorspace index (" << m_inputColorSpaceIndex << ") out of range.";
        error(err.str().c_str());
        return;
    }

    int outputColorSpaceCount = static_cast<int>(m_outputColorSpaceCstrNames.size()) - 1;
    if(m_outputColorSpaceIndex < 0 || m_outputColorSpaceIndex >= outputColorSpaceCount)
    {
        std::ostringstream err;
        err << "Output colorspace index (" << m_outputColorSpaceIndex << ") out of range.";
        error(err.str().c_str());
        return;
    }

    try
    {
        OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
        
        const char * inputName = config->getColorSpaceNameByIndex(m_inputColorSpaceIndex);
        const char * outputName = config->getColorSpaceNameByIndex(m_outputColorSpaceIndex);
        
        OCIO::LookTransformRcPtr transform = OCIO::LookTransform::Create();
        const char * look = m_lookCstrNames[m_lookIndex];
        if(look != NULL)
        {
            transform->setLooks(look);
        }
        
        OCIO::ConstContextRcPtr context = getLocalContext();
        OCIO::TransformDirection direction = OCIO::TRANSFORM_DIR_UNKNOWN;
        bool invertTransform = (m_dirIndex == 0) ? false : true;
        
        // Forward
        if(!invertTransform)
        {
            transform->setSrc(inputName);
            transform->setDst(outputName);
            direction = OCIO::TRANSFORM_DIR_FORWARD;
        }
        else
        {
            // The TRANSFORM_DIR_INVERSE applies an inverse for the end-to-end transform,
            // which would otherwise do dst->inv look -> src.
            // This is an unintuitive result for the artist (who would expect in, out to
            // remain unchanged), so we account for that here by flipping src/dst
            
            transform->setSrc(outputName);
            transform->setDst(inputName);
            direction = OCIO::TRANSFORM_DIR_INVERSE;
        }
        
        try
        {
            m_processor = config->getProcessor(context, transform, direction);
        }
        // We only catch the exceptions for missing files, and try to succeed
        // in this case. All other errors represent more serious problems and
        // should fail through.
        catch(const OCIO::ExceptionMissingFile &e)
        {
            if(!m_ignoreErrors) throw;
            m_processor = config->getProcessor(context, inputName, outputName);
        }
    }
    catch(const OCIO::Exception &e)
    {
        error(e.what());
        return;
    }
    catch (...)
    {
        error("OCIOLookTransform: Unknown exception during _validate.");
        return;
    }
    
    if(m_processor->isNoOp())
    {
        set_out_channels(DD::Image::Mask_None); // prevents engine() from being called
    } else {    
        set_out_channels(DD::Image::Mask_All);
    }

    DD::Image::PixelIop::_validate(for_real);
}