def setUp(self):
     test_dir = os.path.join(os.path.dirname(__file__), 'test_files')
     self.tmp_dir = os.path.join(tempfile.gettempdir(), 'testCoPipe')
     if not os.path.exists(self.tmp_dir):
         os.mkdir(self.tmp_dir)
     # create OCIO processor
     lut1d = os.path.join(test_dir, 'CineonToLin_1D.csp')
     lut3d = os.path.join(test_dir, 'saturation.3dl')
     self.processor_1d = create_ocio_processor(lut1d,
                                               interpolation=INTERP_LINEAR)
     self.processor_3d = create_ocio_processor(lut3d,
                                               interpolation=INTERP_TETRAHEDRAL)
     self.helpers_1d_to_test = [
         (CUBE_HELPER, '.cube'),
         [SPI_HELPER, '.spi1d'],
         (CSP_HELPER, '.csp'),
         ]
     self.helpers_3d_to_test = [
         (CUBE_HELPER, '.cube', True),
         [SPI_HELPER, '.spi3d', True],
         (CSP_HELPER, '.csp', True),
         (THREEDL_HELPER, '.3dl', True),
         (CLCC_HELPER, '.cc', False),
         (JSON_HELPER, '.json', False)
         ]
Exemple #2
0
def plot_that_lut(lutfile, plot_type=None, count=None, inverse=False,
                  prelutfile=None, postlutfile=None):
    """Plot a lut depending on its type and/or args

    Args:
        lutfile (str): path to a color transformation file (lut, matrix...)

    kwargs:
        plot_type (str): possible values are 'curve' or 'cube'

        count: possible values are curve size or curve samples count or 'auto'

        prelutfile (str): path to a pre LUT

        postlutfile (str): path to a post LUT

    Raises:
        PlotThatLutException
        Exception from OpenColorIO binding

    """
    set_matplotlib_backend()
    # check if LUT format is supported
    fileext = os.path.splitext(lutfile)[1]
    if not fileext:
        raise PlotThatLutException((
            "Error: Couldn't extract extension in this\n"
            "path : {0}"
        ).format(lutfile))
    if fileext not in OCIO_LUTS_FORMATS:
        raise PlotThatLutException("Error: {0} file aren't supported.\n{1}"
                                   .format(fileext, supported_formats()))
    # create OCIO processor
	processor = create_ocio_processor(lutfile, 0, inverse,
                                      prelutfile, postlutfile)
    # init args
    if not plot_type or plot_type == 'auto':
        if is_3d_lut(processor, lutfile):
            plot_type = 'cube'
        else:
            plot_type = 'curve'
    if not count or count == 'auto':
        # set plot_type from the command line and init default count
        if plot_type == 'curve':
            count = DEFAULT_SAMPLE
        else:
            count = DEFAULT_CUBE_SIZE
    # plot
    print "Plotting a {0} with {1} samples...".format(plot_type, count)
    if plot_type == 'curve':
        return plot_curve(lutfile, count, processor)
    elif plot_type == 'cube':
        return plot_cube(lutfile, count, processor)
    else:
        raise PlotThatLutException((
            "Unknown plot type : {0}\n"
            "Plot type should be curve or cube.\n"
        ).format(plot_type))
    def test_float_luts(self):
        """ Test float LUT transparency

        """
        helpers_float_to_test = [(CSP_HELPER, '.csp'),
                                 (SPI_HELPER, '.spi1d')]
        colorspace_to_test = [REC709, SGAMUTSLOG, ALEXALOGCV3]
        delta = 0.00001
        for helper, ext in helpers_float_to_test:
            for colorspace in colorspace_to_test:
                # define file name
                name = colorspace.__class__.__name__
                encode_filename = "linTo{0}_1D{1}".format(name, ext)
                decode_filename = "{0}ToLin_1D{1}".format(name, ext)
                encode_filepath = os.path.join(self.tmp_dir, encode_filename)
                decode_filepath = os.path.join(self.tmp_dir, decode_filename)
                # set preset
                args_1d = CSP_HELPER.get_default_preset()
                args_1d[presets.OUT_BITDEPTH] = 16
                decode_min = colorspace.decode_gradation(0)
                decode_max = colorspace.decode_gradation(1)
                args_1d[presets.IN_RANGE] = get_input_range(colorspace,
                                                            "encode",
                                                            10)
                # write encode LUT
                helper.write_2d_lut(colorspace.encode_gradation,
                                    encode_filepath,
                                    args_1d)
                # write decode LUT
                args_1d[presets.IN_RANGE] = get_input_range(colorspace,
                                                            "decode",
                                                            10)
                helper.write_2d_lut(colorspace.decode_gradation,
                                    decode_filepath,
                                    args_1d)
                # test transparency
                proc = create_ocio_processor(encode_filepath,
                                             postlutfile=decode_filepath,
                                             interpolation=INTERP_LINEAR)
                test_values = [[decode_min] * 3,
                               [decode_max] * 3,
                               [0] * 3,
                               [0.5] * 3,
                               [1] * 3]
                for rgb in test_values:
                    res = proc.applyRGB(rgb)
                    abs_value = abs(rgb[0] - res[0])
                    self.assert_(abs_value < delta,
                                 "{0} transparency test failed : {1:8f} >"
                                 " acceptable delta ({2:8f})".format(name,
                                                                     abs_value,
                                                                     delta)
                                 )
Exemple #4
0
    def test_convert_from_preset(self):
        """Read a preset file and write a LUT

        """
        preset = presets.read_preset(self.sample_preset)
        outlutfile = os.path.join(self.tmp_dir, 'test_preset.cube')
        lut_to_lut(self.lut3d, preset=preset, outlutfile=outlutfile)
        proc = create_ocio_processor(outlutfile, interpolation=INTERP_LINEAR)
        proc.applyRGB([0, 0, 0])
        proc.applyRGB([1, 1, 1])
        if DISPLAY:
            import plot_that_lut
            plot_that_lut.plot_that_lut(outlutfile)
    def test_default_3d_lut(self):
        """ Test a default 3d LUT export

        """
        for helper, ext, ocio_compatible in self.helpers_3d_to_test:
            outlutfile = os.path.join(self.tmp_dir, "default_3D" + ext)
            args_3d = helper.get_default_preset()
            helper.write_3d_lut(self.processor_3d.applyRGB,
                                outlutfile,
                                args_3d)
            if ocio_compatible:
                # create a processor and try it
                proc = create_ocio_processor(outlutfile,
                                             interpolation=INTERP_LINEAR)
                proc.applyRGB([0, 0, 0])
                proc.applyRGB([1, 1, 1])
                if DISPLAY:
                    import plot_that_lut
                    plot_that_lut.plot_that_lut(outlutfile)
    def test_default_1d_lut(self):
        """ Test a default 1d LUT export

        """
        outlutfiles = []
        for helper, ext in self.helpers_1d_to_test:
            outlutfile = os.path.join(self.tmp_dir, "default_1D" + ext)
            args_1d = helper.get_default_preset()
            helper.write_1d_lut(self.processor_1d.applyRGB, outlutfile,
                                args_1d)
            # create a processor and try it
            proc = create_ocio_processor(outlutfile,
                                         interpolation=INTERP_LINEAR)
            proc.applyRGB([0, 0, 0])
            proc.applyRGB([1, 1, 1])
            outlutfiles.append(outlutfile)
        if DISPLAY:
            import plot_that_lut
            plot_that_lut.plot_that_lut(outlutfiles)
def lut_to_lut(inlutfile, outlutfile=None, type='1D_CUBE',
               lutsize=16):
    """Extract the tone mapping curve of a 3D LUT

    Args:
        inlutfile (str): an input 3D LUT

    Kwargs:
        outlutfile (str): the output 1D LUT. If not define, LUT is written in
        the input LUT directory and post-fixed with "_export"

        type (str): specify output LUT format. For now only 2D csp and 2D cube
        are available.

        lutsize (int): out LUT bit precision. Ex : 16 (bits)

    """
    samples_count = pow(2, lutsize)
    if type == '1D_CUBE':
        ext = ".cube"
        write_function = write_2d_cube_lut
    elif type == '1D_CSP':
        ext = ".csp"
        write_function = write_2d_csp_lut
    else:
        raise LutToLutException("Unsupported export format!")
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfile, ext)
    processor = create_ocio_processor(inlutfile)
        # init vars
    max_value = samples_count - 1.0
    red_values = []
    green_values = []
    blue_values = []
    # process color values
    for n in range(0, samples_count):
        x = n/max_value
        res = processor.applyRGB([x, x, x])
        red_values.append(res[0])
        green_values.append(res[1])
        blue_values.append(res[2])
    # write
    write_function(outlutfile, red_values, green_values, blue_values)
Exemple #8
0
def lut_to_lut(inlutfile, outlutfile=None, type='1D_CUBE', lutsize=16):
    """Extract the tone mapping curve of a 3D LUT

    Args:
        inlutfile (str): an input 3D LUT

    Kwargs:
        outlutfile (str): the output 1D LUT. If not define, LUT is written in
        the input LUT directory and post-fixed with "_export"

        type (str): specify output LUT format. For now only 2D csp and 2D cube
        are available.

        lutsize (int): out LUT bit precision. Ex : 16 (bits)

    """
    samples_count = pow(2, lutsize)
    if type == '1D_CUBE':
        ext = ".cube"
        write_function = write_2d_cube_lut
    elif type == '1D_CSP':
        ext = ".csp"
        write_function = write_2d_csp_lut
    else:
        raise LutToLutException("Unsupported export format!")
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfile, ext)
    processor = create_ocio_processor(inlutfile)
    # init vars
    max_value = samples_count - 1.0
    red_values = []
    green_values = []
    blue_values = []
    # process color values
    for n in range(0, samples_count):
        x = n / max_value
        res = processor.applyRGB([x, x, x])
        red_values.append(res[0])
        green_values.append(res[1])
        blue_values.append(res[2])
    # write
    write_function(outlutfile, red_values, green_values, blue_values)
def plot_that_lut(lutfiles,
                  plot_type=None,
                  count=None,
                  inverse=False,
                  prelutfile=None,
                  postlutfile=None,
                  display_markers=False):
    """Plot a lut depending on its type and/or args

    Args:
        lutfiles (str): pathes to color transformation files (lut, matrix...)

    kwargs:
        plot_type (str): possible values are 'curve' or 'cube'

        count: possible values are curve size or curve samples count or 'auto'

        prelutfile (str): path to a pre LUT

        postlutfile (str): path to a post LUT

        display_markers (bool): should display markers on curve

    Raises:
        PlotThatLutException
        Exception from OpenColorIO binding

    """
    if not isinstance(lutfiles, list):
        lutfiles = [lutfiles]
    mplh.set_matplotlib_backend()
    processors = []
    for lutfile in lutfiles:
        # check if LUT format is supported
        fileext = os.path.splitext(lutfile)[1]
        if not fileext:
            raise PlotThatLutException(
                ("Error: Couldn't extract extension in this\n"
                 "path : {0}").format(lutfile))
        if fileext not in OCIO_LUTS_FORMATS:
            raise PlotThatLutException(
                "Error: {0} file aren't supported.\n{1}".format(
                    fileext, supported_formats()))
        # create OCIO processor
        processors.append(
            create_ocio_processor(lutfile, INTERP_LINEAR, inverse, prelutfile,
                                  postlutfile))
    # init args
    if not plot_type or plot_type == 'auto':
        # deduce plot type considering first lutfile
        if is_3d_lut(processors[0], lutfiles[0]):
            plot_type = 'cube'
        else:
            plot_type = 'curve'
    if not count or count == 'auto':
        # set plot_type from the command line and init default count
        if 'curve' in plot_type:
            count = DEFAULT_SAMPLE
        else:
            count = DEFAULT_CUBE_SIZE
    # plot
    print "Plotting a {0} with {1} samples...".format(plot_type, count)
    if 'curve' in plot_type:
        draw_red_curve = True
        draw_green_curve = True
        draw_blue_curve = True
        if 'red' in plot_type:
            #red_curve option
            draw_green_curve = False
            draw_blue_curve = False
        elif 'green' in plot_type:
            #green_curve option
            draw_red_curve = False
            draw_blue_curve = False
        elif 'blue' in plot_type:
            #blue_curve option
            draw_red_curve = False
            draw_green_curve = False
        return plot_curve(lutfiles,
                          count,
                          processors,
                          draw_red_curve=draw_red_curve,
                          draw_green_curve=draw_green_curve,
                          draw_blue_curve=draw_blue_curve,
                          display_markers=display_markers)
    elif plot_type == 'cube':
        # TODO support multiple cubes display
        return plot_cube(lutfiles[0], count, processors[0])
    else:
        raise PlotThatLutException(
            ("Unknown plot type : {0}\n"
             "Plot type should be curve or cube.\n").format(plot_type))
def plot_that_lut(lutfiles, plot_type=None, count=None, inverse=False,
                  prelutfile=None, postlutfile=None, display_markers=False):
    """Plot a lut depending on its type and/or args

    Args:
        lutfiles (str): pathes to color transformation files (lut, matrix...)

    kwargs:
        plot_type (str): possible values are 'curve' or 'cube'

        count: possible values are curve size or curve samples count or 'auto'

        prelutfile (str): path to a pre LUT

        postlutfile (str): path to a post LUT

        display_markers (bool): should display markers on curve

    Raises:
        PlotThatLutException
        Exception from OpenColorIO binding

    """
    if not isinstance(lutfiles, list):
        lutfiles = [lutfiles]
    mplh.set_matplotlib_backend()
    processors = []
    for lutfile in lutfiles:
        # check if LUT format is supported
        fileext = os.path.splitext(lutfile)[1]
        if not fileext:
            raise PlotThatLutException((
                "Error: Couldn't extract extension in this\n"
                "path : {0}"
            ).format(lutfile))
        if fileext not in OCIO_LUTS_FORMATS:
            raise PlotThatLutException("Error: {0} file aren't supported.\n{1}"
                                       .format(fileext, supported_formats()))
        # create OCIO processor
        processors.append(create_ocio_processor(lutfile, INTERP_LINEAR,
                                                inverse, prelutfile,
                                                postlutfile))
    # init args
    if not plot_type or plot_type == 'auto':
        # deduce plot type considering first lutfile
        if is_3d_lut(processors[0], lutfiles[0]):
            plot_type = 'cube'
        else:
            plot_type = 'curve'
    if not count or count == 'auto':
        # set plot_type from the command line and init default count
        if 'curve' in plot_type:
            count = DEFAULT_SAMPLE
        else:
            count = DEFAULT_CUBE_SIZE
    # plot
    print "Plotting a {0} with {1} samples...".format(plot_type, count)
    if 'curve' in plot_type:
        draw_red_curve = True
        draw_green_curve = True
        draw_blue_curve = True
        if 'red' in plot_type:
            #red_curve option
            draw_green_curve = False
            draw_blue_curve = False
        elif 'green' in plot_type:
            #green_curve option
            draw_red_curve = False
            draw_blue_curve = False
        elif 'blue' in plot_type:
            #blue_curve option
            draw_red_curve = False
            draw_green_curve = False
        return plot_curve(lutfiles, count, processors,
                          draw_red_curve=draw_red_curve,
                          draw_green_curve=draw_green_curve,
                          draw_blue_curve=draw_blue_curve,
                          display_markers=display_markers)
    elif plot_type == 'cube':
        # TODO support multiple cubes display
        return plot_cube(lutfiles[0], count, processors[0])
    else:
        raise PlotThatLutException((
            "Unknown plot type : {0}\n"
            "Plot type should be curve or cube.\n"
        ).format(plot_type))
def lut_to_lut(inlutfile,
               outlutfile=None,
               lut_type='1D_CUBE',
               lutsize=16,
               cubesize=17,
               inverse=False):
    """Extract the tone mapping curve of a 3D LUT

    Args:
        inlutfile (str): an input 3D LUT

    Kwargs:
        outlutfile (str): the output 1D LUT. If not define, LUT is written in
        the input LUT directory and post-fixed with "_export"

        lut_type (str): specify output LUT format. For now only 2D/3D csp and
        2D cube are available.

        lutsize (int): out LUT bit precision for 1D. Ex : 16 (bits)

    """
    samples_count = pow(2, lutsize)
    if lut_type == '1D_CUBE':
        ext = ".cube"
        write_function = write_2d_cube_lut
        interp = INTERP_LINEAR
    elif lut_type == '3D_CUBE':
        ext = ".cube"
        write_function = write_3d_cube_lut
        interp = INTERP_TETRAHEDRAL
    elif lut_type == '1D_CSP':
        ext = ".csp"
        write_function = write_2d_csp_lut
        interp = INTERP_LINEAR
    elif lut_type == '3D_JSON':
        ext = ".json"
        write_function = write_3d_json_file
        interp = INTERP_TETRAHEDRAL
    elif lut_type == '3D_CLCC':
        ext = ".cc"
        write_function = write_3d_clcc_lut
        interp = INTERP_TETRAHEDRAL
    else:
        raise LutToLutException("Unsupported export format!")
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfile, ext)
    processor = create_ocio_processor(inlutfile,
                                      interpolation=interp,
                                      inverse=inverse)
    # init vars
    max_value = samples_count - 1.0
    red_values = []
    green_values = []
    blue_values = []
    if "1D" in lut_type:
        # process color values
        for code_value in range(0, samples_count):
            norm_value = code_value / max_value
            res = processor.applyRGB([norm_value, norm_value, norm_value])
            red_values.append(res[0])
            green_values.append(res[1])
            blue_values.append(res[2])
        # write
        write_function(outlutfile, red_values, green_values, blue_values)
    elif "3D" in lut_type:
        # write
        write_function(outlutfile, cubesize, processor)
    print "{0} was converted into {1}.".format(inlutfile, outlutfile)
def lut_to_lut(inlutfiles,
               out_type=None,
               out_format=None,
               outlutfile=None,
               input_range=None,
               output_range=None,
               out_bit_depth=None,
               inverse=False,
               out_cube_size=None,
               verbose=False,
               smooth_size=None,
               preset=None,
               overwrite_preset=False):
    """ Concert a LUT in another LUT
    Arguments testing are delegated to LUT helpers

    Args:
        lutfiles (str or [str]): path to a LUT or list of LUT paths

        out_type (str): 1D, 2D or 3D

        out_format (str): '3dl', 'csp', 'cube', 'lut', 'spi', 'clcc', 'json'...

    Kwargs:
        outlutfile (str): path to output LUT

        input_range ([int/float, int/float]): input range.
        Ex: [0.0, 1.0] or [0, 4095]

        output_range ([int/float, int/float]): output range.
        Ex: [0.0, 1.0] or [0, 4095]

        out_bit_depth (int): output lut bit precision (1D only).
        Ex : 10, 16, 32.

        inverse (bool): inverse input LUT (1D only)

        out_cube_size (int): output cube size (3D only). Ex : 17, 32.

        verbose (bool): print log if true

        smooth_size (int): smooth exported LUT (1D only).
        Specify how many points are computed.
        A first subsampled curve is first processed and then resample with
        a smooth to fit input lutsize.
        So the smaller this value is, the smoother the curve will be.
        Ex: 10, 20,...

        preset (dict): lut generic and sampling informations

    """
    if preset:
        write_function = get_write_function(preset, overwrite_preset, out_type,
                                            out_format, input_range,
                                            output_range, out_bit_depth,
                                            out_cube_size, verbose)
    elif out_type is None or out_format is None:
        raise LutToLutException("Specify out_type/out_format or a preset.")
    else:
        preset, write_function = get_preset_and_write_function(
            out_type, out_format, input_range, output_range, out_bit_depth,
            out_cube_size)
    ext = preset[presets.EXT]
    if not isinstance(inlutfiles, (list, tuple)):
        inlutfiles = [inlutfiles]
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfiles, ext)
    elif os.path.isdir(outlutfile):
        filename = os.path.splitext(ntpath.basename(inlutfiles[0]))[0] + ext
        outlutfile = os.path.join(outlutfile, filename)
    else:
        check_extension(outlutfile, ext)
    # smooth
    if smooth_size:
        preset[presets.SMOOTH] = smooth_size
    if verbose:
        print "{0} will be converted into {1}.".format(inlutfiles, outlutfile)
        print "Final setting:\n{0}".format(presets.string_preset(preset))
    processor = create_ocio_processor(inlutfiles,
                                      interpolation=INTERP_LINEAR,
                                      inverse=inverse)
    # change interpolation if 3D LUT
    if is_3d_lut(processor, inlutfiles[0]):
        processor = create_ocio_processor(inlutfiles,
                                          interpolation=INTERP_TETRAHEDRAL,
                                          inverse=inverse)
    # write LUT
    message = write_function(processor.applyRGB, outlutfile, preset)
    if verbose:
        print_success_message(message)
Exemple #13
0
def lut_to_lut(inlutfiles, out_type=None, out_format=None, outlutfile=None,
               input_range=None, output_range=None, out_bit_depth=None,
               inverse=False, out_cube_size=None, verbose=False,
               smooth_size=None, preset=None, overwrite_preset=False):
    """ Concert a LUT in another LUT
    Arguments testing are delegated to LUT helpers

    Args:
        lutfiles (str or [str]): path to a LUT or list of LUT paths

        out_type (str): 1D, 2D or 3D

        out_format (str): '3dl', 'csp', 'cube', 'lut', 'spi', 'clcc', 'json'...

    Kwargs:
        outlutfile (str): path to output LUT

        input_range ([int/float, int/float]): input range.
        Ex: [0.0, 1.0] or [0, 4095]

        output_range ([int/float, int/float]): output range.
        Ex: [0.0, 1.0] or [0, 4095]

        out_bit_depth (int): output lut bit precision (1D only).
        Ex : 10, 16, 32.

        inverse (bool): inverse input LUT (1D only)

        out_cube_size (int): output cube size (3D only). Ex : 17, 32.

        verbose (bool): print log if true

        smooth_size (int): smooth exported LUT (1D only).
        Specify how many points are computed.
        A first subsampled curve is first processed and then resample with
        a smooth to fit input lutsize.
        So the smaller this value is, the smoother the curve will be.
        Ex: 10, 20,...

        preset (dict): lut generic and sampling informations

    """
    if preset:
        write_function = get_write_function(preset, overwrite_preset,
                                            out_type, out_format,
                                            input_range,
                                            output_range,
                                            out_bit_depth,
                                            out_cube_size,
                                            verbose)
    elif out_type is None or out_format is None:
        raise LutToLutException("Specify out_type/out_format or a preset.")
    else:
        preset, write_function = get_preset_and_write_function(out_type,
                                                               out_format,
                                                               input_range,
                                                               output_range,
                                                               out_bit_depth,
                                                               out_cube_size)
    ext = preset[presets.EXT]
    if not isinstance(inlutfiles, (list, tuple)):
        inlutfiles = [inlutfiles]
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfiles, ext)
    elif os.path.isdir(outlutfile):
        filename = os.path.splitext(ntpath.basename(inlutfiles[0]))[0] + ext
        outlutfile = os.path.join(outlutfile, filename)
    else:
        check_extension(outlutfile, ext)
    # smooth
    if smooth_size:
        preset[presets.SMOOTH] = smooth_size
    if verbose:
        print "{0} will be converted into {1}.".format(inlutfiles,
                                                       outlutfile)
        print "Final setting:\n{0}".format(presets.string_preset(preset))
    processor = create_ocio_processor(inlutfiles,
                                      interpolation=INTERP_LINEAR,
                                      inverse=inverse)
    # change interpolation if 3D LUT
    if is_3d_lut(processor, inlutfiles[0]):
        processor = create_ocio_processor(inlutfiles,
                                          interpolation=INTERP_TETRAHEDRAL,
                                          inverse=inverse)
    # write LUT
    message = write_function(processor.applyRGB, outlutfile, preset)
    if verbose:
        print_success_message(message)
def extract_1d_lut(inlutfile, lutsize, outlutfile=None, smooth=False,
                   smooth_size=17, display=False):
    """Extract the tone mapping curve of a 3D LUT

    Args:
        inlutfile (str): an input 3D LUT

        lutsize (int): out 1D LUT bit precision. Ex : 16 (bits)

    Kwargs:
        outlutfile (str): the output 1D lut. If not define, LUT is written in
        the input LUT directory and post-fixed with "_export"

        smooth (bool): smooth the resulting curve with a bicubic monotonic
        interpolation. See also smooth_size.

        smooth_size (int): only used when smooth is true. Specify how many
        points are sampled using OpenColorIO processor. The result curve is then
        smoothed and resample to fit input lutsize.
        So the smaller this value is, the smoother the curve will be.

    """
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfile, ".csp")
    # create OCIO processor
    processor = create_ocio_processor(inlutfile)
    if not is_3d_lut(processor, inlutfile):
        raise Ext1DLutException("Input lut must be a 3D LUT !")
    # init vars
    if smooth:
        # subsample OCIO processed curve
        count = smooth_size
    else:
        count = pow(2, lutsize)
    max_value = count - 1.0
    red_values = []
    green_values = []
    blue_values = []
    for n in range(0, count):
        x = n/max_value
        res = processor.applyRGB([x, x, x])
        red_values.append(res[0])
        green_values.append(res[1])
        blue_values.append(res[2])
    if smooth:
        # get full range
        xnew = numpy.arange(0, max_value, float(count-1)/(pow(2, lutsize)))
        # get a monotonic cubic function from subsampled curve
        red_cubic_monotonic_func = PchipInterpolator(numpy.arange(0, count),
                                                     red_values)
        green_cubic_monotonic_func = PchipInterpolator(numpy.arange(0, count),
                                                       green_values)
        blue_cubic_monotonic_func = PchipInterpolator(numpy.arange(0, count),
                                                      blue_values)
        # sample on the full range
        reds = red_cubic_monotonic_func(xnew)
        greens = green_cubic_monotonic_func(xnew)
        blues = blue_cubic_monotonic_func(xnew)
    else:
        reds = red_values
        greens = green_values
        blues = blue_values
    write_2d_csp_lut(outlutfile, reds, greens, blues)
    if display:
        try:
        # init plot
            from matplotlib.pyplot import (title, plot, grid,
                                           figure, show)
        except:
            raise Ext1DLutException("Install matplotlib to use display option")

        fig = figure()
        fig.canvas.set_window_title('Plot That 1D LUT')

        title("Compare")
        grid(True)
        # plot curves
        plot(reds, 'r-', label='numpy', linewidth=1)
        plot(greens, 'g-', label='numpy', linewidth=1)
        plot(blues, 'b-', label='numpy', linewidth=1)
        show()
def extract_1d_lut(inlutfile, lutsize, outlutfile=None, smooth=False,
                   smooth_size=17, display=False):
    """Extract the tone mapping curve of a 3D LUT

    Args:
        inlutfile (str): an input 3D LUT

        lutsize (int): out 1D LUT bit precision. Ex : 16 (bits)

    Kwargs:
        outlutfile (str): the output 1D lut. If not define, LUT is written in
        the input LUT directory and post-fixed with "_export"

        smooth (bool): smooth the resulting curve with a bicubic monotonic
        interpolation. See also smooth_size.

        smooth_size (int): only used when smooth is true. Specify how many
        points are sampled using OpenColorIO processor.
        The result curve is then smoothed and resample to fit input lutsize.
        So the smaller this value is, the smoother the curve will be.

    """
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfile, ".csp")
    # create OCIO processor
    processor = create_ocio_processor(inlutfile)
    if not is_3d_lut(processor, inlutfile):
        raise Ext1DLutException("Input lut must be a 3D LUT !")
    # init vars
    if smooth:
        # subsample OCIO processed curve
        count = smooth_size
    else:
        count = pow(2, lutsize)
    max_value = count - 1.0
    red_values = []
    green_values = []
    blue_values = []
    for code_value in range(0, count):
        norm_value = code_value / max_value
        res = processor.applyRGB([norm_value, norm_value, norm_value])
        red_values.append(res[0])
        green_values.append(res[1])
        blue_values.append(res[2])
    if smooth:
        # get full range
        xnew = numpy.arange(0, max_value, float(count - 1) / (pow(2, lutsize)))
        # get a monotonic cubic function from subsampled curve
        red_cubic_monotonic_func = PchipInterpolator(numpy.arange(0, count),
                                                     red_values)
        green_cubic_monotonic_func = PchipInterpolator(numpy.arange(0, count),
                                                       green_values)
        blue_cubic_monotonic_func = PchipInterpolator(numpy.arange(0, count),
                                                      blue_values)
        # sample on the full range
        reds = red_cubic_monotonic_func(xnew)
        greens = green_cubic_monotonic_func(xnew)
        blues = blue_cubic_monotonic_func(xnew)
    else:
        reds = red_values
        greens = green_values
        blues = blue_values
    write_2d_csp_lut(outlutfile, reds, greens, blues)
    if display:
        try:
        # init plot
            from matplotlib.pyplot import (title, plot, grid,
                                           figure, show)
        except:
            raise Ext1DLutException("Install matplotlib to use display option")

        fig = figure()
        fig.canvas.set_window_title('Plot That 1D LUT')

        title("Compare")
        grid(True)
        # plot curves
        plot(reds, 'r-', label='numpy', linewidth=1)
        plot(greens, 'g-', label='numpy', linewidth=1)
        plot(blues, 'b-', label='numpy', linewidth=1)
        show()
def lut_to_lut(inlutfile, outlutfile=None, lut_type='1D_CUBE',
               lutsize=16, cubesize=17, inverse=False):
    """Extract the tone mapping curve of a 3D LUT

    Args:
        inlutfile (str): an input 3D LUT

    Kwargs:
        outlutfile (str): the output 1D LUT. If not define, LUT is written in
        the input LUT directory and post-fixed with "_export"

        lut_type (str): specify output LUT format. For now only 2D/3D csp and
        2D cube are available.

        lutsize (int): out LUT bit precision for 1D. Ex : 16 (bits)

    """
    samples_count = pow(2, lutsize)
    if lut_type == '1D_CUBE':
        ext = ".cube"
        write_function = write_2d_cube_lut
        interp = INTERP_LINEAR
    elif lut_type == '3D_CUBE':
        ext = ".cube"
        write_function = write_3d_cube_lut
        interp = INTERP_TETRAHEDRAL
    elif lut_type == '1D_CSP':
        ext = ".csp"
        write_function = write_2d_csp_lut
        interp = INTERP_LINEAR
    elif lut_type == '3D_JSON':
        ext = ".json"
        write_function = write_3d_json_file
        interp = INTERP_TETRAHEDRAL
    elif lut_type == '3D_CLCC':
        ext = ".cc"
        write_function = write_3d_clcc_lut
        interp = INTERP_TETRAHEDRAL
    else:
        raise LutToLutException("Unsupported export format!")
    if not outlutfile:
        outlutfile = get_default_out_path(inlutfile, ext)
    processor = create_ocio_processor(inlutfile, interpolation=interp,
                                      inverse=inverse)
    # init vars
    max_value = samples_count - 1.0
    red_values = []
    green_values = []
    blue_values = []
    if "1D" in lut_type:
        # process color values
        for code_value in range(0, samples_count):
            norm_value = code_value / max_value
            res = processor.applyRGB([norm_value, norm_value, norm_value])
            red_values.append(res[0])
            green_values.append(res[1])
            blue_values.append(res[2])
        # write
        write_function(outlutfile, red_values, green_values, blue_values)
    elif "3D" in lut_type:
        # write
        write_function(outlutfile, cubesize, processor)
    print "{0} was converted into {1}.".format(inlutfile, outlutfile)