Skip to content

Commit

Permalink
- Fixed #271 (#275)
Browse files Browse the repository at this point in the history
- Fixed #271
  • Loading branch information
eoyilmaz authored Jul 4, 2023
1 parent b07002e commit 60f80fc
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 37 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/build/
/dist/
/venv/
.venv/
/INSTALLED_FILES
/MANIFEST.in
/VERSION
Expand Down
70 changes: 33 additions & 37 deletions DisplayCAL/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2178,6 +2178,8 @@ def __init__(self, owner=None):
self.displays = []
self.instruments = []
self.lut_access = []
self.paused = False
self._patterngenerator_wait = False

self.send_buffer = None
self.owner = owner # owner should be a wxFrame or similar
Expand Down Expand Up @@ -13058,9 +13060,9 @@ def patterngenerator_send(
f = needed_bgrgb_apl / bgrgb_apl
bgrgb = [v * f for v in bgrgb]
self.log(
"%s: Sending RGB %.3f %.3f %.3f, background RGB %.3f %.3f %.3f, "
"x %.4f, y %.4f, w %.4f, h %.4f"
% ((appname,) + tuple(rgb) + tuple(bgrgb) + (x, y, w, h))
f"{appname}: Sending RGB {rgb[0]:.3f} {rgb[1]:.3f} {rgb[2]:.3f}, "
f"background RGB {bgrgb[0]:.3f} {bgrgb[1]:.3f} {bgrgb[2]:.3f}, "
f"x {x:.4f}, y {y:.4f}, w {w:.4f}, h {h:.4f}"
)
if self._use_patternwindow:
# Preliminary Wayland support. This still needs a lot
Expand Down Expand Up @@ -13123,30 +13125,25 @@ def prepare_colprof(
"""Prepare a colprof commandline.

All options are read from the user configuration.
Profile name and display name can be ovverridden by passing the
corresponding arguments.

Profile name and display name can be overridden by passing thecorresponding arguments.
"""
if profile_name is None:
profile_name = getcfg("profile.name.expanded")
inoutfile = self.setup_inout(profile_name)
if not inoutfile or isinstance(inoutfile, Exception):
return inoutfile, None
if not os.path.exists(inoutfile + ".ti3"):
in_out_file = self.setup_inout(profile_name)
if not in_out_file or isinstance(in_out_file, Exception):
return in_out_file, None
if not os.path.exists(f"{in_out_file}.ti3"):
return (
Error(
lang.getstr("error.measurement.file_missing", inoutfile + ".ti3")
lang.getstr("error.measurement.file_missing", f"{in_out_file}.ti3")
),
None,
)
if not os.path.isfile(inoutfile + ".ti3"):
return Error(lang.getstr("file_notfile", inoutfile + ".ti3")), None
#
if not os.path.isfile(f"{in_out_file}.ti3"):
return Error(lang.getstr("file_notfile", f"{in_out_file}.ti3")), None

cmd = get_argyll_util("colprof")
args = []
args.append("-v") # verbose
args.append("-q" + getcfg("profile.quality"))
args.append("-a" + getcfg("profile.type"))
args = ["-v", f"-q{getcfg('profile.quality')}", f"-a{getcfg('profile.type')}"]
gamap_args = args
if getcfg("profile.type") in ["l", "x", "X"]:
if getcfg("gamap_saturation"):
Expand Down Expand Up @@ -13181,19 +13178,19 @@ def prepare_colprof(
and "bTRC" in gamap_profile.tags
):
self.log("Delegating CIECAM02 gamut mapping to collink")
# Make a copy so we can store options without adding them
# Make a copy, so we can store options without adding them
# to actual colprof arguments
gamap_args = []
gamap_profile = None
gamap_args.append("-" + gamap)
gamap_args.append(f"-{gamap}")
gamap_args.append(getcfg("gamap_profile"))
gamap_args.append("-t" + getcfg("gamap_perceptual_intent"))
gamap_args.append(f"-t{getcfg('gamap_perceptual_intent')}")
if gamap == "S":
gamap_args.append("-T" + getcfg("gamap_saturation_intent"))
gamap_args.append(f"-T{getcfg('gamap_saturation_intent')}")
if getcfg("gamap_src_viewcond"):
gamap_args.append("-c" + getcfg("gamap_src_viewcond"))
gamap_args.append(f"-c{getcfg('gamap_src_viewcond')}")
if getcfg("gamap_out_viewcond"):
gamap_args.append("-d" + getcfg("gamap_out_viewcond"))
gamap_args.append(f"-d{getcfg('gamap_out_viewcond')}")
b2a_q = getcfg("profile.quality.b2a")
if (
getcfg("profile.b2a.hires")
Expand All @@ -13203,20 +13200,20 @@ def prepare_colprof(
rgb = False
is_lab_clut_ptype = getcfg("profile.type") == "l"
if is_lab_clut_ptype:
with open(inoutfile + ".ti3", "rb") as ti3_file:
with open(f"{in_out_file}.ti3", "rb") as ti3_file:
for line in ti3_file:
if line.startswith("COLOR_REP"):
if "RGB_XYZ" in line:
if line.startswith(b"COLOR_REP"):
if b"RGB_XYZ" in line:
rgb = True
break
if rgb or not is_lab_clut_ptype:
# Disable B2A creation in colprof, B2A is handled
# by A2B inversion code (only for cLUT profiles)
b2a_q = "n"
if b2a_q and b2a_q != getcfg("profile.quality"):
args.append("-b" + b2a_q)
args.append(f"-b{b2a_q}")
args.append("-C")
args.append(getcfg("copyright").encode("ASCII", "asciize"))
args.append(getcfg("copyright").encode("ASCII", "asciize").decode("utf-8"))
if getcfg("extra_args.colprof").strip():
args += parse_argument_string(getcfg("extra_args.colprof"))
options_dispcal = []
Expand All @@ -13226,7 +13223,7 @@ def prepare_colprof(
if len(self.displays):
args.extend(
self.update_display_name_manufacturer(
inoutfile + ".ti3",
f"{in_out_file}.ti3",
display_name,
display_manufacturer,
write=False,
Expand All @@ -13237,10 +13234,10 @@ def prepare_colprof(
self.options_colprof.extend(gamap_args)
args.append("-D")
args.append(profile_name)
args.append(inoutfile)
args.append(in_out_file)
# Add dispcal and colprof arguments to ti3
ti3 = add_options_to_ti3(
inoutfile + ".ti3", options_dispcal, self.options_colprof
f"{in_out_file}.ti3", options_dispcal, self.options_colprof
)
if ti3:
color_rep = (ti3.queryv1("COLOR_REP").decode("utf-8") or "").split("_")
Expand All @@ -13258,7 +13255,7 @@ def prepare_colprof(
else:
XYZ = (colorant["XYZ_X"], colorant["XYZ_Y"], colorant["XYZ_Z"])
chrm.channels.append(colormath.XYZ2xyY(*XYZ)[:-1])
with open(inoutfile + ".chrm", "wb") as blob:
with open(in_out_file + ".chrm", "wb") as blob:
blob.write(chrm.tagData)
self.log("Storing settings in TI3")
# Black point compensation
Expand Down Expand Up @@ -13373,13 +13370,13 @@ def prepare_colprof(
# 3D LUT content color space (currently only used for HDR)
for color in ("white", "red", "green", "blue"):
for coord in "xy":
keyword = "3DLUT_CONTENT_COLORSPACE_%s_%s" % (
keyword = "3DLUT_CONTENT_COLORSPACE_{}_{}".format(
color.upper(),
coord.upper(),
)
if getcfg("3dlut.create"):
value = getcfg(
"3dlut.content.colorspace.%s.%s" % (color, coord)
"3dlut.content.colorspace.{}.{}".format(color, coord)
)
ti3[0].add_keyword(keyword, safe_str(value, "UTF-7"))
elif keyword in ti3[0]:
Expand All @@ -13397,8 +13394,7 @@ def prepare_dispcal(self, calibrate=True, verify=False, dry_run=False):

"""
cmd = get_argyll_util("dispcal")
args = []
args.append("-v2") # verbose
args = ["-v2"]
if getcfg("argyll.debug"):
args.append("-D8")
result = self.add_measurement_features(args, allow_nondefault_observer=True)
Expand Down
7 changes: 7 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ def data_files():
yield d_files


@pytest.fixture(scope="module")
def data_path():
"""Return the tests/data folder path."""
displaycal_parent_dir = pathlib.Path(DisplayCAL.__file__).parent
return displaycal_parent_dir.parent / "tests" / "data"


@pytest.fixture(scope="module")
def argyll():
"""Setup ArgyllCMS.
Expand Down
1 change: 1 addition & 0 deletions tests/data/sample/issue271/test_profile.ti3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
COLOR_REP RGB_XYZ
54 changes: 54 additions & 0 deletions tests/test_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from __future__ import annotations

import io
import pathlib
import os
import shutil
from typing import Tuple, Dict

import pytest
Expand Down Expand Up @@ -458,3 +461,54 @@ def test_check_ti3_criteria1(sample: Dict[str:float], result: bool) -> None:
print_debuginfo=True,
)
assert criteria[3] == result


def test_prepare_colprof_for_271(monkeypatch, data_path):
"""Bug report 271."""
assert isinstance(data_path, pathlib.Path)

def patched_getcfg(key):
"""patched getcfg()"""
cfg = {
"argyll.version": "2.3.1",
"profile.name.expanded": "test_profile",
"profile.quality": "m",
"profile.type": "l",
"gamap_saturation": False,
"gamap_perceptual": False,
"profile.quality.b2a": "h",
"profile.b2a.hires": True,
"copyright": "",
"extra_args.colprof": "",
"profile.black_point_compensation": False,
"profile.black_point_correction": False,
"profile.b2a.hires.size": 17,
"profile.b2a.hires.smooth": True,
"measure.override_min_display_update_delay_ms": False,
"measure.override_display_settle_time_mult": False,
"patterngenerator.ffp_insertion": False,
"testchart.patch_sequence": "",
"3dlut.create": False,
}
return cfg[key]
monkeypatch.setattr("DisplayCAL.worker.getcfg", patched_getcfg)

def patched_os_path_exists(filepath):
return True
monkeypatch.setattr("DisplayCAL.worker.os.path.exists", patched_os_path_exists)

def patched_os_path_isfile(filepath):
return True
monkeypatch.setattr("DisplayCAL.worker.os.path.isfile", patched_os_path_isfile)

worker = Worker()
in_out_file = pathlib.Path(worker.setup_inout("test_profile")).with_suffix(".ti3")

# copy the test file to the target path
test_file_path = data_path / "sample" / "issue271" / "test_profile.ti3"
os.makedirs(in_out_file.parent, exist_ok=True)
shutil.copy(test_file_path, in_out_file)

# This should not raise the:
# TypeError: startswith first arg must be bytes or a tuple of bytes, not str
worker.prepare_colprof()

0 comments on commit 60f80fc

Please sign in to comment.