philgyford / python-halftone

A python module that uses PIL/Pillow to give images a halftone effect
87 stars 27 forks source link

Fix CMYK/RGB conversion for JPEGs and PNGs #7

Open philgyford opened 3 years ago

philgyford commented 3 years ago

The colours in output files are darker in JPEGs compared to PNGs. The JPEGs are saved with CMYK mode, while PNGs must be RGB.

The difference in output colours is something to do with conversion between CMYK and RGB, and colour profiles, but I don't understand how to fix this.

e.g. converting this image (which is actually an RGB JPEG):

cmyk

We output a JPEG that looks like this:

cmyk_halftoned

Or a PNG that looks like this:

cmyk_halftoned

Minimal code for trying this out:

import halftone

h = halftone.Halftone("/path/to/file.jpg")
h.make(output_format="png")

Change output_format to "jpeg" to see the alternative version.

shankhya commented 3 years ago

Does this help? https://pillow.readthedocs.io/en/stable/reference/ImageCms.html

Maybe the JPEG image can be transformed to the output ICC profile first and then halftoning can be done?

I tried the following simply on an image. If you try incorporating something like can it work? I am not confident with coding, but I guess the idea may be something similar.

from PIL import Image from PIL import ImageCms

im = Image.open('Banff.jpg') a = ImageCms.buildTransform('sRGB Color Space Profile.icm', 'SWOP2006_Coated3v2.icc', 'RGB', 'CMYK') b = ImageCms.applyTransform(im, a) b.show()

I think the applyTransform function converts the image from input to output profile much like photoshop or any other CMS does.

philgyford commented 3 years ago

Thanks. I don't understand colour profiles unfortunately although I'm happy to give things a try. Your example seems to rely on those profile files existing - I get "PIL.ImageCms.PyCMSError: cannot open profile file".

shankhya commented 3 years ago

ICC profiles contains Look Up Tables that can be used to convert images from one color space to the other. In the above example, I have used the sRGB profile as my input (display RGB) profile and converted the image to SWOP (offset printer CMYK) profile. There are in-built color profiles that comes with the OS. For windows, the location of such profile is: C:\Windows\System32\spool\drivers\color. I had copied both the profiles in question to my working python folder. I think your error is caused as your working directory doesn't have those profiles. If you are using Mac, then you can try Mac HD/Library/ColorSync/Profiles or Mac HD/Users/username/Library/ColorSync/Profiles.

philgyford commented 3 years ago

I'm on a Mac, but don't have those profiles in that directory. I'm not sure how one would write code that would work for everyone. Or provide the correct profile for them. Or instruct them what to do to get the correct profile.

shankhya commented 3 years ago

I don't think there is any correct profile, because the profile combination will depend upon your working display profile (for ex, Windows normally has sRGB by default as its working display profile) and the printer in which you want to print the image with (for ex, SWOP, GRACoL, FOGRA, etc). Maybe adding some sample input and output profiles in a folder, just like the one you have done for the example folder in your code for some example images. Can that work out? I am attaching a link for a folder that I have created which contains all the ICC profiles I had on with my OS. https://github.com/shankhya/Color-Profiles/tree/main/ICC%20Profiles