github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/gift/colors_test.go (about) 1 package gift 2 3 import ( 4 "image" 5 "image/color" 6 "image/draw" 7 "math" 8 "testing" 9 ) 10 11 func TestLut(t *testing.T) { 12 fn := func(v float32) float32 { 13 return v 14 } 15 for _, size := range []int{10, 100, 1000} { 16 lut := prepareLut(size, fn) 17 l := len(lut) 18 if l != size { 19 t.Errorf("LUT bad size: expected %v got %v", size, l) 20 } 21 if lut[0] != 0 { 22 t.Errorf("LUT bad start value: expected 0 got %v", lut[0]) 23 } 24 if lut[l-1] != 1 { 25 t.Errorf("LUT bad end value: expected 1 got %v", lut[l-1]) 26 } 27 } 28 lut := prepareLut(10000, fn) 29 for _, u := range []float32{0.0, 0.0001, 0.5555, 0.9999, 1.0} { 30 v := getFromLut(lut, u) 31 if math.Abs(float64(v-u)) > 0.0001 { 32 t.Errorf("LUT bad value: expected %v got %v", u, v) 33 } 34 } 35 } 36 37 func TestInvert(t *testing.T) { 38 src := image.NewGray(image.Rect(0, 0, 256, 1)) 39 for i := 0; i <= 255; i++ { 40 src.Pix[i] = uint8(i) 41 } 42 g := New(Invert()) 43 dst := image.NewGray(g.Bounds(src.Bounds())) 44 g.Draw(dst, src) 45 46 for i := 0; i <= 255; i++ { 47 if dst.Pix[i] != 255-src.Pix[i] { 48 t.Errorf("InvertColors: index %d: expected %d got %d", i, 255-src.Pix[i], dst.Pix[i]) 49 } 50 } 51 } 52 53 func TestColorspaceSRGBToLinear(t *testing.T) { 54 vals := []float32{ 55 0.00000, 56 0.01002, 57 0.03310, 58 0.07324, 59 0.13287, 60 0.21404, 61 0.31855, 62 0.44799, 63 0.60383, 64 0.78741, 65 1.00000, 66 } 67 68 imgs := []draw.Image{ 69 image.NewGray(image.Rect(0, 0, 11, 11)), 70 image.NewGray(image.Rect(0, 0, 111, 111)), 71 image.NewGray16(image.Rect(0, 0, 11, 11)), 72 image.NewGray16(image.Rect(0, 0, 1111, 1111)), 73 } 74 for _, img := range imgs { 75 for i := 0; i <= 10; i++ { 76 img.Set(i, 0, color.Gray{uint8(255 * float32(i) / 10.0)}) 77 } 78 img2 := image.NewGray(img.Bounds()) 79 New(ColorspaceSRGBToLinear()).Draw(img2, img) 80 if !img2.Bounds().Size().Eq(img.Bounds().Size()) { 81 t.Errorf("ColorspaceSRGBToLinear bad result size: expected %v got %v", img.Bounds().Size(), img2.Bounds().Size()) 82 } 83 for i := 0; i <= 10; i++ { 84 expected := uint8(vals[i]*255.0 + 0.5) 85 c := img2.At(i, 0).(color.Gray) 86 if math.Abs(float64(c.Y)-float64(expected)) > 1 { 87 t.Errorf("ColorspaceSRGBToLinear bad color value at index %v expected %v got %v", i, expected, c.Y) 88 } 89 } 90 } 91 } 92 93 func TestColorspaceLinearToSRGB(t *testing.T) { 94 vals := []float32{ 95 0.00000, 96 0.34919, 97 0.48453, 98 0.58383, 99 0.66519, 100 0.73536, 101 0.79774, 102 0.85431, 103 0.90633, 104 0.95469, 105 1.00000, 106 } 107 108 imgs := []draw.Image{ 109 image.NewGray(image.Rect(0, 0, 11, 11)), 110 image.NewGray(image.Rect(0, 0, 111, 111)), 111 image.NewGray16(image.Rect(0, 0, 11, 11)), 112 image.NewGray16(image.Rect(0, 0, 1111, 1111)), 113 } 114 for _, img := range imgs { 115 for i := 0; i <= 10; i++ { 116 img.Set(i, 0, color.Gray{uint8(255 * float32(i) / 10.0)}) 117 } 118 img2 := image.NewGray(img.Bounds()) 119 New(ColorspaceLinearToSRGB()).Draw(img2, img) 120 if !img2.Bounds().Size().Eq(img.Bounds().Size()) { 121 t.Errorf("ColorspaceLinearRGBToSRGB bad result size: expected %v got %v", img.Bounds().Size(), img2.Bounds().Size()) 122 } 123 for i := 0; i <= 10; i++ { 124 expected := uint8(vals[i]*255.0 + 0.5) 125 c := img2.At(i, 0).(color.Gray) 126 if math.Abs(float64(c.Y)-float64(expected)) > 1 { 127 t.Errorf("ColorspaceLinearRGBToSRGB bad color value at index %v expected %v got %v", i, expected, c.Y) 128 } 129 } 130 } 131 132 } 133 134 func TestAdjustGamma(t *testing.T) { 135 src := image.NewGray(image.Rect(0, 0, 256, 1)) 136 dst := image.NewGray(image.Rect(0, 0, 256, 1)) 137 for i := 0; i <= 255; i++ { 138 src.Pix[i] = uint8(i) 139 } 140 ag := Gamma(2.0) 141 ag.Draw(dst, src, nil) 142 143 for i := 100; i <= 150; i++ { 144 if dst.Pix[i] <= src.Pix[i] { 145 t.Errorf("Gamma unexpected color") 146 } 147 } 148 149 ag = Gamma(0.5) 150 ag.Draw(dst, src, nil) 151 152 for i := 100; i <= 150; i++ { 153 if dst.Pix[i] >= src.Pix[i] { 154 t.Errorf("Gamma unexpected color") 155 } 156 } 157 158 ag = Gamma(1.0) 159 ag.Draw(dst, src, nil) 160 161 for i := 100; i <= 150; i++ { 162 if dst.Pix[i] != src.Pix[i] { 163 t.Errorf("Gamma unexpected color") 164 } 165 } 166 } 167 168 func TestContrast(t *testing.T) { 169 testData := []struct { 170 desc string 171 p float32 172 srcb, dstb image.Rectangle 173 srcPix, dstPix []uint8 174 }{ 175 { 176 "contrast (0)", 177 0, 178 image.Rect(-1, -1, 4, 2), 179 image.Rect(0, 0, 5, 3), 180 []uint8{ 181 0x00, 0x40, 0x00, 0x40, 0x00, 182 0x60, 0xB0, 0xA0, 0xB0, 0x60, 183 0x00, 0x80, 0x00, 0x80, 0x00, 184 }, 185 []uint8{ 186 0x00, 0x40, 0x00, 0x40, 0x00, 187 0x60, 0xB0, 0xA0, 0xB0, 0x60, 188 0x00, 0x80, 0x00, 0x80, 0x00, 189 }, 190 }, 191 { 192 "contrast (30)", 193 30, 194 image.Rect(-1, -1, 4, 2), 195 image.Rect(0, 0, 5, 3), 196 []uint8{ 197 0x00, 0x40, 0x00, 0x40, 0x00, 198 0x60, 0xB0, 0xA0, 0xB0, 0x60, 199 0x00, 0x80, 0x00, 0x80, 0x00, 200 }, 201 []uint8{ 202 0x00, 0x25, 0x00, 0x25, 0x00, 203 0x53, 0xC5, 0xAE, 0xC5, 0x53, 204 0x00, 0x80, 0x00, 0x80, 0x00, 205 }, 206 }, 207 { 208 "contrast (-30)", 209 -30, 210 image.Rect(-1, -1, 4, 2), 211 image.Rect(0, 0, 5, 3), 212 []uint8{ 213 0x00, 0x40, 0x00, 0x40, 0x00, 214 0x60, 0xB0, 0xA0, 0xB0, 0x60, 215 0x00, 0x80, 0x00, 0x80, 0x00, 216 }, 217 []uint8{ 218 0x26, 0x53, 0x26, 0x53, 0x26, 219 0x69, 0xA1, 0x96, 0xA1, 0x69, 220 0x26, 0x80, 0x26, 0x80, 0x26, 221 }, 222 }, 223 { 224 "contrast (100)", 225 100, 226 image.Rect(-1, -1, 4, 2), 227 image.Rect(0, 0, 5, 3), 228 []uint8{ 229 0x00, 0x40, 0x00, 0x40, 0x00, 230 0x60, 0xB0, 0xA0, 0xB0, 0x60, 231 0x00, 0x80, 0x00, 0x80, 0x00, 232 }, 233 []uint8{ 234 0x00, 0x00, 0x00, 0x00, 0x00, 235 0x00, 0xFF, 0xFF, 0xFF, 0x00, 236 0x00, 0xFF, 0x00, 0xFF, 0x00, 237 }, 238 }, 239 { 240 "contrast (200)", 241 200, 242 image.Rect(-1, -1, 4, 2), 243 image.Rect(0, 0, 5, 3), 244 []uint8{ 245 0x00, 0x40, 0x00, 0x40, 0x00, 246 0x60, 0xB0, 0xA0, 0xB0, 0x60, 247 0x00, 0x80, 0x00, 0x80, 0x00, 248 }, 249 []uint8{ 250 0x00, 0x00, 0x00, 0x00, 0x00, 251 0x00, 0xFF, 0xFF, 0xFF, 0x00, 252 0x00, 0xFF, 0x00, 0xFF, 0x00, 253 }, 254 }, 255 { 256 "contrast (-100)", 257 -100, 258 image.Rect(-1, -1, 4, 2), 259 image.Rect(0, 0, 5, 3), 260 []uint8{ 261 0x00, 0x40, 0x00, 0x40, 0x00, 262 0x60, 0xB0, 0xA0, 0xB0, 0x60, 263 0x00, 0x80, 0x00, 0x80, 0x00, 264 }, 265 []uint8{ 266 0x80, 0x80, 0x80, 0x80, 0x80, 267 0x80, 0x80, 0x80, 0x80, 0x80, 268 0x80, 0x80, 0x80, 0x80, 0x80, 269 }, 270 }, 271 { 272 "contrast (-200)", 273 -200, 274 image.Rect(-1, -1, 4, 2), 275 image.Rect(0, 0, 5, 3), 276 []uint8{ 277 0x00, 0x40, 0x00, 0x40, 0x00, 278 0x60, 0xB0, 0xA0, 0xB0, 0x60, 279 0x00, 0x80, 0x00, 0x80, 0x00, 280 }, 281 []uint8{ 282 0x80, 0x80, 0x80, 0x80, 0x80, 283 0x80, 0x80, 0x80, 0x80, 0x80, 284 0x80, 0x80, 0x80, 0x80, 0x80, 285 }, 286 }, 287 } 288 289 for _, d := range testData { 290 src := image.NewGray(d.srcb) 291 src.Pix = d.srcPix 292 293 f := Contrast(d.p) 294 dst := image.NewGray(f.Bounds(src.Bounds())) 295 f.Draw(dst, src, nil) 296 297 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 298 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 299 } 300 } 301 } 302 303 func TestBrightness(t *testing.T) { 304 testData := []struct { 305 desc string 306 p float32 307 srcb, dstb image.Rectangle 308 srcPix, dstPix []uint8 309 }{ 310 { 311 "brightness (0)", 312 0, 313 image.Rect(-1, -1, 4, 2), 314 image.Rect(0, 0, 5, 3), 315 []uint8{ 316 0x00, 0x40, 0x00, 0x40, 0x00, 317 0x60, 0xB0, 0xA0, 0xB0, 0x60, 318 0x00, 0x80, 0x00, 0x80, 0x00, 319 }, 320 []uint8{ 321 0x00, 0x40, 0x00, 0x40, 0x00, 322 0x60, 0xB0, 0xA0, 0xB0, 0x60, 323 0x00, 0x80, 0x00, 0x80, 0x00, 324 }, 325 }, 326 { 327 "brightness (30)", 328 30, 329 image.Rect(-1, -1, 4, 2), 330 image.Rect(0, 0, 5, 3), 331 []uint8{ 332 0x00, 0x40, 0x00, 0x40, 0x00, 333 0x60, 0xB0, 0xA0, 0xB0, 0x60, 334 0x00, 0x80, 0x00, 0x80, 0x00, 335 }, 336 []uint8{ 337 0x4D, 0x8D, 0x4D, 0x8D, 0x4D, 338 0xAD, 0xFD, 0xED, 0xFD, 0xAD, 339 0x4D, 0xCD, 0x4D, 0xCD, 0x4D, 340 }, 341 }, 342 { 343 "brightness (-30)", 344 -30, 345 image.Rect(-1, -1, 4, 2), 346 image.Rect(0, 0, 5, 3), 347 []uint8{ 348 0x00, 0x40, 0x00, 0x40, 0x00, 349 0x60, 0xB0, 0xA0, 0xB0, 0x60, 350 0x00, 0x80, 0x00, 0x80, 0x00, 351 }, 352 []uint8{ 353 0x00, 0x00, 0x00, 0x00, 0x00, 354 0x14, 0x64, 0x53, 0x64, 0x14, 355 0x00, 0x34, 0x00, 0x34, 0x00, 356 }, 357 }, 358 359 { 360 "brightness (100)", 361 100, 362 image.Rect(-1, -1, 4, 2), 363 image.Rect(0, 0, 5, 3), 364 []uint8{ 365 0x00, 0x40, 0x00, 0x40, 0x00, 366 0x60, 0xB0, 0xA0, 0xB0, 0x60, 367 0x00, 0x80, 0x00, 0x80, 0x00, 368 }, 369 []uint8{ 370 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 371 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 372 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 373 }, 374 }, 375 { 376 "brightness (200)", 377 200, 378 image.Rect(-1, -1, 4, 2), 379 image.Rect(0, 0, 5, 3), 380 []uint8{ 381 0x00, 0x40, 0x00, 0x40, 0x00, 382 0x60, 0xB0, 0xA0, 0xB0, 0x60, 383 0x00, 0x80, 0x00, 0x80, 0x00, 384 }, 385 []uint8{ 386 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 387 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 388 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 389 }, 390 }, 391 { 392 "brightness (-100)", 393 -100, 394 image.Rect(-1, -1, 4, 2), 395 image.Rect(0, 0, 5, 3), 396 []uint8{ 397 0x00, 0x40, 0x00, 0x40, 0x00, 398 0x60, 0xB0, 0xA0, 0xB0, 0x60, 399 0x00, 0x80, 0x00, 0x80, 0x00, 400 }, 401 []uint8{ 402 0x00, 0x00, 0x00, 0x00, 0x00, 403 0x00, 0x00, 0x00, 0x00, 0x00, 404 0x00, 0x00, 0x00, 0x00, 0x00, 405 }, 406 }, 407 { 408 "brightness (-200)", 409 -200, 410 image.Rect(-1, -1, 4, 2), 411 image.Rect(0, 0, 5, 3), 412 []uint8{ 413 0x00, 0x40, 0x00, 0x40, 0x00, 414 0x60, 0xB0, 0xA0, 0xB0, 0x60, 415 0x00, 0x80, 0x00, 0x80, 0x00, 416 }, 417 []uint8{ 418 0x00, 0x00, 0x00, 0x00, 0x00, 419 0x00, 0x00, 0x00, 0x00, 0x00, 420 0x00, 0x00, 0x00, 0x00, 0x00, 421 }, 422 }, 423 } 424 425 for _, d := range testData { 426 src := image.NewGray(d.srcb) 427 src.Pix = d.srcPix 428 429 f := Brightness(d.p) 430 dst := image.NewGray(f.Bounds(src.Bounds())) 431 f.Draw(dst, src, nil) 432 433 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 434 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 435 } 436 } 437 } 438 439 func TestSigmoid(t *testing.T) { 440 testData := []struct { 441 desc string 442 midpoint, factor float32 443 srcb, dstb image.Rectangle 444 srcPix, dstPix []uint8 445 }{ 446 { 447 "sigmoid (0.5, 0)", 448 0.5, 0, 449 image.Rect(-1, -1, 4, 2), 450 image.Rect(0, 0, 5, 3), 451 []uint8{ 452 0x00, 0x40, 0x00, 0x40, 0x00, 453 0x60, 0xB0, 0xA0, 0xB0, 0x60, 454 0x00, 0x80, 0x00, 0x80, 0x00, 455 }, 456 []uint8{ 457 0x00, 0x40, 0x00, 0x40, 0x00, 458 0x60, 0xB0, 0xA0, 0xB0, 0x60, 459 0x00, 0x80, 0x00, 0x80, 0x00, 460 }, 461 }, 462 { 463 "sigmoid (0.5, 3)", 464 0.5, 3, 465 image.Rect(-1, -1, 4, 2), 466 image.Rect(0, 0, 5, 3), 467 []uint8{ 468 0x00, 0x40, 0x00, 0x40, 0x00, 469 0x60, 0xB0, 0xA0, 0xB0, 0x60, 470 0x00, 0x80, 0x00, 0x80, 0x00, 471 }, 472 []uint8{ 473 0x00, 0x38, 0x00, 0x38, 0x00, 474 0x5B, 0xB7, 0xA5, 0xB7, 0x5B, 475 0x00, 0x80, 0x00, 0x80, 0x00, 476 }, 477 }, 478 { 479 "sigmoid (0.5, -3)", 480 0.5, -3, 481 image.Rect(-1, -1, 4, 2), 482 image.Rect(0, 0, 5, 3), 483 []uint8{ 484 0x00, 0x40, 0x00, 0x40, 0x00, 485 0x60, 0xB0, 0xA0, 0xB0, 0x60, 486 0x00, 0x80, 0x00, 0x80, 0x00, 487 }, 488 []uint8{ 489 0x00, 0x48, 0x00, 0x48, 0x00, 490 0x65, 0xA9, 0x9B, 0xA9, 0x65, 491 0x00, 0x80, 0x00, 0x80, 0x00, 492 }, 493 }, 494 } 495 496 for _, d := range testData { 497 src := image.NewGray(d.srcb) 498 src.Pix = d.srcPix 499 500 f := Sigmoid(d.midpoint, d.factor) 501 dst := image.NewGray(f.Bounds(src.Bounds())) 502 f.Draw(dst, src, nil) 503 504 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 505 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 506 } 507 } 508 } 509 510 func TestGrayscale(t *testing.T) { 511 testData := []struct { 512 desc string 513 srcb, dstb image.Rectangle 514 srcPix, dstPix []uint8 515 }{ 516 517 { 518 "grayscale 0x0", 519 image.Rect(0, 0, 0, 0), 520 image.Rect(0, 0, 0, 0), 521 []uint8{}, 522 []uint8{}, 523 }, 524 { 525 "grayscale 2x3", 526 image.Rect(-1, -1, 1, 2), 527 image.Rect(0, 0, 2, 3), 528 []uint8{ 529 0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF, 530 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 531 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 532 }, 533 []uint8{ 534 0x0D, 0x0D, 0x0D, 0x30, 0x5C, 0x5C, 0x5C, 0xFF, 535 0xE3, 0xE3, 0xE3, 0xC0, 0x56, 0x56, 0x56, 0x00, 536 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 537 }, 538 }, 539 } 540 541 for _, d := range testData { 542 src := image.NewNRGBA(d.srcb) 543 src.Pix = d.srcPix 544 545 f := Grayscale() 546 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 547 f.Draw(dst, src, nil) 548 549 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 550 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 551 } 552 } 553 } 554 555 func TestSepia(t *testing.T) { 556 testData := []struct { 557 desc string 558 p float32 559 srcb, dstb image.Rectangle 560 srcPix, dstPix []uint8 561 }{ 562 563 { 564 "sepia 100 0x0", 565 100, 566 image.Rect(0, 0, 0, 0), 567 image.Rect(0, 0, 0, 0), 568 []uint8{}, 569 []uint8{}, 570 }, 571 { 572 "sepia 0 2x3", 573 0, 574 image.Rect(-1, -1, 1, 2), 575 image.Rect(0, 0, 2, 3), 576 []uint8{ 577 0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF, 578 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 579 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 580 }, 581 []uint8{ 582 0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF, 583 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 584 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 585 }, 586 }, 587 { 588 "sepia 100 2x3", 589 100, 590 image.Rect(-1, -1, 1, 2), 591 image.Rect(0, 0, 2, 3), 592 []uint8{ 593 0x00, 0x10, 0x20, 0x30, 0xFF, 0x00, 0x88, 0xFF, 594 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 595 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 596 }, 597 []uint8{ 598 0x12, 0x10, 0x0D, 0x30, 0x7E, 0x70, 0x57, 0xFF, 599 0xFF, 0xFF, 0xD4, 0xC0, 0x78, 0x6B, 0x54, 0x00, 600 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 601 }, 602 }, 603 } 604 605 for _, d := range testData { 606 src := image.NewNRGBA(d.srcb) 607 src.Pix = d.srcPix 608 609 f := Sepia(d.p) 610 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 611 f.Draw(dst, src, nil) 612 613 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 614 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 615 } 616 } 617 } 618 619 func TestNormalizeHue(t *testing.T) { 620 testData := []struct { 621 h0, h1 float32 622 }{ 623 {0, 0}, 624 {0.1, 0.1}, 625 {0.5, 0.5}, 626 {0.9, 0.9}, 627 {1.1, 0.1}, 628 {3.0, 0.0}, 629 {5.7, 0.7}, 630 {-0.1, 0.9}, 631 {-0.5, 0.5}, 632 {-0.9, 0.1}, 633 {-3.0, 0.0}, 634 {-5.7, 0.3}, 635 } 636 637 for _, d := range testData { 638 h := normalizeHue(d.h0) 639 if absf32(h-d.h1) > 0.00001 { 640 t.Errorf("normalizeHue(%#v) failed: %#v expected: %#v", d.h0, h, d.h1) 641 } 642 } 643 644 } 645 646 func TestHue(t *testing.T) { 647 testData := []struct { 648 desc string 649 p float32 650 srcb, dstb image.Rectangle 651 srcPix, dstPix []uint8 652 }{ 653 654 { 655 "hue 0 0x0", 656 0, 657 image.Rect(0, 0, 0, 0), 658 image.Rect(0, 0, 0, 0), 659 []uint8{}, 660 []uint8{}, 661 }, 662 { 663 "hue 0", 664 0, 665 image.Rect(-1, -1, 1, 3), 666 image.Rect(0, 0, 2, 4), 667 []uint8{ 668 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 669 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 670 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 671 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 672 }, 673 []uint8{ 674 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 675 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 676 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 677 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 678 }, 679 }, 680 { 681 "hue -720", // same as 0 682 -720, 683 image.Rect(-1, -1, 1, 3), 684 image.Rect(0, 0, 2, 4), 685 []uint8{ 686 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 687 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 688 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 689 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 690 }, 691 []uint8{ 692 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 693 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 694 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 695 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 696 }, 697 }, 698 { 699 "hue -90", 700 -90, 701 image.Rect(-1, -1, 1, 3), 702 image.Rect(0, 0, 2, 4), 703 []uint8{ 704 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 705 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 706 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 707 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 708 }, 709 []uint8{ 710 0x00, 0x20, 0x00, 0x30, 0x99, 0x33, 0x99, 0xFF, 711 0xF0, 0xD0, 0xF0, 0xC0, 0x11, 0xBB, 0x11, 0x00, 712 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 713 0x50, 0x51, 0xEE, 0x77, 0xFE, 0xFE, 0xFD, 0xFD, 714 }, 715 }, 716 { 717 "hue 630", // same as -90 718 630, 719 image.Rect(-1, -1, 1, 3), 720 image.Rect(0, 0, 2, 4), 721 []uint8{ 722 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 723 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 724 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 725 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 726 }, 727 []uint8{ 728 0x00, 0x20, 0x00, 0x30, 0x99, 0x33, 0x99, 0xFF, 729 0xF0, 0xD0, 0xF0, 0xC0, 0x11, 0xBB, 0x11, 0x00, 730 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 731 0x50, 0x51, 0xEE, 0x77, 0xFE, 0xFE, 0xFD, 0xFD, 732 }, 733 }, 734 { 735 "hue 90", 736 90, 737 image.Rect(-1, -1, 1, 3), 738 image.Rect(0, 0, 2, 4), 739 []uint8{ 740 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 741 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 742 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 743 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 744 }, 745 []uint8{ 746 0x20, 0x00, 0x20, 0x30, 0x33, 0x99, 0x33, 0xFF, 747 0xD0, 0xF0, 0xD0, 0xC0, 0xBB, 0x11, 0xBB, 0x00, 748 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 749 0xEE, 0xED, 0x50, 0x77, 0xFD, 0xFE, 0xFE, 0xFD, 750 }, 751 }, 752 { 753 "hue 3690", // same as 90 754 3690, 755 image.Rect(-1, -1, 1, 3), 756 image.Rect(0, 0, 2, 4), 757 []uint8{ 758 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 759 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 760 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 761 0xEE, 0x50, 0xA0, 0x77, 0xFD, 0xFE, 0xFD, 0xFD, 762 }, 763 []uint8{ 764 0x20, 0x00, 0x20, 0x30, 0x33, 0x99, 0x33, 0xFF, 765 0xD0, 0xF0, 0xD0, 0xC0, 0xBB, 0x11, 0xBB, 0x00, 766 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 767 0xEE, 0xED, 0x50, 0x77, 0xFD, 0xFE, 0xFE, 0xFD, 768 }, 769 }, 770 } 771 772 for _, d := range testData { 773 src := image.NewNRGBA(d.srcb) 774 src.Pix = d.srcPix 775 776 f := Hue(d.p) 777 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 778 f.Draw(dst, src, nil) 779 780 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 781 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 782 } 783 } 784 } 785 786 func TestSaturation(t *testing.T) { 787 testData := []struct { 788 desc string 789 p float32 790 srcb, dstb image.Rectangle 791 srcPix, dstPix []uint8 792 }{ 793 794 { 795 "saturation 0 0x0", 796 0, 797 image.Rect(0, 0, 0, 0), 798 image.Rect(0, 0, 0, 0), 799 []uint8{}, 800 []uint8{}, 801 }, 802 { 803 "saturation 0", 804 0, 805 image.Rect(-1, -1, 1, 3), 806 image.Rect(0, 0, 2, 4), 807 []uint8{ 808 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 809 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 810 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 811 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 812 }, 813 []uint8{ 814 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 815 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 816 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 817 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 818 }, 819 }, 820 { 821 "saturation -50", 822 -50, 823 image.Rect(-1, -1, 1, 3), 824 image.Rect(0, 0, 2, 4), 825 []uint8{ 826 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 827 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 828 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 829 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 830 }, 831 []uint8{ 832 0x08, 0x10, 0x18, 0x30, 0x80, 0x66, 0x4D, 0xFF, 833 0xE8, 0xE0, 0xD8, 0xC0, 0x3B, 0x66, 0x91, 0x00, 834 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 835 0xBC, 0x74, 0x9C, 0x77, 0xF2, 0xFA, 0xF2, 0xFD, 836 }, 837 }, 838 { 839 "saturation 100", 840 100, 841 image.Rect(-1, -1, 1, 3), 842 image.Rect(0, 0, 2, 4), 843 []uint8{ 844 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 845 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 846 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 847 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 848 }, 849 []uint8{ 850 0x00, 0x10, 0x20, 0x30, 0xCC, 0x66, 0x00, 0xFF, 851 0xFF, 0xE0, 0xC1, 0xC0, 0x00, 0x66, 0xCC, 0x00, 852 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 853 0xFF, 0x31, 0xA3, 0x77, 0xED, 0xFF, 0xED, 0xFD, 854 }, 855 }, 856 } 857 858 for _, d := range testData { 859 src := image.NewNRGBA(d.srcb) 860 src.Pix = d.srcPix 861 862 f := Saturation(d.p) 863 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 864 f.Draw(dst, src, nil) 865 866 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 867 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 868 } 869 } 870 } 871 872 func TestColorize(t *testing.T) { 873 testData := []struct { 874 desc string 875 h, s, p float32 876 srcb, dstb image.Rectangle 877 srcPix, dstPix []uint8 878 }{ 879 880 { 881 "colorize 0, 0, 0, 0x0", 882 0, 0, 0, 883 image.Rect(0, 0, 0, 0), 884 image.Rect(0, 0, 0, 0), 885 []uint8{}, 886 []uint8{}, 887 }, 888 { 889 "colorize 0, 100, 0", 890 0, 100, 0, 891 image.Rect(-1, -1, 1, 3), 892 image.Rect(0, 0, 2, 4), 893 []uint8{ 894 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 895 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 896 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 897 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 898 }, 899 []uint8{ 900 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 901 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 902 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 903 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 904 }, 905 }, 906 907 { 908 "colorize 0, 100, 100", 909 0, 100, 100, 910 image.Rect(-1, -1, 1, 3), 911 image.Rect(0, 0, 2, 4), 912 []uint8{ 913 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 914 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 915 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 916 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 917 }, 918 []uint8{ 919 0x20, 0x00, 0x00, 0x30, 0xCC, 0x00, 0x00, 0xFF, 920 0xFF, 0xC1, 0xC1, 0xC0, 0xCC, 0x00, 0x00, 0x00, 921 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 922 0xFF, 0x31, 0x31, 0x77, 0xFF, 0xED, 0xED, 0xFD, 923 }, 924 }, 925 } 926 927 for _, d := range testData { 928 src := image.NewNRGBA(d.srcb) 929 src.Pix = d.srcPix 930 931 f := Colorize(d.h, d.s, d.p) 932 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 933 f.Draw(dst, src, nil) 934 935 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 936 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 937 } 938 } 939 } 940 941 func TestColorBalance(t *testing.T) { 942 testData := []struct { 943 desc string 944 r, g, b float32 945 srcb, dstb image.Rectangle 946 srcPix, dstPix []uint8 947 }{ 948 949 { 950 "color balance 0, 0, 0, 0x0", 951 0, 0, 0, 952 image.Rect(0, 0, 0, 0), 953 image.Rect(0, 0, 0, 0), 954 []uint8{}, 955 []uint8{}, 956 }, 957 { 958 "color balance 0, 0, 0", 959 0, 0, 0, 960 image.Rect(-1, -1, 1, 3), 961 image.Rect(0, 0, 2, 4), 962 []uint8{ 963 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 964 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 965 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 966 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 967 }, 968 []uint8{ 969 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 970 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 971 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 972 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 973 }, 974 }, 975 976 { 977 "color balance 10, -20, 200", 978 10, -20, 200, 979 image.Rect(-1, -1, 1, 3), 980 image.Rect(0, 0, 2, 4), 981 []uint8{ 982 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 983 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 984 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 985 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 986 }, 987 []uint8{ 988 0x00, 0x0D, 0x60, 0x30, 0xA8, 0x52, 0x99, 0xFF, 989 0xFF, 0xB3, 0xFF, 0xC0, 0x13, 0x52, 0xFF, 0x00, 990 0x00, 0x00, 0x00, 0x00, 0xFF, 0xCC, 0xFF, 0xFF, 991 0xF6, 0x40, 0xFF, 0x77, 0xFF, 0xCB, 0xFF, 0xFD, 992 }, 993 }, 994 } 995 996 for _, d := range testData { 997 src := image.NewNRGBA(d.srcb) 998 src.Pix = d.srcPix 999 1000 f := ColorBalance(d.r, d.g, d.b) 1001 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 1002 f.Draw(dst, src, nil) 1003 1004 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 1005 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 1006 } 1007 } 1008 } 1009 1010 func TestColorFunc(t *testing.T) { 1011 testData := []struct { 1012 desc string 1013 fn func(r0, g0, b0, a0 float32) (r, g, b, a float32) 1014 srcb, dstb image.Rectangle 1015 srcPix, dstPix []uint8 1016 }{ 1017 1018 { 1019 "color func 0x0", 1020 func(r0, g0, b0, a0 float32) (r, g, b, a float32) { 1021 return r0, g0, b0, a0 1022 }, 1023 image.Rect(0, 0, 0, 0), 1024 image.Rect(0, 0, 0, 0), 1025 []uint8{}, 1026 []uint8{}, 1027 }, 1028 { 1029 "color func swap channels", 1030 func(r0, g0, b0, a0 float32) (r, g, b, a float32) { 1031 return a0, b0, g0, r0 1032 }, 1033 image.Rect(-1, -1, 1, 3), 1034 image.Rect(0, 0, 2, 4), 1035 []uint8{ 1036 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 1037 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 1038 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 1039 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 1040 }, 1041 []uint8{ 1042 0x30, 0x20, 0x10, 0x00, 0xFF, 0x33, 0x66, 0x99, 1043 0xC0, 0xD0, 0xE0, 0xF0, 0x00, 0xBB, 0x66, 0x11, 1044 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 1045 0x77, 0xA0, 0x50, 0xE0, 0xFD, 0xEE, 0xFE, 0xEE, 1046 }, 1047 }, 1048 1049 { 1050 "color func invert all", 1051 func(r0, g0, b0, a0 float32) (r, g, b, a float32) { 1052 return 1 - r0, 1 - g0, 1 - b0, 1 - a0 1053 }, 1054 image.Rect(-1, -1, 1, 3), 1055 image.Rect(0, 0, 2, 4), 1056 []uint8{ 1057 0x00, 0x10, 0x20, 0x30, 0x99, 0x66, 0x33, 0xFF, 1058 0xF0, 0xE0, 0xD0, 0xC0, 0x11, 0x66, 0xBB, 0x00, 1059 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 1060 0xE0, 0x50, 0xA0, 0x77, 0xEE, 0xFE, 0xEE, 0xFD, 1061 }, 1062 []uint8{ 1063 0xFF, 0xEF, 0xDF, 0xCF, 0x66, 0x99, 0xCC, 0x00, 1064 0x0F, 0x1F, 0x2F, 0x3F, 0xEE, 0x99, 0x44, 0xFF, 1065 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 1066 0x1F, 0xAF, 0x5F, 0x88, 0x11, 0x01, 0x11, 0x02, 1067 }, 1068 }, 1069 } 1070 1071 for _, d := range testData { 1072 src := image.NewNRGBA(d.srcb) 1073 src.Pix = d.srcPix 1074 1075 f := ColorFunc(d.fn) 1076 dst := image.NewNRGBA(f.Bounds(src.Bounds())) 1077 f.Draw(dst, src, nil) 1078 1079 if !checkBoundsAndPix(dst.Bounds(), d.dstb, dst.Pix, d.dstPix) { 1080 t.Errorf("test [%s] failed: %#v, %#v", d.desc, dst.Bounds(), dst.Pix) 1081 } 1082 } 1083 }