[18:15:21] <tremalo> I have some question about embedded ICC profiles and transforming them to something like sRGB.
[18:16:20] <tremalo> Reading the source I can basically see how transforming profiles works, but my source profile is embedded in an image (not a file on a disk).
[18:19:10] <wiredfool> does it work with a io.bytesio object?
[18:19:27] <tremalo> Hrm, that’s a great question. Let me try it.
[18:24:56] <tremalo> Sweet, I got some transform working.
[18:25:06] <tremalo> I have another question, more about profiles in general though.
[18:25:36] <tremalo> My goal right now is to transform N images into a common profile so that when they are stitched together in a collage they all look like their originals.
[18:26:34] <tremalo> I know there is a lot of variability in color and color rendering… not even sure if it would work. My first attempt does indeed change the color of the output image but it still doesn’t match the original.
[18:29:34] <wiredfool> I'm not entirely sure that is going to work
[18:31:20] <tremalo> right now I’m just doing something like this: https://gist.github.com/xealot/d6bf8730e525ed65a0ae
[18:31:29] <wiredfool> so, if you've got a source image with a device specific color profile, and you change it to sRGB (frex), you should get an approximation of the original image mapped into the sRGB color space in a way that if you were to put it on different sRGB devices, you should get similar results
[18:31:42] <wiredfool> they're going to be different from the original, but consistent
[18:32:23] <wiredfool> where device specific color profile is really anything other than sRGB
[18:33:21] <tremalo> I read somewhere that sRGB is sort of the go to profile for use on the web anyway, so I thought maybe converting images to that before manipulation would have a better result. It just seems odd that even on the same device the translation is an approximation.
[18:38:01] <wiredfool> do you know that what you're displaying when you look at the original image uses the embedded profile?
[18:38:43] <tremalo> Well, I believe it takes into account (Chrome window in this case). Because when I save the image without the ‘icc_profile’ kwarg on save() it looks totally different.
[18:39:11] <tremalo> The only thing I’ve done so far that achieves the exact same image display is to pass in the icc_profile kwarg during save with the embedded profile from the loaded image.
[18:39:33] <tremalo> That produces the same results… based on that evidence I have concluded that the profile is being considered for rendering.
[18:44:59] <wiredfool> so there's two possibilities: sRGB is a smaller/different output space than the input profile, so the original is unrepresentable in the output space
[18:45:07] <wiredfool> 2) it's not working correctly
[18:45:26] <tremalo> Alright, well I’m happy to assume the first option as the second would suck more.
[18:45:38] <wiredfool> otoh, the second might be fixable
[18:45:45] <tremalo> I’m not really stuck on sRGB I just saw that it was “very compatible”
[18:45:45] <wiredfool> you have access to photoshop?
[18:46:07] <tremalo> I would be fine translating it into another common profile… or something.
[18:46:59] <wiredfool> sRGB is a least common denominator, so it's smaller than most other color spaces. Widely supported, but not very good. But happens to be pretty compatible with things like photoprinters and web browsers
[18:47:34] <wiredfool> so, what I'd do is load one of these into PS, and convert to sRGB. Check to see if the output is similar
[18:51:21] <tremalo> But if the image is already using sRGB the transform should look the same right?
[18:53:05] <wiredfool> it should, or at least, it should be very similar
[18:54:57] <tremalo> Hrm, my current code tries to convert the embedded profile to sRGB. When I told PS to go ahead and strip the profile the image preview is exactly the same coloring as the “converted” image that I use Python to create.
[18:55:36] <wiredfool> are you actually getting the profile in the output image?
[18:56:59] <tremalo> I lied, it’s not exact. It’s really close though. I don’t know how to check for a color profile, but photoshop does not ask me to strip it when I load the image from PIL
[18:57:32] <wiredfool> load it back into Pillow and look for the embedded profile like you were doing on the initial image
[18:57:49] <wiredfool> or try imagemagik: identify -verbose img.jpg
[19:02:41] <wiredfool> It's got some profile info, since there's a Chromaticity entry
[19:03:37] <tremalo> Perhaps that’s where it’s losing accuracy?
[19:04:09] <tremalo> If I pull the profile out of the image.info and then re-save it using the icc_profile kwarg it’s accurate.
[19:04:45] <tremalo> But right now I am actually converting the pixels from the original profile to “sRGB”… then it looks like it still has some profile being applied right?
[19:06:14] <tremalo> maybe I don’t understand exactly how all this works, does the transform modify the image or the pixels? (I assume the pixels)
[19:06:25] <tremalo> modify the profile or the pixels**
[19:08:55] <tremalo> (ok, I turned that stupid setting off in PS. Opening the original image in photoshop renders the exact same pixels as the browser does I think)
[19:19:32] <wiredfool> The transform modifies the image, and stores it with the new profile and the new pixels. When the display program reads that, it takes that profile and interprets the pixels accordingly and displays them.
[19:19:55] <wiredfool> if there's no profile, then it's just the standard linear 0-255, splat stuff up.
[19:20:12] <wiredfool> (or, if the profile is being ignored, or not understood)
[19:21:05] <tremalo> I just checked the input and output images, same color profile name and same “chromaticity” values.
[19:21:18] <wiredfool> but when you investigate the image data, looking at the bytes or the pixel values, that's generally going to be just the raw data, the profile is going to sit on top of that and interpret it for the display.
[19:21:47] <wiredfool> I'm goign to go with option 2 then, something is broken
[19:22:12] <tremalo> The transform isn’t accurate? Or am I doing something stupid?
[19:23:35] <tremalo> I wish I could produce even a halfway decent bug report… but I’m not sure what is broken.
[19:24:31] <wiredfool> Well, I'm probably the one who'd be fixing it, unless you found the bug first
[19:24:41] <wiredfool> and then I'd be reviewing it.
[19:25:14] <tremalo> Then, is there anything I can do to better narrow down where things are going astray?
[19:25:22] <wiredfool> the lcms stuff had a big rev a couple releases ago, and I'm not sure how much people use it, so I wouldn't consider it battle tested
[19:25:59] <tremalo> Yeah, based on my findings in Google people don’t seem to concern themselves with colorspace too much.
[19:26:16] <tremalo> Our photgraphers have complained about it to me a number of times however :)
[19:26:42] <wiredfool> It's going to take step by step verification of the image data + profiles, checking for sanity against transforms from other programs
[19:27:22] <wiredfool> things I'd look at: Can Pillow save a jpeg with a profile and have that profile respected by other programs
[19:27:45] <wiredfool> It may take pretty outlandish profiles to make sure that it's respected.
[19:27:59] <tremalo> well, I know it can take the profile the is embedded in a jpeg and pass it in to the save() method and have it work… that’s my only success today though.
[19:28:11] <wiredfool> IIRC, there are at least a couple ways that profiles cna be represented, by name, and by actually embedding the profile.
[19:28:49] <tremalo> I also tried to take a CMSProfile object and put it back into the image somehow but I couldn’t work that one out.
[19:28:52] <wiredfool> IIRC, you had to do both to get some web browsers to twig on to it, but that was years ago, when flash wasn't color managed and most everything else wasn't either
[19:29:19] <wiredfool> not that flash is managed now, but you wouldn't know that with photographer's websites all being in flash
[19:29:38] <wiredfool> there may be missing bits of the lcms api
[19:30:10] <wiredfool> the next thing I'd look at is do the conversion in PS, save it with the profile, and check the bits in pillow
[19:30:23] <tremalo> Well, from my own experience it was a little bit of a struggle to figure out how to work with profiles that were already in memory (e.g. loaded in PIL)
[19:30:25] <wiredfool> there are test routines for assert_image_similar and assert_imageesual
[19:31:27] <wiredfool> there are lots of tests, but we need more.
[19:32:37] <wiredfool> so if we take the image through the workflow manually using ps, and we do it automatically through pillow, we should end up with images that are similar enough to pass the test
[19:33:02] <wiredfool> at assert_image_similar(pillow, ps, 3) or so. 3 being the average numerical difference
[19:36:17] <tremalo> I would agree with you, I’m sure the color profile and color management suite is far less tested and used. I’ve been using PIL (and pillow) now for going on 7-8 years probably and am just starting to try to “do it right” with color profiles.
[19:39:04] <tremalo> If I someone who knows almost nothing about color profiles and image maths could be useful I would be happy to help! For now I’ll just step around this little issue as best I can.
[19:39:57] <wiredfool> do what you can, I'll help where I can. I hang out here, and on github
[19:40:27] <tremalo> Thanks for the time, I appreciate the effort.
[19:40:37] <wiredfool> iif you get it to a test case, that is a great start
[19:40:56] <tremalo> I can produce a test case with a test image for you if that’s what it takes.
[21:00:34] <tremalo> I have compared the before/after image in a few different applications now (Preview, Photoshop, Chrome, Firefox) and I see slightly different things.
[21:01:19] <tremalo> If I load these images in Firefox or Chrome the different is pretty noticeable, esp. in skin tones. However in Preview and Phtoshop the color is a *lot* closer to the original.
[21:03:06] <wiredfool> bet safari does it right too
[21:04:33] <tremalo> safari does keep the skin tones much closer, you’re right
[21:04:58] <tremalo> the primary difference in the “close” applications is highlights and lowlights