def vcgt_to_cal(profile): """ Return a CAL (CGATS instance) from vcgt """ cgats = CGATS.CGATS(file_identifier="CAL") context = cgats.add_data({"DESCRIPTOR": "Argyll Device Calibration State"}) context.add_data({"ORIGINATOR": "vcgt"}) context.add_data({ "CREATED": strftime("%a %b %d %H:%M:%S %Y", profile.dateTime.timetuple()) }) context.add_keyword("DEVICE_CLASS", "DISPLAY") context.add_keyword("COLOR_REP", "RGB") context.add_keyword("RGB_I") key = "DATA_FORMAT" context[key] = CGATS.CGATS() context[key].key = key context[key].parent = context context[key].root = cgats context[key].type = key context[key].add_data(("RGB_I", "RGB_R", "RGB_G", "RGB_B")) key = "DATA" context[key] = CGATS.CGATS() context[key].key = key context[key].parent = context context[key].root = cgats context[key].type = key values = profile.tags.vcgt.getNormalizedValues() for i, triplet in enumerate(values): context[key].add_data(("%.7f" % (i / float(len(values) - 1)), ) + triplet) return cgats
def can_update_cal(path): """ Check if cal can be updated by checking for required fields. """ try: calstat = os.stat(path) except Exception as exception: safe_print("Warning - os.stat('%s') failed: %s" % tuple(safe_unicode(s) for s in (path, exception))) return False if not path in cals or cals[path].mtime != calstat.st_mtime: try: cal = CGATS.CGATS(path) except (IOError, CGATS.CGATSInvalidError, CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError, CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception: if path in cals: del cals[path] safe_print("Warning - couldn't process CGATS file '%s': %s" % tuple(safe_unicode(s) for s in (path, exception))) else: if cal.queryv1("DEVICE_CLASS") == "DISPLAY" and not None in \ (cal.queryv1("TARGET_WHITE_XYZ"), cal.queryv1("TARGET_GAMMA"), cal.queryv1("BLACK_POINT_CORRECTION"), cal.queryv1("QUALITY")): cals[path] = cal return path in cals and cals[path].mtime == calstat.st_mtime
def add_dispcal_options_to_cal(cal, options_dispcal): # Add dispcal options to cal options_dispcal = quote_nonoption_args(options_dispcal) try: cgats = CGATS.CGATS(cal) cgats[0].add_section( "ARGYLL_DISPCAL_ARGS", " ".join(options_dispcal).encode("UTF-7", "replace")) return cgats except Exception as exception: safe_print(safe_unicode(traceback.format_exc()))
def verify_cgats(cgats, required, ignore_unknown=True): """ Verify and return a CGATS instance or None on failure. Verify if a CGATS instance has a section with all required fields. Return the section as CGATS instance on success, None on failure. If ignore_unknown evaluates to True, ignore fields which are not required. Otherwise, the CGATS data must contain only the required fields, no more, no less. """ cgats_1 = cgats.queryi1(required) if cgats_1 and cgats_1.parent and cgats_1.parent.parent: cgats_1 = cgats_1.parent.parent if cgats_1.queryv1("NUMBER_OF_SETS"): if cgats_1.queryv1("DATA_FORMAT"): for field in required: if not field in list( cgats_1.queryv1("DATA_FORMAT").values()): raise CGATS.CGATSKeyError( "Missing required field: %s" % field) if not ignore_unknown: for field in list(cgats_1.queryv1("DATA_FORMAT").values()): if not field in required: raise CGATS.CGATSError("Unknown field: %s" % field) else: raise CGATS.CGATSInvalidError("Missing DATA_FORMAT") else: raise CGATS.CGATSInvalidError("Missing NUMBER_OF_SETS") modified = cgats_1.modified cgats_1.filename = cgats.filename cgats_1.modified = modified return cgats_1 else: raise CGATS.CGATSKeyError("Missing required fields: %s" % ", ".join(required))
def cal_to_vcgt(cal, return_cgats=False): """ Create a vcgt tag from calibration data. cal must refer to a valid Argyll CAL file and can be a CGATS instance or a filename. """ if not isinstance(cal, CGATS.CGATS): try: cal = CGATS.CGATS(cal) except (IOError, CGATS.CGATSInvalidError, CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError, CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception: safe_print("Warning - couldn't process CGATS file '%s': %s" % tuple(safe_unicode(s) for s in (cal, exception))) return None required_fields = ("RGB_I", "RGB_R", "RGB_G", "RGB_B") data_format = cal.queryv1("DATA_FORMAT") if data_format: for field in required_fields: if not field in list(data_format.values()): if debug: safe_print("[D] Missing required field:", field) return None for field in list(data_format.values()): if not field in required_fields: if debug: safe_print("[D] Unknown field:", field) return None entries = cal.queryv(required_fields) if len(entries) < 1: if debug: safe_print("[D] No entries found in calibration", cal.filename) return None vcgt = ICCP.VideoCardGammaTableType("", "vcgt") vcgt.update({ "channels": 3, "entryCount": len(entries), "entrySize": 2, "data": [[], [], []] }) for n in entries: for i in range(3): vcgt.data[i].append(entries[n][i + 1] * 65535.0) if return_cgats: return vcgt, cal return vcgt
def add_options_to_ti3(ti3, options_dispcal=None, options_colprof=None): # Add dispcal and colprof options to ti3 try: cgats = CGATS.CGATS(ti3) if options_colprof: options_colprof = quote_nonoption_args(options_colprof) cgats[0].add_section( "ARGYLL_COLPROF_ARGS", " ".join(options_colprof).encode("UTF-7", "replace")) if options_dispcal and 1 in cgats: options_dispcal = quote_nonoption_args(options_dispcal) cgats[1].add_section( "ARGYLL_DISPCAL_ARGS", " ".join(options_dispcal).encode("UTF-7", "replace")) return cgats except Exception as exception: safe_print(safe_unicode(traceback.format_exc()))
def ti3_to_ti1(ti3_data): """ Create and return TI1 data converted from TI3. ti3_data can be a file object, a list of strings or a string holding the data. """ ti3 = CGATS.CGATS(ti3_data) if not ti3: return "" ti3[0].type = "CTI1" ti3[0].DESCRIPTOR = "Argyll Calibration Target chart information 1" ti3[0].ORIGINATOR = "Argyll targen" if hasattr(ti3[0], "COLOR_REP"): color_rep = ti3[0].COLOR_REP.split('_')[0] else: color_rep = "RGB" ti3[0].add_keyword("COLOR_REP", color_rep) ti3[0].remove_keyword("DEVICE_CLASS") if hasattr(ti3[0], "LUMINANCE_XYZ_CDM2"): ti3[0].remove_keyword("LUMINANCE_XYZ_CDM2") if hasattr(ti3[0], "ARGYLL_COLPROF_ARGS"): del ti3[0].ARGYLL_COLPROF_ARGS return str(ti3[0])
def __init__(self, parent, cgats, worker=None): """ Init new CCXPlot window. parent Parent window (only used for error dialogs) cgats A CCMX/CCSS CGATS instance worker Worker instance """ self.is_ccss = cgats[0].type == "CCSS" desc = cgats.get_descriptor() if cgats.filename: fn, ext = os.path.splitext(os.path.basename(cgats.filename)) else: fn = desc if self.is_ccss: ext = ".ccss" else: ext = ".ccmx" desc = lang.getstr(ext[1:] + "." + fn, default=desc) if self.is_ccss: ccxx_type = "spectral" else: ccxx_type = "matrix" title = "%s: %s" % (lang.getstr(ccxx_type), desc) if self.is_ccss: # Convert to TI3 so we can get XYZ from spectra for coloring temp = worker.create_tempdir() if isinstance(temp, Exception): show_result_dialog(temp, parent) else: basename = make_filename_safe(desc) temp_path = os.path.join(temp, basename + ".ti3") cgats[0].type = "CTI3" cgats[0].DEVICE_CLASS = "DISPLAY" cgats.write(temp_path) temp_out_path = os.path.join(temp, basename + ".CIE.ti3") result = worker.exec_cmd(get_argyll_util("spec2cie"), [temp_path, temp_out_path], capture_output=True) if isinstance(result, Exception) or not result: show_result_dialog( UnloggedError(result or "".join(worker.errors)), parent) worker.wrapup(False) else: try: cgats = CGATS.CGATS(temp_out_path) except Exception as exception: show_result_dialog(exception, parent) finally: worker.wrapup(False) data_format = cgats.queryv1("DATA_FORMAT") data = cgats.queryv1("DATA") XYZ_max = 0 self.samples = [] if self.is_ccss: x_min = cgats.queryv1("SPECTRAL_START_NM") x_max = cgats.queryv1("SPECTRAL_END_NM") bands = cgats.queryv1("SPECTRAL_BANDS") lores = bands <= 40 if lores: # Interpolate if lores # 1nm intervals steps = int(x_max - x_min) + 1 safe_print("Up-interpolating", bands, "spectral bands to", steps) step = (x_max - x_min) / (steps - 1.) else: step = (x_max - x_min) / (bands - 1.) y_min = 0 y_max = 1 Y_max = 0 for i, sample in data.items(): # Get nm and spectral power values = [] x = x_min for k in data_format.values(): if k.startswith("SPEC_"): y = sample[k] y_min = min(y, y_min) y_max = max(y, y_max) if lores: values.append(y) else: values.append((x, y)) x += step if lores: # Interpolate if lores. Use Catmull-Rom instead of # PolySpline as we want curves to go through points exactly numvalues = len(values) interp = ICCP.CRInterpolation(values) values = [] for i in range(steps): values.append( (x, interp(i / (steps - 1.) * (numvalues - 1.)))) x += step # Get XYZ for colorization XYZ = [] for component in "XYZ": label = "XYZ_" + component if label in sample: v = sample[label] XYZ_max = max(XYZ_max, v) if label == "XYZ_Y": Y_max = max(Y_max, v) XYZ.append(v) self.samples.append((XYZ, values, {})) Plot = plot.PolyLine Plot._attributes["width"] = 1 else: # CCMX cube_size = 2 x_min = 0 y_min = 0 mtx = colormath.Matrix3x3( [[sample[k] for k in data_format.values()] for sample in data.values()]) imtx = mtx.inverted() # Get XYZ that colorimeter would measure without matrix (sRGB ref, # so not accurate, but useful for visual representation which is all # we care about here) if cube_size == 2: scale = 1 x_max = 100 * scale y_max = x_max * (74.6 / 67.4) if sys.platform != "win32": x_center = x_max / 2. else: x_center = x_max / 2. - 2.5 y_center = y_max / 2. x_center *= scale y_center *= scale pos2rgb = [((x_center - 23.7, y_center - 13.7), (0, 0, 1)), ((x_center, y_center + 27.3), (0, 1, 0)), ((x_center + 23.7, y_center - 13.7), (1, 0, 0)), ((x_center - 23.7, y_center + 13.7), (0, 1, 1)), ((x_center, y_center - 27.3), (1, 0, 1)), ((x_center + 23.7, y_center + 13.7), (1, 1, 0)), ((x_center, y_center), (1, 1, 1))] attrs_c = {'size': 10} attrs_r = {'size': 5} else: x_max = 100 y_max = 100 y = -5 pos2rgb = [] for R in range(cube_size): for G in range(cube_size): x = -5 y += 10 for B in range(cube_size): x += 10 pos2rgb.append(((x, y), (v / (cube_size - 1.0) for v in (R, G, B)))) attrs_c = {'marker': 'square', 'size': 10} attrs_r = {'marker': 'square', 'size': 5} Y_max = (imtx * colormath.get_whitepoint("D65"))[1] for i, ((x, y), (R, G, B)) in enumerate(pos2rgb): XYZ = list(colormath.RGB2XYZ(R, G, B)) X, Y, Z = imtx * XYZ XYZ_max = max(XYZ_max, X, Y, Z) self.samples.append(([X, Y, Z], [(x, y)], attrs_c)) self.samples.append((XYZ, [(x, y)], attrs_r)) Plot = plot.PolyMarker if self.is_ccss: # Protect against division by zero when range is zero if not x_max - x_min: x_min = 350.0 x_max = 750.0 if not y_max - y_min: y_min = 0.0 y_max = 10.0 y_zero = 0 self.ccxx_axis_x = (math.floor(x_min / 50.) * 50, math.ceil(x_max / 50.) * 50) self.spec_x = (self.ccxx_axis_x[1] - self.ccxx_axis_x[0]) / 50. graph_range = nicenum(y_max - y_zero, False) d = nicenum(graph_range / (NTICK - 1.0), True) self.spec_y = math.ceil(y_max / d) self.ccxx_axis_y = (math.floor(y_zero / d) * d, self.spec_y * d) else: self.ccxx_axis_x = (math.floor(x_min / 20.) * 20, math.ceil(x_max / 20.) * 20) self.ccxx_axis_y = (math.floor(y_min), math.ceil(y_max)) self.gfx = [] for XYZ, values, attrs in self.samples: if len(XYZ) == 3: # Got XYZ if attrs.get("size") > 11.25: # Colorimeter XYZ if Y_max > 1: # Colorimeter brighter than ref XYZ[:] = [v / Y_max for v in XYZ] else: # Colorimeter dimmer than ref XYZ[:] = [v * Y_max for v in XYZ] else: # Ref XYZ if Y_max > 1: # Colorimeter brighter than ref XYZ[:] = [v / Y_max for v in XYZ] RGB = tuple( int(v) for v in colormath.XYZ2RGB(*XYZ, scale=255, round_=True)) else: RGB = (153, 153, 153) self.gfx.append(Plot(values, colour=wx.Colour(*RGB), **attrs)) if self.is_ccss: # Add a few points at the extremes to define a bounding box self.gfx.append( plot.PolyLine( [(self.ccxx_axis_x[0], self.ccxx_axis_y[0]), (self.ccxx_axis_x[1], self.ccxx_axis_y[1] - y_min)], colour=wx.Colour(0, 0, 0, 0))) ref = cgats.queryv1("REFERENCE") if ref: ref = get_canonical_instrument_name(safe_unicode(ref, "UTF-8")) if not self.is_ccss: observers_ab = {} for observer in config.valid_values["observer"]: observers_ab[observer] = lang.getstr("observer." + observer) x_label = [lang.getstr("matrix")] x_label.extend(["%9.6f %9.6f %9.6f" % tuple(row) for row in mtx]) if ref: ref_observer = cgats.queryv1("REFERENCE_OBSERVER") if ref_observer: ref += ", " + observers_ab.get(ref_observer, ref_observer) x_label.append("") x_label.append(ref) fit_method = cgats.queryv1("FIT_METHOD") if fit_method == "xy": fit_method = lang.getstr("ccmx.use_four_color_matrix_method") elif fit_method: fit_method = lang.getstr("perceptual") fit_de00_avg = cgats.queryv1("FIT_AVG_DE00") if not isinstance(fit_de00_avg, float): fit_de00_avg = None fit_de00_max = cgats.queryv1("FIT_MAX_DE00") if not isinstance(fit_de00_max, float): fit_de00_max = None if fit_method: x_label.append(fit_method) fit_de00 = [] if fit_de00_avg: fit_de00.append( "ΔE*00 %s %.4f" % (lang.getstr("profile.self_check.avg"), fit_de00_avg)) if fit_de00_max: fit_de00.append( "ΔE*00 %s %.4f" % (lang.getstr("profile.self_check.max"), fit_de00_max)) if fit_de00: x_label.append("\n".join(fit_de00)) x_label = "\n".join(x_label) else: x_label = "" if ref: x_label += ref + ", " x_label += "%.1fnm, %i-%inm" % ((x_max - x_min) / (bands - 1.0), x_min, x_max) scale = max(getcfg("app.dpi") / config.get_default_dpi(), 1) style = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, None, -1, title, style=style) self.SetIcons(config.get_icon_bundle([256, 48, 32, 16], appname)) self.SetBackgroundColour(BGCOLOUR) self.Sizer = wx.GridSizer(1, 1, 0, 0) bg = wx.Panel(self) bg.SetBackgroundColour(BGCOLOUR) bg.Sizer = wx.BoxSizer(wx.VERTICAL) self.canvas = canvas = LUTCanvas(bg) if self.is_ccss: bg.MinSize = (513 * scale, 557 * scale) btnsizer = wx.BoxSizer(wx.HORIZONTAL) bg.Sizer.Add(btnsizer, flag=wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, border=16) self.toggle_btn = FlatShadedButton(bg, -1, label=lang.getstr("spectral")) btnsizer.Add(self.toggle_btn, 1) self.Sizer.Add(bg, 1, flag=wx.EXPAND) bg.Sizer.Add(canvas, 1, flag=wx.EXPAND) else: self.Sizer.Add(bg, flag=wx.ALIGN_CENTER) canvas_w = 240 * scale canvas.MinSize = (canvas_w, canvas_w * (74.6 / 67.4)) bg.Sizer.Add(canvas, flag=wx.ALIGN_CENTER) label = wx.StaticText(bg, -1, x_label.replace("&", "&&"), style=wx.ALIGN_CENTRE_HORIZONTAL) label.SetForegroundColour(FGCOLOUR) label.SetMaxFontSize(11) bg.Sizer.Add(label, flag=wx.ALIGN_CENTER | wx.ALL & ~wx.TOP, border=16 * scale) canvas.SetBackgroundColour(BGCOLOUR) canvas.SetEnableCenterLines(False) canvas.SetEnableDiagonals(False) canvas.SetEnableGrid(True) canvas.enableTicks = (True, True) canvas.tickPen = wx.Pen(GRIDCOLOUR, canvas._pointSize[0]) canvas.SetEnablePointLabel(False) canvas.SetEnableTitle(True) canvas.SetForegroundColour(FGCOLOUR) canvas.SetGridColour(GRIDCOLOUR) canvas.canvas.BackgroundColour = BGCOLOUR if self.is_ccss: canvas.HandCursor = wx.StockCursor(wx.CURSOR_SIZING) canvas.SetCursor(canvas.HandCursor) else: canvas.canvas.Unbind(wx.EVT_LEFT_DCLICK) canvas.SetEnableDrag(False) canvas.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) canvas.SetXSpec('none') canvas.SetYSpec('none') # CallAfter is needed under GTK as usual wx.CallAfter(self.draw_ccxx) if self.is_ccss: self.Bind(wx.EVT_KEY_DOWN, self.key_handler) for child in self.GetAllChildren(): child.Bind(wx.EVT_KEY_DOWN, self.key_handler) child.Bind(wx.EVT_MOUSEWHEEL, self.OnWheel) self.toggle_btn.Bind(wx.EVT_BUTTON, self.toggle_draw) self.Bind(wx.EVT_SIZE, self.OnSize) else: bg.Sizer.Add((0, 16)) self.Sizer.SetSizeHints(self) self.Sizer.Layout()
print("untethered.min_delta", getcfg("untethered.min_delta")) print("untethered.min_delta.lightness", getcfg("untethered.min_delta.lightness")) print("untethered.max_delta.chroma", getcfg("untethered.max_delta.chroma")) lang.init() lang.update_defaults() app = BaseApp(0) app.TopWindow = UntetheredFrame(start_timer=False) testchart = getcfg("testchart.file") if os.path.splitext(testchart)[1].lower() in (".icc", ".icm"): try: testchart = ICCP.ICCProfile(testchart).tags.targ except: pass try: app.TopWindow.cgats = CGATS.CGATS(testchart) except: app.TopWindow.cgats = CGATS.CGATS("""TI1 BEGIN_DATA_FORMAT SAMPLE_ID RGB_R RGB_G RGB_B XYZ_X XYZ_Y XYZ_Z END_DATA_FORMAT BEGIN_DATA 1 0 0 0 0 0 0 END_DATA """) app.TopWindow.worker = Worker() app.TopWindow.worker.progress_wnd = app.TopWindow app.TopWindow.Show() files = Files([app.TopWindow.worker, app.TopWindow]) def test(bytes=None):
def extract_device_gray_primaries(ti3, gray=True, logfn=None, include_neutrals=False, neutrals_ab_threshold=0.1): """ Extract gray or primaries into new TI3 Return extracted ti3, extracted RGB to XYZ mapping and remaining RGB to XYZ """ filename = ti3.filename ti3 = ti3.queryi1("DATA") ti3.filename = filename ti3_extracted = CGATS.CGATS("""CTI3 DEVICE_CLASS "DISPLAY" COLOR_REP "RGB_XYZ" BEGIN_DATA_FORMAT END_DATA_FORMAT BEGIN_DATA END_DATA""")[0] ti3_extracted.DATA_FORMAT.update(ti3.DATA_FORMAT) subset = [(100.0, 100.0, 100.0), (0.0, 0.0, 0.0)] if not gray: subset.extend([(100.0, 0.0, 0.0), (0.0, 100.0, 0.0), (0.0, 0.0, 100.0), (50.0, 50.0, 50.0)]) if logfn: logfn("Extracting neutrals and primaries from %s" % ti3.filename) else: if logfn: logfn("Extracting neutrals from %s" % ti3.filename) RGB_XYZ_extracted = OrderedDict() RGB_XYZ_remaining = OrderedDict() dupes = {} if include_neutrals: white = ti3.get_white_cie("XYZ") str_thresh = str(neutrals_ab_threshold) round_digits = len(str_thresh[str_thresh.find(".") + 1:]) for i, item in ti3.DATA.items(): if not i: # Check if fields are missing for prefix in ("RGB", "XYZ"): for suffix in prefix: key = "%s_%s" % (prefix, suffix) if not key in item: raise Error( lang.getstr("error.testchart.missing_fields", (ti3.filename, key))) RGB = (item["RGB_R"], item["RGB_G"], item["RGB_B"]) XYZ = (item["XYZ_X"], item["XYZ_Y"], item["XYZ_Z"]) for RGB_XYZ in (RGB_XYZ_extracted, RGB_XYZ_remaining): if RGB in RGB_XYZ: if RGB != (100.0, 100.0, 100.0): # Add to existing values for averaging later # if it's not white (all other readings are scaled to the # white Y by dispread, so we don't alter it. Note that it's # always the first encountered white that will have Y = 100, # even if subsequent white readings may be higher) XYZ = tuple(RGB_XYZ[RGB][i] + XYZ[i] for i in range(3)) if not RGB in dupes: dupes[RGB] = 1.0 dupes[RGB] += 1.0 elif RGB in subset: # We have white already, remove it from the subset so any # additional white readings we encounter are ignored subset.remove(RGB) if ((gray and (item["RGB_R"] == item["RGB_G"] == item["RGB_B"] or (include_neutrals and all( round(abs(v), round_digits) <= neutrals_ab_threshold for v in colormath.XYZ2Lab(item["XYZ_X"], item["XYZ_Y"], item["XYZ_Z"], whitepoint=white)[1:]))) and not RGB in [(100.0, 100.0, 100.0), (0.0, 0.0, 0.0)]) or RGB in subset): ti3_extracted.DATA.add_data(item) RGB_XYZ_extracted[RGB] = XYZ elif not RGB in [(100.0, 100.0, 100.0), (0.0, 0.0, 0.0)]: RGB_XYZ_remaining[RGB] = XYZ for RGB, count in dupes.items(): for RGB_XYZ in (RGB_XYZ_extracted, RGB_XYZ_remaining): if RGB in RGB_XYZ: # Average values XYZ = tuple(RGB_XYZ[RGB][i] / count for i in range(3)) RGB_XYZ[RGB] = XYZ return ti3_extracted, RGB_XYZ_extracted, RGB_XYZ_remaining
def chart_ctrl_handler(self, event): chart = self.chart_ctrl.GetPath() values = [] try: cgats = CGATS.CGATS(chart) except (IOError, CGATS.CGATSInvalidError, CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError, CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception: show_result_dialog(exception, self) else: data_format = cgats.queryv1("DATA_FORMAT") accurate = cgats.queryv1("ACCURATE_EXPECTED_VALUES") == "true" if data_format: basename, ext = os.path.splitext(chart) for column in data_format.values(): column_prefix = column.split("_")[0] if (column_prefix in ("CMYK", "LAB", "RGB", "XYZ") and column_prefix not in values and (((ext.lower() == ".cie" or accurate) and column_prefix in ("LAB", "XYZ")) or (ext.lower() == ".ti1" and column_prefix in ("CMYK", "RGB")) or (ext.lower() not in (".cie", ".ti1")))): values.append(column_prefix) if values: self.panel.Freeze() self.fields_ctrl.SetItems(values) self.fields_ctrl.GetContainingSizer().Layout() self.panel.Thaw() fields = getcfg("measurement_report.chart.fields") if ext.lower() == ".ti1": index = 0 elif "RGB" in values and not ext.lower() == ".cie": index = values.index("RGB") elif "CMYK" in values: index = values.index("CMYK") elif "XYZ" in values: index = values.index("XYZ") elif "LAB" in values: index = values.index("LAB") else: index = 0 self.fields_ctrl.SetSelection(index) setcfg("measurement_report.chart", chart) self.chart_patches_amount.Freeze() self.chart_patches_amount.SetLabel( str(cgats.queryv1("NUMBER_OF_SETS") or "")) self.update_estimated_measurement_time("chart") self.chart_patches_amount.GetContainingSizer().Layout() self.chart_patches_amount.Thaw() self.chart_white = cgats.get_white_cie() if not values: if chart: show_result_dialog( lang.getstr("error.testchart.missing_fields", (chart, "RGB/CMYK %s LAB/XYZ" % lang.getstr("or"))), self) self.chart_ctrl.SetPath(getcfg("measurement_report.chart")) else: self.chart_btn.Enable("RGB" in values) if self.Parent: parent = self.Parent else: parent = self if (event and self.chart_btn.Enabled and hasattr(parent, "tcframe") and self.tcframe.IsShownOnScreen() and (not hasattr(parent.tcframe, "ti1") or chart != parent.tcframe.ti1.filename)): parent.tcframe.tc_load_cfg_from_ti1( None, chart, "measurement_report.chart", "mr_set_testchart") self.fields_ctrl.Enable(self.fields_ctrl.GetCount() > 1) self.fields_ctrl_handler(event)
def __init__(self, profile, intent="r", direction="f", order="n", pcs=None, scale=1, cwd=None, startupinfo=None, use_icclu=False, use_cam_clipping=False, logfile=None, worker=None, show_actual_if_clipped=False, input_encoding=None, output_encoding=None, convert_video_rgb_to_clut65=False, verbose=1): if not profile: raise Error("Xicclu: Profile is %r" % profile) WorkerBase.__init__(self) self.scale = scale self.convert_video_rgb_to_clut65 = convert_video_rgb_to_clut65 self.logfile = logfile self.worker = worker self.temp = False utilname = "icclu" if use_icclu else "xicclu" xicclu = get_argyll_util(utilname) if not xicclu: raise Error(lang.getstr("argyll.util.not_found", utilname)) if not isinstance(profile, (CGATS.CGATS, ICCP.ICCProfile)): if profile.lower().endswith(".cal"): profile = CGATS.CGATS(profile) else: profile = ICCP.ICCProfile(profile) is_profile = isinstance(profile, ICCP.ICCProfile) if (is_profile and profile.version >= 4 and not profile.convert_iccv4_tags_to_iccv2()): raise Error("\n".join([ lang.getstr("profile.iccv4.unsupported"), profile.getDescription() ])) if not profile.fileName or not os.path.isfile(profile.fileName): if profile.fileName: prefix = os.path.basename(profile.fileName) elif is_profile: prefix = make_filename_safe(profile.getDescription(), concat=False) + profile_ext else: # CGATS (.cal) prefix = "cal" prefix += "-" if not cwd: cwd = self.create_tempdir() if isinstance(cwd, Exception): raise cwd fd, profile.fileName = tempfile.mkstemp("", prefix, dir=cwd) stream = os.fdopen(fd, "wb") profile.write(stream) stream.close() self.temp = True elif not cwd: cwd = os.path.dirname(profile.fileName) profile_basename = safe_unicode(os.path.basename(profile.fileName)) profile_path = profile.fileName if sys.platform == "win32": profile_path = win32api.GetShortPathName(profile_path) self.profile_path = safe_str(profile_path) if sys.platform == "win32" and not startupinfo: startupinfo = sp.STARTUPINFO() startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW startupinfo.wShowWindow = sp.SW_HIDE xicclu = safe_str(xicclu) cwd = safe_str(cwd) self.verbose = verbose args = [xicclu, "-v%i" % verbose, "-s%s" % scale] self.show_actual_if_clipped = False if utilname == "xicclu": if (is_profile and show_actual_if_clipped and "A2B0" in profile.tags and ("B2A0" in profile.tags or direction == "if")): args.append("-a") self.show_actual_if_clipped = True if use_cam_clipping: args.append("-b") if get_argyll_version("xicclu") >= [1, 6]: # Add encoding parameters # Note: Not adding -e -E can cause problems due to unitialized # in_tvenc and out_tvenc variables in xicclu.c for Argyll 1.6.x if not input_encoding: input_encoding = "n" if not output_encoding: output_encoding = "n" args += [ "-e" + safe_str(input_encoding), "-E" + safe_str(output_encoding) ] args.append("-f" + direction) self.output_scale = 1.0 if is_profile: if profile.profileClass not in ("abst", "link"): args.append("-i" + intent) if order != "n": args.append("-o" + order) if profile.profileClass != "link": if (direction in ("f", "ib") and (pcs == "x" or (profile.connectionColorSpace == "XYZ" and not pcs))): # In case of forward lookup with XYZ PCS, use 0..100 scaling # internally so we get extra precision from xicclu for the # decimal part. Scale back to 0..1 later. pcs = "X" self.output_scale = 100.0 if pcs: args.append("-p" + pcs) args.append(self.profile_path) if debug or verbose > 1: self.sessionlogfile = LogFile(profile_basename + ".xicclu", os.path.dirname(profile.fileName)) if is_profile: profile_act = ICCP.ICCProfile(profile.fileName) self.sessionlogfile.write( "Profile ID %s (actual %s)" % (hexlify( profile.ID), hexlify(profile_act.calculateID(False)))) if cwd: self.log(lang.getstr("working_dir")) indent = " " for name in cwd.split(os.path.sep): self.log( textwrap.fill(name + os.path.sep, 80, expand_tabs=False, replace_whitespace=False, initial_indent=indent, subsequent_indent=indent)) indent += " " self.log("") self.log(lang.getstr("commandline")) printcmdline(xicclu, args[1:], fn=self.log, cwd=cwd) self.log("") self.startupinfo = startupinfo self.args = args self.cwd = cwd self.spawn()