canvas-display-p3.js (10593B)
1 // Each PNG: 2 // * is 2x2 and has a single color 3 // * has a filename that indicates its contents: 4 // <embedded-profile>-<8-or-16-bit-color-value>.png 5 // * was generated using ImageMagick commands like: 6 // convert -size 2x2 xc:'#BB0000FF' -profile Display-P3.icc Display-P3-BB0000FF.png 7 // convert -size 2x2 xc:'#BBBC00000000FFFF' -profile Adobe-RGB.icc Adobe-RGB-BBBC00000000FFFF.png 8 9 // Top level key is the image filename. Second level key is the pair of 10 // CanvasRenderingContext2DSettings.colorSpace and ImageDataSettings.colorSpace. 11 const imageTests = { 12 // 8 bit source images 13 14 "sRGB-FF0000FF.png": { 15 "srgb srgb": [255, 0, 0, 255], 16 "srgb display-p3": [234, 51, 35, 255], 17 "display-p3 srgb": [255, 0, 0, 255], 18 "display-p3 display-p3": [234, 51, 35, 255], 19 }, 20 "sRGB-FF0000CC.png": { 21 "srgb srgb": [255, 0, 0, 204], 22 "srgb display-p3": [234, 51, 35, 204], 23 "display-p3 srgb": [255, 0, 0, 204], 24 "display-p3 display-p3": [234, 51, 35, 204], 25 }, 26 "sRGB-BB0000FF.png": { 27 "srgb srgb": [187, 0, 0, 255], 28 "srgb display-p3": [171, 35, 23, 255], 29 "display-p3 srgb": [187, 1, 0, 255], 30 "display-p3 display-p3": [171, 35, 23, 255], 31 }, 32 "sRGB-BB0000CC.png": { 33 "srgb srgb": [187, 0, 0, 204], 34 "srgb display-p3": [171, 35, 23, 204], 35 "display-p3 srgb": [187, 1, 0, 204], 36 "display-p3 display-p3": [171, 35, 23, 204], 37 }, 38 39 "Display-P3-FF0000FF.png": { 40 "srgb srgb": [255, 0, 0, 255], 41 "srgb display-p3": [234, 51, 35, 255], 42 "display-p3 srgb": [255, 0, 0, 255], 43 "display-p3 display-p3": [255, 0, 0, 255], 44 }, 45 "Display-P3-FF0000CC.png": { 46 "srgb srgb": [255, 0, 0, 204], 47 "srgb display-p3": [234, 51, 35, 204], 48 "display-p3 srgb": [255, 0, 0, 204], 49 "display-p3 display-p3": [255, 0, 0, 204], 50 }, 51 "Display-P3-BB0000FF.png": { 52 "srgb srgb": [205, 0, 0, 255], 53 "srgb display-p3": [188, 39, 26, 255], 54 "display-p3 srgb": [205, 0, 0, 255], 55 "display-p3 display-p3": [187, 0, 0, 255], 56 }, 57 "Display-P3-BB0000CC.png": { 58 "srgb srgb": [205, 0, 0, 204], 59 "srgb display-p3": [188, 39, 26, 204], 60 "display-p3 srgb": [205, 0, 0, 204], 61 "display-p3 display-p3": [187, 0, 0, 204], 62 }, 63 64 "Adobe-RGB-FF0000FF.png": { 65 "srgb srgb": [255, 0, 0, 255], 66 "srgb display-p3": [234, 51, 35, 255], 67 "display-p3 srgb": [255, 19, 11, 255], 68 "display-p3 display-p3": [255, 61, 43, 255], 69 }, 70 "Adobe-RGB-FF0000CC.png": { 71 "srgb srgb": [255, 0, 0, 204], 72 "srgb display-p3": [234, 51, 35, 204], 73 "display-p3 srgb": [255, 19, 11, 204], 74 "display-p3 display-p3": [255, 61, 43, 204], 75 }, 76 "Adobe-RGB-BB0000FF.png": { 77 "srgb srgb": [219, 0, 0, 255], 78 "srgb display-p3": [201, 42, 29, 255], 79 "display-p3 srgb": [219, 0, 1, 255], 80 "display-p3 display-p3": [201, 42, 29, 255], 81 }, 82 "Adobe-RGB-BB0000CC.png": { 83 "srgb srgb": [219, 0, 0, 204], 84 "srgb display-p3": [201, 42, 29, 204], 85 "display-p3 srgb": [219, 0, 1, 204], 86 "display-p3 display-p3": [201, 42, 29, 204], 87 }, 88 89 "Generic-CMYK-FF000000.jpg": { 90 "srgb srgb": [0, 163, 218, 255], 91 "srgb display-p3": [72, 161, 213, 255], 92 "display-p3 srgb": [0, 163, 218, 255], 93 "display-p3 display-p3": [0, 160, 213, 255], 94 }, 95 "Generic-CMYK-BE000000.jpg": { 96 "srgb srgb": [0, 180, 223, 255], 97 "srgb display-p3": [80, 177, 219, 255], 98 "display-p3 srgb": [0, 180, 223, 255], 99 "display-p3 display-p3": [65, 177, 219, 255], 100 }, 101 102 // 16 bit source images 103 104 "sRGB-FFFF00000000FFFF.png": { 105 "srgb srgb": [255, 0, 0, 255], 106 "srgb display-p3": [234, 51, 35, 255], 107 "display-p3 srgb": [255, 0, 0, 255], 108 "display-p3 display-p3": [234, 51, 35, 255], 109 }, 110 "sRGB-FFFF00000000CCCC.png": { 111 "srgb srgb": [255, 0, 0, 204], 112 "srgb display-p3": [234, 51, 35, 204], 113 "display-p3 srgb": [255, 0, 0, 204], 114 "display-p3 display-p3": [234, 51, 35, 204], 115 }, 116 "sRGB-BBBC00000000FFFF.png": { 117 "srgb srgb": [187, 0, 0, 255], 118 "srgb display-p3": [171, 35, 23, 255], 119 "display-p3 srgb": [187, 1, 0, 255], 120 "display-p3 display-p3": [171, 35, 23, 255], 121 }, 122 "sRGB-BBBC00000000CCCC.png": { 123 "srgb srgb": [187, 0, 0, 204], 124 "srgb display-p3": [171, 35, 23, 204], 125 "display-p3 srgb": [187, 1, 0, 204], 126 "display-p3 display-p3": [171, 35, 23, 204], 127 }, 128 129 "Display-P3-FFFF00000000FFFF.png": { 130 "srgb srgb": [255, 0, 0, 255], 131 "srgb display-p3": [234, 51, 35, 255], 132 "display-p3 srgb": [255, 0, 0, 255], 133 "display-p3 display-p3": [255, 0, 0, 255], 134 }, 135 "Display-P3-FFFF00000000CCCC.png": { 136 "srgb srgb": [255, 0, 0, 204], 137 "srgb display-p3": [234, 51, 35, 204], 138 "display-p3 srgb": [255, 0, 0, 204], 139 "display-p3 display-p3": [255, 0, 0, 204], 140 }, 141 "Display-P3-BBBC00000000FFFF.png": { 142 "srgb srgb": [205, 0, 0, 255], 143 "srgb display-p3": [188, 39, 26, 255], 144 "display-p3 srgb": [205, 0, 0, 255], 145 "display-p3 display-p3": [187, 0, 0, 255], 146 }, 147 "Display-P3-BBBC00000000CCCC.png": { 148 "srgb srgb": [205, 0, 0, 204], 149 "srgb display-p3": [188, 39, 26, 204], 150 "display-p3 srgb": [205, 0, 0, 204], 151 "display-p3 display-p3": [187, 0, 0, 204], 152 }, 153 154 "Adobe-RGB-FFFF00000000FFFF.png": { 155 "srgb srgb": [255, 0, 0, 255], 156 "srgb display-p3": [234, 51, 35, 255], 157 "display-p3 srgb": [255, 19, 11, 255], 158 "display-p3 display-p3": [255, 61, 43, 255], 159 }, 160 "Adobe-RGB-FFFF00000000CCCC.png": { 161 "srgb srgb": [255, 0, 0, 204], 162 "srgb display-p3": [234, 51, 35, 204], 163 "display-p3 srgb": [255, 19, 11, 204], 164 "display-p3 display-p3": [255, 61, 43, 204], 165 }, 166 "Adobe-RGB-BBBC00000000FFFF.png": { 167 "srgb srgb": [219, 0, 0, 255], 168 "srgb display-p3": [201, 42, 29, 255], 169 "display-p3 srgb": [219, 0, 1, 255], 170 "display-p3 display-p3": [201, 42, 29, 255], 171 }, 172 "Adobe-RGB-BBBC00000000CCCC.png": { 173 "srgb srgb": [219, 0, 0, 204], 174 "srgb display-p3": [201, 42, 29, 204], 175 "display-p3 srgb": [219, 0, 1, 204], 176 "display-p3 display-p3": [201, 42, 29, 204], 177 }, 178 }; 179 180 const svgImageTests = { 181 // SVG source images 182 183 "sRGB-FF0000.svg": { 184 "srgb srgb": [255, 0, 0, 255], 185 "srgb display-p3": [234, 51, 35, 255], 186 "display-p3 srgb": [255, 0, 0, 255], 187 "display-p3 display-p3": [234, 51, 35, 255], 188 }, 189 "sRGB-BB0000.svg": { 190 "srgb srgb": [187, 0, 0, 255], 191 "srgb display-p3": [171, 35, 23, 255], 192 "display-p3 srgb": [187, 1, 0, 255], 193 "display-p3 display-p3": [171, 35, 23, 255], 194 }, 195 196 "Display-P3-1-0-0.svg": { 197 "srgb srgb": [255, 0, 0, 255], 198 "srgb display-p3": [234, 51, 35, 255], 199 "display-p3 srgb": [255, 0, 0, 255], 200 "display-p3 display-p3": [255, 0, 0, 255], 201 }, 202 "Display-P3-0.7333-0-0.svg": { 203 "srgb srgb": [205, 0, 0, 255], 204 "srgb display-p3": [188, 39, 26, 255], 205 "display-p3 srgb": [205, 0, 0, 255], 206 "display-p3 display-p3": [187, 0, 0, 255], 207 }, 208 }; 209 210 // Each video: 211 // * is 300x200 and has a single color 212 // * has a filename base that indicates its contents: 213 // 214 // <color-space>-<8-or-10-bit-color-value> 215 // 216 // * was generated using commands like: 217 // 218 // W=300 H=200 Y=3F Cb=66 Cr=F0 ; \ 219 // perl -e "print pack('c', 0x$Y) x ($W * $H), pack('c', 0x$Cb) x ($W * $H / 4), pack('c', 0x$Cr) x ($W * $H / 4)" | \ 220 // ffmpeg -f rawvideo -pix_fmt yuv420p -s:v ${W}x$H -r 25 -i - -pix_fmt yuv420p -colorspace bt709 -color_primaries bt709 -color_trc iec61966_2_1 sRGB-FF0100.webm 221 // 222 // W=300 H=200 Y=0BB Cb=1BD Cr=2EF ; \ 223 // perl -e "print pack('s', 0x$Y) x ($W * $H), pack('s', 0x$Cb) x ($W * $H / 4), pack('s', 0x$Cr) x ($W * $H / 4)" | \ 224 // ffmpeg -f rawvideo -pix_fmt yuv420p10le -s:v ${W}x$H -r 25 -i - -c:v libx265 -vtag hvc1 -pix_fmt yuv420p10le -colorspace bt2020nc -color_primaries bt2020 -color_trc bt2020-10 Rec2020-222000000.mp4 225 // 226 // W=300 H=200 Y=0BB Cb=1BD Cr=2EF ; \ 227 // perl -e "print pack('s', 0x$Y) x ($W * $H), pack('s', 0x$Cb) x ($W * $H / 4), pack('s', 0x$Cr) x ($W * $H / 4)" | \ 228 // ffmpeg -f rawvideo -pix_fmt yuv420p10le -s:v ${W}x$H -r 25 -i - -vcodec libvpx-vp9 -profile:v 2 -pix_fmt yuv420p10le -colorspace bt2020nc -color_primaries bt2020 -color_trc bt2020-10 Rec2020-222000000.webm 229 // 230 // where the Y'CbCr values were computed using https://jdashg.github.io/misc/colors/from-coeffs.html. 231 const videoTests = { 232 // Rec.709 Y'CbCr (0x3F, 0x66, 0xF0) = sRGB (0xFF, 0x01, 0x00) 233 "sRGB-FF0100": { 234 "srgb srgb": [255, 1, 0, 255], 235 "srgb display-p3": [234, 51, 35, 255], 236 "display-p3 srgb": [255, 0, 0, 255], 237 "display-p3 display-p3": [234, 51, 35, 255], 238 }, 239 // Rec.709 Y'CbCr (0x32, 0x6D, 0xD2) = sRGB (0xBB, 0x00, 0x00) 240 "sRGB-BB0000": { 241 "srgb srgb": [187, 0, 0, 255], 242 "srgb display-p3": [171, 35, 23, 255], 243 "display-p3 srgb": [187, 1, 0, 255], 244 "display-p3 display-p3": [171, 35, 23, 255], 245 }, 246 247 // 10 bit Rec.2020 Y'CbCr (0x126, 0x183, 0x3C0) = Rec.2020 (0x3FF, 0x000, 0x000) 248 "Rec2020-3FF000000": { 249 "srgb srgb": [255, 0, 0, 255], 250 "srgb display-p3": [234, 51, 35, 255], 251 "display-p3 srgb": [255, 0, 0, 255], 252 "display-p3 display-p3": [255, 0, 9, 255], 253 }, 254 // 10 bit Rec.2020 Y'CbCr (0x0BB, 0x1BD, 0x2EF) = Rec.2020 (0x222, 0x000, 0x000) 255 "Rec2020-222000000": { 256 "srgb srgb": [186, 0, 0, 255], 257 "srgb display-p3": [170, 34, 23, 255], 258 "display-p3 srgb": [186, 0, 0, 255], 259 "display-p3 display-p3": [169, 0, 3, 255], 260 }, 261 }; 262 263 const fromSRGBToDisplayP3 = { 264 "255,0,0,255": [234, 51, 35, 255], 265 "255,0,0,204": [234, 51, 35, 204], 266 "187,0,0,255": [171, 35, 23, 255], 267 "187,0,0,204": [171, 35, 23, 204], 268 }; 269 270 const fromDisplayP3ToSRGB = { 271 "255,0,0,255": [255, 0, 0, 255], 272 "255,0,0,204": [255, 0, 0, 204], 273 "187,0,0,255": [205, 0, 0, 255], 274 "187,0,0,204": [205, 0, 0, 204], 275 }; 276 277 function pixelsApproximatelyEqual(p1, p2) { 278 for (let i = 0; i < 4; ++i) { 279 if (Math.abs(p1[i] - p2[i]) > 3) 280 return false; 281 } 282 return true; 283 }