16 bit TIFF file #144

Closed
opened 2022-06-16 09:59:30 +00:00 by jpnp · 17 comments

I am trying to convert a 16bit CMYK image to PDF.

When I use

img2pdf -o out.pdf testCMYK.tif

I get

error: PIL is unable to preserve more than 8 bits per sample

Is it possible to support 16bit TIFF data with img2pdf?

I am trying to convert a 16bit CMYK image to PDF. When I use ``` img2pdf -o out.pdf testCMYK.tif ``` I get ``` error: PIL is unable to preserve more than 8 bits per sample ``` Is it possible to support 16bit TIFF data with img2pdf?
Owner

Can you share your input tif image? How did you create it?

Here is a PIL issue about this: https://github.com/python-pillow/Pillow/issues/1888

Either this limitation of PIL gets fixed or we write our own parser of some image format that understands CMYK as well as 16 bit samples. Does such a format exist apart from tif?

You could also first convert your image to 8bit but that wouldn't be lossless anymore of course. :/

Can you share your input tif image? How did you create it? Here is a PIL issue about this: https://github.com/python-pillow/Pillow/issues/1888 Either this limitation of PIL gets fixed or we write our own parser of some image format that understands CMYK as well as 16 bit samples. Does such a format exist apart from tif? You could also first convert your image to 8bit but that wouldn't be lossless anymore of course. :/
Author

I'm afraid I do need 16bit as the CMYK ends up sent to a non-linear device where 8 bits isn't smooth enough.

Here is a 16bit image of colour test patches made with argyllcms.

Doesn't look like we can hold out much hope for Pillow support soon. Imagemagick has decent enough 16bit handling (though their PDF output isn't so great and only does 8bit).

Photoshop PSD can hold 16bit fine (though not really an easier to support support than TIFF).

Imagemagick can write out raw CMYK data, but with no header so not even row length is included.

Interesting though: Imagemagick also has its own MIFF format, an ASCII header followed by the raw data. That looks pretty simple to parse.

https://imagemagick.org/script/miff.php

I'm afraid I do need 16bit as the CMYK ends up sent to a non-linear device where 8 bits isn't smooth enough. Here is a 16bit image of colour test patches made with argyllcms. Doesn't look like we can hold out much hope for Pillow support soon. Imagemagick has decent enough 16bit handling (though their PDF output isn't so great and only does 8bit). Photoshop PSD can hold 16bit fine (though not really an easier to support support than TIFF). Imagemagick can write out raw CMYK data, but with no header so not even row length is included. Interesting though: Imagemagick also has its own MIFF format, an ASCII header followed by the raw data. That looks pretty simple to parse. https://imagemagick.org/script/miff.php
Owner

Hrm... yeah parsing MIFF is an option but I don't really like splitting off a imagemagick process to create the MIFF. This will be very platform specific. Your problem is also that you need CMYK or otherwise you could use PNG as another format that supportrs 16bit while at the same time we do not go through PIL to include it. So 16bit PNG works well but only as RGB and not as CMYK.

What are you doing with the PDF in the end? Why the need not only for 16bit but also for CMYK? Usually I see people use 16bit if they have medical imaging data as input where the color channels map to different sensors. But then I'm puzzled that CMYK is needed. Can printers print precisely enough for 16 bit colors?

Hrm... yeah parsing MIFF is an option but I don't really like splitting off a imagemagick process to create the MIFF. This will be very platform specific. Your problem is also that you need CMYK or otherwise you could use PNG as another format that supportrs 16bit while at the same time we do not go through PIL to include it. So 16bit PNG works well but only as RGB and not as CMYK. What are you doing with the PDF in the end? Why the need not only for 16bit but also for CMYK? Usually I see people use 16bit if they have medical imaging data as input where the color channels map to different sensors. But then I'm puzzled that CMYK is needed. Can printers print precisely enough for 16 bit colors?
Author

The printer does dither to 16 bits, but the individual steps would likely not be visible. If the printer's response was roughly perceptually linear then 8bit would be enough but as it is I need extra headroom so when input values are mapped into a small part of the device range they still get discrete output values and smooth gradients (the full 16 bits aren't really needed, but more than 8).

You're right that 16 bit RGB PNGs work fine. These days things mostly work well with sending RGB to print drivers and letting the device/driver do the conversion, but I'm using a non-standard ink set and doing that the response is too irregular (and non-monotonic) to be corrected by a profile. So, I'm looking at CMYK where I can control the black separation myself.

I'd be very happy with MIFF support built in rather than img2pdf trying to manage Imagemagick converting itself. I can easily put the Imagemagick conversion in my workflow, and anyone else with an unusual format supported by IM could do likewise.

The printer does dither to 16 bits, but the individual steps would likely not be visible. If the printer's response was roughly perceptually linear then 8bit would be enough but as it is I need extra headroom so when input values are mapped into a small part of the device range they still get discrete output values and smooth gradients (the full 16 bits aren't really needed, but more than 8). You're right that 16 bit RGB PNGs work fine. These days things mostly work well with sending RGB to print drivers and letting the device/driver do the conversion, but I'm using a non-standard ink set and doing that the response is too irregular (and non-monotonic) to be corrected by a profile. So, I'm looking at CMYK where I can control the black separation myself. I'd be very happy with MIFF support built in rather than img2pdf trying to manage Imagemagick converting itself. I can easily put the Imagemagick conversion in my workflow, and anyone else with an unusual format supported by IM could do likewise.
Owner

A non-standard ink set... At which point should I get worried what people are doing with my software? :D

So I guess you want to convert your tiff into pdf because pdf is what you send to your printer? I'm surprised that your printer driver preserves the full 16bit cmyk but great if it does! If you have a website, blog or scientific paper describing what you do, I'd love to read it. :)

Ah you are right, if img2pdf would get MIFF reading support then this would solve your problem and could be done without using either PIL or calling imagemagick from within img2pdf. I think this can be done! Either wait until I find some freetime to implement this myself or, if you don't want to wait, feel free to send a merge request implementing MIFF input for me to review.

Thanks!

A non-standard ink set... At which point should I get worried what people are doing with my software? :D So I guess you want to convert your tiff into pdf because pdf is what you send to your printer? I'm surprised that your printer driver preserves the full 16bit cmyk but great if it does! If you have a website, blog or scientific paper describing what you do, I'd love to read it. :) Ah you are right, if img2pdf would get MIFF *reading* support then this would solve your problem and could be done without using either PIL or calling imagemagick from within img2pdf. I think this can be done! Either wait until I find some freetime to implement this myself or, if you don't want to wait, feel free to send a merge request implementing MIFF input for me to review. Thanks!
Author

Ha ha. Nothing as exciting as you're thinking, just syringe refilling cartridges with actual ink, but not a good match to that the printers were tuned with.

There are quite a few users for adapted prosumer printers though. T-shirt printers find it's a very cost effective way to get a high quality print head, but you're always pushing against the manufacturers' view of how things should work.

If I get somehting working I'll send you a PR.

Ha ha. Nothing as exciting as you're thinking, just syringe refilling cartridges with actual ink, but not a good match to that the printers were tuned with. There are quite a few users for adapted prosumer printers though. T-shirt printers find it's a very cost effective way to get a high quality print head, but you're always pushing against the manufacturers' view of how things should work. If I get somehting working I'll send you a PR.
Owner

Here is a MIFF parser:

import glob
import re
import zlib

line_re = re.compile(
    r"""
    [^\x00-\x20\x7f-\x9f] # the field name must not start with a control char or space
    [^=]+                 # the field name can even contain spaces
    =                     # field name and value are separated by an equal sign
    (?:
        [^\x00-\x20\x7f-\x9f{}] # either chars that are not braces and not control chars
        |{[^}]*}                # or any kind of char surrounded by braces
    )+""",
    re.VERBOSE,
)

# https://imagemagick.org/script/miff.php
def parse_miff(data):
    results = []
    header, rest = data.split(b":\x1a", 1)
    header = header.decode("ISO-8859-1")
    assert header.lower().startswith("id=imagemagick")
    hdata = {}
    for i, line in enumerate(re.findall(line_re, header)):
        if not line:
            continue
        k, v = line.split("=", 1)
        if i == 0:
            assert k.lower() == "id"
            assert v.lower() == "imagemagick"
        match k.lower():
            case "class":
                match v:
                    case "DirectClass" | "PseudoClass":
                        hdata["class"] = v
                    case _:
                        print("cannot understand class", v)
            case "colorspace":
                # theoretically RGBA and CMYKA should be supported as well
                # please teach me how to create such a MIFF file
                match v:
                    case "sRGB" | "CMYK" | "Gray":
                        hdata["colorspace"] = v
                    case _:
                        print("cannot understand colorspace", v)
            case "depth":
                match v:
                    case "8" | "16" | "32":
                        hdata["depth"] = int(v)
                    case _:
                        print("cannot understand depth", v)
            case "colors":
                hdata["colors"] = int(v)
            case "matte":
                match v:
                    case "True":
                        hdata["matte"] = True
                    case "False":
                        hdata["matte"] = False
                    case _:
                        print("cannot understand matte", v)
            case "columns" | "rows":
                hdata[k.lower()] = int(v)
            case "compression":
                print("compression not yet supported")
            case "profile":
                assert v in ["icc", "exif"]
                hdata["profile"] = v
            case "resolution":
                dpix, dpiy = v.split("x", 1)
                hdata["resolution"] = (float(dpix), float(dpiy))

    assert "depth" in hdata
    assert "columns" in hdata
    assert "rows" in hdata
    match hdata["class"]:
        case "DirectClass":
            if "colors" in hdata:
                assert hdata["colors"] == 0
            match hdata["colorspace"]:
                case "sRGB":
                    numchannels = 3
                case "CMYK":
                    numchannels = 4
                case "Gray":
                    numchannels = 1
            if hdata["matte"]:
                numchannels += 1
            if hdata.get("profile"):
                # there is no key encoding the length of icc or exif data
                # according to the docs, the profile-icc key is supposed to do this
                print("FAIL: exif")
            else:
                lenimgdata = (
                    hdata["depth"] // 8 * numchannels * hdata["columns"] * hdata["rows"]
                )
                assert len(rest) >= lenimgdata, (
                    len(rest),
                    hdata["depth"],
                    numchannels,
                    hdata["columns"],
                    hdata["rows"],
                    lenimgdata,
                )
                results.append(
                    (
                        hdata["colorspace"],
                        hdata.get("resolution") or 0,
                        "MIFF",
                        zlib.compress(rest[:lenimgdata]),
                        None,  # smask
                        hdata["columns"],
                        hdata["rows"],
                        [],  # palette
                        False,  # inverted
                        hdata["depth"],
                        0,  # rotation
                        None,  # icc profile
                    )
                )
                if len(rest) > lenimgdata:
                    # another image is here
                    assert rest[lenimgdata:].lower().startswith(b"id=imagemagick")
                    results.extend(parse_miff(rest[lenimgdata:]))
        case "PseudoClass":
            assert "colors" in hdata
            if hdata["matte"]:
                numchannels = 2
            else:
                numchannels = 1
            lenpal = 3 * hdata["colors"] * hdata["depth"] // 8
            lenimgdata = numchannels * hdata["rows"] * hdata["columns"]
            assert len(rest) >= lenpal + lenimgdata, (len(rest), lenpal, lenimgdata)
            results.append(
                (
                    "sRGB",
                    hdata.get("resolution") or 0,
                    "MIFF",
                    zlib.compress(rest[lenpal : lenpal + lenimgdata]),
                    None,  # FIXME: allow alpha channel smask
                    hdata["columns"],
                    hdata["rows"],
                    rest[:lenpal],  # palette
                    False,  # inverted
                    hdata["depth"],
                    0,  # rotation
                    None,  # icc profile
                )
            )
            if len(rest) > lenpal + lenimgdata:
                # another image is here
                assert (
                    rest[lenpal + lenimgdata :].lower().startswith(b"id=imagemagick")
                ), (len(rest), lenpal, lenimgdata)
                results.extend(parse_miff(rest[lenpal + lenimgdata :]))
    return results
Here is a MIFF parser: ```py import glob import re import zlib line_re = re.compile( r""" [^\x00-\x20\x7f-\x9f] # the field name must not start with a control char or space [^=]+ # the field name can even contain spaces = # field name and value are separated by an equal sign (?: [^\x00-\x20\x7f-\x9f{}] # either chars that are not braces and not control chars |{[^}]*} # or any kind of char surrounded by braces )+""", re.VERBOSE, ) # https://imagemagick.org/script/miff.php def parse_miff(data): results = [] header, rest = data.split(b":\x1a", 1) header = header.decode("ISO-8859-1") assert header.lower().startswith("id=imagemagick") hdata = {} for i, line in enumerate(re.findall(line_re, header)): if not line: continue k, v = line.split("=", 1) if i == 0: assert k.lower() == "id" assert v.lower() == "imagemagick" match k.lower(): case "class": match v: case "DirectClass" | "PseudoClass": hdata["class"] = v case _: print("cannot understand class", v) case "colorspace": # theoretically RGBA and CMYKA should be supported as well # please teach me how to create such a MIFF file match v: case "sRGB" | "CMYK" | "Gray": hdata["colorspace"] = v case _: print("cannot understand colorspace", v) case "depth": match v: case "8" | "16" | "32": hdata["depth"] = int(v) case _: print("cannot understand depth", v) case "colors": hdata["colors"] = int(v) case "matte": match v: case "True": hdata["matte"] = True case "False": hdata["matte"] = False case _: print("cannot understand matte", v) case "columns" | "rows": hdata[k.lower()] = int(v) case "compression": print("compression not yet supported") case "profile": assert v in ["icc", "exif"] hdata["profile"] = v case "resolution": dpix, dpiy = v.split("x", 1) hdata["resolution"] = (float(dpix), float(dpiy)) assert "depth" in hdata assert "columns" in hdata assert "rows" in hdata match hdata["class"]: case "DirectClass": if "colors" in hdata: assert hdata["colors"] == 0 match hdata["colorspace"]: case "sRGB": numchannels = 3 case "CMYK": numchannels = 4 case "Gray": numchannels = 1 if hdata["matte"]: numchannels += 1 if hdata.get("profile"): # there is no key encoding the length of icc or exif data # according to the docs, the profile-icc key is supposed to do this print("FAIL: exif") else: lenimgdata = ( hdata["depth"] // 8 * numchannels * hdata["columns"] * hdata["rows"] ) assert len(rest) >= lenimgdata, ( len(rest), hdata["depth"], numchannels, hdata["columns"], hdata["rows"], lenimgdata, ) results.append( ( hdata["colorspace"], hdata.get("resolution") or 0, "MIFF", zlib.compress(rest[:lenimgdata]), None, # smask hdata["columns"], hdata["rows"], [], # palette False, # inverted hdata["depth"], 0, # rotation None, # icc profile ) ) if len(rest) > lenimgdata: # another image is here assert rest[lenimgdata:].lower().startswith(b"id=imagemagick") results.extend(parse_miff(rest[lenimgdata:])) case "PseudoClass": assert "colors" in hdata if hdata["matte"]: numchannels = 2 else: numchannels = 1 lenpal = 3 * hdata["colors"] * hdata["depth"] // 8 lenimgdata = numchannels * hdata["rows"] * hdata["columns"] assert len(rest) >= lenpal + lenimgdata, (len(rest), lenpal, lenimgdata) results.append( ( "sRGB", hdata.get("resolution") or 0, "MIFF", zlib.compress(rest[lenpal : lenpal + lenimgdata]), None, # FIXME: allow alpha channel smask hdata["columns"], hdata["rows"], rest[:lenpal], # palette False, # inverted hdata["depth"], 0, # rotation None, # icc profile ) ) if len(rest) > lenpal + lenimgdata: # another image is here assert ( rest[lenpal + lenimgdata :].lower().startswith(b"id=imagemagick") ), (len(rest), lenpal, lenimgdata) results.extend(parse_miff(rest[lenpal + lenimgdata :])) return results ```
Owner

The code above works with all my MIFF test cases. Now I just need a 16 bit CMYK MIFF image. If I try to convert your testCMYK.tif to MIFF using convert I get:

convert-im6.q16: Sorry, can not handle image. `/home/josch/Downloads/testCMYK.tif' @ error/tiff.c/TIFFErrors/606.

Do you have more luck or can supply me with a 16 bit CMYK MIFF file?

The code above works with all my MIFF test cases. Now I just need a 16 bit CMYK MIFF image. If I try to convert your `testCMYK.tif` to MIFF using convert I get: convert-im6.q16: Sorry, can not handle image. `/home/josch/Downloads/testCMYK.tif' @ error/tiff.c/TIFFErrors/606. Do you have more luck or can supply me with a 16 bit CMYK MIFF file?
Owner

Something about your TIFF file seems odd. When I run tifftopnm from netpbm I get the following message:

tifftopnm: This color separation file uses an inkset (41712) we can't handle.  We handle only CMYK.

so then I ran tiffinfo on your file and I got this:

=== TIFF directory 0 ===
TIFF Directory at offset 0xc98b4 (825524)
  Image Width: 780 Image Length: 1122
  Resolution: 39.3701, 39.3701 pixels/cm
  Position: 0.6, 0.6
  Bits/Sample: 16
  Compression Scheme: LZW
  Photometric Interpretation: separated
  Ink Names: cyan, magenta, yellow, 
  Orientation: row 0 top, col 0 lhs
  Samples/Pixel: 4
  Planar Configuration: single image plane
  ImageDescription: Test chart created with Argyll
  InkSet: 1

So is this really a CMYK TIFF or is it just a cyan, magenta, yellow TIFF?

In any case, I managed to create a 16 bit CMYK test file by converting a 16 bit RGB png to CMYK using:

convert rgb16bit.png -colorspace CMYK test.miff

That MIFF file then looks how we would like it:

id=ImageMagick  version=1.0
class=DirectClass  colors=0  matte=False
columns=60  rows=60  depth=16
type=ColorSeparation
colorspace=CMYK

And together with the following patch I get a 16 bit CMYK PDF as I put into the attachment:

https://paste.debian.net/1245266/

Something about your TIFF file seems odd. When I run `tifftopnm` from `netpbm` I get the following message: tifftopnm: This color separation file uses an inkset (41712) we can't handle. We handle only CMYK. so then I ran `tiffinfo` on your file and I got this: ``` === TIFF directory 0 === TIFF Directory at offset 0xc98b4 (825524) Image Width: 780 Image Length: 1122 Resolution: 39.3701, 39.3701 pixels/cm Position: 0.6, 0.6 Bits/Sample: 16 Compression Scheme: LZW Photometric Interpretation: separated Ink Names: cyan, magenta, yellow, Orientation: row 0 top, col 0 lhs Samples/Pixel: 4 Planar Configuration: single image plane ImageDescription: Test chart created with Argyll InkSet: 1 ``` So is this really a CMYK TIFF or is it just a cyan, magenta, yellow TIFF? In any case, I managed to create a 16 bit CMYK test file by converting a 16 bit RGB png to CMYK using: convert rgb16bit.png -colorspace CMYK test.miff That MIFF file then looks how we would like it: ``` id=ImageMagick version=1.0 class=DirectClass colors=0 matte=False columns=60 rows=60 depth=16 type=ColorSeparation colorspace=CMYK ``` And together with the following patch I get a 16 bit CMYK PDF as I put into the attachment: https://paste.debian.net/1245266/
7 KiB
Author

Curious. It is CMYK (it's 4 channel and the InkSet:1 on last line of your tiffinfo output means exactly this), but it does seem to have only cmy inks named which is perhaps capable of confusing some applications.

Certainly, my version of ImageMagick (default Ubuntu 20.04 package) has no problem with the testCMYK TIFF.

convert --version
Version: ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
Copyright: © 1999-2019 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff webp wmf x xml zlib

It will happily process it, including converting to MIFF. It also opens fine as a 16bit CMYK file in KDE krita (not gimp which doesn't handle cmyk).

In any case, your patch works a treat and (via converting to a MIFF) I can embed testCMYK in a pdf successfully. Fantastic - Thanks!

The new code is rather python 3.10-y in it's use of match. I had to install a newer interpretor to get it to run on Ubuntu 20.04. Something to note if you merge into the mainline.

Curious. It is CMYK (it's 4 channel and the InkSet:1 on last line of your tiffinfo output means exactly [this](https://www.awaresystems.be/imaging/tiff/tifftags/inkset.html)), but it does seem to have only cmy inks named which is perhaps capable of confusing some applications. Certainly, my version of ImageMagick (default Ubuntu 20.04 package) has no problem with the testCMYK TIFF. ``` convert --version Version: ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org Copyright: © 1999-2019 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC Modules OpenMP Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff webp wmf x xml zlib ``` It will happily process it, including converting to MIFF. It also opens fine as a 16bit CMYK file in KDE krita (not gimp which doesn't handle cmyk). In any case, your patch works a treat and (via converting to a MIFF) I can embed testCMYK in a pdf successfully. Fantastic - Thanks! The new code is rather python 3.10-y in it's use of match. I had to install a newer interpretor to get it to run on Ubuntu 20.04. Something to note if you merge into the mainline.
Author

From the patch:

_# theoretically RGBA and CMYKA should be supported as well
_# please teach me how to create such a MIFF file

Note you can quite easily create a 16bpc CMYKA MIFF file with

convert logo: -background none -transparent white -flatten -depth 16 -colorspace cmyk out.miff

Remove the -depth 16 or -colorspace cmyk for 8bit or RGBA.

From the patch: > _# theoretically RGBA and CMYKA should be supported as well > _# please teach me how to create such a MIFF file Note you can quite easily create a 16bpc CMYKA MIFF file with ``` convert logo: -background none -transparent white -flatten -depth 16 -colorspace cmyk out.miff ``` Remove the `-depth 16` or `-colorspace cmyk` for 8bit or RGBA.
josch closed this issue 2022-06-27 12:22:29 +00:00
Owner

thank you for your feedback!

i committed the preliminary MIFF support to main and will add more test cases later but your use-case of 16bit CMYK should be covered already so have fun! :)

thank you for your feedback! i committed the preliminary MIFF support to main and will add more test cases later but your use-case of 16bit CMYK should be covered already so have fun! :)
Contributor

As @jpnp has mentioned already, the new MIFF parser code uses match/case, which is only available since Python 3.10. You'll either want to set python_requires to >= 3.10 in setup.py, or switch back to classical if clauses.

As @jpnp has mentioned already, the new MIFF parser code uses `match`/`case`, which is only available since Python 3.10. You'll either want to set `python_requires` to `>= 3.10` in `setup.py`, or switch back to classical `if` clauses.
Owner

@mara0004 yeah i'm still thinking about that bit. The match/case syntax is a feature i've waited for since i started using python a decade ago so i'm really eager to use it now. I'm not sure how much of a problem this is for any users.

@mara0004 yeah i'm still thinking about that bit. The `match`/`case` syntax is a feature i've waited for since i started using python a decade ago so i'm really eager to use it now. I'm not sure how much of a problem this is for any users.
Contributor

While newer Linux distributions probably come with recent enough versions of Python, I think it might cause trouble for users who are still on older distros. Installing another Python in parallel isn't always desirable, and might not be an option if img2pdf is used in a larger app or framework that depends on system packages.


I too have been looking forward to the introduction of a switch/case-like feature in Python, but am quite disappointed with the way it was implemented. As you might have noticed, non-dotted constants aren't usable with Python's match/case. The increased indentation level doesn't feel very nice, either.

While newer Linux distributions probably come with recent enough versions of Python, I think it might cause trouble for users who are still on older distros. Installing another Python in parallel isn't always desirable, and might not be an option if img2pdf is used in a larger app or framework that depends on system packages. **** I too have been looking forward to the introduction of a switch/case-like feature in Python, but am quite disappointed with the way it was implemented. As you might have noticed, non-dotted constants aren't usable with Python's match/case. The increased indentation level doesn't feel very nice, either.
Author

Both Debian Stable, and Ubuntu 20.04 (it'll be a while before we upgrade at work) are pre 3.10 - never mind RHEL and the rest. I'd guess that unless they have a specific need for a newer version, users on those OSs are using the .debs anyway.

I think it's OK to use match (it's easy to see how much cleaner it makes the parsing code), but you'd want to flag it in the package metadata, and in the installation section of the Readme. Finding out while trying it out is more off-putting.

Both Debian Stable, and Ubuntu 20.04 (it'll be a while before we upgrade at work) are pre 3.10 - never mind RHEL and the rest. I'd guess that unless they have a specific need for a newer version, users on those OSs are using the .debs anyway. I think it's OK to use match (it's easy to see how much cleaner it makes the parsing code), but you'd want to flag it in the package metadata, and in the installation section of the Readme. Finding out while trying it out is more off-putting.
Owner

@mara0004 thank you for your input -- i've reverted the match/case usage for now: af6fe27d53

@mara0004 thank you for your input -- i've reverted the match/case usage for now: af6fe27d53476fe68d43b11766651a6637a098a7
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: josch/img2pdf#144
No description provided.