diff --git a/Dockerfile b/Dockerfile index 11ecb7a..b9c3ea6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,23 +6,24 @@ ENV TMPDIR=$APPETISER_DIR/tmp ENV OUTPUT_DIR=$APPETISER_DIR/out/ RUN apt-get update -y && apt-get install -y \ - cmake=3.31.6-2 \ - netpbm=2:11.10.02-1 \ - ghostscript=10.05.1~dfsg-1 \ - libgs10=10.05.1~dfsg-1 \ - libgs10-common=10.05.1~dfsg-1 \ - libffi-dev=3.4.8-2 \ - libjpeg-turbo-progs=1:2.1.5-4 \ - libtiff5-dev=4.7.0-3 \ - libjpeg62-turbo-dev=1:2.1.5-4 \ - zlib1g-dev=1:1.3.dfsg+really1.3.1-1+b1 \ - liblcms2-dev=2.16-2 \ - libwebp-dev=1.5.0-0.1 \ - tcl8.6-dev=8.6.16+dfsg-1 \ - tk8.6-dev=8.6.16-1 \ - python3-tk=3.13.5-1\ - libharfbuzz-dev=10.2.0-1+b1 \ - libfribidi-dev=1.0.16-1 + cmake \ + netpbm \ + ghostscript \ + libgs10 \ + libgs10-common \ + libffi-dev \ + libjpeg-turbo-progs \ + libtiff5-dev \ + libjpeg62-turbo-dev \ + zlib1g-dev \ + liblcms2-dev \ + libwebp-dev \ + tcl8.6-dev \ + tk8.6-dev \ + python3-tk \ + libharfbuzz-dev \ + libfribidi-dev \ + && rm -rf /var/lib/apt/lists/* COPY ./appetiser/ $APPETISER_DIR/appetiser/ COPY ./pyproject.toml $APPETISER_DIR diff --git a/appetiser/convert/color_profiles/GRACoL2006_Coated1v2.icc b/appetiser/convert/color_profiles/GRACoL2006_Coated1v2.icc new file mode 100644 index 0000000..72cf855 Binary files /dev/null and b/appetiser/convert/color_profiles/GRACoL2006_Coated1v2.icc differ diff --git a/appetiser/convert/image.py b/appetiser/convert/image.py index d6896b6..660d329 100644 --- a/appetiser/convert/image.py +++ b/appetiser/convert/image.py @@ -167,25 +167,33 @@ def _image_has_transparency(img: PILImage) -> bool: return False +CMYK_COLOUR_PROFILE = str( + Path(__file__).resolve().parent / "color_profiles/GRACoL2006_Coated1v2.icc" +) + + def _convert_img_colour_profile(img: PILImage, img_filename: str = "") -> PILImage: """If the image has ICC profile information, apply a transformation to this image from that ICC colour profile to the sRGB colour profile. """ + source_profile = None img_colour_profile_bytes = img.info.get("icc_profile") if img_colour_profile_bytes: logger.debug(f"Extracting embedded colour profile: {img_filename}") - img_colour_profile = ImageCms.ImageCmsProfile( - io.BytesIO(img_colour_profile_bytes) - ) - img_colour_profile_name = ImageCms.getProfileName(img_colour_profile) - logger.debug(f"Using icc colour profile: {img_colour_profile_name}") + source_profile = ImageCms.ImageCmsProfile(io.BytesIO(img_colour_profile_bytes)) + elif img.mode == "CMYK": + logger.debug(f"Loading default CMYK colour profile: {CMYK_COLOUR_PROFILE}") + source_profile = ImageCms.ImageCmsProfile(CMYK_COLOUR_PROFILE) + if source_profile: + source_profile_name = ImageCms.getProfileName(source_profile) + logger.debug(f"Using icc colour profile: {source_profile_name}") sRGB_profile = ImageCms.createProfile("sRGB") logger.debug( - f"Converting colour profile: {img_colour_profile_name} to {sRGB_profile.profile_description}, {img_filename}" + f"Converting colour profile: {source_profile_name} to {sRGB_profile.profile_description}, {img_filename}" ) output_mode = "RGBA" if _image_has_transparency(img) else "RGB" img = ImageCms.profileToProfile( - img, img_colour_profile, sRGB_profile, outputMode=output_mode + img, source_profile, sRGB_profile, outputMode=output_mode ) return img @@ -207,6 +215,7 @@ def _convert_img_to_tiff(filepath: Path) -> tuple[Path, dict]: ) logger.debug("%s: saving as raw to %s", filepath, tiff_filepath) img.save(tiff_filepath, compression=None) + img_info["mode"] = img.mode return tiff_filepath, img_info diff --git a/appetiser/convert/operations.py b/appetiser/convert/operations.py index b8663cc..5323b7a 100644 --- a/appetiser/convert/operations.py +++ b/appetiser/convert/operations.py @@ -47,12 +47,7 @@ def convert_image_to_jp2( else: image_mode = image_info.get("mode") logger.debug( - "Converting with colour profile: {prepared_source=}, {image_mode=}" - ) - logger.debug( - "%s: Being used for conversion to JPEG2000, with colour mode: %s", - prepared_source, - image_mode, + f"Converting with colour profile: {prepared_source=}, {image_mode=}" ) kdu_compress( config=config, @@ -240,7 +235,7 @@ def create_thumbnails( width=calc_thumb_info.width, height=calc_thumb_info.height, dest_path=calc_thumb_info.path, - config=config + config=config, ) thumbnail_info.append( ThumbInfo( diff --git a/tests/fixtures/10_02_18.jpg b/tests/fixtures/10_02_18.jpg new file mode 100644 index 0000000..b4e2ae9 Binary files /dev/null and b/tests/fixtures/10_02_18.jpg differ diff --git a/tests/test_convert_image_cmyk.py b/tests/test_convert_image_cmyk.py new file mode 100644 index 0000000..d16ed05 --- /dev/null +++ b/tests/test_convert_image_cmyk.py @@ -0,0 +1,17 @@ +from .utils import ( + convert_test_runner, +) + + +def test_convert_cmyk_image(appetiser_service, fixtures_dir, output_dir): + convert_test_runner( + appetiser_service=appetiser_service, + output_dir=output_dir, + fixtures_dir=fixtures_dir, + img_path="10_02_18.jpg", + expected_jp2_name="10_02_18.jp2", + optimisation="kdu_med", + operation="image-only", + thumb_iiif_sizes=None, + expected_thumb_sizes=None, + )