need explicitly linear and nonlinear GRAY colorspaces

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

need explicitly linear and nonlinear GRAY colorspaces

Post by Dabrosny »

As it stands in 6.8.7-0, IM doesn't seem to distinguish between linear and nonlinear gray colorspaces, i.e. there's no analogue to RGB vs sRGB for single-channel images.
This causes problems.

To avoid ambiguity with "Gray", I suggest that we add an explicitly-linear 1-channel colorspace called Luminance (or LinearGray...)

And also a nonlinear 1-channel colorspace called sRGBgray (which is related to Luminance in precisely the same way that each sRGB color channel is related to its corresponding RGB color channel).

Then plain "Gray" colorspace could be depracated. Reading in a grayscale image in most formats would be set as sRGBgray by default, and any operations producing a linear grayscale result (e.g. a linear transformation of another linear colorspace like RGB) would set the colorspace to Luminance. A single channel extracted from sRGB would be sRGBgray by default, while a channel extracted from linear RGB would be Luminance by default (to indicate its linearity as an image itself).

Here's an example of the problem with having a single gray colorspace. I have an 8-bit sRGB input image and I want to make a grayscale version of it using a linear method:

$ convert mysrgb.png text:-
0,0: (6,6,6) #060606 srgb(6,6,6)
0,1: (81,180,7) #51B407 srgb(81,180,7)
$ convert mysrgb.png -grayscale Rec709Luminance text:-
0,0: (0,0,0) #000000 gray(0)
0,1: (88,88,88) #585858 gray(88)

As advertised, it has in fact transformed my input values to linear RGB and it's giving me the correct result but in the *linear* gray colorspace (the 0,0,0 may look strange; that's why we don't normally do linear colorspaces in 8 bits)

I want it back in sRGB like it was originally, so I'll try converting it:

$ convert mysrgb.png -grayscale Rec709Luminance -colorspace sRGB text:-
0,0: (0,0,0) #000000 srgb(0,0,0)
0,1: (88,88,88) #585858 srgb(88,88,88)

It seems to think it was *already* nonlinear and didn't change it at all!

The only way I was able to get the correct nonlinear result (as single-channel "sRGBgray") was this:

$ convert mysrgb.png -grayscale Rec709Luminance -set colorspace RGB -colorspace sRGB -separate +delete +delete text:-
0,0: (6,6,6) #060606 gray(6)
0,1: (158,158,158) #9E9E9E gray(158)

I'm only showing the 8-bit result but I did some spot checks on float results to about 7 significant figures and I believe it's correct.

Using -colorspace rec601luma or rec709luma usually gets about the same result as sRGB just above, but not *exactly* the same in all cases, esp. for some HDRI float images. Anyway the relationship to sRGB would be much clearer for a colorspace called sRGBgray (or sRGBLuma or even sGray I guess).

If you ask "why not just use -grayscale Rec709Luma?", it's because Rec709Luminance is the only transformation that correctly maps sRGB to CIE Luminance as in the sRGB standard, rather than using a linear combination of nonlinear lumas, which is just an expedient.

Version: ImageMagick 2013-09-30 Q16
Features: 6.8.7-0 DPC HDRI

-Dabrosny
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by snibgo »

Dabrosny wrote:$ convert mysrgb.png -grayscale Rec709Luminance -set colorspace RGB -colorspace sRGB -separate +delete +delete text:-
0,0: (6,6,6) #060606 gray(6)
0,1: (158,158,158) #9E9E9E gray(158)
You don't need "-separate +delete +delete". They have no net effect.

I agree that IM doesn't keep good track of whether an image is currently RGB or sRGB. For example, after "-grayscale Rec709Luminance", IM should know the image is RGB.

This isn't helped by the general paucity in file formats for recording colorspaces. But that's a separate issue.

But I don't see how your proposal for new colorspaces within IM will help. In what way would processing a "LinearGray" image differ from "RGB"? And how would processing "sRGBgray" differ from "sRGB"?
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by fmw42 »

The only way I was able to get the correct nonlinear result (as single-channel "sRGBgray") was this:

$ convert mysrgb.png -grayscale Rec709Luminance -set colorspace RGB -colorspace sRGB -separate +delete +delete text:-
0,0: (6,6,6) #060606 gray(6)
0,1: (158,158,158) #9E9E9E gray(158)

In IM 6, you will always have 3 channels even for grayscale. So your deletes are unnecessary. IM 7 will allow 1 channel images.

I get the same results as you by using:

convert xc:"gray(6)" xc:"rgb(81,180,7)" -set colorspace sRGB -append -depth 8 mysrgb.png
convert mysrgb.png txt:
# ImageMagick pixel enumeration: 1,2,255,srgb
0,0: (6,6,6) #060606 srgb(6,6,6)
0,1: (81,180,7) #51B407 srgb(81,180,7)


convert mysrgb.png -grayscale rec709luminance mysrgb_lin.png

convert mysrgb_lin.png txt:
# ImageMagick pixel enumeration: 1,2,255,gray
0,0: (0,0,0) #000000 gray(0)
0,1: (88,88,88) #585858 gray(88)

-grayscale rec709luminance is the proper linear grayscale when using sRGB (whereas rec709luma is non-linear gray). See the last bullet in the section at http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness where it indicates that sRGB uses rec709 and not rec601.

But IM (actually the image formats such as png or jpg or gif or tiff, etc) have no way to keep track of the fact that it is linear gray rather than non-linear gray. You can see this from the verbose information.

Code: Select all

Image: mysrgb_lin.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: PseudoClass
  Geometry: 1x2+0+0
  Units: Undefined
  Type: Grayscale  <==== does not say whether linear or nonlinear
  Endianess: Undefined
  Colorspace: Gray  <==== does not say whether linear or nonlinear
  Depth: 8/1-bit
  Channel depth:
    gray: 8-bit
  Channel statistics:
    Gray:
      min: 0 (0)
      max: 88 (0.345098)
      mean: 44 (0.172549)
      standard deviation: 44 (0.172549)
      kurtosis: -2
      skewness: 0
  Colors: 2
  Histogram:
         1: (  0,  0,  0) #000000 gray(0)
         1: ( 88, 88, 88) #585858 gray(88)
  Colormap entries: 256
  Colormap:
         0: (  0,  0,  0) #000000 gray(0)
         1: (  1,  1,  1) #010101 gray(1)
         2: (  2,  2,  2) #020202 gray(2)
         3: (  3,  3,  3) #030303 gray(3)
         4: (  4,  4,  4) #040404 gray(4)
         5: (  5,  5,  5) #050505 gray(5)
         6: (  6,  6,  6) #060606 gray(6)
         7: (  7,  7,  7) #070707 gray(7)
         8: (  8,  8,  8) #080808 gray(8)
         9: (  9,  9,  9) #090909 gray(9)
        10: ( 10, 10, 10) #0A0A0A gray(10)
        11: ( 11, 11, 11) #0B0B0B gray(11)
        12: ( 12, 12, 12) #0C0C0C gray(12)
        13: ( 13, 13, 13) #0D0D0D gray(13)
        14: ( 14, 14, 14) #0E0E0E gray(14)
        15: ( 15, 15, 15) #0F0F0F gray(15)
        16: ( 16, 16, 16) #101010 gray(16)
        17: ( 17, 17, 17) #111111 gray(17)
        18: ( 18, 18, 18) #121212 gray(18)
        19: ( 19, 19, 19) #131313 gray(19)
        20: ( 20, 20, 20) #141414 gray(20)
        21: ( 21, 21, 21) #151515 gray(21)
        22: ( 22, 22, 22) #161616 gray(22)
        23: ( 23, 23, 23) #171717 gray(23)
        24: ( 24, 24, 24) #181818 gray(24)
        25: ( 25, 25, 25) #191919 gray(25)
        26: ( 26, 26, 26) #1A1A1A gray(26)
        27: ( 27, 27, 27) #1B1B1B gray(27)
        28: ( 28, 28, 28) #1C1C1C gray(28)
        29: ( 29, 29, 29) #1D1D1D gray(29)
        30: ( 30, 30, 30) #1E1E1E gray(30)
        31: ( 31, 31, 31) #1F1F1F gray(31)
        32: ( 32, 32, 32) #202020 gray(32)
        33: ( 33, 33, 33) #212121 gray(33)
        34: ( 34, 34, 34) #222222 gray(34)
        35: ( 35, 35, 35) #232323 gray(35)
        36: ( 36, 36, 36) #242424 gray(36)
        37: ( 37, 37, 37) #252525 gray(37)
        38: ( 38, 38, 38) #262626 gray(38)
        39: ( 39, 39, 39) #272727 gray(39)
        40: ( 40, 40, 40) #282828 gray(40)
        41: ( 41, 41, 41) #292929 gray(41)
        42: ( 42, 42, 42) #2A2A2A gray(42)
        43: ( 43, 43, 43) #2B2B2B gray(43)
        44: ( 44, 44, 44) #2C2C2C gray(44)
        45: ( 45, 45, 45) #2D2D2D gray(45)
        46: ( 46, 46, 46) #2E2E2E gray(46)
        47: ( 47, 47, 47) #2F2F2F gray(47)
        48: ( 48, 48, 48) #303030 gray(48)
        49: ( 49, 49, 49) #313131 gray(49)
        50: ( 50, 50, 50) #323232 gray(50)
        51: ( 51, 51, 51) #333333 gray(51)
        52: ( 52, 52, 52) #343434 gray(52)
        53: ( 53, 53, 53) #353535 gray(53)
        54: ( 54, 54, 54) #363636 gray(54)
        55: ( 55, 55, 55) #373737 gray(55)
        56: ( 56, 56, 56) #383838 gray(56)
        57: ( 57, 57, 57) #393939 gray(57)
        58: ( 58, 58, 58) #3A3A3A gray(58)
        59: ( 59, 59, 59) #3B3B3B gray(59)
        60: ( 60, 60, 60) #3C3C3C gray(60)
        61: ( 61, 61, 61) #3D3D3D gray(61)
        62: ( 62, 62, 62) #3E3E3E gray(62)
        63: ( 63, 63, 63) #3F3F3F gray(63)
        64: ( 64, 64, 64) #404040 gray(64)
        65: ( 65, 65, 65) #414141 gray(65)
        66: ( 66, 66, 66) #424242 gray(66)
        67: ( 67, 67, 67) #434343 gray(67)
        68: ( 68, 68, 68) #444444 gray(68)
        69: ( 69, 69, 69) #454545 gray(69)
        70: ( 70, 70, 70) #464646 gray(70)
        71: ( 71, 71, 71) #474747 gray(71)
        72: ( 72, 72, 72) #484848 gray(72)
        73: ( 73, 73, 73) #494949 gray(73)
        74: ( 74, 74, 74) #4A4A4A gray(74)
        75: ( 75, 75, 75) #4B4B4B gray(75)
        76: ( 76, 76, 76) #4C4C4C gray(76)
        77: ( 77, 77, 77) #4D4D4D gray(77)
        78: ( 78, 78, 78) #4E4E4E gray(78)
        79: ( 79, 79, 79) #4F4F4F gray(79)
        80: ( 80, 80, 80) #505050 gray(80)
        81: ( 81, 81, 81) #515151 gray(81)
        82: ( 82, 82, 82) #525252 gray(82)
        83: ( 83, 83, 83) #535353 gray(83)
        84: ( 84, 84, 84) #545454 gray(84)
        85: ( 85, 85, 85) #555555 gray(85)
        86: ( 86, 86, 86) #565656 gray(86)
        87: ( 87, 87, 87) #575757 gray(87)
        88: ( 88, 88, 88) #585858 gray(88)
        89: ( 89, 89, 89) #595959 gray(89)
        90: ( 90, 90, 90) #5A5A5A gray(90)
        91: ( 91, 91, 91) #5B5B5B gray(91)
        92: ( 92, 92, 92) #5C5C5C gray(92)
        93: ( 93, 93, 93) #5D5D5D gray(93)
        94: ( 94, 94, 94) #5E5E5E gray(94)
        95: ( 95, 95, 95) #5F5F5F gray(95)
        96: ( 96, 96, 96) #606060 gray(96)
        97: ( 97, 97, 97) #616161 gray(97)
        98: ( 98, 98, 98) #626262 gray(98)
        99: ( 99, 99, 99) #636363 gray(99)
       100: (100,100,100) #646464 gray(100)
       101: (101,101,101) #656565 gray(101)
       102: (102,102,102) #666666 gray(102)
       103: (103,103,103) #676767 gray(103)
       104: (104,104,104) #686868 gray(104)
       105: (105,105,105) #696969 gray(105)
       106: (106,106,106) #6A6A6A gray(106)
       107: (107,107,107) #6B6B6B gray(107)
       108: (108,108,108) #6C6C6C gray(108)
       109: (109,109,109) #6D6D6D gray(109)
       110: (110,110,110) #6E6E6E gray(110)
       111: (111,111,111) #6F6F6F gray(111)
       112: (112,112,112) #707070 gray(112)
       113: (113,113,113) #717171 gray(113)
       114: (114,114,114) #727272 gray(114)
       115: (115,115,115) #737373 gray(115)
       116: (116,116,116) #747474 gray(116)
       117: (117,117,117) #757575 gray(117)
       118: (118,118,118) #767676 gray(118)
       119: (119,119,119) #777777 gray(119)
       120: (120,120,120) #787878 gray(120)
       121: (121,121,121) #797979 gray(121)
       122: (122,122,122) #7A7A7A gray(122)
       123: (123,123,123) #7B7B7B gray(123)
       124: (124,124,124) #7C7C7C gray(124)
       125: (125,125,125) #7D7D7D gray(125)
       126: (126,126,126) #7E7E7E gray(126)
       127: (127,127,127) #7F7F7F gray(127)
       128: (128,128,128) #808080 gray(128)
       129: (129,129,129) #818181 gray(129)
       130: (130,130,130) #828282 gray(130)
       131: (131,131,131) #838383 gray(131)
       132: (132,132,132) #848484 gray(132)
       133: (133,133,133) #858585 gray(133)
       134: (134,134,134) #868686 gray(134)
       135: (135,135,135) #878787 gray(135)
       136: (136,136,136) #888888 gray(136)
       137: (137,137,137) #898989 gray(137)
       138: (138,138,138) #8A8A8A gray(138)
       139: (139,139,139) #8B8B8B gray(139)
       140: (140,140,140) #8C8C8C gray(140)
       141: (141,141,141) #8D8D8D gray(141)
       142: (142,142,142) #8E8E8E gray(142)
       143: (143,143,143) #8F8F8F gray(143)
       144: (144,144,144) #909090 gray(144)
       145: (145,145,145) #919191 gray(145)
       146: (146,146,146) #929292 gray(146)
       147: (147,147,147) #939393 gray(147)
       148: (148,148,148) #949494 gray(148)
       149: (149,149,149) #959595 gray(149)
       150: (150,150,150) #969696 gray(150)
       151: (151,151,151) #979797 gray(151)
       152: (152,152,152) #989898 gray(152)
       153: (153,153,153) #999999 gray(153)
       154: (154,154,154) #9A9A9A gray(154)
       155: (155,155,155) #9B9B9B gray(155)
       156: (156,156,156) #9C9C9C gray(156)
       157: (157,157,157) #9D9D9D gray(157)
       158: (158,158,158) #9E9E9E gray(158)
       159: (159,159,159) #9F9F9F gray(159)
       160: (160,160,160) #A0A0A0 gray(160)
       161: (161,161,161) #A1A1A1 gray(161)
       162: (162,162,162) #A2A2A2 gray(162)
       163: (163,163,163) #A3A3A3 gray(163)
       164: (164,164,164) #A4A4A4 gray(164)
       165: (165,165,165) #A5A5A5 gray(165)
       166: (166,166,166) #A6A6A6 gray(166)
       167: (167,167,167) #A7A7A7 gray(167)
       168: (168,168,168) #A8A8A8 gray(168)
       169: (169,169,169) #A9A9A9 gray(169)
       170: (170,170,170) #AAAAAA gray(170)
       171: (171,171,171) #ABABAB gray(171)
       172: (172,172,172) #ACACAC gray(172)
       173: (173,173,173) #ADADAD gray(173)
       174: (174,174,174) #AEAEAE gray(174)
       175: (175,175,175) #AFAFAF gray(175)
       176: (176,176,176) #B0B0B0 gray(176)
       177: (177,177,177) #B1B1B1 gray(177)
       178: (178,178,178) #B2B2B2 gray(178)
       179: (179,179,179) #B3B3B3 gray(179)
       180: (180,180,180) #B4B4B4 gray(180)
       181: (181,181,181) #B5B5B5 gray(181)
       182: (182,182,182) #B6B6B6 gray(182)
       183: (183,183,183) #B7B7B7 gray(183)
       184: (184,184,184) #B8B8B8 gray(184)
       185: (185,185,185) #B9B9B9 gray(185)
       186: (186,186,186) #BABABA gray(186)
       187: (187,187,187) #BBBBBB gray(187)
       188: (188,188,188) #BCBCBC gray(188)
       189: (189,189,189) #BDBDBD gray(189)
       190: (190,190,190) #BEBEBE gray(190)
       191: (191,191,191) #BFBFBF gray(191)
       192: (192,192,192) #C0C0C0 gray(192)
       193: (193,193,193) #C1C1C1 gray(193)
       194: (194,194,194) #C2C2C2 gray(194)
       195: (195,195,195) #C3C3C3 gray(195)
       196: (196,196,196) #C4C4C4 gray(196)
       197: (197,197,197) #C5C5C5 gray(197)
       198: (198,198,198) #C6C6C6 gray(198)
       199: (199,199,199) #C7C7C7 gray(199)
       200: (200,200,200) #C8C8C8 gray(200)
       201: (201,201,201) #C9C9C9 gray(201)
       202: (202,202,202) #CACACA gray(202)
       203: (203,203,203) #CBCBCB gray(203)
       204: (204,204,204) #CCCCCC gray(204)
       205: (205,205,205) #CDCDCD gray(205)
       206: (206,206,206) #CECECE gray(206)
       207: (207,207,207) #CFCFCF gray(207)
       208: (208,208,208) #D0D0D0 gray(208)
       209: (209,209,209) #D1D1D1 gray(209)
       210: (210,210,210) #D2D2D2 gray(210)
       211: (211,211,211) #D3D3D3 gray(211)
       212: (212,212,212) #D4D4D4 gray(212)
       213: (213,213,213) #D5D5D5 gray(213)
       214: (214,214,214) #D6D6D6 gray(214)
       215: (215,215,215) #D7D7D7 gray(215)
       216: (216,216,216) #D8D8D8 gray(216)
       217: (217,217,217) #D9D9D9 gray(217)
       218: (218,218,218) #DADADA gray(218)
       219: (219,219,219) #DBDBDB gray(219)
       220: (220,220,220) #DCDCDC gray(220)
       221: (221,221,221) #DDDDDD gray(221)
       222: (222,222,222) #DEDEDE gray(222)
       223: (223,223,223) #DFDFDF gray(223)
       224: (224,224,224) #E0E0E0 gray(224)
       225: (225,225,225) #E1E1E1 gray(225)
       226: (226,226,226) #E2E2E2 gray(226)
       227: (227,227,227) #E3E3E3 gray(227)
       228: (228,228,228) #E4E4E4 gray(228)
       229: (229,229,229) #E5E5E5 gray(229)
       230: (230,230,230) #E6E6E6 gray(230)
       231: (231,231,231) #E7E7E7 gray(231)
       232: (232,232,232) #E8E8E8 gray(232)
       233: (233,233,233) #E9E9E9 gray(233)
       234: (234,234,234) #EAEAEA gray(234)
       235: (235,235,235) #EBEBEB gray(235)
       236: (236,236,236) #ECECEC gray(236)
       237: (237,237,237) #EDEDED gray(237)
       238: (238,238,238) #EEEEEE gray(238)
       239: (239,239,239) #EFEFEF gray(239)
       240: (240,240,240) #F0F0F0 gray(240)
       241: (241,241,241) #F1F1F1 gray(241)
       242: (242,242,242) #F2F2F2 gray(242)
       243: (243,243,243) #F3F3F3 gray(243)
       244: (244,244,244) #F4F4F4 gray(244)
       245: (245,245,245) #F5F5F5 gray(245)
       246: (246,246,246) #F6F6F6 gray(246)
       247: (247,247,247) #F7F7F7 gray(247)
       248: (248,248,248) #F8F8F8 gray(248)
       249: (249,249,249) #F9F9F9 gray(249)
       250: (250,250,250) #FAFAFA gray(250)
       251: (251,251,251) #FBFBFB gray(251)
       252: (252,252,252) #FCFCFC gray(252)
       253: (253,253,253) #FDFDFD gray(253)
       254: (254,254,254) #FEFEFE gray(254)
       255: (255,255,255) #FFFFFF gray(255)
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: gray(255)
  Border color: gray(223)
  Matte color: gray(189)
  Transparent color: gray(0)
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 1x2+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: Zip
  Orientation: Undefined
  Properties:
    date:create: 2013-10-02T15:10:39-07:00
    date:modify: 2013-10-02T15:10:39-07:00
    png:bKGD: chunk was found (see Background color, above)
    png:gAMA: gamma=1 (See Gamma, above)
    png:IHDR.bit-depth-orig: 8
    png:IHDR.bit_depth: 8
    png:IHDR.color-type-orig: 0
    png:IHDR.color_type: 0 (Grayscale)  <==== does not say whether linear or nonlinear
    png:IHDR.interlace_method: 0 (Not interlaced)
    png:IHDR.width,height: 1, 2
    png:text: 2 tEXt/zTXt/iTXt chunks were found
    signature: 62c2a0d38aeb55f6b569cb9fb3a78c17b0386618764f134cbd395826f3256e78
  Artifacts:
    filename: mysrgb_lin.png
    verbose: true
  Tainted: True
  Filesize: 197B
  Number pixels: 2
  Pixels per second: 2PB
  User time: 0.000u
  Elapsed time: 0:01.000
  Version: ImageMagick 6.8.7-0 2013-09-26 Q16 http://www.imagemagick.org
As you can see there is no flag that says it is linear only simply grayscale. Thus you must specify linear or non-linear by using -set colorspace. Thus to convert it back to sRGB, you will then set the colorspace as RGB (linear) and then change the colorspace to nonlinear sRGB.


convert mysrgb.png -grayscale rec709luminance -set colorspace RGB -colorspace sRGB txt:
# ImageMagick pixel enumeration: 1,2,255,srgb
0,0: (6,6,6) #060606 srgb(6,6,6)
0,1: (158,158,158) #9E9E9E srgb(158,158,158)

As far as I understand it, the above is correct (within the limits of 8-bit data)
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by Dabrosny »

In what way would processing a "LinearGray" image differ from "RGB"? And how would processing "sRGBgray" differ from "sRGB"?
In that case, we should label the result of "convert mysrgb.png -grayscale Rec709Luminance" as being in RGB colorspace (linear) rather than the ambiguous Gray. That way, any further operations would know whether they need to gamma expand or compress the image before performing certain operations on it, such as converting to another colorspace.

That would be a big improvement, especially in IM6 where gray isn't implemented as a single channel anyway.

But conceptually (and presumably for IM7) we have the Gray colorspace for a reason.

The fact is, we *do* have a Gray colorspace, and when we convert to it, we lose the information on whether the result is (still) encoded linearly or nonlinearly, even though this information is available in most (though not all) cases from the colorspace of the source image and the type of operation/conversion applied. This affects operations that come afterwards, which no longer know whether they need to convert to linear or nonlinear for a conversion to sRGB or RGB or some operations or even saving the file.

Many file formats are assumed to be sRGB by default when we read them (unless they specifiy explicitly). If they have a single-channel version I believe we make the same assumption -- just as if this channel were repeated three times and treated as sRGB. The same should be done on writing such a file format -- we should make the same assumption for grayscale as for color (i.e. usually sRGB nonlinearity). There's seldom any need to store linear values in a png file, and anyway the resulting loss of visible resolution at the dark end is often extreme if it's 8-bit. If you want to store a linear encoding, use a format that can indicate this internally, or else use an explicit -set colorspace to override the default.

Also by having more explicit gray colorspaces, most of us wouldn't have to worry so much about specifying the intensity type for -grayscale or -colorspace gray -- the appropriate defaults would give reasonable results:
convert mysrgb.png -colorspace LinearGray would produce a Linear luminance (Y as defined in the sRGB standard), i.e. the same as -grayscale Rec709Luminance but labeling the result as LinearGray.
convert mysrgb.png -colorspace sRGBgray would give produce an sRGB-gamma result that would be numerically identical to the way I did it, but labeling the result as sRGBgray so that any later explicit or implicit -colorspace RGB (or -colorspace LinearGray) would know that it has to linearize it.

In fact we can already do -colorspace Rec709Luma or Rec601Luma, though they presumably use the corresponding direct formulas (no intermediate conversion to linear luminance) which would give different results from -colorspace sRGBgray. (The sRGB standard does not use or define a Luma that could be be calculated, so the only correct way to get greyscale using the sRGB standard is to go through linear Y, which it does define a relationship to.)

If you want to just start treating the Gray colorspace as definitively linear (and we can use the others like Rec709Luma if it isn't), that would be okay, but I think it's better to name it more explicitly as CieLuminance or Luminance or LinearGray or what ever. And maybe there's a benefit to retaining an ambiguous colorspace like Gray such that no transformations will be performed on it implicitly but only when you do so explicitly.

-Dabrosny
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by fmw42 »

My understanding is that most image formats either do not distinguish linear gray from non-linear gray or do not support a linear RGB. PNG may possibly be the only one that does. Thus the PNG image rather than being colorspace=gray, would have to be colorspace=RGB (vs sRGB) and type=grayscale.

I am not sure what the IM developers can actually do in the software if the formats do not support that. Internally IM could possibly support it and may already do so. But once the image is written, it would lose that information.

The IM developers would have to respond to give you more accurate information.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by snibgo »

An internal colorspace value of Gray is treated as the same as sRGB. Thus, in the command ...

Code: Select all

convert h8.png -colorspace gray -colorspace sRGB h8gsRGB.png
... the second "-colorspace" makes no changes.

A "-grayscale XX" operation changes the internal colorspace value to Gray, for all values of XX. This is misleading, as after "-grayscale Rec709Luminance" the result is actually RGB (not sRGB). Also, I'm not sure that "-grayscale RMS" etc should change the internal colorspace value at all.
snibgo's IM pages: im.snibgo.com
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by Dabrosny »

Okay, so we agree that at least the output of -grayscale Rec709Luminance (and similar) in IM6 should automatically be labeled as some linear colorspace such as RGB (or ultimately something like LinearGray either now or in IM7).

Would any maintainers or other care to comment in favor or against this? Should I submit this request formally?

And what about creating an explicitly-linear gray colorspace like LinearGray (in IM6) so that -colorspace LinearGray (on sRGB input) automatically linearizes and applies the appropriate linear grayscale operator (i.e. Rec709Luminance) ? (As opposed to -colorspace Gray (or, better yet, -colorspace sGray) which will still produce a nonlinear result like today.)

-Dabrosny
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by fmw42 »

Dabrosny wrote:Okay, so we agree that at least the output of -grayscale Rec709Luminance (and similar) in IM6 should automatically be labeled as some linear colorspace such as RGB (or ultimately something like LinearGray either now or in IM7).
I will defer to the IM developers.

But again, I do not think you can save that information in most image formats. So it would have to be specially coded in the IM internal format and used only within a single command or saved to one of the IM formats such as MIFF or MPC or possibly PNG. Which I think it already does. But that means that no other tool will be able to detect that it is linear (unless saved as PNG), since no other tool reads IM MIFF or MPC formats (that I know about).

Example that shows PNG and MIFF distinguishes (looking at the verbose information):

convert rose: -grayscale rec709luma rose_luma.png
gamma=0.4545

convert rose: -grayscale rec709luminance rose_luminance.png
gamma=1



convert rose: -grayscale rec709luma rose_luma.miff
gamma=0.4545

convert rose: -grayscale rec709luminance rose_luminance.miff
gamma=1


But JPG does not support this:

convert rose: -grayscale rec709luma rose_luma.jpg
gamma=0.4545

convert rose: -grayscale rec709luminance rose_luminance.jpg
gamma=0.4545


If I misunderstand what you are suggesting, I apologize.

I certainly will defer to the IM developers for clarification.
Last edited by fmw42 on 2013-10-04T14:52:37-07:00, edited 1 time in total.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by snibgo »

Dabrosny wrote:Okay, so we agree that at least the output of -grayscale Rec709Luminance (and similar) in IM6 should automatically be labeled as some linear colorspace such as RGB (or ultimately something like LinearGray either now or in IM7).
I'm not sure that I entirely agree. I think it is wrong that -grayscale Rec709Luminance is labelled Gray, but also that -grayscale RMS is labelled Gray.

Another option is that "-grayscale XX" shouldn't change the colorspace at all.

As far as I know, -grayscale is the only operation aside from "-colorspace" and "-set colorspace" that modifies the internal colorspace value. It might be cleaner if -grayscale didn't change the colorspace.

I don't know the full implications of adding a LinearGray colorspace (and ensuring it processes correctly). I can't see much harm, from a user's point of view. The only slight harm would be that some scripts that currently make "Gray" images would instead make "LinearGray" images.
snibgo's IM pages: im.snibgo.com
Dabrosny
Posts: 111
Joined: 2013-10-02T10:49:39-07:00
Authentication code: 6789
Location: New York, US

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by Dabrosny »

But again, I do not think you can save that information in most image formats. So it would have to specially coded in the IM internal format and used only within a single command or saved to one of the IM formats such as MIFF or MPC or possibly PNG.
That is a separate problem and won't be affected by this change! The following two commands produce an identical jpeg file (I verified with a 6.8.7-0 2013-09-30 Q16 HDRI build):

Code: Select all

convert file.png -grayscale Rec709Luminance gray.jpg

Code: Select all

convert file.png -grayscale Rec709Luminance -set colorspace RGB gray.jpg
(If that is undesirable behavior, then IM should automatically convert to sRGB when saving an image to a presumed-sRGB format. I would in fact favor that, but it's a separate question and deserves its own forum topic.)

On the other hand, for png, it is today storing an *incorrect* gamma (i.e. that of sRGB) in the png file today when we do this:

Code: Select all

convert file.png -grayscale Rec709Luminance gray.png
Whereas after the change the above will implicitly do the equivalent of this:

Code: Select all

convert file.png -grayscale Rec709Luminance -set colorspace RGB gray.png
which stores the *correct* gamma of 1.0 in the png file.

But this is not just about storing the image in an external file format. The first order of business is labeling things correctly inside of IM so that the next operation *within* IM will do the correct thing, regardless of how we eventually store the image.

The present situation *falsely* "labels" (or at least treats) the output of -grayscale Rec709Luminance as if it were nonlinear, when in fact it is linear. If you (manually via -colorspace RGB) or another IM operation itself (automatically) transforms it to linear, the result will be just plain wrong, because in fact it was already linear and now it is nonlinear in the opposite direction (instead of being in gamma 2.2 or gamma 1 space it is now actually in gamma 0.454545 space!).

If you *want* to make it nonlinear after -grayscale Rec709Luminance, for purposes of other operations or for saving in a format that can't label it as linear, that's what -colorspace sRGB is for, and it will do this correctly.

-Dabrosny
-Dabrosny [Using IM7.0.6 or higher, Q16 HDRI x64 native executable, command line, often invoked from cygwin bash/sh (as of Aug. 2017)]
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by fmw42 »

convert file.png -grayscale Rec709Luminance gray.png
For PNG and MIFF, it already stores gamma=1 to indicate that it is linear as I showed above (IM 6.8.7.0 Q16 Mac OSX non-hdri). I am not sure about changing colorspace from gray to RGB. That may be misleading, because that would imply 3 channels, whereas it is truly gray. Thus other tools will see it as 3 channels if you use -set colorspace RGB, whereas if left as colorspace gray, it will be read as one channel by other tools. Most if not all the other image formats do not support RGB (as opposed to sRGB) as a colorspace value.

But again I will defer to the IM developers for a proper reply to this topic. I would agree that we do need to hear back from them.
Last edited by fmw42 on 2013-10-04T14:49:39-07:00, edited 1 time in total.
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by glennrp »

Rec709 is like sRGB, with gamma=1/.45 (.22222...) except for a linear portion in the low intensity region: http://en.wikipedia.org/wiki/Rec._709
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by fmw42 »

glennrp wrote:Rec709 is like sRGB, with gamma=1/.45 (.22222...) except for a linear portion in the low intensity region: http://en.wikipedia.org/wiki/Rec._709

Glenn,

For PNG and MIFF:

I believe the issue is whether -grayscale rec709luminance (with gamma=1) is truly linear grayscale vs -grayscale rec709luma (with gamma=0.4545) which is non-linear sRGB grayscale. I believe that the former is linear.

The OP seems to be of the opinion that it needs -set colorspace RGB following it to make it properly linear. But as I understand it, the colorspace gray will then allow other tools to see it as 1 channel grayscale vs 3 channels for colorspace RGB with the same data in all channels. So I think the former is correct already, since it has gamma=1 already.

Correct me if wrong, but I do not think other image formats (such as JPG) support linear grayscale.

Fred
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by fmw42 »

If the OP is getting gamma=0.4545 for -grayscale rec709luminance in HDRI mode, then that is a bug. In non-hdri mode it produces gamma=1.

Doing a test with and without hdri, I find the OP was right contrary to my earlier tests

convert rose: -grayscale rec709luminance rose_tmp.png
gamma=0.4545

But the PNG info shows gamma=1
Properties:
date:create: 2013-10-04T15:11:22-07:00
date:modify: 2013-10-04T15:11:22-07:00
png:bKGD: chunk was found (see Background color, above)
png:gAMA: gamma=1 (See Gamma, above)
png:IHDR.bit-depth-orig: 8
png:IHDR.bit_depth: 8
png:IHDR.color-type-orig: 0
png:IHDR.color_type: 0 (Grayscale)
png:IHDR.interlace_method: 0 (Not interlaced)
png:IHDR.width,height: 70, 46
png:text: 2 tEXt/zTXt/iTXt chunks were found
signature: b9e4563ff80920640476d2955c0d9e962912a4af5571fe3056b56f1e167d2ea2


So there is an inconsistency between the IM gamma and PNG gamma in which the IM gamma appears wrong.

My apologies to the OP.

I will report this as a potential bug.

P.S It works fine with miff output format showing gamma=1.
Last edited by fmw42 on 2013-10-04T15:54:20-07:00, edited 5 times in total.
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: need explicitly linear and nonlinear GRAY colorspaces

Post by glennrp »

This is slightly confusing to me. There is no Rec709LuminanceColorspace defined in magick/colorspace.h (however, there is a Rec709LuminancePixelIntensityMethod defined in magick/pixel.h) so I would expect
the "-grayscale Rec709Luminance" to have the same effect as "-grayscale Undefined", which may or may not be what was expected. I note that in IM7, Rec709LumaColorspace became Rec709YCbCrColorspace, and Rec709Luminance still does not appear in the enumeration of colorspace names in colorspace.h.
Post Reply