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?
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. :/
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.
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
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?
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.
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!
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.
importglobimportreimportzlibline_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.phpdefparse_miff(data):results=[]header,rest=data.split(b":\x1a",1)header=header.decode("ISO-8859-1")assertheader.lower().startswith("id=imagemagick")hdata={}fori,lineinenumerate(re.findall(line_re,header)):ifnotline:continuek,v=line.split("=",1)ifi==0:assertk.lower()=="id"assertv.lower()=="imagemagick"matchk.lower():case"class":matchv:case"DirectClass"|"PseudoClass":hdata["class"]=vcase_: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 filematchv:case"sRGB"|"CMYK"|"Gray":hdata["colorspace"]=vcase_:print("cannot understand colorspace",v)case"depth":matchv:case"8"|"16"|"32":hdata["depth"]=int(v)case_:print("cannot understand depth",v)case"colors":hdata["colors"]=int(v)case"matte":matchv:case"True":hdata["matte"]=Truecase"False":hdata["matte"]=Falsecase_:print("cannot understand matte",v)case"columns"|"rows":hdata[k.lower()]=int(v)case"compression":print("compression not yet supported")case"profile":assertvin["icc","exif"]hdata["profile"]=vcase"resolution":dpix,dpiy=v.split("x",1)hdata["resolution"]=(float(dpix),float(dpiy))assert"depth"inhdataassert"columns"inhdataassert"rows"inhdatamatchhdata["class"]:case"DirectClass":if"colors"inhdata:asserthdata["colors"]==0matchhdata["colorspace"]:case"sRGB":numchannels=3case"CMYK":numchannels=4case"Gray":numchannels=1ifhdata["matte"]:numchannels+=1ifhdata.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 thisprint("FAIL: exif")else:lenimgdata=(hdata["depth"]//8*numchannels*hdata["columns"]*hdata["rows"])assertlen(rest)>=lenimgdata,(len(rest),hdata["depth"],numchannels,hdata["columns"],hdata["rows"],lenimgdata,)results.append((hdata["colorspace"],hdata.get("resolution")or0,"MIFF",zlib.compress(rest[:lenimgdata]),None,# smaskhdata["columns"],hdata["rows"],[],# paletteFalse,# invertedhdata["depth"],0,# rotationNone,# icc profile))iflen(rest)>lenimgdata:# another image is hereassertrest[lenimgdata:].lower().startswith(b"id=imagemagick")results.extend(parse_miff(rest[lenimgdata:]))case"PseudoClass":assert"colors"inhdataifhdata["matte"]:numchannels=2else:numchannels=1lenpal=3*hdata["colors"]*hdata["depth"]//8lenimgdata=numchannels*hdata["rows"]*hdata["columns"]assertlen(rest)>=lenpal+lenimgdata,(len(rest),lenpal,lenimgdata)results.append(("sRGB",hdata.get("resolution")or0,"MIFF",zlib.compress(rest[lenpal:lenpal+lenimgdata]),None,# FIXME: allow alpha channel smaskhdata["columns"],hdata["rows"],rest[:lenpal],# paletteFalse,# invertedhdata["depth"],0,# rotationNone,# icc profile))iflen(rest)>lenpal+lenimgdata:# another image is hereassert(rest[lenpal+lenimgdata:].lower().startswith(b"id=imagemagick")),(len(rest),lenpal,lenimgdata)results.extend(parse_miff(rest[lenpal+lenimgdata:]))returnresults
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
```
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?
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/
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.
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.
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.
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! :)
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.
@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.
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.
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.
I am trying to convert a 16bit CMYK image to PDF.
When I use
I get
Is it possible to support 16bit TIFF data with img2pdf?
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. :/
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
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?
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.
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!
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.
Here is a MIFF parser:
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:Do you have more luck or can supply me with a 16 bit CMYK MIFF file?
Something about your TIFF file seems odd. When I run
tifftopnm
fromnetpbm
I get the following message:so then I ran
tiffinfo
on your file and I got this: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:
That MIFF file then looks how we would like it:
And together with the following patch I get a 16 bit CMYK PDF as I put into the attachment:
https://paste.debian.net/1245266/
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.
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.
From the patch:
Note you can quite easily create a 16bpc CMYKA MIFF file with
Remove the
-depth 16
or-colorspace cmyk
for 8bit or RGBA.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! :)
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 setpython_requires
to>= 3.10
insetup.py
, or switch back to classicalif
clauses.@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.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.
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.
@mara0004 thank you for your input -- i've reverted the match/case usage for now:
af6fe27d53