Exemple #1
0
    def configure(cls, qscreen=None, colorSpace=-1, workingProfile=None):
        """
        Try to configure color management for the monitor
        specified by QScreen, and build an image transformation
        from the working profile (default sRGB) to the monitor profile.
        This transformation is convenient to match image colors to screen colors.
        @param qscreen: QScreen instance
        @type qscreen: QScreen
        @param colorSpace:
        @type colorSpace
        @param workingProfile:
        @type workingProfile:
        """
        cls.HAS_COLOR_MANAGE = False
        # look for valid profiles
        try:
            # get monitor profile as CmsProfile object.
            if qscreen is not None:
                cls.monitorProfile = cls.getMonitorProfile(qscreen=qscreen)
                if cls.monitorProfile is None:  # not handled by PIL
                    raise ValueError
                # get profile info, a PyCmsError exception is raised if monitorProfile is invalid
                cls.monitorProfileInfo = getProfileInfo(cls.monitorProfile)
            # get working profile as CmsProfile object
            if colorSpace == 1:
                cls.workingProfile = getOpenProfile(SRGB_PROFILE_PATH)
            elif colorSpace == 2:
                cls.workingProfile = getOpenProfile(ADOBE_RGB_PROFILE_PATH)
            elif type(workingProfile) is ImageCmsProfile:
                cls.workingProfile = workingProfile
            else:
                cls.workingProfile = getOpenProfile(
                    SRGB_PROFILE_PATH)  # default

            cls.workingProfileInfo = getProfileInfo(cls.workingProfile)
            # init CmsTransform object : working profile ---> monitor profile
            cls.workToMonTransform = buildTransformFromOpenProfiles(
                cls.workingProfile,
                cls.monitorProfile,
                "RGB",
                "RGB",
                renderingIntent=INTENT_PERCEPTUAL)
            """
                                    INTENT_PERCEPTUAL            = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
                                    INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
                                    INTENT_SATURATION            = 2 (ImageCms.INTENT_SATURATION)
                                    INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
            """
            cls.HAS_COLOR_MANAGE = (cls.monitorProfile is not None) and \
                                   (cls.workingProfile is not None) and (cls.workToMonTransform is not None)
            cls.COLOR_MANAGE = cls.HAS_COLOR_MANAGE and cls.COLOR_MANAGE
        except (OSError, IOError) as e:
            print("I/O error({0}): {1}".format(e.errno, e.strerror))
        except (ValueError, TypeError, PyCMSError):
            pass
        except:
            print("Unexpected error:", sys.exc_info()[0])
            raise
Exemple #2
0
    def __generate_master__(self):
        """
        create a master file from the original already in the package and set all metadata
        """
        # open original
        # capture existing ICC profile (if there is one)
        # if no ICC profile, assign sRGB
        # if ICC profile and != sRGB, convert to sRGB
        # save as uncompressed TIFF

        logger = logging.getLogger(sys._getframe().f_code.co_name)

        profile_srgb2 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'icc',
            'sRGB_IEC61966-2-1_black_scaled.icc')
        profile_srgb4 = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'icc',
            'sRGB_v4_ICC_preference.icc')
        original_path = os.path.join(self.path, self.original)
        original_image = Image.open(original_path)
        try:
            raw_profile = original_image.info['icc_profile']
        except KeyError:
            raw_profile = getOpenProfile(profile_srgb2).tobytes()
            logger.warning(
                '{original} does not have an internal ICC color profile'.
                format(original=self.original))
        else:
            logger.debug(
                'detected internal ICC color profile in {original}'.format(
                    original=self.original))
        original_profile = getOpenProfile(BytesIO(raw_profile))
        original_profile_name = getProfileName(original_profile).strip()
        target_profile = getOpenProfile(profile_srgb4)
        target_profile_name = getProfileName(target_profile).strip()
        logger.debug(
            'attempting to convert from "{original}" to "{target}"'.format(
                original=original_profile_name, target=target_profile_name))
        converted_image = profileToProfile(original_image, original_profile,
                                           target_profile)
        master_path = os.path.join(self.path, 'master.tif')
        tiffinfo = TiffImagePlugin.ImageFileDirectory()
        tiffinfo[TiffImagePlugin.ICCPROFILE] = target_profile.tobytes()
        tiffinfo.tagtype[
            TiffImagePlugin.ICCPROFILE] = 1  # byte according to TiffTags.TYPES
        converted_image.DEBUG = True
        converted_image.save(master_path, tiffinfo=tiffinfo)
        hash_master = hash_of_file(master_path)
        logger.debug('saved converted master image to {master}'.format(
            master=master_path))
        self.__append_event__(
            'created master.tif file at {master}'.format(master=master_path))
        self.manifest.set('master.tif', hash_master)
 def test_master_maker_icc(self):
     srgb = 'IEC 61966-2-1 Default RGB Colour Space - sRGB'
     pp = 'ProPhoto - little cms'
     expected_icc = {
         'cat_drawer.jpf': srgb,
         'cat_drawer.jpg': srgb,
         'cat_drawer.png': srgb,
         'cat_drawer.tif': srgb,
         'cat_drawer_adobe.tif': pp,
         'cat_drawer_posterized.bmp': srgb,
         'cat_drawer_posterized.gif': srgb,
         'cat_drawer_posterized.png': srgb,
         'cat_drawer_posterized.tif': srgb,
         'morning-alley-2010.jpg': srgb
     }
     for fn, im in self.images.items():
         self.logger.debug('icc test handling file {}'.format(fn))
         maker = MasterMaker(im, logging_threshold=logging.DEBUG)
         maker.make()
         master = maker.master
         assert_equal(
             getProfileName(
                 getOpenProfile(
                     BytesIO(master.info['icc_profile']))).strip(),
             expected_icc[fn])
Exemple #4
0
 def B_get_display_profile(handle=None, device_id=None):
     """
     bLUe version of ImageCms get_display_profile.
     @param handle: screen handle (Windows)
     @type handle: int
     @param device_id: name of display
     @type device_id: str
     @return: monitor profile or None
     @rtype: ImageCmsProfile or None
     """
     profile_path = DEFAULT_MONITOR_PROFILE_PATH
     if sys.platform == "win32":
         profile_path = core.get_display_profile_win32(handle, 1)
     elif HAS_GI:
         try:
             from PySide2.QtWidgets import QApplication, QMainWindow
             GIO_CANCELLABLE = Gio.Cancellable.new()
             client = Colord.Client.new()
             client.connect_sync(GIO_CANCELLABLE)
             device = client.find_device_sync('xrandr-' + device_id,
                                              GIO_CANCELLABLE)
             device.connect_sync(GIO_CANCELLABLE)
             default_profile = device.get_default_profile()
             default_profile.connect_sync(GIO_CANCELLABLE)
             profile_path = default_profile.get_filename()
         except (NameError, ImportError, GLib.GError) as e:
             from bLUeTop.QtGui1 import window
             dlgWarn('Cannot detect monitor profile',
                     info=str(e),
                     parent=window)
     try:
         Cms_profile = getOpenProfile(profile_path)
     except PyCMSError:
         Cms_profile = get_default_monitor_profile()
     return Cms_profile
    def test_master_maker_save(self):
        self.logger.debug('test_master_maker_save')
        profile_target_path = abspath(join(
            dirname(realpath(__file__)),
            '..',
            'isaw',
            'awib',
            'icc',
            '{}.icc'.format('ProPhoto')))
        profile_target = getOpenProfile(profile_target_path)
        i = 0
        for fn, im_in in self.images.items():
            i += 1
            self.logger.debug('input filename: "{}"'.format(fn))
            maker = MasterMaker(im_in, logging_threshold=logging.DEBUG)
            master = maker.make()
            name, extension = splitext(fn)
            fn_out = 'test{}.tif'.format(i)
            self.logger.debug('output filename: "{}"'.format(fn_out))
            path_out = join(self.data_dir, 'scratch', fn_out)
            maker.save(path_out)
            continue

            im_out = Image.open(path_out)
            im_out.load()
            try:
                im_out.fp.close()
            except AttributeError:
                pass
            assert_equal(im_out.format, 'TIFF')
            assert_equal(master.mode, im_out.mode)
            stat_im_out = Stat(im_out)
            stat_master = Stat(master)
            assert_equal(stat_im_out.extrema, stat_master.extrema)
            assert_equal(stat_im_out.count, stat_master.count)
            assert_equal(stat_im_out.sum, stat_master.sum)
            assert_equal(stat_im_out.mean, stat_master.mean)
            assert_equal(stat_im_out.median, stat_master.median)
            assert_equal(stat_im_out.rms, stat_master.rms)
            assert_equal(stat_im_out.var, stat_master.var)
            self.logger.debug('info keys: {}'.format(im_out.info.keys()))
            assert_equal(
                getProfileName(
                    getOpenProfile(BytesIO(master.info['icc_profile']))),
                getProfileName(profile_target))
Exemple #6
0
def get_default_monitor_profile():
    """
    try to find a default image profile
    @return: profile or None
    @rtype: ImageCmsProfile or None
    """
    profile = None
    try:
        profile = getOpenProfile(DEFAULT_MONITOR_PROFILE_PATH)
    except PyCMSError:
        pass
    return profile
Exemple #7
0
    def __generate_master__(self):
        """
        create a master file from the original already in the package and set all metadata
        """
        # open original
        # capture existing ICC profile (if there is one)
        # if no ICC profile, assign sRGB
        # if ICC profile and != sRGB, convert to sRGB
        # save as uncompressed TIFF

        logger = logging.getLogger(sys._getframe().f_code.co_name)

        profile_srgb2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icc', 'sRGB_IEC61966-2-1_black_scaled.icc')
        profile_srgb4 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icc', 'sRGB_v4_ICC_preference.icc')
        original_path = os.path.join(self.path, self.original)
        original_image = Image.open(original_path)
        try:
            raw_profile = original_image.info['icc_profile']
        except KeyError:
            raw_profile = getOpenProfile(profile_srgb2).tobytes()
            logger.warning('{original} does not have an internal ICC color profile'.format(original=self.original))
        else:
            logger.debug('detected internal ICC color profile in {original}'.format(original=self.original))
        original_profile = getOpenProfile(BytesIO(raw_profile))
        original_profile_name = getProfileName(original_profile).strip()
        target_profile = getOpenProfile(profile_srgb4)
        target_profile_name = getProfileName(target_profile).strip()
        logger.debug('attempting to convert from "{original}" to "{target}"'.format(original=original_profile_name, target=target_profile_name))
        converted_image = profileToProfile(original_image, original_profile, target_profile)
        master_path = os.path.join(self.path, 'master.tif')
        tiffinfo = TiffImagePlugin.ImageFileDirectory()
        tiffinfo[TiffImagePlugin.ICCPROFILE] = target_profile.tobytes()
        tiffinfo.tagtype[TiffImagePlugin.ICCPROFILE] = 1 # byte according to TiffTags.TYPES
        converted_image.DEBUG=True
        converted_image.save(master_path, tiffinfo=tiffinfo)
        hash_master = hash_of_file(master_path)
        logger.debug('saved converted master image to {master}'.format(master=master_path))
        self.__append_event__('created master.tif file at {master}'.format(master=master_path))
        self.manifest.set('master.tif', hash_master)
Exemple #8
0
def get_default_working_profile():
    """
    try to find a default image profile
    @return: profile
    @rtype: ImageCmsProfile
    """
    try:
        profile = getOpenProfile(SRGB_PROFILE_PATH)
    except PyCMSError:
        dlgWarn(
            'No valid sRGB color profile found.\nSet SYSTEM_PROFILE_DIR and SRGB_PROFILE_NAME in your config.json',
            info='Invalid profile %s' % SRGB_PROFILE_PATH)
        sys.exit()
    return profile
Exemple #9
0
 def _get_original_profile(self):
     try:
         raw_profile = getOpenProfile(
             BytesIO(self.original.info['icc_profile']))
     except KeyError:
         raw_profile = self._get_profile_from_file(
             'sRGB_IEC61966-2-1_black_scaled')
         self.log(
             'Original image does not have an internal ICC color profile.'
             '{} has been assigned.'
             ''.format(getProfileName(raw_profile).strip()))
     else:
         self.log(
             'Detected internal ICC color profile in original image: {}.'
             ''.format(getProfileName(raw_profile).strip()))
     return raw_profile
Exemple #10
0
 def test_profiles(self):
     for fn, im in self.images.items():
         self.logger.debug('{} info includes "{}"'.format(
             fn, im.info.keys()))
         name, extension = splitext(fn)
         if extension[1:] in HAS_PROFILE:
             assert_in('icc_profile', im.info.keys())
             profile = getOpenProfile(BytesIO(im.info['icc_profile']))
             try:
                 expected_profile = ALT_PROFILE[fn]
             except KeyError:
                 expected_profile = (
                     'IEC 61966-2.1 Default RGB colour space - sRGB')
             assert_equal(getProfileName(profile).strip(), expected_profile)
         else:
             assert_not_in('icc_profile', im.info.keys())
Exemple #11
0
 def _get_profile_from_file(self, profile_name):
     fn = join(dirname(realpath(__file__)), 'icc',
               '{}.icc'.format(profile_name))
     return getOpenProfile(fn)
Exemple #12
0
    if sys.platform == 'win32':
        import win32gui
    else:
        # python-gi flag
        HAS_GI = False
        try:
            from gi.repository import GLib, Gio, Colord
            HAS_GI = True
        except ImportError:
            pass
        if not HAS_GI:
            dlgWarn(
                "Automatic detection of monitor profile needs gi installed.\n trying to use %s instead"
                % DEFAULT_MONITOR_PROFILE_PATH)
            try:
                getOpenProfile(DEFAULT_MONITOR_PROFILE_PATH)
            except PyCMSError:
                dlgWarn("Invalid profile %s" % DEFAULT_MONITOR_PROFILE_PATH,
                        info="Color management is disabled")


def get_default_working_profile():
    """
    try to find a default image profile
    @return: profile
    @rtype: ImageCmsProfile
    """
    try:
        profile = getOpenProfile(SRGB_PROFILE_PATH)
    except PyCMSError:
        dlgWarn(