Page 1 of 2 12 LastLast
Results 1 to 40 of 55

Thread: Color Management (ICC Profile) support in VB6: guide and sample project

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Lightbulb Color Management (ICC Profile) support in VB6: guide and sample project

    Name:  Color_Management_Screenshot.jpg
Views: 2945
Size:  108.4 KB


    Download the sample project (258kb, including sample images)

    VB6_ColorManagement.zip (updated 08 Dec 2013)


    What does the sample project include?

    • Color_Management (module). This contains all the necessary code for adding color management to your VB project.
    • pdLayer (class). A DIB wrapper borrowed from this vb6 project (hence the "pd" prefix). Useful if you want to load JPEG/PNG/TIFF files with embedded profiles. Not necessary if your application won't support loading images at run-time.
    • frmColorManagement (form). Sample form. Demonstrates use of the included module.
    • cCommonDialog (class). Code-only common dialog wrapper by Steve McMahon. Included to make loading images easier.


    Change log

    Code:
    08 December 2013
    * CMYK format JPEGs and TIFFs with embedded profiles are now supported
    * The interface now reports if an image contains an embedded ICC profile 
    * 32bpp images are now drawn on a checkerboard background
    * Fixed swapped red and blue channels on 32bpp images
    * Added a 32bpp PNG with embedded profile to the sample images folder
    * Miscellaneous performance and coding improvements, with thanks to Bonnie West for her help and expertise
    
    08 November 2013
    * Original version
    Acknowledgments

    Many thanks to LaVolpe for this helpful post and sample code, which provided a great starting point for this topic.

    What is color management and why does it matter?

    Short answer: if your application uses images (and especially if it lets the user load or modify images), those images won't look 100% correct without color management.

    Long answer: Color Management article on Wikipedia.

    Do I need color management in my application?

    It depends. If you do not use images in your application, then no - color management is a waste of your time.

    If you do use images in your application, then color management is worth considering.

    Most importantly, if you allow users to load their own images, I would consider color management a "must-have". Without it, you risk images not looking the same way they do in other software (including Windows photo viewer, PhotoShop, GIMP, etc). Users may think your software is broken, when really, it is just not color managed.

    Is it difficult to support color management in a VB6 app?

    Yes and no, with an emphasis on "mostly no". Color management can be broken into two broad categories:

    + Color management for your forms and picture boxes. Retrieving the stock system color profile, assigning it to VB picture boxes and forms, then activating color management is relatively simple. With the sample project, you can do it in two lines of code. (Note that image boxes cannot be easily color managed, because they do not expose an hDC property.)

    + Color management for imported images. This is trickier, and it requires the use of GDI+ (or some other imaging library, like FreeImage) to parse the image data and extract any embedded ICC profile. The sample project simplifies the process to a few lines of code, but it assumes GDI+ is present (something that should be true for most anyone on Win XP SP2 or later, but which may not be guaranteed for earlier XP users). It also requires the use of DIBs. The sample project includes a fairly comprehensive 24/32bpp DIB wrapper, but it's quite a bit of code, and may complicate your project more than you want.

    Can I drop your code into my project and assume everything is color managed?

    Mostly. As I said, you'll need to manually activate color management for any forms or picture boxes that display images. This is done using two lines of code:

    Code:
    assignColorProfileToDC PictureBox.hDC
    setColorManagementForDC PictureBox.hDC, True
    Please note that if your picture boxes and/or forms use AutoRedraw, you may need to re-activate color management prior to drawing on the picture box, because AutoRedraw can cause the hDC of the picture box to change. (There is no measurable performance overhead in reapplying color management settings.)

    If you allow the user to load images in your software, it will take more work to ensure color management for said images. Refer to the sample project for details.

    What versions of Windows are supported?

    Anything XP or later, assuming GDI+ is present on the target machine. If you don't care about supporting ICC profiles embedded in images, the code should work for Windows 2000 as well, though I haven't tested this.

    Are any special dependencies required?

    Nope! Windows itself provides a very capable color management engine, so you don't need to add any DLLs or other references to your project. Everything is accomplished by flat function calls to mscms.dll.

    Does this code provide the same level of color management as Adobe PhotoShop?

    No, but it's closer than you might think. This project makes a number of assumptions in order to keep things simple and fast (like using the sRGB working space by default, rather than providing a choice). PhotoShop provides much more granular control over every step of the color management chain. That said, you should not notice any difference between images loaded via this sample project and images loaded via PhotoShop, assuming your copy of PhotoShop uses recommended settings.
    Last edited by Tanner_H; Dec 8th, 2013 at 10:43 AM. Reason: See changelog
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    I've updated the sample project with a number of fixes and improvements - some small, some large. The biggest change involves proper handling of CMYK format JPEGs and TIFFs. To my knowledge, the CMYK pixel format wasn't added until later versions of GDI+, so the new code may not work on unpatched XP or Vista installs. (If your version of GDI+ does not support the CMYK format, the program will simply apply a default CMYK -> RGB conversion, rather than using the embedded profile.)

    Minor improvements have also been made to 32bpp image handling, the interface, and the included DIB wrapper. Thank you to Bonnie West for her contributions to this update!
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  3. #3
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Thanx for the mention. I'll probably be mentioning you too when I have a chance to consider including this information in my alpha image control. Currently, I'm looking at extracting images from PDF files. Still fine tuning the parsing & conversion routines. But, many pdf images make use of ICC profiles and was looking at a way to use this info. Even though GDI+ supposedly recognizes embedded ICC profiles, don't think it can apply them with the GDI+ APIs wrapper, only with the .Net classes. Using ICC when loading an image is an optional parameter not available to the GDI+ APIs as far as I know.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Yeah, I had no luck using flat calls to GdipLoadImageFromFileICM(). While I assume it works, I haven't figured out where in the pipeline the color management is actually applied. You can clearly see in the resulting image that a hard conversion hasn't been applied (e.g. no equivalent of TranslateBitmapBits), so the ICC data must just be flagged somewhere inside the GDI+ Image object... but how to get to it, or activate it, or make of use of it during draw calls, I couldn't solve.

    Granted, if you're going to be moving data between GDI+ and GDI containers, it's probably best to handle color management manually. And for your Alpha Image Control, sRGB should be perfectly sufficient as an intermediate space, so hopefully it won't be too tough to get color management working.

    Good luck with your PDF work.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  5. #5
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by Tanner_H View Post
    Yeah, I had no luck using flat calls to GdipLoadImageFromFileICM(). While I assume it works...
    You know what they say about "assume" ?

    Just FYI, should you revisit this in the near future.

    Per MSDN: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
    GdipLoadImageFromFileICM - This flat function does not use ICM.
    GdipLoadImageFromStreamICM - This flat function does not use ICM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by LaVolpe View Post
    You know what they say about "assume" ?
    A lesson I have apparently still not learned! Thanks for the links. Interesting to me that those are specifically marked as not using ICM, when GdipCreateBitmapFromFile/StreamICM apparently do:

    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  7. #7
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Here's one for you to play with if you feel like a challenge

    The attached jpg is extracted from a PDF file. Not all image viewers will display it correctly. Your project doesn't but can. What makes this jpg a bit different is that:
    1) It is a cmyk color space
    2) It has no embedded color profile & if it did, probably wouldn't display correctly anyway
    3) The jpg does have an ADOBE app marker & that's kinda key here 'cause of the last byte in that app block

    After lots of experimenting, it appears that cmyk jpgs with the Adobe app marker (and the last byte in the app block is 2), they have their cmyk values inverted and GDI+ isn't aware of this. To get it displayed correctly, I did download one of the several cmyk color profiles available on Adobe's website. But that alone isn't enough & a cmyk ICC profile is needed; doesn't have to be Adobe. Then I set your color management class to use that profile. Just prior to applying the profile to the temp DIB, the DIB bits were inverted (i.e., all bytes XOR'd with 255). The result was a far better image rendering.

    Also attached is a png file with 4 images:

    1) The attached jpg as it is displayed in your project & many other viewers
    2) The image after all bytes inverted & a cmyk color profile applied
    3) The image without any color profile applied and after all bytes inverted after rendering
    4) An experiment. Try to get GDI+ to display a better image than #3 w/o a ICM
    I tried creating a blank CMYK GDI+ image via GdipCreateBitmapFromScan0. Then tried updating that GDI+ image's data with the bytes read from the original GDI+ image (after inverting bytes). Thought this might be a better result than just inverting the bytes after rendering, but GDI+ is not playing fair as you can see. The code looks a bit like this:
    Code:
    Dim b() As Byte
    ReDim b(0 To imgHeight * imgWidth * 4 - 1)
    With copyBitmapData
        ...
        .scan0 = VarPtr(b(0))
    End With
    ' read bytes into array
    GdipBitmapLockBits hImage, tmpRect, ImageLockModeUserInputBuf Or ImageLockModeRead, PixelFormat32bppCMYK, copyBitmapData
    GdipBitmapUnlockBits hImage, copyBitmapData
    
     ... invert all bytes by XORing with 255
    
    ' create new CMYK image
    GdipCreateBitmapFromScan0 imgWidth, imgHeight, copyBitmapData.stride, PixelFormat32bppCMYK, ByVal 0&, tImage
    
    ' update new image with inverted bytes
    GdipBitmapLockBits tImage, tmpRect, ImageLockModeUserInputBuf Or ImageLockModeWrite, PixelFormat32bppCMYK, copyBitmapData
    GdipBitmapUnlockBits tImage, copyBitmapData
    So, 1) it is possible to display these types of jpgs pretty well with a decent cmyk profile and 2) not sure it is possible to get a good rendering without a color profile.

    Also note that I haven't tried this with GDI+ v1.0. I do not believe you can get the original cmyk data since there is no color space of PixelFormat32bppCMYK with that version. With GDI+ v1.0, something like #3 above, in the conversion results, may be best that can be hoped for without finding a way of getting the raw cmyk bytes.

    Edited: Thought I'd show you a cmyk jpeg with no ICC profile and the last byte in the app block is not 2. The grayscale left image is with a cmyk color profile applied, the right side is without. Virtually indistinguishable, i.e., GDI+ has no problems with it.

    FYI: here are the Adobe app marker blocks for the 2 images: 1) color 2) grayscale
    1) FF D8 FF EE 0 E 41 64 6F 62 65 0 64 80 0 0 0 2
    2) FF D8 FF EE 0 E 41 64 6F 62 65 0 64 80 0 0 0 0

    Conversation finished, removed the sample images
    Last edited by LaVolpe; Aug 25th, 2014 at 08:58 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Interesting case. This link seems to define the problem pretty well:

    http://blog.idrsolutions.com/2011/10...-in-pdf-files/

    So it seems like it's an issue specific to JPEGs coming from PDFs, which require their own custom conversion. I'd be curious to see how much the end result differs if the Postscript conversion formula is used.

    I'd be leery to change this for standard JPEG detection, however, because I can't see how you'd know to perform that custom conversion, unless you somehow knew the JPEG came from a PDF. Regular CMYK JPEGs can also be marked as YCCK in the Adobe block (which is the 2 value you found - ExifTool will verify this nicely), but they render just fine - here's a test image:

    http://photodemon.org/images/ColorCMYK.jpg

    So you can't use the Adobe block alone, or you risk breaking handling of non-PDF CMYK JPEGs.

    Also you are absolutely right, CMYK bytes can't be returned on GDI+ v1.0. I can't remember details off the top of my head, but I believe CMYK JPEGs will be loaded and returned as RGB, but GDI+ transparently performs a brute-force CMYK to RGB conversion, without use of an attached profile (if any). So the results are not optimal, but the image should at least be identifiable. I can verify this for certain if you'd like.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    One other interesting note - reading the comments on the Java link included above, I think the first comment (about libJPEG) is perhaps out of date. For your problematic CMYK image above, libJPEG returns inverted bytes, just like GDI+. However libJPEG (and GDI+) return correct bytes on the test image I linked to, which is also marked as YCCK.

    So maybe something else is afoot.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  10. #10
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    I'll play with that colorcmyk.jpg example when I get home from work. Interesting. I have seen that GDI+ can have issues when both the JFIF & Adobe markers exist, depending on that last byte. Don't know if that is that case with the jpg you offered.

    As far as v1.0, you are right and re-verified that last night. Knew there was a reason why I aborted jpg cmyk support early on with v1.0. If there is no bullet-proof way (at least 99.9%) of knowing whether to invert the bytes before applying the ICC profile, then it's problematic for automation
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    ICC profiles for embedded PDF objects is a complicated topic, but I thought this description was interesting:

    https://forums.adobe.com/message/5575644#5575644

    The explanation is complicated, but different PDF versions, combined with user settings, will affect the way ICC profiles are treated for imported objects in the PDF. The relevant statement seems to be:

    When PDF/X-4 is placed in InDesign or Illustrator, similar to the case of PDF/X-1a, the Output Intent ICC profile is indeed ignored and DeviceCMYK colors assume the document's default CMYK color space.
    If I understand that correctly, it sounds like you could retrieve the base ICC profile for the PDF itself, then apply its transform to any untagged CMYK-format images to arrive at the correct image representation. "In theory," anyway.

    Not sure if it's feasible to retrieve the base ICC profile from a PDF, but that may be the easiest solution for your case.

    In truth, I've never encountered a CMYK-format JPEG, without attached ICC profile, in the wild. While it's probably possible to create one, you'd have to assume the creator had no idea what they were doing, because CMYK data without an attached ICC profile cannot be represented correctly on any output device, screen or print or otherwise. I'm not actually aware of any software other than Adobe products that even write CMYK JPEGs (makes sense given that they're Adobe's own creation and not even part of the JPEG spec), and I assume Adobe products would default to always embedding the relevant profile.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  12. #12
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    After a bit more research, I've come to a more informed conclusion, so far...

    First, an excerpt from adobe regarding YCCK (last byte of app marker being 2): "... that particular color transform used is an artifact of the filter intended to increase compressibility. It is intended that the inverse transform be performed during expansion before using the image."

    Now, regarding CMYK jpeg extraction from PDFs. The image's colors space is defined as cmyk, not ycck. There is an optional parameter in the pdf image tag's description that describes how the bytes should be handled after decoded. If this parameter is missing, for cmyk/ycck images, it appears the assumption is that the bytes are inverted. After reading another interesting post where someone added a 'proper' cmyk jpg to a pdf document, the pdf displayed it color-inverted. The solution was to add the optional parameter, which is really a matrix, to invert the image & that worked. That case seems to reinforce the assertion that within pdf, cmyk is assumed inverted before decoding, unless specifically told otherwise.

    Since my code will be extracting the cmyk jpgs from pdfs, I can overcome this issue in two ways:
    1) add a private jpeg APP marker that my rendering routines know about. GDI+ & others won't display it correctly, but my code can
    2) decompress the jpg, invert the colors (and/or apply the optional martix), & then re-save the jpg. Downside, re-compression. Optionally can save to png vs jpg to avoid recompression

    Regarding tweaking your project. Completely agree that it is a bad idea as it would break non-PDF CMYK images
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  13. #13
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Tanner, great project.

    Think I'll head off in a slightly different direction though. As you know, most of my work is based off of GDI+ vs GDI & dibs. So, through trial and error, figured out a decent way to have GDI+ apply ICM after an image is loaded. Downside is that ICC profiles cannot be loaded via memory as GDI offers, but must be file based (guess that's what user folders are for). Retrieving the ICC profiles is a piece of cake with/without GDI+ if one knows how to parse the image files.

    But even though GDI+ can perform ICM, it is still very limited. Regarding cmyk and your method of converting to sRGB when a profile is provided... GDI+ can't do that either & still requires old fashioned GDI as stated in this msdn link. The advantage of GDI+, if you want to call it that, is that is not DC based, it isn't even image based. It is simply an attribute class added to any image. One of the final tests I need to make is to see the results when a GDI+ ICC-enabled image is painted to a GDI hdc that has also been associated with an ICC

    Enjoyed reviewing your code and in the process re-learning what I forgot over the past couple years. I don't think ppl will really appreciate the "importance" of enabling their projects with ICM unless they were given a fair amount of before & after shots showing the quality change that ICC can provide, especially if the images were embedded with the profiles since that was the author's intent for displaying it.

    Last but not least: Just a follow up with GDI+ v1.0. CMYK is supported via TIFFs. A TIFF can have it's image encoded as JPG. Therefore, theoretically, manually construct a TIFF with a cmyk JPG & set the appropriate TIFF tags & bingo: v1.0 supports cmyk jpegs. But unfortunately, v1.0 doesn't support jpeg encoded TIFFs . Always a catch
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  14. #14

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Thanks, LaVolpe. Very fun to chat with another person interested in this kind of graphics work. (And of course, my project probably wouldn't exist without your original ICC experiment - so thanks again!)

    Good luck with your additional work. I'll be curious to see what happens with your aforementioned "when a GDI+ ICC-enabled image is painted to a GDI hdc that has also been associated with an ICC". This is all automatic when painting from one DC to another, but GDI+ to GDI... I will be amazed if that goes smoothly.

    I am fortunate to have access to FreeImage in my main project, so on XP and Vista I use that instead of GDI+ for handling CMYK JPEGs. Of course your Alpha Image Control is going to be trickier...

    I'm sure you know this, but maybe worth mentioning - color management is a deep rabbit hole. I haven't checked out your alpha image control in many years, but depending on what kind of drawing capabilities it offers, it may be quite the exercise to make it "fully" color managed. For example any brush requests, fills, and other draw calls all require consideration depending on your painting order and setup, so full color management could be a big task. Fairly trivial when working with DCs, but GDI+/GDI interoperability could greatly complicated things.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  15. #15
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by Tanner_H View Post
    ... For example any brush requests, fills, and other draw calls all require consideration depending on your painting order and setup, so full color management could be a big task. Fairly trivial when working with DCs, but GDI+/GDI interoperability could greatly complicated things.
    If one does all the painting on a GDI+ DC (graphics context based on an image), then shouldn't be an issue since the image would be rendered in sRGB and any additional modifications would also be sRGB. But keep in mind that the control I built (am revising) is for display. It would be the user's responsibility to deal with ICM if they are creating a Paint-like app.

    For my purposes, I have to deal with saving modified images or saving to other image formats. But I think the rule of thumb will be that if the image wasn't modified before saving, then save to the other format & transfer the ICC profile if format supports it else convert to sRGB before saving to non-ICC supported format. If image modified, save in RGB/sRGB without profile. Additionally, the only ICM issue I need to be concerned with, other than that, is whether the usercontrol's hosting container (form, picbox, etc) is color managed. However, I don't expect that to be an issue & won't know til I run those experiments. Windowless controls are painted on the host container's DC.

    The sticking point in me moving forward is how to efficiently handle color space transformations and embedded ICC profiles. Obviously we want to convert the source to sRGB for display as needed, but do we use a secondary image for that purpose? If not, permanent irreversible pixel changes would occur to the source. If using a secondary, potentially large memory usage if many ICM images are being used throughout app. Converting from source to sRGB back to source will not produce the original colors due to rounding errors and/or color space changes

    Some FYI points:

    1) For fun, within next day or two, I'll be creating an ICM gif & running tests. If interested, I can upload it so you can play with it

    2) Noticed your routines are hardcoded with source/destination rendering intents of Perceptual. The source ICC has a rendering intent it was written for. This can be parsed from the 128 byte ICC header. From limited tests, Perceptual & ReliatveColorimetric are most common

    3) You may want to include other bit depths in your conversions or add traps to prevent them & subsequent errors. For example, ICCs can also exist for 8,16,48,64 bit image formats. And 16,64 bit formats can have alpha channels.

    4) ICM strongly recommends that color translation NOT be done if the source & destination ICCs are same as color shifts occur due to rounding errors in the ICC functions. I wrote a simple routine that compares the ICC 128-byte headers. If not identical, then assume they are not the same ICC. There is no GDI API like AreColorProfilesEqual. See GetColorProfileHeader API call if interested
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  16. #16

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by LaVolpe View Post
    The sticking point in me moving forward is how to efficiently handle color space transformations and embedded ICC profiles. Obviously we want to convert the source to sRGB for display as needed, but do we use a secondary image for that purpose?
    You can always leave the image in its original space, tag the container with the supplied profile, then rely on ICM to perform the implicit conversion only at draw-time. However this has performance considerations, for example CMYK transforms tend to be very expensive, so depending on the profile, you might experience a serious performance hit on every draw.

    The other problem, as you say, is if multiple images are in use, each with potentially different profiles. Memory and performance are both going to be problematic.

    After a lot of deliberation and testing, I ultimately decided to forcibly convert all source images to sRGB in my own applications. This not only improves performance and memory usage, but also results in saved files that display properly across a wider array of applications. (For example, some web browsers are still not properly color managed, and unknowing users may blame your control if saved images don't display correctly on Facebook, etc.) Also you get much more predictable results when modifying image attributes, e.g. levels or curves or contrast.

    I don't think there's a perfect answer, but for interoperability, defaulting to sRGB is an easy case to make. As an added bonus, you'll also avoid the need to deal with complications like WCS vs ICC v2/v4 data and which image formats support which color profile formats.

    1) For fun, within next day or two, I'll be creating an ICM gif & running tests. If interested, I can upload it so you can play with it
    Er... does GIF support embedded ICC profiles? If so, that's news to me!

    Noticed your routines are hardcoded with source/destination rendering intents of Perceptual. The source ICC has a rendering intent it was written for. This can be parsed from the 128 byte ICC header. From limited tests, Perceptual & ReliatveColorimetric are most common.
    Be careful here. I originally used the source intent (you can actually see the function on line 62 of my source project) but later deactivated it.

    Specified rendering intents should only be used if the current render target matches the intended purpose of the profile. Otherwise, you'll get very poor results. Easy example - a CMYK image destined for printing will typically request Absolute Colorimetric intent, to ensure that things like company branding colors are rendered perfectly.

    However if you attempt to display such an image on the screen, using the print-based profile with Absolute Colorimetric will result in a very perceptually poor image on an LCD panel. Considering your use case of an image control, I'd consider defaulting to Perceptual, as the image is always going to be displayed on a screen. Relative colorimetric is nice for print proofing on a screen, where accuracy is preferred over "pleasantness" of the image, but again, not sure that would be relevant to an image UC.

    Something to think about, anyway.

    3) You may want to include other bit depths in your conversions or add traps to prevent them & subsequent errors. For example, ICCs can also exist for 8,16,48,64 bit image formats. And 16,64 bit formats can have alpha channels.
    Yep, great advice. In my master project I do this extensively, but not sure if it would be too much work for this sample - I'll give it a thought.

    4) ICM strongly recommends that color translation NOT be done if the source & destination ICCs are same as color shifts occur due to rounding errors in the ICC functions. I wrote a simple routine that compares the ICC 128-byte headers. If not identical, then assume they are not the same ICC. There is no GDI API like AreColorProfilesEqual. See GetColorProfileHeader API call if interested
    Interesting consideration - I'll have to do some tests to see if I can generate different images. Fairly rare for image files to include an embedded sRGB profile (usually sRGB is just specified via metadata), but if that happens, worthwhile to skip the transform. Thanks for the tip.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  17. #17
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    1) about efficiency. Users have option to load & maintain original image data for whatever purposes they may need it for. If loaded this way, rendering comes from the GDI+ handle. If not done that way, a memory-friendly GDI+ bitmap is created instead & rendering comes from that. In the later case, implicit conversion is a go. In the other case, can't permanently adjust the pixels, so a secondary likely needed depending on purpose/need & that's where some decisions can be made. Small images can be converted quickly enough on demand; large images not so much. Animated image formats would take a performance hit if each frame needs to be translated. But low frame count images can be converted into a single image like a film strip & rendered from that. Note that animation formats I support that also support ICC profiles are limited to: GIF & PNG. But as you said, just requires a bit of forethought & user-options to override default behavior. Being windowless and dc-less, the control is a slave to the container's refresh events

    2) per ICC website, GIFs can contain embedded profiles, however GDI+ v1.0 (not sure about v1.1 yet) won't save an ICC to gif; no problems with jpg, png & tiff. If v1.1 won't save it, will it read it? If not, to support GIF ICC would require parsing the format & looking for the ICC tag. If familiar with parsing gifs, this task would be extremely quick. I'll have the answer regarding reading/writing ICCs for either version, after I create that ICM GIF.

    3) Good point on the intended intent. Will give it more thought. Thanx.

    4) Same source/dest profiles: really depends on where image saved at & what app(s) saved the image. If on the same machine and in sRGB and ICC profiles saved by default, then likely gonna find images with your default sRGB profile embedded. Again with limited tests, I got a hit where headers were identical just once out of about 20 ICC-embedded images not originating from my machine. 128 bytes = 32 longs. Looping thru a max of 32 longs is a small price, IMO, of ensuring not using same profile

    Edited: Regarding sRGB embedding... not suppose to be common. For PNGs, GDI+ doesn't save the profile, but does indicate the PNG is in sRGB color space & includes the Gamma and cHRM tags/chunks. A knowledgeable image viewer would adjust the colors by those values & get the same results as if the the profile was actually embedded (as I understand it)
    Last edited by LaVolpe; Aug 27th, 2014 at 01:05 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  18. #18
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Follow up. May be easy to not support ICC-embedded gifs. Try finding one out there. I found one, but it was not written correctly. So, I had to create my own based off of the ICC standards and I believe I did it correctly. Haven't found an app yet that will color correct it. GDI+ v1.1 (Vista and lower) won't embed an ICC in a image format that is 8 bits or less. Tried with GIF, PNG, TIFF (jpgs are 24bpp via GDI+).

    Attached is ICC-embedded jpg & the GIF I created based off of it. The way I wrote the GIF is structurally correct per ICC standards. Just haven't found anything that will process the ICC tag: ICCRGBG1012. Maybe ImageMagick, as its gif decoders both appear to read/write that tag. Will look into it later just to verify I wrote the tag properly. If interested google ICCRGBG1012

    For visitors: hint, the car is not purple

    Removed images. Think GIF was uploaded as JPEG, may have to zip it. Will post them back in a bit
    Attached Files Attached Files
    Last edited by LaVolpe; Aug 28th, 2014 at 07:00 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  19. #19
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Tanner, just FYI. Submitted a thread also about ICM that about wraps up what I started two years ago.

    That project is primarily GDI+ based vs. your GDI based approach. Between our two projects, I think VB6ers out there have a couple of good resources if they choose to pursue color management
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  20. #20
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Just a heads up. Call it professional courtesy...

    I'm using v1.1 on Vista. GDI+ does not read JPG profiles correctly in a specific case & unfortunately, that case is not too uncommon.

    If you look at the length of the profile returned by GDI+ for the CMYK image you provided in post #8 and it returns 65490 bytes. It's wrong. The actual embedded profile is 557168 bytes. Within JPG format, a tag/chunk cannot be larger than 65536 bytes so if more than 1 chunk is needed, additional chunks are appended. These chunks for ICC profiles are specifically formatted with a 18 byte prefix. GDI+ if reporting the size wrong is only reading the 1st chunk, which is indeed 65490 bytes. The correct color shift with the embedded profile when correctly applied is noticeable.

    I discovered this when processing some jpgs where Windows says the ICC returned by GDI+ was invalid or failed to create a profile handle. After manually parsing the JPG and extracting the profile chunks to a file and then applying that file profile, no problems. I've also downloaded an ICC profile validation tool from color.org which further verifies the ICC is perfectly fine.

    So, bottom line: In order to process JPG embedded profiles correctly when GDI+ returns wrong profile size, the JPG will have to be manually parsed and the ICC profile chunks put together in the order specified within the chunk prefix. Curious what your results are for Win7/8 for that specific JPG.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  21. #21

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Hi LaVolpe. Couple of follow-ups:

    Quote Originally Posted by LaVolpe View Post
    I'm using v1.1 on Vista. GDI+ does not read JPG profiles correctly in a specific case & unfortunately, that case is not too uncommon.

    If you look at the length of the profile returned by GDI+ for the CMYK image you provided in post #8 and it returns 65490 bytes. It's wrong. The actual embedded profile is 557168 bytes. Within JPG format, a tag/chunk cannot be larger than 65536 bytes so if more than 1 chunk is needed, additional chunks are appended. These chunks for ICC profiles are specifically formatted with a 18 byte prefix. GDI+ if reporting the size wrong is only reading the 1st chunk, which is indeed 65490 bytes. The correct color shift with the embedded profile when correctly applied is noticeable.

    ...

    So, bottom line: In order to process JPG embedded profiles correctly when GDI+ returns wrong profile size, the JPG will have to be manually parsed and the ICC profile chunks put together in the order specified within the chunk prefix. Curious what your results are for Win7/8 for that specific JPG.
    No problem with GDI+ on Win 7. Returned profile size is 557168 and image is processed correctly. So GDI+ seems like a capable standalone solution on Win 7 and later.

    Vista and XP are clearly a different story. Perhaps in the future I'll put together a sample on color management via FreeImage, which honestly makes the whole thing much easier, especially when working with exotic filetypes and/or color depths.

    Quote Originally Posted by LaVolpe
    Follow up. May be easy to not support ICC-embedded gifs. Try finding one out there. I found one, but it was not written correctly. So, I had to create my own based off of the ICC standards and I believe I did it correctly. Haven't found an app yet that will color correct it. GDI+ v1.1 (Vista and lower) won't embed an ICC in a image format that is 8 bits or less. Tried with GIF, PNG, TIFF (jpgs are 24bpp via GDI+).
    Not sure it's worthwhile to even attempt ICC processing for GIFs. From what I can see, all mechanisms for embedding ICC profiles in GIFs reference the same white paper (http://www.color.org/wpaper2.xalter), which is not part of the GIF spec. It seems to be mostly an academic exercise to show that GIFs could theoretically embed ICC data.

    Additional research shows that embedding profiles in GIFs can raise false-positives on some malware scanners (https://tracker.moodle.org/browse/MDL-18052). Also the obvious file size increase from an embedded ICC profiles seems to defeat the primary point of using a GIF.

    Finally, no idea why a knowledgeable image creator would ever do this with a GIF when PNGs support ICC profiles much more elegantly, at smaller file sizes, and with all this being part of the official spec! My $0.02.

    Quote Originally Posted by LaVolpe
    Tanner, just FYI. Submitted a thread also about ICM that about wraps up what I started two years ago.
    Thanks for the tip - I'll definitely give this a look. Good idea to reference it here so developers can try out the various approaches, hopefully find one that works well for their project.

    Quote Originally Posted by LaVolpe
    Edited: Regarding sRGB embedding... not suppose to be common. For PNGs, GDI+ doesn't save the profile, but does indicate the PNG is in sRGB color space & includes the Gamma and cHRM tags/chunks. A knowledgeable image viewer would adjust the colors by those values & get the same results as if the the profile was actually embedded (as I understand it).
    I just checked some of my own photos and sure enough, some taken with an older dSLR include embedded sRGB profiles. So certainly possible to encounter this in the wild.

    Also, I'm hoping that GDI+ only saves default gAMA and cHRM values for sRGB PNG files (e.g. 2.2 gamma, etc). The assumption with the sRGB indicator is that further processing is not required. Otherwise, there is risk of double-processing the sRGB data.

    Similarly, even if only default gAMA and cHRM values are written, it's redundant to record gAMA and cHRM chunks alongside the sRGB chunk (which already encompasses these values). But then again GDI+ is not typically known for its brevity when saving files.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  22. #22
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by Tanner_H View Post
    Not sure it's worthwhile to even attempt ICC processing for GIFs. From what I can see, all mechanisms for embedding ICC profiles in GIFs reference the same white paper (http://www.color.org/wpaper2.xalter), which is not part of the GIF spec. It seems to be mostly an academic exercise to show that GIFs could theoretically embed ICC data.

    Additional research shows that embedding profiles in GIFs can raise false-positives on some malware scanners (https://tracker.moodle.org/browse/MDL-18052). Also the obvious file size increase from an embedded ICC profiles seems to defeat the primary point of using a GIF.

    Finally, no idea why a knowledgeable image creator would ever do this with a GIF when PNGs support ICC profiles much more elegantly, at smaller file sizes, and with all this being part of the official spec! My $0.02
    Per color.org their GIF tag of ICCRGBG1012 is a registered tag extension, so it isn't just academic. Regarding the malware issue, I suspect it is related to early attempts of ppl trying to include the ICC but not coding it right. Plus, any tagged format has potential of hackers trying to use it for malicious reasons. As far as anyone using it with PNG available? Agreed. I think this may have been a viable option before PNG became the format of choice for the web over GIF. When GIF was the web-king of images, having screen colors match actual colors for shopping sites would've been a real need & embedding profiles in GIFs was a real attempt of satisfying that need. But nowadays, GIF is no longer king
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  23. #23

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by LaVolpe View Post
    Per color.org their GIF tag of ICCRGBG1012 is a registered tag extension, so it isn't just academic.
    Hmm, are you sure? According to the whitepaper that describes the tag (linked above), he specifically states:

    "The only user-definable block offered is the Application Extension. Different user-defined blocks are indicated by an Application Identifier which begins the Application Extension block. So that was where the embedded profile information had to be placed. Since this was only an experiment, I created an Application Identifier, the string "ICCRGBG1012", but did not register it with CompuServe."

    Similarly, color.org's list of standards that support ICC fails to include GIF:

    http://www.color.org/standardsprofiles.xalter

    Apologies for belaboring the point, but it just strikes me as unnecessary overhead to cover this case, when the odds of encountering it in the wild are so incredibly remote. (Granted, you have an effective fallback implemented, so maybe pointless debate since the work is already done!)
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  24. #24
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    No biggie. I saw that article/experiment also. Haven't compared dates, but I was assuming that was trial/error before getting the tag registered? Another reason why I believe this to be so, is that many of the parsers out there (high quality, big name ones) do test for that GIF tag. I agree that supporting that tag is a matter of choice, since it's real-world usage was probably limited
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  25. #25
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Useful guide and good sample code.

    Just to append a little additional info. On systems below Win7, the conversion from ICC to sRGB might fail for some files (one such file attached below), owing to GdipGetPropertyItemSize bug which often may falsely return a zero profile size. (In the sample program, a blank would result.)

    I believe Tanner has no problem in his main program which uses FreeImage. For the benefit of those who use GDIplus only, a workaround could be to pass the bytes obtained from, e.g. JPEG APP2 marker, excluding marker (2 bytes). The total bytes so obtained being the profile size. Memo: First 16 bytes in the array should be excluded, like whenever after calling GdipGetPropertyItem.

    For those using FreeImage, "Size" of the following struct can be referred alright.

    Public Type COLORPROFILE
    flags As Long
    Data As Long
    Size As Long
    End Type


    .
    Attached Files Attached Files
    Last edited by Brenker; Sep 13th, 2014 at 01:14 AM. Reason: Add "memo"

  26. #26
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Tanner, thought about addressing this topic a bit more and have some theoretical issues I'd like your input on the following ramblings...

    As a baseline, I am going to make the assumption that the best color management flow for displaying images would be to convert image colors from the source profile (if provided) to the destination profile (if exists). The destination profile would be the monitor's specific, custom profile (device dependent) and is likely not the same as sRGB (device indepedent). As of Vista, Windows uses the following logic
    Quote Originally Posted by msdn
    When no input color space is specified, by default WCS 1.0 uses the sRGB color space as the input color space for color mapping.

    When no output profile is specified, but a default device is specified, WCS 1.0 selects a default output profile. If the default device does not have an associated profile, WCS 1.0 uses the sRGB color space as the output profile.
    So, by default IMHO, we should be converting from source to display monitor's profiles (or default to sRGB if no monitor profile exists). That would display the image with the best possible representation of the original colors. But in doing so, we should not (really must not) save any edited image, as is, as displayed because the image/display pixels are in the color space of that device dependent profile. And saving an image that way has 2 disadvantages:

    1. We should be embedding the profile with the image and this should not be the norm, default process. This adds to overall image size and not all image formats support embedded profiles anyway.

    2. Apps that are not color managed and use the image would not display the image correctly because they ignore the embedded profile, assuming the image format even supports profiles.

    Ok, that's one downside of using the device dependent profile over sRGB for display: it complicates saving images. Another downside is that color conversion needs to be considered: adding another obstacle for saving images. We can probably agree that a monitor's profile offers a wider/better gamut than sRGB as a general rule of thumb. If the source profile was also a wider gamut than sRGB, then when saving a modified image, as seen on the screen, to sRGB, the saved image may be different than the displayed image. Why? We converted from source to destination color spaces, both wide gamut and both not sRGB. sRGB's gamut would be smaller than either the source or destination. This means that when image is saved to sRGB, some color shifting would occur. Would it be better to convert from destination to source and save the image while embedding the original source profile? Imagine some color loss would occur also.

    And yet another issue. As an example. Let's assume a user wants to set a pixel to some color obtained from a palette or scraped from the screen outside of the displayed image. What color should be applied to the image? No way to know what color space it came from. Should it be assumed that the color is in sRGB color space and it be converted to the monitor's color space for display? Should it be considered the color is in the monitor's color space?

    Keeping with the baseline assumption of displaying images in device dependent color spaces, how do we save an image that was displayed and/or edited in that color space? Maybe using this logic: Default would be to convert to sRGB but include an option for user to specify color space unless image format does not support embedded profiles. Something else?

    I know that working in sRGB would be the easiest solution other than simply not dealing with color management. But when offering color management, sRGB is not the best solution for displaying images on a monitor.

    P.S. In your sample project, I believe you are double color matching in some cases. Per MSDN when SetCMMode is called and BitBlt/StretchBlt is called with a DIB as a source color matching occurs when block transferred to a DC that is CM enabled. If you use translatebitmapbits to a DIB, color matching already took place. Then blt'ing to CM enabled DC causes matching to occur again. I tested that question by remming out your SetCMMode calls and loading the image with the embedded whacked profile, the image displayed as expected: color corrected.
    Last edited by LaVolpe; Jun 11th, 2015 at 02:27 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  27. #27

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Hi LaVolpe. Hope you don't mind some rambling in return. I've spent a lot of time with color management tech since our previous conversations, including working with CMMs other than Microsoft's, so I feel much more comfortable with the topic now.

    Basically, your questions - and color management in general - fundamentally involve imperfect trade-offs. Which trade-off is "least bad" depends on many factors.

    1) The quality of the images being operated on. (e.g. an iPhone photo from Casual Joe has different considerations than a CMYK TIFF from Professional Jane.)

    2) Performance considerations/constraints of your project. The Windows color management engine prefers sRGB, and performance may decrease with other profiles. (Of course, color-managing very large images is slow regardless.) 16-bit per channel data offers different trade-offs than 8-bit. Etc.

    3) Destination of the edited images. Is the image just being displayed on-screen? Shared with friends on Facebook? Printed to some arbitrary material/object? Without knowing a preferred destination, it's impossible to make a "right" decision regarding color management.

    For software targeting anyone other than hardcore professionals, the standard color-management chain involves two color space conversions per image: at load-time, converting from a file-embedded profile to a device-independent working space. Then, when displaying on-screen, converting from the device-independent working space to a device-dependent monitor profile.

    While you can theoretically cut out the middle step and leave a profile-tagged image in its original profile, this creates many problems if you plan to edit and/or export the image later. For example, a user is unlikely to have any idea why painting with bright red results in a grayish red color on one PNG, even though it looks fine on a different PNG. These kinds of surprises are inevitable if you force edits to conform to the gamut of an image file (which may be terribly small, especially if the photo came from a cheap phone or webcam or something).

    Editing in a device-independent space like sRGB provides maximum consistency, regardless of an image source's, and this is the approach taken by nearly all software. (The exception is expensive, pro-grade tools where the user is likely to understand these issues, and know how to deal with them on a per-image basis.)

    So with those general-purpose caveats out of the way, let me attempt a few specifics in regard to your comments.

    But when offering color management, sRGB is not the best solution for displaying images on a monitor.
    I'm not really sure what this means. Typically, bitmap data - I'll use DIB for specificity - *is* stored in a device-agnostic working space like sRGB. All edits to the image are applied in this space.

    When rendering to the screen, a copy of the image data is used. That copy is forcibly converted to the monitor's color profile prior to display. (GDI's ICM-enabled APIs save us the trouble of creating such a duplicate DIB, because they will convert colors in-transit to the new DC.)

    Anyway, sRGB is generally the best working space for digital images, but using it does not negate the need to convert images to a monitor-specific profile prior to display.

    Said another way, device-independent working spaces and device-specific profiles are complementary. Most color-managed software will use both at different points in the chain.

    Let's assume a user wants to set a pixel to some color obtained from a palette or scraped from the screen outside of the displayed image. What color should be applied to the image? No way to know what color space it came from. Should it be assumed that the color is in sRGB color space and it be converted to the monitor's color space for display? Should it be considered the color is in the monitor's color space?
    If a program is serious about color management, it should provide its own color selection UI. There is no way around this. Whatever the specific color management solution, the policy for bitmap data must be the same as any color selection UI elements.

    For 99% of applications, the solution is obvious: convert incoming images to a device-independent working space. Perform all RGB math in this working space. Prior to displaying colors on the screen - be they image colors or pure RGB shades for a color selector - convert the colors to the current monitor's profile. When the user "selects" a color, you already know the underlying device-independent value, and can apply *that* value (not the monitor-converted value) to the image.

    This guarantees that something like RGB(255, 0, 0) looks the same in the color selector UC as it does when placed in the target DIB.

    The important thing is to treat conversions to the monitor's color space as one-way only. This guarantees that the user's image does not change, simply because they looked at it on a different monitor.

    As for colors scraped from unknown sources, my $0.02 is to always assume sRGB. This is the least of many evils, and the most probable "correct" solution in the absence of other data.

    Keeping with the baseline assumption of displaying images in device dependent color spaces, how do we save an image that was displayed and/or edited in that color space? Maybe using this logic: Default would be to convert to sRGB but include an option for user to specify color space unless image format does not support embedded profiles. Something else?
    I'm getting redundant at this point, but again, once a DIB is converted to a monitor-specific space, you should never reuse it for editing and/or saving. You must always maintain a separate, device-independent copy for those purposes.

    For most use-cases, the sRGB working-space copy can be happily saved directly to file. Common formats (PNG and JPEG specifically) allow an image to be tagged as sRGB, without actually embedding a redundant sRGB profile. Saving in sRGB guarantees that images look "right" in the widest array of devices and software, including non-color-managed ones.

    If the image is destined for some particular place, e.g. a CMYK-separated TIFF going off to a printer, it would be appropriate to seek the user's input first. But it's an extremely small subset of users and software where this is relevant.

    Similarly, unless you have a very good reason for doing so, you should not return the image to its original profile. In consumer-grade hardware, embedded color profiles are primarily used to compensate for weaknesses in a camera's sensor. (e.g. a smartphone camera that does a poor job of capturing certain hues) These days, many devices are powerful enough to perform an sRGB conversion right there on the device, so things like iPhones only produce sRGB images anyway. But older cameras simply dump the CCD array to file, with a device-specific ICC profile attached to notify subsequent software of how to "fix" the image. Converting an edited image back to such a profile accomplishes nothing, and risks screwing up any edits the user might have made.

    Options can always be provided for non-default behavior, but for 99% of images (and 100% if destined for the web, per W3C recs), sRGB should be used when saving.

    We can probably agree that a monitor's profile offers a wider/better gamut than sRGB as a general rule of thumb.
    Just the opposite, actually.

    sRGB covers a wider gamut than most LCD monitors can physically display. sRGB was originally designed against CRTs, which have better gamuts than LCDs since LCDs are limited by the need for a dedicated, always-on backlight. Only recently, with the advent of things like IPS and OLEDs, have LCDs returned to the gamuts originally afforded by CRTs. (Further complicating the matter is that monitors lose color resolution over time, so even if a monitor starts with a gamut approaching sRGB, it won't be able to provide that as years go by.)

    Also, worth pointing out that wider != better. A wider gamut captures more colors, but introduces banding. It's always a trade-off. sRGB is widely considered the best compromise between gamut size and avoiding banding. (Obviously this assumes 8-bits per channel; everything is different when you move to 16+.)

    Generally speaking, only high-end monitors produce true sRGB gamuts. This feature is a big deal because the better a display can match sRGB, the less work the display driver has to do on 99+% of image data. This improves performance and greatly reduces the computing load of color-managed software, including the OS.

    Random side-note: Apple's iDevices are actually one of the leaders in this area. To quote the linked article: "With the iPhone 5, we see an average dE2000 of only 2.09, which would make it the best LCD monitor I have reviewed at this point (in terms of out-of-the-box performance)... To put this in perspective, in the past few years I've reviewed probably 30-40 different displays, from PC monitors to TVs to projectors. Not a single one, out of the box, can put up the Gretag Macbeth dE numbers that the iPhone can, and perhaps one projector (which listed for $20,000) can approach the grayscale and color accuracy out of the box." So an iPhone is likely the most color-correct display in your house, crazily enough.

    Anyway, I'm beating this to death to make the point that forcibly converting an image to the sRGB working space is generally The Right Decision (tm). Digital camera sensors are unilaterally worse than sRGB at all but the high-end. Images originating from software will all be sRGB anyway. Converting incoming images to an sRGB working space is the accepted solution for pretty much all software. (Note that you still convert an sRGB DIB to the monitor profile when displaying it, obviously.)

    Again, professional users may have different requirements. Can discuss in more detail if curious.

    P.S. In your sample project, I believe you are double color matching in some cases. Per MSDN when SetCMMode is called and BitBlt/StretchBlt is called with a DIB as a source color matching occurs when block transferred to a DC that is CM enabled. If you use translatebitmapbits to a DIB, color matching already took place. Then blt'ing to CM enabled DC causes matching to occur again. I tested that question by remming out your SetCMMode calls and loading the image with the embedded whacked profile, the image displayed as expected: color corrected.
    I should probably double-check to be sure, but I think this is a misunderstanding of the processing chain. The sample project demonstrates the recommended approach of device-dependent embedded profile -> device-independent working space -> device-dependent monitor profile.

    Specifically, the sample project:

    1) Forcibly converts incoming images from their embedded color profile to sRGB. TranslateBitmapBits handles this.
    2) The now-sRGB DIB is maintained in its own container. The DIB never leaves the sRGB space.
    3) When rendering the sRGB DIB to the screen, it is implicitly converted from sRGB to the active monitor profile, using ICM-enabled GDI API functions. If we weren't using ICM-enabled functions, we would need to duplicate the DIB, convert the duplicate to the monitor profile, then send that data to the screen, so as to leave the original DIB untouched.

    As mentioned earlier, if there was no possibility of editing the image or later saving it to file, you could skip step 2 entirely and simply convert the image from its embedded profile to the monitor profile, saving some code and processing time.

    Also, if your current monitor is using an sRGB or sRGB-like profile, commenting out SetCMMode won't make a difference, because the device-independent working-space DIB (sRGB) and your device-dependent monitor profile (sRGB or likely something similar) are practically identical.

    Set your monitor profile to something dramatic, like the Whacked profile, and commenting out SetCMMode will make a huge difference.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  28. #28
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Thanks for your thoughts & sharing your recent discoveries.

    In summary. When editing, do so in sRGB space. When displaying, do so in device color space. That does make better sense. In GDI+, when rendering with image attributes will be a bit of a speed bump because the attributes should be adjusting the sRGB pixels, then the result translated to device color space

    Regarding common user-practices... I'd imagine in a VB picbox that is assigned a device profile, GetPixel/VB's Point functions could be an issue since the displayed color is likely not sRGB. For a custom control, retrieving pixel colors is more controlled ... return the RGB from the sRGB workspace, not the display workspace

    I'm still playing with ideas in trying to determine if 2 profiles are identical or not. Ideally we wouldn't convert to/from identical profiles. Comparing the first 128 bytes of a profile is a fair attempt, but in reality, the actual comparison should be made based on the matrix/LUT, white point, and/or possibly a couple other key transformation properties.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  29. #29

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by LaVolpe View Post
    Regarding common user-practices... I'd imagine in a VB picbox that is assigned a device profile, GetPixel/VB's Point functions could be an issue since the displayed color is likely not sRGB. For a custom control, retrieving pixel colors is more controlled ... return the RGB from the sRGB workspace, not the display workspace
    Same goes for things like the Windows color selector, too. Since there's no "right" way for Microsoft to handle it - because color-managing it would return "visually incorrect" colors for non-color-managed apps, and vice-versa - I don't know that it can be reliably trusted as color-managed or not.

    Quote Originally Posted by LaVolpe View Post
    I'm still playing with ideas in trying to determine if 2 profiles are identical or not. Ideally we wouldn't convert to/from identical profiles. Comparing the first 128 bytes of a profile is a fair attempt, but in reality, the actual comparison should be made based on the matrix/LUT, white point, and/or possibly a couple other key transformation properties.
    Well, the trouble with using anything but the header is that there are only four required tags inside the profile itself: profileDescriptionTag, copyrightTag, mediaWhitePointTag, and chromaticAdaptationTag. (The last two are technically required, but DeviceLink profiles have an exemption.) No other tags are guaranteed to exist in the file, making 1:1 comparisons difficult.

    Sure, you could parse the tag list for identical entries, but IMO that's overkill, especially when the vast majority of source files are lossy JPEGs anyway. ICC profile headers contain sufficient uniquely identifiable data (including an MD5 hash in the Profile ID field, and a dedicated date/time field) that profiles with identical headers but different transforms should be impossible.

    My $0.02 - a better effort would be covering some of the ICC-like options in various file formats, e.g. PNGs that can include CHRM and GAMA chunks independent of a full profile. While rare, those require special handling since you can't just pass them off to the Windows CMS.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  30. #30
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Tanner, FYI after some more play time.... Transforming without use of TranslateBitmapBits, creating/destroying hTransforms, etc. Not as much of a low-level approach follows.

    Disclaimer. This logic not fully tested and haven't played with alpha images, i.e., AlphaBlend

    Example:
    1. CreateCompatibleDC and assign/activate to it the source image's profile (SetICMProfile & SetICMMode)
    -- if no profile exists then set to default/standard sRGB
    2. Select into that DC the bitmap, i.e., handle from LoadPicture(bmp/jpg) call
    -- next 3 steps can be skipped if 1st DC is sRGB
    3. Create another compatible DC and assign it the default sRGB profile & activate ICM
    4. Create a new bitmap of same size as that from step #2 and select it into this 2nd DC
    5. BitBlt from source to destination DC, color management performed
    -- at this point, one can destroy the 1st DC & bitmap if desired and these last 3 steps weren't skipped
    6. From the sRGB DC, you can Stretch/BitBlt it to the form, picbox, etc. If the target DC has ICM set, transformation is performed

    The above works really well and has some dependencies
    1. Not tested with alpha images (now tested: works well)
    2. May not work with CMYK sources, but untested (now tested: CMYK needs TranslateBitmapBits)
    3. Requires bitmaps obviously, so PNG/TIF still need to be loaded via other means & bits set to a bitmap
    4. Requires ICM profiles written to disk which means extraction from source image & saved to user folders
    5. Memory DCs are used because VB DC to VB DC scenarios don't seem to work (kinda sorta; there are issues when AutoRedraw=True)
    Also need to keep GDI in mind, i.e., destroy stuff when no longer needed else leaks occur

    -- Follow up: I'll post an example this week. Found better efficiencies than that listed above by using SetDIBits and using overall less GDI objects to perform the transformation (no BitBlt used).

    Edited: Per MSDN > SetICMProfile supports only RGB profiles in compatible DCs.
    Quick follow-up to MSDN statement: True. When trying to apply a CMYK profile to a DC via SetICMProfile, the call fails. Simply put, CMYK transformation must be handled via TranslateBitmapBits

    Note regarding default device-independent sRGB profiles. In your code, you request LCS_sRGB. Makes sense and what I also used in most of my code. However, on my system and playing 'what if", I downloaded a manufacture's color profile for my specific monitor and assigned it to the device (i.e., monitor/display). Now DCs retrun from GetICMProfile that profile path/name as expected. What was unexpected as that sRGB also returned that monitor profile when GetStandardColorSpaceProfile was called, not the Windows device-independent sRGB profile. That is important if saving images and stating they are in sRGB color space when in reality, they are in device-dependent color space. Instead of using LCS_sRGB, LCS_WINDOWS_COLOR_SPACE returned what I expected, the device-independent sRGB profile. P.S. not sure your LCS_WINDOWS_COLOR_SPACE constant is correct, believe it should be "Win " 4 characters converted to 4 byte ASCII.
    Last edited by LaVolpe; Jun 22nd, 2015 at 05:19 PM. Reason: added some follow-up comments
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  31. #31

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Quote Originally Posted by LaVolpe View Post
    P.S. not sure your LCS_WINDOWS_COLOR_SPACE constant is correct, believe it should be "Win " 4 characters converted to 4 byte ASCII.
    Thanks, LaVolpe. I get the same thing in the latest wingdi.h. No idea why so many online references declare it as simply "2". (That's what I get for Googling constants instead of looking them up myself, I guess... )
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  32. #32
    New Member
    Join Date
    Jul 2015
    Posts
    1

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Hi,
    someone can help me?
    i would like to read a tiff in cmyk + Alpha channel then i need make some expression on bit of plane c other on m then save all in the format of origin (tiff cmyk + Alpha)...

    i don't understand how to access direct to bitmap of plane...

    Thanks to all

  33. #33

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Nonso1, if you post your question in the appropriate forum, you're much more likely to get an answer. Your problem has nothing to do with color management so I doubt you'll get many eyeballs here.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  34. #34
    New Member
    Join Date
    Aug 2015
    Posts
    9

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Hi,
    I tried Color Management, and find it very interesting and well done.
    I noticed that with the embedded profile and enabled the default profile of the display, the image has color different than preview windows or photoshop (I'm using it on Windows 7).
    It 'a strange interpretation of the ICC profile that is in the file?
    I tried with different file tif and I used photoshop setting using embedded profile file.
    Thanks

  35. #35

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Hi flyman02. Thank you for your feedback.

    It's hard to say more without access to the image in question. As an FYI, "Preview" in Windows doesn't honor embedded color profiles (crazy, I know). Photoshop has a ton of settings that can affect how color management operates, and if I can take a look at the file, I might be able to give you a more detailed explanation on why it renders different from this little sample project.

    If you want to upload the image here (inside a .zip file, to prevent the forum software from messing with it) or get in touch with me directly, I'll take a closer look. Thanks!
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  36. #36
    New Member
    Join Date
    Aug 2015
    Posts
    9

    Smile Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Thanks Tanner_H,
    I created this file stemming from an example of Color Managment vb6 (Browser_Color_Test.jpg).
    From the picture you can see that in photoshop and windows preview, captured colors from a color picker are equal, while in Color Managment vb6 are different.
    If you are interested, this is the link color picker http://www.maurorossi.net/pagine/programmi/mycolor.htm
    Color Problem.zip

  37. #37

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Thanks for the screenshot. Very interesting results! For comparison, here is the same test image (Browser_Color_Test.jpg) on my Windows 10 PC, using GIMP as an extra comparison:

    Name:  color management comparison.jpg
Views: 1903
Size:  35.2 KB

    As you can see, Windows Photo Viewer (at least on my PC?) doesn't use the embedded color profile. I'm curious why it seems to working on your PC, as I've never seen that before...? Very strange!

    Anyway, minor differences in color rendering can come down to a few possibilities:

    1) The rendering intent used. For viewing on a screen, Perceptual rendering intent is the preferred choice. In the sample project, Perceptual rendering intent is hard-coded, but the comments describe where you can change it. Embedded profiles can also specify their own rendering intent, which you can respect if you choose, but this comes with caveats. (I can explain more if you're curious, but it's somewhat complicated.)

    2) The underlying color engine. Microsoft (and by extension, this sample project) uses a different color management module (CMM) than Photoshop. Different engines can produce minor differences in the final result, depending on a variety of criteria.

    3) Format of the original image. Lossy formats like JPEG are especially prone to this, because different JPEG decoders will produce different JPEGs, prior to doing any actual color correction. Usually the differences are subtle (and some engines may give a choice over this, e.g. "Fast" vs "Quality" decoding), but it can lead to minor RGB differences in the final image.

    4) Working space used. In the sample project, the incoming image is hard-converted to sRGB before conversion to the screen color space. This is equivalent to the Photoshop color management policy called "Convert to Working RGB", and it greatly simplifies things if you plan on editing or modifying the image. However, this step isn't really necessary if you just want to display the image on-screen, because you can implicitly convert from the source profile to the screen profile in a single step, skipping the need for a working space. I believe LaVolpe has a project that uses this method; try this link for a sample project.

    So those are some possible explanations. I've never noticed dramatic results like those in the screenshot you provided, so maybe something else is at play that I'm not familiar with. I'm still curious about how that image looks correct in Windows Photo Viewer, when I get an uncorrected image on my PC. Maybe it's a Windows 10 thing and I need to test again on Windows 7. I'll do some research and return if I can find a better explanation.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  38. #38
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Tanner, just FYI. Another possible reason for differences is if the monitor has its own ICM profile in use. Does your project take that into consideration when rendering? If not, just a thought and may be moot anyway.

    On XP (on purpose), the color displayed via translating ICM produced the same color as displayed in XP's 'viewer'. I took screen shot of both & pasted into Paint to return the color values from Paint's eye-dropper tool. The reason I used XP is that I know 'viewer' uses GDI+ which is what our VB code is using to create the image. On newer O/S, starting with Vista?, WIC is used for image loading I think. But not positive on that. If that is the case, could be a reason for slight color shifts? Just throwing it out there as a possibility.

    P.S. My system 'viewer' uses the embedded ICM profile
    Last edited by LaVolpe; Aug 27th, 2015 at 11:03 AM. Reason: WIC not WMI
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  39. #39
    New Member
    Join Date
    Aug 2015
    Posts
    9

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    Thank you all...
    These your considerations made me think about the problem .....
    I use a XRite i1 calibrator for calibrating the monitor and this generates an ICC file that resides in the system folder, and I tried to exclude him get results similar to the image of Tanner_H.
    There remains only to understand why in ColorManagment has different behavior when converting the monitor profile than preview windows and photoshop.
    I also tried to play with the variables LCS_CALIBRATED_RGB, LCS_sRGB, LCS_WINDOWS_COLOR_SPACE and also INTENT_PERCEPTUAL, INTENT_RELATIVECOLORIMETRIC, INTENT_SATURATION, INTENT_ABSOLUTECOLORIMETRIC finding no difference ....
    Probably the problem is generated when doing the conversion to the color space of the monitor that perhaps always considers sRGB.
    Do you have any idea?!?
    Thanks

  40. #40

    Thread Starter
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Color Management (ICC Profile) support in VB6: guide and sample project

    @LaVolpe: thanks for the idea, but you can see in the screenshot at the top that there are radio buttons for toggling use of the current display profile.

    What's stranger to me are the varying results of Windows Photo Viewer. I just tested an old Win 7 PC and got color-corrected results, so I was clearly wrong. Apologies for my incorrect statement earlier about Windows Photo Viewer not honoring embedded profiles.

    Windows 10 still gives me uncorrected results by default, but if I switch the photo viewer to "edit" mode, the image suddenly snaps to the ICC-correct result. Apparently there are still some kinks to work out in the new OS. :/

    @flyman02: thanks for the updated information. If inside the sample project, you select "Turn off color management" inside the "Display (Monitor) Color Management" section, does it make a difference?

    Also, you mentioned using an XRite i1 calibrator to generate an ICC profile for your monitor. If you go to the color management settings in Windows, under the "Devices" tab, what ICC profile (if any) is associated with your current monitor?

    Also, what device profile and viewing conditions profile are currently active? (These are listed under the last tab, "Advanced", in the section "Windows Color System Defaults".) Maybe those could give us another clue.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width