What is vulkan color space? - graphics

During creation of vulkan swapchain i've stuck at imageColorSpace and imageFormat parameters in VkSwapchainCreateInfoKHR. I do understand that imageFormat is how actual pixel is encoded and stored in memory and if it color isn't linear then vulkan converts it to such during sampling and writing operations in shaders. My hardware supports only VK_COLOR_SPACE_SRGB_NONLINEAR_KHR which i suppose means that color in swapchain image should be stored in a non-linear fashion but VK_FORMAT_B8G8R8A8_SRGB results in gamma 0.44 corected colors, while VK_FORMAT_B8G8R8A8_UNORM works fine. How imageFormat relates to imageColorSpace and what does imageColorSpace specify?

Vulkan is colorspace agnostic. Though at some point before the bits are converted to photons, the colorspace must become known. That's why it is asked for in the swapchain creation.
imageFormat specifies what the image format is (same as it does in vkCreateImage()). imageColorSpace is how the swapchain\display interprets the values when the image is presented.
So if you have UNORM, that means unspecified color space, and they are good ol' raw bits. Or rather it means that you are in charge of the color space (if the image even stores color, and not something else entirely). If you use VK_COLOR_SPACE_SRGB_NONLINEAR_KHR with *_UNORM, it means the swapchain takes your bits and it is gonna assume it is already SRGB when presented. If it is *_SRGB, then that is no different for the swapchain itself, but what happens is that the created VkImages are *_SRGB format, which means when you use them then the color is being linearized for you (same as would happen if you created a non-swapchain VkImage).

Related

Are RGB images converted to sRGB automatically before being viewed in web browser?

If we have an RGB image, most browsers and, in fact, monitors only support sRGB space. I am trying to understand something important. Does the monitor/web then convert each of the pixels in the image to sRGB and then display it? Meaning we are actually seeing the sRGB version of the image.
Also, if that is the case, which formula can we use to do the conversion, and if we did the conversion ourself, I assume we would get an image that 'looks' exactly the same as the original?
The pixel values in an image file are just numbers. If the image is "in" a space larger than sRGB (such as ProPhoto), the pixel values will only be "converted" to sRGB if you have color management enabled, OR you perform the conversion yourself.
A browser or device will only convert tagged images of a non-sRGB colorspace TO sRGB IF there is a color management engine.
With no color management, and a standard sRGB monitor, all images will displays "as if" they were sRGB, regardless of their colorspace. I.e. they may display incorrectly.
Even with color management, if the image is untagged, it will be displayed as whatever default (usually sRGB) the system is set to use.
As for formulas: the conversion is known generally as "gamut mapping" — you are literally mapping the chromaticity components from one space to another. There are multiple techniques and methods which I will discuss below with links.
If you want to do you own colorspace conversions, take a look at Bruce Lindbloom's site. If you want a color management engine you can play around with, check out Argyll, and here is a list of open source tools.
EDIT TO ADD: Terms & Techniques
Because there are other answers here with some "alternate" (spurious) information, I'm editing my answer here to add and help clarify.
Corrections
sRGB uses the same primary and whitepoint chromaticities as Rec.709 (aka HDTV). The tone response curve is slightly different.
sRGB was developed by HP and Microsoft in 1996, and was set as an international standard by IEC circa 1998.
W3.org (World Wide Web Consortium.) set sRGB as the standard for all web content, defined in CSS Color.
Side note, "HTML" is not a standards organization, it is a markup language. sRGB was added to the CSS 3 standard.
Profiles do nothing if there is no color management system in place.
And to be clear (in reference to another answer): RGB is a color MODEL, sRGB is a color SPACE, and a parsable description like an ICC profile of sRGB is a color PROFILE.
Second, sRGB is the STANDARD for web content, and RGB values with no profile displayed in a web browser are nominally assumed to be sRGB, and thus interpreted as sRGB in most browsers. HOWEVER, if the user has wide gamut (non-sRGB monitors) and no color management, then a non-color managed browser is typically displaying at the display's colorspace which can have unexpected results.
Terms
RGB is an additive COLOR MODEL. It is so named as it is a tristimulus model that uses three narrow band light "colors" (red green and blue) which are chosen to stimulate each of the eye's cone types as independently as possible.
sRGB is a colorSPACE. A color space is a subset of a color model, but adding in specifics such as the chromaticities of the primary colors, the white point, and the tone response curve (aka TRC or gamma).
sRGB-IEC61966-2.1.icc is an ICC color PROFILE of the sRGB colorspace, used to inform color management software to the specifics such that appropriate conversion can take place.
Some profiles relate to a specific device like a printer.
Some profiles are used as a "working space".
An ICC profile includes some of the math related information to apply the profile to a given target.
Color Management is a system that uses information about device profiles and working color space to handle the conversion for output, viewing, soft proofing on a monitor, etc. See This Crash Course on CM
LUT or LookUp Table is another file type that can be used to convert images or apply color "looks".
Gamut mapping is the technique to convert, or map, the color coordinates of one color space to the coordinates of a different color space. The method for doing this depends on a number of factors, and the desired result or rendering intent.
Rendering intent means the approach used, as in, should it be perceptual? Absolute colorimetric? Relative with black point compensation? Saturation? See this discussion of mapping and Argyll.
Techniques
Colorspace transforms and conversions are non-trivial. It's not as if you can just stick image data through a nominal formula and have a good result.
A reading through the several links above will help, and I'd also like to suggest Elle Stone's site. particularly regarding profiles.
Note: I use what I think the most common notation (so as the alternate notation in the previous answer): RGB is a colour model, [so formula to calculate various things, but without defined colorimetry, scale, and gamma; sRGB is a colour space, so with a defined gamut; with a colour space we know which colour could be described and which not; and profile is a characterisation of a device (so it defines device specific colour space), intent, and often also some calculation methods to transform colours.
sRGB was defined by computer manufacturers and software companies, to standardize colours, but with old screens and low resolution, it really didn't matter much. Note: They used the primary colour of Rec.709 (HDTV), but with a different white point and gamma (view conditions are different: we watched TV and movies in darker rooms; we have computer for work that we use in brighter lit rooms).
So the normal way (before colour profiles): An image had 3 channels with values from 0 to 255 each, one for red, one for green, one for blue. This was send directly to video memory, and the video card sent these values without modifying them (on digital RGB signals) to the screen. The screen used the 3 channel values for the intensities of the 3 sub-pixels. Note: contrast and brightness control [on CRT screens] permitted some correction.
Because the assumed colour space was sRGB (and screens were built to display sRGB), this was the standard, and it was standardized by HTML (as default colour space). So if your browser has not an explicit colour space (e.g. for an image), it will assume it is sRGB, so it will not change the values.
Screens improved, creation and modification of content started to be done on computers, and there are many media which have a different colour space, images started to specify the colour space: TV has a restricted range (16-235) and a different gamma (and white point), DCI-P3 (digital cinema) has different gamma and primaries (wide-gamut), printing requires often wider gamut (forget small CMYK printers), printing photos also requires different dynamic ranges, gamma, white, and colour space.
So now (assuming an RGB image, but note that many images are not RGB, but YCC (e.g. JPEG)), an image should have its own profile, which tells us the colour characteristic of the camera (so which red is the value 255,0,0). A colour aware program will check the output profile, and the input profile, and it will adapt the colours, so that the final result is near to the intended colour.
So, if you have an unprofiled or an sRGB image, and no profile for your screen (or a fake sRGB profile): the value 255,0,0 will display the most intense and "red-dest" Red that your screen can display.
If you have an unprofiled image, but a profile for the output screen: if the intent is "absolute": the screen tries as best as it can to match the colours according to sRGB. Out of gamut will be just as the nearer in gamut colour. The "relative" intent: it scales many values, so that you will not see highlights (same colour for many out of gamut values). Eyes will correct, so you will adapt (and we adapt quickly e.g. to unsaturated colour spaces as sRGB). The other intents are more about graphics, so it keeps the values: different as the original, but as distinct as possible (for plots and comics this could be good).
If you have a profiled image, it is nearly the same, just that you will find more differences.
An AdobeRGB image (but without profile) will be displayed with the correct saturation on most wide-gamut screens (with wide gamut enabled), and it will be displayed as unsaturated on a RGB screen (if there is no profile; "absolute and perceptual intent" could correct the lack of saturation).
On contrary, an sRGB image, but displayed on AdobeRGB will be seen as too saturated. If the image has a profile, the image will be seen correctly.
On an RGB image (usual formats) you cannot have colour out of gamut of such image: 255,0,0 and 0,255,0 and 0,0,255 are the primary colour of the image colour space, so you can describe only colours in its colour space (assume sRGB if none is specified). This is not true on some formats, where negative values, or values above "white values" are allowed, e.g. on format with float point values (openEXR).
Note: Wide gamut screens have often a hardware button to switch colour space, from the native to sRGB (and back), because many applications were not compatible with colour profiles, but we still need browsers and mails.
If you are interested, the book of Giorgianni et al. (from Kodak) is a good introduction: both authors worked at Kodak (so film [photo, movies], but they were working creating the PhotoCD), so with a lot of problems with screens and colour spaces, and intent. ICC (the standard for profile) is (in my opinion) the follow up of such book: the ICC site has various information about the topic.
In very simple terms: RGB is a color space while sRGB is a color profile.
A profile interprets the RGB values to a specific context e.g. device, software, browser etc. to make sure you have consistent colors across a wide range of devices where a user might see your picture.
RGB values without a profile are basically useless because the displaying device or software has to guess how to map the RGB values to the displays color space. An equivalent is to imagine you getting 100 bills of an unknown currency and being asked to convert this to your home currency. It doesn't work – you need to know how to map these two valuewise.
So basically you don't have to worry about interpreting your images yourself. For web is seems the soundest approach to always convert to the sRGB profile (the images color space is still RGB) and let the browser do the interpretation.
You'll find seemingly up to date info with a graphic of the main browsers and their ability to correctly display the sRGB profile on this EIZO page.
PS: To add to the general confusion around color management – a color space might sometimes be called color model while a color profile might sometimes be called color space.

How do I deal with color spaces and gamma in the PNG file format?

Here's my problem:
I'm doing some rendering using spectral samples, and want to save an image showing the results. I am weighting my spectral power function by the CIE XYZ color matching functions to obtain an XYZ color space result. I multiply this XYZ color tuple by the matrix given by this page for converting to sRGB, and clamp the results to (0,1).
To save the image, I scale the converted tuple by 255 and cast it to bytes, and pass the array to libpng's png_write_image(). When I view a uniform intensity, pure-color spectrum rendered this way, it looks wrong; there are dark bands in the transitions between the colors. This is perhaps not surprising, because to convert from XYZ to sRGB, the color components must be raised to 2.4 after the matrix multiply (or linearly scaled if they are small enough). But if I do this, it looks worse! Only after raising to 1/2.2 does it start to look right. It seems like, in the absence of me doing anything, the decoded images are having a gamma of ~2.2 applied twice.
Here's the way I would expect it to work: I apply the matrix to XYZ, and I have a roughly energy-linear RGB tuple. I raise this to 2.2, and now have a perceptually linear color tuple. I encode these numbers as they are (thus making efficient use of the file precision), and store a field in the file that says "these bytes have been encoded with gamma 2.2". Then at image load time, the decoding system un-applies the encoded gamma, then applies the system gamma before display. (And thus from an authoring perspective, I shouldn't have to care what the viewer's system gamma is). But the results I'm getting suggest it doesn't work this way.
Worse, I have tried calling png_set_gAMA() with both 2.2 and 1/2.2 and see no difference in the image. I get similar results with png_set_sRGB() (which I believe should force the gamma to 1/2.2).
There must be something I have backwards or don't understand with regards to either how I should be converting my color values, or how PNG handles gamma and color spaces. To break this down into a few clarifying questions:
What is the color space of the byte values I am expected to pass to write_png()?
What calls, if any, must I make to libpng in order to specify the color space and gamma of the passed bytes, to ensure proper display? Why might they fail?
How does the gamma field in the the png file relate to the exponent I have applied to the passed color channel values, if any?
If I am expected to invert a gamma curve before sending my image data (which I doubt, but seems necessary now), should that inversion include the linear part of the sRGB curve?
Furthermore, I see hints that "white point" matters in conversion between XYZ and sRGB. It is unclear to me whether the matrices in the site given above include a renormalization to D65 (it does not match Wikipedia's matrix)-- or even when such a conversion is necessary. Most of the literature I've found glosses over the details. Is there yet another step in the conversion not mentioned in the wiki article, or will this be handled automatically?
It is pretty much the way you expected. png_set_gAMA() causes libpng to write a gAMA
chunk in the output PNG file. It doesn't change the pixels themselves. A png-compliant
viewer is supposed to use the gamma value from the chunk, combined with the gamma of the display, to write the pixel intensity values properly on the display. Most decoders won't actually do the two-step (unapply the image gamma, then apply the system gamma) method you described, although the result is conceptually the same: It will combine the image gamma with the system gamma to create a lookup table, then use that table to convert the pixels in one step.
From what you observed (gamma=2.2 and gamma=1/2.2 behaving the same), it appears that you are using a viewer that doesn't do anything with the PNG gAMA chunk data.
You said:
because to convert from XYZ to sRGB, the color components must be raised to 2.4 after the matrix multiply...
No, this is incorrect. Going from linear (XYZ) to sRGB, you do NOT raise to 2.4 nor 2.2, that is for going FROM sRGB to linear.
Going from linear to sRGB you raise to ^(1/2.2) or if using the sRGB piecewise, you'll see 1/2.4 — the effective gamma you are applying is ^0.45455
On the wikipedia page you linked, this is the FORWARD transformation.
From XYZ to sRGB:
That of course being after the correct matrix is applied. Assuming everything is in D65, then:
Straight Talk about Linear
Light in the real world is linear. If you triple 100 photons, you then have 300 photons. But the human eye does not see a trippling, we see only a modest increast by comparison.
This is in part why transfer curves or "gamma" is used, to make the most of the available code space in an 8 bit image (oversimplification on my part I know).
To do this, a linear light value is raised to the power of 0.455, and to get that sRGB value back to a linear space, then we raise it to the inverse, i.e. ^1/0.455 otherwise known as ^2.2
The use of the matrixes must be done in linear space. but after transiting the matrix, you need to apply the trc or "gamma" encoding. Based on your statements, no, things are not having 2.2 added twice, you are simply going the wrong way.
You wrote: " It seems like, in the absence of me doing anything, the decoded images are having a gamma of ~2.2 applied twice. "
I think your monitor (hardwrare or your systems icc profile) has already a gamma setting itself.

What are the exact color spaces of DXGI_FORMATs?

In the official documentation of DXGI_FORMAT, it tells us that only a format with _SRGB enumeration postfix is in sRGB color space. I thought other format without this postfix are all in the linear space. But I found a very strange behavior of format conversion function in DirectXTex library. ( You can download it from http://directxtex.codeplex.com/ )
At first, I exported a texture file as DXGI_FORMAT_R32G32B32A32_FLOAT by using NVIDIA Photoshop DDS Plugin. Then I load this file by LoadFromDDSFile() function, and convert its format to DXGI_FORMAT_R16G16B16A16_UNORM by Convert() function. (Both of these two functions are provided by DirectXTex library.)
You guess what? After the image was converted to DXGI_FORMAT_R16G16B16A16_UNORM, the brightness of all pixels were also changed, the whole image becomes brighter than before.
If I manually convert the pixel values from sRGB space to Linear space after the image was converted to DXGI_FORMAT_R16G16B16A16_UNORM format, the resultant pixel values are same as input. Therefore, I suppose that the DirectXTex library treats DXGI_FORMAT_R32G32B32A32_FLOAT as a format in linear color space, and treats DXGI_FORMAT_R16G16B16A16_UNORM as a format in sRGB color space, then it did the color space transforming from linear space to sRGB space. ( I tried to find out why the Convert() function also converts the color space, but it was implemented by WIC, and there is no source code for it. )
So, is there any bug in DirectXTex library? Or is it the real standard for DXGI_FORMATs? If there were different color spaces for some special DXGI_FORMATs, please tell me that where can I find the specification for it.
Any help will be grateful. Thanks!
By convention float RGB values are linear, and integer RGB values are gamma-compressed. There is no particular benefit to gamma-compressing floats since the reason for gamma is to use more bits where it is perceptually needed, and floats have sufficient (perhaps excessive) number of bits throughout and are already pseudo-log encoded (using the exponent). (source)
Note that the colorspace of integer RGB textures in DXGI which are not specifically *_SRGB is not sRGB, it is driver dependent, and usually has a fixed gamma of 0.5.
The DirectXTex library does appear to be behaving correctly. However, please note that you are also relying on the behavior of whatever software you use to both capture and display the DDS files. A better test for just DirectXTex is simply to do a round-trip conversion float->int->float in the library and compare the results numerically rather than visually.

ARGB Color Format

Does Java ME support 0xAARRGGBB color format? I mean can I change the opacity of an image by modifying the alpha value of pixels? I work with Graphics and Image classes.
This will undoubtedly vary between devices. Why not just try it and see?
Edit: OK so I guess you want to know actually how to do it. The method you will need is Image.getRGB() -- as per the docs:
Obtains ARGB pixel data from the
specified region of this image and
stores it in the provided array of
integers. Each pixel value is stored
in 0xAARRGGBB format, where the
high-order byte contains the alpha
channel and the remaining bytes
contain color components for red,
green and blue, respectively. The
alpha channel specifies the opacity of
the pixel, where a value of 0x00
represents a pixel that is fully
transparent and a value of 0xFF
represents a fully opaque pixel.
Modify the pixels you want then use the data to create a new image using Image.createRGBImage().
Edit: The spec says that all devices should allow alpha manipulation.
One way to tell whether they do or not is to create a mutable image, get its graphics object, write some ARGB data to it, then read it back, and see if the alpha data is still present; if not then you can bet alpha transparency is not supported.
The methods I've linked to should be all you need to do this, the actual method I leave as an exercise ;)

detect color space with openCV

how can I see the color space of my image with openCV ?
I would like to be sure it is RGB, before to convert to another one using cvCvtColor() function
thanks
Unfortunately, OpenCV doesn't provide any sort of indication as to the color space in the IplImage structure, so if you blindly pick up an IplImage from somewhere there is just no way to know how it was encoded. Furthermore, no algorithm can definitively tell you if an image should be interpreted as HSV vs. RGB - it's all just a bunch of bytes to the machine (should this be HSV or RGB?). I recommend you wrap your IplImages in another struct (or even a C++ class with templates!) to help you keep track of this information. If you're really desperate and you're dealing only with a certain type of images (outdoor scenes, offices, faces, etc.) you could try computing some statistics on your images (e.g. build histogram statistics for natural RGB images and some for natural HSV images), and then try to classify your totally unknown image by comparing which color space your image is closer to.
txandi makes an interesting point. OpenCV has a BGR colorspace which is used by default. This is similar to the RGB colorspace except that the B and R channels are physically switched in the image. If the physical channel ordering is important to you, you will need to convert your image with this function: cvCvtColor(defaultBGR, imageRGB, CV_BGR2RGB).
As rcv said, there is no method to programmatically detect the color space by inspecting the three color channels, unless you have a priori knowledge of the image content (e.g., there is a marker in the image whose color is known). If you will be accepting images from unknown sources, you must allow the user to specify the color space of their image. A good default would be to assume RGB.
If you modify any of the pixel colors before display, and you are using a non-OpenCV viewer, you should probably use cvCvtColor(src,dst,CV_BGR2RGB) after you have finished running all of your color filters. If you are using OpenCV for the viewer or will be saving the images out to file, you should make sure they are in BGR color space.
The IplImage struct has a field named colorModel consisting of 4 chars. Unfortunately, OpenCV ignores this field. But you can use this field to keep track of different color models.
I basically split the channels and display each one to figure out the color space of the image I'm using. It may not be the best way, but it works for me.
For detailed explanation, you can refer the below link.
https://dryrungarage.wordpress.com/2018/03/11/image-processing-basics/

Resources