[argyllcms] Re: targen?

  • From: Ben Goren <ben@xxxxxxxxxxxxxxxx>
  • To: argyllcms@xxxxxxxxxxxxx
  • Date: Wed, 29 Nov 2017 10:20:20 -0700

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: