[Lcms-user] Multithreading - Transformation and lcms context
An ICC-based CMM for color management
Brought to you by:
mm2
From: Marco F. <Mar...@en...> - 2017-08-25 09:08:57
|
All, I've got a multithreading / lcms context related question on lcms2. I'm currently using lcms 2.7, but certainly can upgrade to latest release, if that makes any difference. I tried to find the answer to this somewhere in the documentation, but couldn't get a definite answer. For a project, I need to do color space conversion (from RGB -> CMYK, not that it matters) in a dll. The CMYK profiles are mostly large table based device profiles, so creating the transformation takes a while (depending on the image size, most often longer than applying it). The code might be called thousands of times in an hour. As all the transformations are likely from the same one or two RGB profile(s) to the same (or a little number of different) CMYK profile(s), I would like to cache transformations. The problem is, that the dll calls might be called from different threads and might be called concurrently. For each of the calls, in the original implementation I was: - creating a lcms context - load the profiles - create the transformation - close the profiles - apply the transformation to the image (potentially in multiple threads) - delete the transformation - delete the lcms context. As I said, I would like to cache a small number of transformations. As I wasn't sure about the multithreading (transformation potentially used in different threads) and concurrency (code might be called multiple times) aspects, my first implementation is trying to play save going through a device link: - create a lcms context - check if transformation from IN->OUT is in chache. if not: load profiles, create transformation, close profiles, CREATE A DEVICELINK FROM TRANSFORMATION, SAVE DEVICELINK IN MEMORY (CACHE) - if it is in cache: load transformation from devicelink in cache - apply the transformation to the image (potentially in multiple threads) - delete the transformation (not the devicelink). - delete the lcms context. - if cache item needs to be cleared, delete the devicelink buffer. That process as two downsides: (a) loading a transformation from devicelink profile is much faster than creating it from the in and out profile, but still takes quite some time. (b) the results are slightly different (not as accurate?) when loading the transformation from devicelink. I'm getting some CMYK value differences up to ~2 or 3 values per channel on 8 bit images. What I'm wondering is: Once I've got a handle to a transformation, I can apply it to one image in multiple threads (although right now I'm doing that while the lcmsContext still exists). Also, to apply it, I don't need to pass in a lcms context to cmsDoTransform (at least not explicitly - maybe a handle is stored in the transformation). So - my questions: 1. Does that mean I could actually just cache the transformation (cmsHTRANSFORM) and re-use it, although the lcms context originally used to load the profiles the transformation was deleted? Can I delete the transformation from a different thread it was created from? 2. Alternatively, if that doesn't work, could I just cache the transformation together with the lcmsContext it was created in and use it from different threads concurrently on different images? And if so, could multiple DIFFERENT transformations, which might be applied concurrently, share the same context (assuming they are not CREATED concurrently) or would I need a separate context per transformation? Thanks for any useful input... Marco |