def create_testcharts(overwrite=False): min_bcc_steps, max_bcc_steps = 7, 11 # Profile, amount of dark region emphasis precond = { "eRGBv2": (ICCP.ICCProfile("eciRGB_v2.icc").fileName, 1.0), "aRGB": (config.get_data_path("ref/ClayRGB1998.icm"), 1.6), "Rec709_Gamma22": (config.get_data_path("ref/Rec709_Gamma22.icm"), 1.6), "sRGB": (config.get_data_path("ref/sRGB.icm"), 1.6) } worker = Worker() targen = get_argyll_util("targen") for bcc_steps in xrange(min_bcc_steps, max_bcc_steps + 1): single_channel = bcc_steps * 4 - 3 gray_channel = single_channel * 3 - 2 total = config.get_total_patches(4, 4, single_channel, gray_channel, bcc_steps, bcc_steps, 0) for name, (filename, demphasis) in precond.iteritems(): cwd = os.path.join(root, meta.name, "ti1") outname = "d3-e4-s%i-g%i-m0-f%i-c%s" % (single_channel, gray_channel, total, name) if (not os.path.isfile(os.path.join(cwd, outname + ".ti1")) or overwrite): result = worker.exec_cmd(targen, [ "-v", "-d3", "-e4", "-s%i" % single_channel, "-g%i" % gray_channel, "-m0", "-f%i" % total, "-G", "-c" + filename, "-V%.1f" % demphasis, outname ], working_dir=cwd, sessionlogfile=sys.stdout) if isinstance(result, Exception): print result worker.wrapup(False)
def set_profile_desc_to_basename_sans_ext(profile): if isinstance(profile, basestring): profile = iccp.ICCProfile(profile) if isinstance(profile, iccp.ICCProfile): name = os.path.splitext(os.path.basename(profile.fileName))[0] if isinstance(profile.tags.desc, iccp.TextDescriptionType): profile.tags.desc.ASCII = name.encode('ASCII', 'asciize') profile.tags.desc.Unicode = name profile.tags.desc.Macintosh = name else: profile.tags.desc = iccp.MultiLocalizedUnicodeType() profile.tags.desc.add_localized_string('en', 'US', name) profile.write() else: for item in profile: set_profile_desc_to_basename_sans_ext(item)
def profileinfo(profile): if not isinstance(profile, ICCP.ICCProfile): profile = ICCP.ICCProfile(profile) # Attributes print "Size:", profile.size, "Bytes (%.1f KB)" % (profile.size / 1024.0) print "Preferred CMM:", profile.preferredCMM print "ICC version:", profile.version print "Class:", profile.profileClass print "Colorspace:", profile.colorSpace print "PCS:", profile.connectionColorSpace print "Date/Time:", strftime("%Y-%m-%d %H:%M:%S", profile.dateTime + (0, 0, -1)) print "Platform:", profile.platform print "Embedded:", profile.embedded print "Independent:", profile.independent print "Device:" for key in ("manufacturer", "model"): profile.device[key] = binascii.hexlify(profile.device[key]).upper() prettyprint(profile.device) print "Rendering Intent:", profile.intent print "Illuminant:", " ".join( str(n * 100) for n in profile.illuminant.values()) print "Creator:", profile.creator print "ID:", binascii.hexlify(profile.ID).upper() # Tags print "Description:", profile.getDescription() print "Copyright:", profile.getCopyright() if "dmnd" in profile.tags: print "Device Manufacturer Description:", print profile.getDeviceManufacturerDescription() if "dmdd" in profile.tags: print "Device Model Description:", profile.getDeviceModelDescription() if "vued" in profile.tags: print "Viewing Conditions Description:", print profile.getViewingConditionsDescription() wtpt_profile_norm = tuple(n * 100 for n in profile.tags.wtpt.values()) if "chad" in profile.tags: # undo chromatic adaption of profile whitepoint X, Y, Z = wtpt_profile_norm M = colormath.Matrix3x3(profile.tags.chad).inverted() XR = X * M[0][0] + Y * M[0][1] + Z * M[0][2] YR = X * M[1][0] + Y * M[1][1] + Z * M[1][2] ZR = X * M[2][0] + Y * M[2][1] + Z * M[2][2] wtpt_profile_norm = tuple((n / YR) * 100.0 for n in (XR, YR, ZR)) if "lumi" in profile.tags and isinstance(profile.tags.lumi, ICCP.XYZType): print "Luminance:", profile.tags.lumi.Y print "Actual Whitepoint XYZ:", " ".join(str(n) for n in wtpt_profile_norm) print "Correlated Color Temperature:", colormath.XYZ2CCT( *wtpt_profile_norm)
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from DisplayCAL import ICCProfile as iccp from DisplayCAL.defaultpaths import iccprofiles, iccprofiles_home from DisplayCAL.safe_print import safe_print for p in set(iccprofiles_home + iccprofiles): if os.path.isdir(p): for f in os.listdir(p): try: profile = iccp.ICCProfile(os.path.join(p, f)) except: pass else: if profile.profileClass == "spac": safe_print(f) safe_print("ICC Version:", profile.version) safe_print("Color space:", profile.colorSpace) safe_print("Connection color space:", profile.connectionColorSpace) safe_print("")
def create_rendering_intent_test_profile(filename, add_fallback_matrix=True, generate_B2A_tables=True, swap=False): desc = "Rendering Intent Test Profile" if not add_fallback_matrix: desc += " (cLUT only)" else: desc += " (cLUT + fallback matrix)" srgb = get_rgb_space("sRGB") if swap: rgb_space = list(srgb) rgb_space[2:5] = rgb_space[3], rgb_space[4], rgb_space[2] rgb_space = get_rgb_space(rgb_space) else: rgb_space = srgb clutres = 9 # Minimum 9 because we require f >= 2 f = int(round((clutres - 1) / 4.0)) p = ICCP.create_synthetic_clut_profile(rgb_space, desc, clutres=clutres) tagnames = ["A2B"] if generate_B2A_tables: p.tags.B2A0.clut = [] tagnames.append("B2A") else: del p.tags["B2A0"] for i in xrange(1, 3): for tagname in tagnames: tag0 = p.tags[tagname + "0"] tag = p.tags[tagname + "%i" % i] = ICCP.LUT16Type() for component_name in ("matrix", "input", "clut", "output"): component = getattr(tag0, component_name) if component_name == "clut": component = deepcopy(component) setattr(tag, component_name, component) for i in xrange(3): for tagname in tagnames: tag = p.tags[tagname + "%i" % i] if i == 0: # Perceptual RGB = (f, f, 0) elif i == 1: # Colorimetric RGB = (0, f, f) else: # Saturation RGB = (0, f, 0) block = 0 for R in xrange(clutres): r = min(max(R, f), clutres - 2) b1 = min(max(R, f) + 1, clutres - 2) b2 = min(max(R - 1, f), clutres - 2) for G in xrange(clutres): if tagname == "B2A": tag.clut.append([]) for B in xrange(clutres): if tagname == "B2A": tag.clut[block].append([ v / (clutres - 1.0) * 65535 for v in (R, G, B) ]) # Everything should be good as long as primaries # are sensible (otherwise, when embedded in a PNG, # some programs like Firefox and XnView will ignore # the profile. This doesn't happen when embedded in # JPEG. Go figure...) if (R, G, B) in ( (f, f, 0), (0, f, f), (0, f, 0), # Magenta 64..223 (r, 0, r), (r, 0, b1), (r, 0, b2), # Red 64..223 (r, 0, 0), (r, 0, 1), (r, 1, 0), # CMY 255 (0, clutres - 1, clutres - 1), (clutres - 1, 0, clutres - 1), (clutres - 1, clutres - 1, 0)): if (R, G, B) == (0, clutres - 1, clutres - 1): # Map C -> R if tagname == "B2A": triplet = (65535, 0, 0) else: triplet = RGB2XYZ(1, 0, 0, scale=32768) elif (R, G, B) == (clutres - 1, 0, clutres - 1): # Map M -> G if tagname == "B2A": triplet = (0, 65535, 0) else: triplet = RGB2XYZ(0, 1, 0, scale=32768) elif (R, G, B) == (clutres - 1, clutres - 1, 0): # Map Y -> B if tagname == "B2A": triplet = (0, 0, 65535) else: triplet = RGB2XYZ(0, 0, 1, scale=32768) elif (R, G, B) != RGB: triplet = [0, 0, 0] else: if tagname == "B2A": # White RGB triplet = [65535] * 3 else: # White XYZ D50 triplet = get_whitepoint("D50", 32768) tag.clut[block][B] = triplet block += 1 tag.clut_writepng(filename[:-3] + tagname + "%i.CLUT.png" % i) if tagname == "A2B": tag.clut_writecgats(filename[:-3] + tagname + "%i.CLUT.ti3" % i) if add_fallback_matrix: srgb_icc = ICCP.ICCProfile.from_rgb_space(srgb, "sRGB") p.tags.rTRC = srgb_icc.tags.rTRC p.tags.gTRC = srgb_icc.tags.gTRC p.tags.bTRC = srgb_icc.tags.bTRC if False: # NEVER # Don't really need this...? t = specialpow(1 / 3.0, -2.4) for i, v in enumerate(p.tags.gTRC[1:], 1): v /= 65535.0 p.tags.rTRC[i] = p.tags.gTRC[i] = max( convert_range(v, t, 1, 0, 1), 0) * 65535 p.tags.bTRC[i] = min(convert_range(v, 0, t, 0, 1), 1) * 65535 p.tags.rXYZ = ICCP.XYZType() # Map red to black p.tags.gXYZ = ICCP.XYZType() # Map green to black p.tags.bXYZ = srgb_icc.tags.wtpt.pcs # Map blue to white p.calculateID() p.write(filename)
def update_preset(name): print "Preset name:", name pth = config.get_data_path("presets/%s.icc" % name) if not pth: print "ERROR: Preset not found" return False print "Path:", pth with open( os.path.join(os.path.dirname(__file__), "..", "misc", "ti3", "%s.ti3" % name), "rb") as f: ti3 = f.read() prof = ICCP.ICCProfile(pth) if prof.tags.targ != ti3: print "Updating 'targ'..." prof.tags.targ = ICCP.TextType("text\0\0\0\0%s\0" % ti3, "targ") options_dispcal, options_colprof = worker.get_options_from_profile(prof) trc_a2b = {"240": -240, "709": -709, "l": -3, "s": -2.4} t_a2b = {"t": colormath.CIEDCCT2XYZ, "T": colormath.planckianCT2XYZ} trc = None for option in options_dispcal: if option[0] in ("g", "G"): trc = trc_a2b.get(option[1:]) if not trc: try: trc = float(option[1:]) except ValueError: trc = False print "Invalid dispcal -g parameter:", option[1:] if trc: print "dispcal -%s parameter:" % option[0], option[1:] print "Updating tone response curves..." for chan in ("r", "g", "b"): prof.tags["%sTRC" % chan].set_trc(trc, 256) print "Transfer function:", prof.tags[ "%sTRC" % chan].get_transfer_function()[0][0] elif option[0] in ("t", "T") and option[1:]: print "dispcal -t parameter:", option[1:] print "Updating white point..." (prof.tags.wtpt.X, prof.tags.wtpt.Y, prof.tags.wtpt.Z) = t_a2b[option[0]](float(option[1:])) elif option[0] == "w": print "dispcal -w parameter:", option[1:] x, y = [float(v) for v in option[1:].split(",")] print "Updating white point..." (prof.tags.wtpt.X, prof.tags.wtpt.Y, prof.tags.wtpt.Z) = colormath.xyY2XYZ(x, y) elif option[0] in ("t", "T"): print "Updating white point..." (prof.tags.wtpt.X, prof.tags.wtpt.Y, prof.tags.wtpt.Z) = colormath.get_whitepoint("D65") for option in options_colprof: if option[0] == "M": print "Updating device model description..." prof.setDeviceModelDescription(option[2:].strip('"')) if "CIED" in prof.tags: print "Removing 'CIED'..." del prof.tags["CIED"] if "DevD" in prof.tags: print "Removing 'DevD'..." del prof.tags["DevD"] if "clrt" in prof.tags: print "Removing 'clrt'..." del prof.tags["clrt"] print "Setting RGB matrix column tags to reference values..." prof.tags.rXYZ = ref.tags.rXYZ prof.tags.gXYZ = ref.tags.gXYZ prof.tags.bXYZ = ref.tags.bXYZ print "Updating profile ID..." prof.calculateID() prof.write() print "" return True
#!/usr/bin/env python2 # -*- coding: utf-8 -*- import glob import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from DisplayCAL import ICCProfile as ICCP, colormath, config, worker config.initcfg() srgb = config.get_data_path("ref/sRGB.icm") if not srgb: raise OSError("File not found: ref/sRGB.icm") ref = ICCP.ICCProfile(srgb) print "sRGB:", ref.fileName def update_preset(name): print "Preset name:", name pth = config.get_data_path("presets/%s.icc" % name) if not pth: print "ERROR: Preset not found" return False print "Path:", pth with open( os.path.join(os.path.dirname(__file__), "..", "misc", "ti3", "%s.ti3" % name), "rb") as f: ti3 = f.read() prof = ICCP.ICCProfile(pth)
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from DisplayCAL import ICCProfile as ICCP, xrandr from DisplayCAL.safe_print import safe_print from DisplayCAL.RealDisplaySizeMM import RealDisplaySizeMM as RDSMM for i in xrange(5): # Show ICC info for first five screens / outputs try: x_icc_c = xrandr.get_atom( "_ICC_PROFILE" if i < 1 else "_ICC_PROFILE_%i" % i) except ValueError: x_icc_c = None if x_icc_c: safe_print("Root window %s" % ("_ICC_PROFILE" if i < 1 else "_ICC_PROFILE_%i" % i)) x_icc = ICCP.ICCProfile("".join(chr(n) for n in x_icc_c)) safe_print("Description:", x_icc.getDescription()) safe_print("Checksum ID:", hexlify(x_icc.calculateID())) safe_print("") try: xrr_icc_c = xrandr.get_output_property(i, "_ICC_PROFILE") except ValueError: xrr_icc_c = None if xrr_icc_c: safe_print("XRandR Output %i _ICC_PROFILE:" % i) xrr_icc = ICCP.ICCProfile("".join(chr(n) for n in xrr_icc_c)) safe_print("Description:", xrr_icc.getDescription()) safe_print("Checksum ID:", hexlify(xrr_icc.calculateID())) safe_print("")
def main(icc_profile_filename, target_whitepoint=None, gamma=2.2, skip_cal=False): profile = ICCP.ICCProfile(icc_profile_filename) worker = Worker() if target_whitepoint: intent = "a" else: intent = "r" gamma = float(gamma) num_cal_entries = 4096 cal_entry_max = num_cal_entries - 1.0 ogamma = { -2.4: "sRGB", -3.0: "LStar", -2084: "SMPTE2084", -709: "BT709", -240: "SMPTE240M", -601: "BT601" }.get(gamma, gamma) owtpt = target_whitepoint and ".%s" % target_whitepoint or "" filename, ext = os.path.splitext(icc_profile_filename) # Get existing calibration CGATS from profile existing_cgats = argyll_cgats.extract_cal_from_profile( profile, raise_on_missing_cal=False) # Enabling this will do a linear blend below interpolation threshold, which # is probably not what we want - rather, the original cal should blend into # the linear portion applycal = False applycal_inverse = not filter( lambda tagname: tagname.startswith("A2B") or tagname.startswith("B2A"), profile.tags) print "Use applycal to apply cal?", applycal print "Use applycal to apply inverse cal?", applycal_inverse print "Ensuring 256 entry TRC tags" _applycal_bug_workaround(profile) if (applycal or applycal_inverse) and existing_cgats: print "Writing TMP profile for applycal" profile.write(filename + ".tmp" + ext) if applycal and existing_cgats: # Apply cal existing_cgats.write(filename + ".tmp.cal") result = worker.exec_cmd(get_argyll_util("applycal"), [ "-v", filename + ".tmp.cal", filename + ".tmp" + ext, filename + ".calapplied" + ext ], capture_output=True, log_output=True) if not result and not os.path.isfile(out_filename): raise Exception("applycal returned a non-zero exit code") elif isinstance(result, Exception): raise result calapplied = ICCP.ICCProfile(filename + ".calapplied" + ext) else: calapplied = profile if target_whitepoint: try: target_whitepoint = float(target_whitepoint) except ValueError: pass target_whitepoint = cm.get_whitepoint(target_whitepoint) # target_whitepoint = cm.adapt(*target_whitepoint, # whitepoint_source=profile.tags.wtpt.ir.values()) logfiles = sys.stdout # Lookup scaled down white XYZ logfiles.write("Looking for solution...\n") for n in xrange(9): XYZscaled = [] for i in xrange(2001): XYZscaled.append([ v * (1 - (n * 2001 + i) / 20000.0) for v in target_whitepoint ]) RGBscaled = worker.xicclu(profile, XYZscaled, intent, "if", pcs="x", get_clip=True) # Find point at which it no longer clips XYZwscaled = None for i, RGBclip in enumerate(RGBscaled): if RGBclip[3] is True or max(RGBclip[:3]) > 1: # Clipped, skip continue # Found XYZwscaled = XYZscaled[i] logfiles.write("Solution found at index %i " "(step size %f)\n" % (i, 1 / 2000.0)) logfiles.write("RGB white %6.4f %6.4f %6.4f\n" % tuple(RGBclip[:3])) logfiles.write("XYZ white %6.4f %6.4f %6.4f, " "CCT %.1f K\n" % tuple(XYZscaled[i] + [cm.XYZ2CCT(*XYZwscaled)])) break else: if n == 8: break if XYZwscaled: # Found solution break if not XYZwscaled: raise Exception("No solution found in %i " "iterations with %i steps" % (n, i)) target_whitepoint = XYZwscaled del RGBscaled if not applycal or applycal_inverse: ccal = get_cal(num_cal_entries, target_whitepoint, gamma, profile, intent, "if", slope_limit=0) out_filename = filename + " %s%s" % ( target_whitepoint and "%s " % owtpt[1:] or "", ogamma) + ext if target_whitepoint is False: # NEVER # Apply inverse CAL with PCS white main(icc_profile_filename, gamma=gamma, skip_cal=True) else: # Generate inverse calibration # Apply inverse CAL and write output file if not applycal_inverse: # Use our own code TRC = [] seen = [] for tagname in ("A2B0", "A2B1", "A2B2", "B2A0", "B2A1", "B2A2", "rTRC", "gTRC", "bTRC"): if not tagname in profile.tags: continue print tagname if profile.tags[tagname] in seen: print "Already seen" continue seen.append(profile.tags[tagname]) if tagname.startswith("A2B"): # Apply calibration to input curves cal = get_cal(num_cal_entries, None, gamma, profile, intent, "if") interp_i = get_interp(cal, True) entries = profile.tags[tagname].input elif tagname.startswith("B2A"): # Apply inverse calibration to output curves if profile.tags[tagname].clut_grid_steps <= 9: # Low quality. Skip. print "Low quality, skipping" continue cal = get_cal(num_cal_entries, None, gamma, profile, intent, "b") interp_i = get_interp(cal, True) entries = profile.tags[tagname].output else: entries = profile.tags[tagname] TRC.append(entries[:]) num_entries = len(entries) j = "rgb".index(tagname[0]) cal = get_cal(num_cal_entries, None, gamma, profile, intent, "if", "r") interp_i = get_interp(cal, True) cinterp = cm.Interp([ interp_i[j](i / (num_entries - 1.0)) for i in xrange(num_entries) ], entries, use_numpy=True) entries[:] = [ cinterp(i / (num_entries - 1.0)) for i in xrange(num_entries) ] continue for j in xrange(3): num_entries = len(entries[j]) if tagname.startswith("A2B"): cinterp = cm.Interp([ interp_i[j](i / (num_entries - 1.0)) for i in xrange(num_entries) ], [v / 65535. for v in entries[j]], use_numpy=True) elif tagname.startswith("B2A"): rinterp = cm.Interp([v / 65535. for v in entries[j]], [ i / (num_entries - 1.0) for i in xrange(num_entries) ], use_numpy=True) cinterp = cm.Interp([ rinterp(i / (num_entries - 1.0)) for i in xrange(num_entries) ], [ interp_i[j](i / (num_entries - 1.0)) for i in xrange(num_entries) ], use_numpy=True) entries[j] = [] num_entries = max(num_entries, 256) for i in xrange(num_entries): entries[j].append( min( max( cinterp(i / (num_entries - 1.0)) * 65535, 0), 65535)) # Check for identical initial TRC tags, and force them identical again if TRC and TRC.count(TRC[0]) == 3: print "Forcing identical TRC tags" for channel in "rb": profile.tags[channel + "TRC"] = profile.tags.gTRC elif existing_cgats: # Use Argyll applycal # XXX: Want to derive different cals for cLUT and TRC tags. # Not possible with applycal unless applying cals separately and # combining the profile parts later? # Get inverse calibration interp_i = get_interp(ccal, True) ical = [] # Argyll can only deal with 256 cal entries for i in xrange(256): ical.append([cinterp(i / 255.) for cinterp in interp_i]) # Write inverse CAL icgats = cgats_header for i, (R, G, B) in enumerate(ical): icgats += "%.7f %.7f %.7f %.7f\n" % (i / 255., R, G, B) icgats += "END_DATA\n" ical_filename = icc_profile_filename + owtpt + ".%s.inverse.cal" % ogamma with open(ical_filename, "wb") as f: f.write(icgats) result = worker.exec_cmd( get_argyll_util("applycal"), ["-v", ical_filename, filename + ".tmp" + ext, out_filename], capture_output=True, log_output=True) if not result and not os.path.isfile(out_filename): raise Exception("applycal returned a non-zero exit code") elif isinstance(result, Exception): raise result profile = ICCP.ICCProfile(out_filename) out_profile = profile if not skip_cal: # Improve existing calibration with new calibration if applycal: ccal = get_cal(256, target_whitepoint, gamma, calapplied, intent, "if", slope_limit=0) num_cal_entries = len(ccal) else: if not existing_cgats: existing_cgats = CGATS.CGATS( config.get_data_path("linear.cal")) num_cal_entries = len(existing_cgats[0].DATA) cal_entry_max = num_cal_entries - 1.0 if not applycal: interp = get_interp(ccal, False, True) # Create CAL diff cgats = cgats_header for i in xrange(num_cal_entries): RGB = [cinterp(i / cal_entry_max) for cinterp in interp] R, G, B = (min(max(v, 0), 1) for v in RGB) cgats += "%.7f %.7f %.7f %.7f\n" % (i / cal_entry_max, R, G, B) cgats += "END_DATA\n" with open(icc_profile_filename + owtpt + ".%s.diff.cal" % ogamma, "wb") as f: f.write(cgats) cgats_cal_interp = [] for i in xrange(3): cgats_cal_interp.append( cm.Interp( [v / cal_entry_max for v in xrange(num_cal_entries)], [])) for i, row in existing_cgats[0].DATA.iteritems(): for j, channel in enumerate("RGB"): cgats_cal_interp[j].fp.append(row["RGB_" + channel]) # Create CAL cgats = cgats_header for i in xrange(num_cal_entries): if applycal: RGB = [ccal[i][j] for j in xrange(3)] else: RGB = [ cgats_cal_interp[j](cinterp(i / cal_entry_max)) for j, cinterp in enumerate(interp) ] R, G, B = (min(max(v, 0), 1) for v in RGB) cgats += "%.7f %.7f %.7f %.7f\n" % (i / cal_entry_max, R, G, B) cgats += "END_DATA\n" with open(icc_profile_filename + owtpt + ".%s.cal" % ogamma, "wb") as f: f.write(cgats) # Add CAL as vcgt to profile out_profile.tags.vcgt = argyll_cgats.cal_to_vcgt(cgats) if target_whitepoint: # Update wtpt tag (out_profile.tags.wtpt.X, out_profile.tags.wtpt.Y, out_profile.tags.wtpt.Z) = target_whitepoint # Write updated profile out_profile.setDescription( out_profile.getDescription() + " %s%s" % (target_whitepoint and "%s " % owtpt[1:] or "", ogamma)) out_profile.calculateID() out_profile.write(out_filename)
def main(*args, **kwargs): # Parse arguments cal_only = kwargs.get("--cal-only", CAL_ONLY) state = None xy = None profile = None outfilename = None for i, arg in enumerate(args): if arg == "-t": state = "COLORTEMP_DAYLIGHT" elif arg == "-T": state = "COLORTEMP_BLACKBODY" elif arg.startswith("-t") or arg.startswith("-T") or state in ( "COLORTEMP_DAYLIGHT", "COLORTEMP_BLACKBODY"): if state in ("COLORTEMP_DAYLIGHT", "COLORTEMP_BLACKBODY"): ctstr = arg else: ctstr = arg[2:] try: ct = float(ctstr) except ValueError: raise Invalid("Invalid color temperature %s" % ctstr) if arg.startswith("-t") or state == "COLORTEMP_DAYLIGHT": xy = cm.CIEDCCT2xyY(ct) if not xy: raise Invalid( "Daylight color temperature %i out of range" % ct) else: xy = cm.planckianCT2xyY(ct) if not xy: raise Invalid( "Blackbody color temperature %i out of range" % ct) state = None elif arg == "-w": state = "CHROMATICITY" elif arg.startswith("-w") or state == "CHROMATICITY": if state == "CHROMATICITY": xystr = arg else: xystr = arg[2:] xy = xystr.split(",") if len(xy) != 2: raise Invalid("Invalid chromaticity: %s" % xystr) try: xy = [float(v) for v in xy] except ValueError: raise Invalid("Invalid chromaticity %s" % xystr) state = None elif os.path.isfile(arg) and i < len(args) - 1: safe_print("Reading profile:", arg) profile = ICCP.ICCProfile(arg) else: outfilename = os.path.abspath(arg) if not xy or not outfilename: raise Invalid( "Usage: %s [-t temp | -T temp | -w x,y] [--cal-only] [inprofile] outfilename" % os.path.basename(__file__)) if not profile: safe_print("Reading display profile") profile = ICCP.get_display_profile() # Setup config.initcfg() lang.init() w = worker.Worker() fn = w.change_display_profile_cal_whitepoint args = profile, xy[0], xy[1], outfilename, cal_only, USE_COLLINK # Process if CAL_ONLY: fn(*args) else: app = BaseApp(0) app.TopWindow = wx.Frame(None) w.start(lambda result: app.ExitMainLoop(), fn, wargs=args, progress_msg=lang.getstr("create_profile")) app.MainLoop()
# Tags print "Description:", profile.getDescription() print "Copyright:", profile.getCopyright() if "dmnd" in profile.tags: print "Device Manufacturer Description:", print profile.getDeviceManufacturerDescription() if "dmdd" in profile.tags: print "Device Model Description:", profile.getDeviceModelDescription() if "vued" in profile.tags: print "Viewing Conditions Description:", print profile.getViewingConditionsDescription() wtpt_profile_norm = tuple(n * 100 for n in profile.tags.wtpt.values()) if "chad" in profile.tags: # undo chromatic adaption of profile whitepoint X, Y, Z = wtpt_profile_norm M = colormath.Matrix3x3(profile.tags.chad).inverted() XR = X * M[0][0] + Y * M[0][1] + Z * M[0][2] YR = X * M[1][0] + Y * M[1][1] + Z * M[1][2] ZR = X * M[2][0] + Y * M[2][1] + Z * M[2][2] wtpt_profile_norm = tuple((n / YR) * 100.0 for n in (XR, YR, ZR)) if "lumi" in profile.tags and isinstance(profile.tags.lumi, ICCP.XYZType): print "Luminance:", profile.tags.lumi.Y print "Actual Whitepoint XYZ:", " ".join(str(n) for n in wtpt_profile_norm) print "Correlated Color Temperature:", colormath.XYZ2CCT( *wtpt_profile_norm) if __name__ == "__main__": for arg in sys.argv[1:] or [ICCP.get_display_profile()]: profileinfo(arg)