[argyllcms] Re: targen?

  • From: "Yves Gauvreau" <gauvreau-yves@xxxxxxxxxxx>
  • To: <argyllcms@xxxxxxxxxxxxx>
  • Date: Thu, 30 Nov 2017 04:04:04 -0500

Ben, maybe you missed my last phrase,

"I suppose that my function doesn't use the same parameter as yours, I tried
a few but obviously it didn't work. Have an idea?"

I may not know much about color science and the works but I would have
thought that a CIEXYZ 1931 "color" when viewed in some specific conditions
was like a reference, a standard if you prefer and that it was device
independent. 

RGB colorspaces are device dependent and without this reference to a device
colorspace the image file are just a bunch of useless numbers like if I say
to you I'm doing 60. You may speculate all you want but until I tie this
number to some reference like say kilometers per hours, miles per hour or
meter per second. You have no idea of what I'm talking about.

Can anyone direct me to or tell me what parameters are use by the targen
algorithm to convert this data from XYZ to RGB or vice versa? 

If by any chance there is a bug in either the code I use or the one use in
Targen, I'm sure both authors would appreciate to know about it.

Thanks in advance,
Yves
   



-----Original Message-----
From: argyllcms-bounce@xxxxxxxxxxxxx [mailto:argyllcms-bounce@xxxxxxxxxxxxx]
On Behalf Of Ben Goren
Sent: Wednesday, November 29, 2017 12:20 PM
To: argyllcms@xxxxxxxxxxxxx
Subject: [argyllcms] Re: targen?

A few things jump out at me. (Of course, I could well be jumping at shadows;
Graeme can clarify if so.)

First, I'm pretty sure Argyll is going to be using D50 for basically
everything unless you specify otherwise. The code below is using D65. That
right there will result in a dramatic difference.

Second, your example is assuming sRGB for the color space. When generating a
target, the color space is as yet unknown. I don't know what color space
Argyll is using to get approximations of XYZ values, but I'll bet you a cup
of coffee that it isn't sRGB. If I had to guess, it'd be something that, in
Graeme's experience, is roughly typical of the type of device you asked the
target to be generated for.

Finally, it's important to understand the purpose of those XYZ values. As I
mentioned, until after you've made the profile, there's no way of knowing
what XYZ values will be generated by the device values; in that sense, the
XYZ values are meaningless. _However,_ a "close enough" value is all you
(typically) need for automatic chart recognition to work -- for, for
example, chartread to be able to tell which row you read and in which
direction. Or for scanin to know how to rotate the chart before reading
values, and so on. The approximate XYZ values targen generates are going to
be plenty for such sorts of things.

A postscript: if you need an accurate translation of device values to an
absolute color space, you can use xicclu. You'll also need a profile, and
the results of the translation will only be as good as the profile.

Cheers,

b&

On Nov 29, 2017, at 9:50 AM, Yves Gauvreau <gauvreau-yves@xxxxxxxxxxx>
wrote:

Just out of curiosity, I've look into a couple it1 file and I see for
example:

 RGB_R    RGB_G    RGB_B    XYZ_X    XYZ_Y    XYZ_Z

1 100.0000 100.0000 100.0000 95.10649 100.0000 108.8440 95.047  100 
108.883
2 34.90846 18.70357 19.19271 6.662239 5.390882 4.420492 5.719344 
4.435405
3.45356
3 53.46272 1.487180 40.57153 13.59305 7.270500 14.37423 12.71993 
6.334173
13.50277
4 12.87608 12.78395 76.12723 11.79817 6.233704 52.05826 10.90296 
5.285513
51.54733
5 76.48620 70.70083 83.16876 51.28491 49.63258 69.47523 50.78692 
49.12363
69.13399


I was curious to see if my program (R version 3.4.2 (2017-09-28)) and 
the colorspace package which uses a Matlab library would give me the 
same result (XYZ).

So I use a function called RGB2XYZ from that packages and the results 
differ, so I'm curious to understand why.

This function assume the following defaults and just so I don't miss 
any, here is the function text:

function (RGBmatrix, illuminant = "D65", observer = 2, RefWhite = 
get("XYZperfectreflectingdiffuser",
   envir = environment()), RGBModel = "sRGB", RefWhiteRGB = 
get("whitepointsRGB",
   envir = environment()), gamma = NA, RefWhiteIllum = 
get("XYZperfectreflectingdiffuser",
   envir = environment()), CAT = "Bradford", CATarray = 
get("ChromaticAdaptation",
   envir = environment()))
{
   if (is.null(dim(RGBmatrix))) 
       if (length(RGBmatrix) > 2) 
           RGBmatrix <- matrix(RGBmatrix, ncol = 3, byrow = TRUE)
   CATmatrix <- CATarray[, , CAT, "direct"]
   Rrgb <- RefWhiteRGB[which(RefWhiteRGB[["description"]] == 
       RGBModel), ]
   Rillum <- unlist(Rrgb["whitepointilluminant"])
   Rgamma <- unlist(Rrgb["gamma"])
   Rrgbwhitergb <- RefWhiteIllum[which(RefWhiteIllum[["Illuminant"]] == 
       Rillum), ]
   Rrgbwhitex <- unlist(Rrgbwhitergb[paste("X", observer, sep = "")])
   Rrgbwhitey <- unlist(Rrgbwhitergb[paste("Y", observer, sep = "")])
   Rrgbwhitez <- unlist(Rrgbwhitergb[paste("Z", observer, sep = "")])
   if (is.na(gamma)) 
       gamma <- Rgamma
   if (RGBModel == "sRGB") 
       gamma <- -gamma
   RGBmatrix <- apply(RGBmatrix, 1:2, function(x) InvCompand(x, 
       gamma))
   R <- RefWhite[which(RefWhite[["Illuminant"]] == illuminant), 
       ]
   Rx <- unlist(R[paste("X", observer, sep = "")])
   Ry <- unlist(R[paste("Y", observer, sep = "")])
   Rz <- unlist(R[paste("Z", observer, sep = "")])
   xr <- unlist(Rrgb["xRed"])
   yr <- unlist(Rrgb["yRed"])
   xg <- unlist(Rrgb["xGreen"])
   yg <- unlist(Rrgb["yGreen"])
   xb <- unlist(Rrgb["xBlue"])
   yb <- unlist(Rrgb["yBlue"])
   m <- matrix(c(xr/yr, xg/yg, xb/yb, 1, 1, 1, (1 - xr - yr)/yr, 
       (1 - xg - yg)/yg, (1 - xb - yb)/yb), 3, 3, byrow = TRUE)
   mi <- solve(m)
   sr <- mi %*% matrix(c(Rrgbwhitex, Rrgbwhitey, Rrgbwhitez), 
       3, 1)
   MtxRGB2XYZ <- t(matrix(sr, 3, 3, byrow = TRUE) * m)
   XYZ <- RGBmatrix %*% MtxRGB2XYZ
   Adz <- CATmatrix %*% matrix(c(Rx, Ry, Rz), 3, 1, byrow = T)
   Asz <- CATmatrix %*% matrix(c(Rrgbwhitex, Rrgbwhitey, Rrgbwhitez), 
       3, 1, byrow = T)
   xyz2 <- t(apply(XYZ, 1, function(x) rowSums(matrix(x, 3, 
       3, byrow = T) * CATmatrix)))
   xyz2 <- xyz2 * matrix(c(Adz/Asz), dim(XYZ)[1], 3, byrow = T)
   XYZ <- t(apply(xyz2, 1, function(x) c(x) %*% t(solve(CATmatrix))))
   XYZ
}

I suppose that my function doesn't use the same parameter as yours, I 
tried a few but obviously it didn't work. Have an idea?

Thanks





Other related posts: