git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/imaging/tools_test.go (about) 1 package imaging 2 3 import ( 4 "bytes" 5 "image" 6 "image/color" 7 "testing" 8 ) 9 10 func TestNew(t *testing.T) { 11 testCases := []struct { 12 name string 13 w, h int 14 c color.Color 15 dstBounds image.Rectangle 16 dstPix []uint8 17 }{ 18 { 19 "New 1x1 transparent", 20 1, 1, 21 color.Transparent, 22 image.Rect(0, 0, 1, 1), 23 []uint8{0x00, 0x00, 0x00, 0x00}, 24 }, 25 { 26 "New 1x2 red", 27 1, 2, 28 color.RGBA{255, 0, 0, 255}, 29 image.Rect(0, 0, 1, 2), 30 []uint8{0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff}, 31 }, 32 { 33 "New 2x1 white", 34 2, 1, 35 color.White, 36 image.Rect(0, 0, 2, 1), 37 []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 38 }, 39 { 40 "New 3x3 with alpha", 41 3, 3, 42 color.NRGBA{0x01, 0x23, 0x45, 0x67}, 43 image.Rect(0, 0, 3, 3), 44 []uint8{ 45 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 46 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 47 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67, 48 }, 49 }, 50 { 51 "New 0x0 white", 52 0, 0, 53 color.White, 54 image.Rect(0, 0, 0, 0), 55 nil, 56 }, 57 { 58 "New 800x600 custom", 59 800, 600, 60 color.NRGBA{1, 2, 3, 4}, 61 image.Rect(0, 0, 800, 600), 62 bytes.Repeat([]byte{1, 2, 3, 4}, 800*600), 63 }, 64 } 65 66 for _, tc := range testCases { 67 t.Run(tc.name, func(t *testing.T) { 68 got := New(tc.w, tc.h, tc.c) 69 want := image.NewNRGBA(tc.dstBounds) 70 want.Pix = tc.dstPix 71 if !compareNRGBA(got, want, 0) { 72 t.Fatalf("got result %#v want %#v", got, want) 73 } 74 }) 75 } 76 } 77 78 func BenchmarkNew(b *testing.B) { 79 b.ReportAllocs() 80 for i := 0; i < b.N; i++ { 81 New(1024, 1024, color.White) 82 } 83 } 84 85 func TestClone(t *testing.T) { 86 testCases := []struct { 87 name string 88 src image.Image 89 want *image.NRGBA 90 }{ 91 { 92 "Clone NRGBA", 93 &image.NRGBA{ 94 Rect: image.Rect(-1, -1, 0, 1), 95 Stride: 1 * 4, 96 Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, 97 }, 98 &image.NRGBA{ 99 Rect: image.Rect(0, 0, 1, 2), 100 Stride: 1 * 4, 101 Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, 102 }, 103 }, 104 { 105 "Clone NRGBA64", 106 &image.NRGBA64{ 107 Rect: image.Rect(-1, -1, 0, 1), 108 Stride: 1 * 8, 109 Pix: []uint8{ 110 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 111 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff, 112 }, 113 }, 114 &image.NRGBA{ 115 Rect: image.Rect(0, 0, 1, 2), 116 Stride: 1 * 4, 117 Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, 118 }, 119 }, 120 { 121 "Clone RGBA", 122 &image.RGBA{ 123 Rect: image.Rect(-1, -1, 0, 2), 124 Stride: 1 * 4, 125 Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, 126 }, 127 &image.NRGBA{ 128 Rect: image.Rect(0, 0, 1, 3), 129 Stride: 1 * 4, 130 Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff}, 131 }, 132 }, 133 { 134 "Clone RGBA64", 135 &image.RGBA64{ 136 Rect: image.Rect(-1, -1, 0, 2), 137 Stride: 1 * 8, 138 Pix: []uint8{ 139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 140 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 141 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff, 142 }, 143 }, 144 &image.NRGBA{ 145 Rect: image.Rect(0, 0, 1, 3), 146 Stride: 1 * 4, 147 Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff}, 148 }, 149 }, 150 { 151 "Clone Gray", 152 &image.Gray{ 153 Rect: image.Rect(-1, -1, 0, 1), 154 Stride: 1 * 1, 155 Pix: []uint8{0x11, 0xee}, 156 }, 157 &image.NRGBA{ 158 Rect: image.Rect(0, 0, 1, 2), 159 Stride: 1 * 4, 160 Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff}, 161 }, 162 }, 163 { 164 "Clone Gray16", 165 &image.Gray16{ 166 Rect: image.Rect(-1, -1, 0, 1), 167 Stride: 1 * 2, 168 Pix: []uint8{0x11, 0x11, 0xee, 0xee}, 169 }, 170 &image.NRGBA{ 171 Rect: image.Rect(0, 0, 1, 2), 172 Stride: 1 * 4, 173 Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff}, 174 }, 175 }, 176 { 177 "Clone Alpha", 178 &image.Alpha{ 179 Rect: image.Rect(-1, -1, 0, 1), 180 Stride: 1 * 1, 181 Pix: []uint8{0x11, 0xee}, 182 }, 183 &image.NRGBA{ 184 Rect: image.Rect(0, 0, 1, 2), 185 Stride: 1 * 4, 186 Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee}, 187 }, 188 }, 189 { 190 "Clone YCbCr", 191 &image.YCbCr{ 192 Rect: image.Rect(-1, -1, 5, 0), 193 SubsampleRatio: image.YCbCrSubsampleRatio444, 194 YStride: 6, 195 CStride: 6, 196 Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e}, 197 Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0}, 198 Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76}, 199 }, 200 &image.NRGBA{ 201 Rect: image.Rect(0, 0, 6, 1), 202 Stride: 6 * 4, 203 Pix: []uint8{ 204 0x00, 0x00, 0x00, 0xff, 205 0xff, 0xff, 0xff, 0xff, 206 0x7f, 0x7f, 0x7f, 0xff, 207 0x7f, 0x00, 0x00, 0xff, 208 0x00, 0x7f, 0x00, 0xff, 209 0x00, 0x00, 0x7f, 0xff, 210 }, 211 }, 212 }, 213 { 214 "Clone YCbCr 444", 215 &image.YCbCr{ 216 Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, 217 Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80}, 218 Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80}, 219 YStride: 4, 220 CStride: 4, 221 SubsampleRatio: image.YCbCrSubsampleRatio444, 222 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 223 }, 224 &image.NRGBA{ 225 Pix: []uint8{0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x49, 0xe1, 0xca, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x7f, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x7f, 0xff, 0x0, 0x0, 0x7f, 0xff, 0x0, 0x7f, 0x7f, 0xff, 0x0, 0x7f, 0x0, 0xff, 0x82, 0x7f, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, 226 Stride: 16, 227 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 228 }, 229 }, 230 { 231 "Clone YCbCr 440", 232 &image.YCbCr{ 233 Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, 234 Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80}, 235 Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80}, 236 YStride: 4, 237 CStride: 4, 238 SubsampleRatio: image.YCbCrSubsampleRatio440, 239 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 240 }, 241 &image.NRGBA{ 242 Pix: []uint8{0x0, 0xb5, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x77, 0x0, 0x0, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0x0, 0xff, 0x1, 0xff, 0xff, 0xff, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, 243 Stride: 16, 244 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 245 }, 246 }, 247 { 248 "Clone YCbCr 422", 249 &image.YCbCr{ 250 Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, 251 Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80}, 252 Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80}, 253 YStride: 4, 254 CStride: 2, 255 SubsampleRatio: image.YCbCrSubsampleRatio422, 256 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 257 }, 258 &image.NRGBA{ 259 Pix: []uint8{0xe2, 0x0, 0xe1, 0xff, 0xff, 0x0, 0xfe, 0xff, 0x0, 0x4d, 0x36, 0xff, 0x49, 0xe1, 0xca, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0x0, 0x34, 0x33, 0xff, 0x1, 0x7f, 0x7e, 0xff, 0x5c, 0x58, 0x0, 0xff, 0x82, 0x7e, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, 260 Stride: 16, 261 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 262 }, 263 }, 264 { 265 "Clone YCbCr 420", 266 &image.YCbCr{ 267 Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, 268 Cb: []uint8{0x01, 0xaa, 0x80, 0x80}, 269 Cr: []uint8{0x95, 0xb5, 0x80, 0x80}, 270 YStride: 4, CStride: 2, 271 SubsampleRatio: image.YCbCrSubsampleRatio420, 272 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 273 }, 274 &image.NRGBA{ 275 Pix: []uint8{0x69, 0x69, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x67, 0x0, 0x67, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, 276 Stride: 16, 277 Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, 278 }, 279 }, 280 { 281 "Clone Paletted", 282 &image.Paletted{ 283 Rect: image.Rect(-1, -1, 5, 0), 284 Stride: 6 * 1, 285 Palette: color.Palette{ 286 color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff}, 287 color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}, 288 color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff}, 289 color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff}, 290 color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff}, 291 color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff}, 292 }, 293 Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5}, 294 }, 295 &image.NRGBA{ 296 Rect: image.Rect(0, 0, 6, 1), 297 Stride: 6 * 4, 298 Pix: []uint8{ 299 0x00, 0x00, 0x00, 0xff, 300 0xff, 0xff, 0xff, 0xff, 301 0x7f, 0x7f, 0x7f, 0xff, 302 0x7f, 0x00, 0x00, 0xff, 303 0x00, 0x7f, 0x00, 0xff, 304 0x00, 0x00, 0x7f, 0xff, 305 }, 306 }, 307 }, 308 } 309 310 for _, tc := range testCases { 311 t.Run(tc.name, func(t *testing.T) { 312 got := Clone(tc.src) 313 delta := 0 314 if _, ok := tc.src.(*image.YCbCr); ok { 315 delta = 1 316 } 317 if !compareNRGBA(got, tc.want, delta) { 318 t.Fatalf("got result %#v want %#v", got, tc.want) 319 } 320 }) 321 } 322 } 323 324 func TestCrop(t *testing.T) { 325 testCases := []struct { 326 name string 327 src image.Image 328 r image.Rectangle 329 want *image.NRGBA 330 }{ 331 { 332 "Crop 2x3 2x3", 333 &image.NRGBA{ 334 Rect: image.Rect(-1, -1, 1, 2), 335 Stride: 2 * 4, 336 Pix: []uint8{ 337 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 338 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 339 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 340 }, 341 }, 342 image.Rect(-1, -1, 1, 2), 343 &image.NRGBA{ 344 Rect: image.Rect(0, 0, 2, 3), 345 Stride: 2 * 4, 346 Pix: []uint8{ 347 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 348 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 349 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 350 }, 351 }, 352 }, 353 { 354 "Crop 2x3 2x1", 355 &image.NRGBA{ 356 Rect: image.Rect(-1, -1, 1, 2), 357 Stride: 2 * 4, 358 Pix: []uint8{ 359 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 360 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 361 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 362 }, 363 }, 364 image.Rect(-1, 0, 1, 1), 365 &image.NRGBA{ 366 Rect: image.Rect(0, 0, 2, 1), 367 Stride: 2 * 4, 368 Pix: []uint8{ 369 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 370 }, 371 }, 372 }, 373 } 374 for _, tc := range testCases { 375 t.Run(tc.name, func(t *testing.T) { 376 got := Crop(tc.src, tc.r) 377 if !compareNRGBA(got, tc.want, 0) { 378 t.Fatalf("got result %#v want %#v", got, tc.want) 379 } 380 }) 381 } 382 } 383 384 func BenchmarkCrop(b *testing.B) { 385 b.ReportAllocs() 386 for i := 0; i < b.N; i++ { 387 Crop(testdataBranchesJPG, image.Rect(100, 100, 300, 300)) 388 } 389 } 390 391 func TestCropCenter(t *testing.T) { 392 testCases := []struct { 393 name string 394 src image.Image 395 w, h int 396 want *image.NRGBA 397 }{ 398 { 399 "CropCenter 2x3 2x1", 400 &image.NRGBA{ 401 Rect: image.Rect(-1, -1, 1, 2), 402 Stride: 2 * 4, 403 Pix: []uint8{ 404 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 405 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 406 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 407 }, 408 }, 409 2, 1, 410 &image.NRGBA{ 411 Rect: image.Rect(0, 0, 2, 1), 412 Stride: 2 * 4, 413 Pix: []uint8{ 414 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 415 }, 416 }, 417 }, 418 { 419 "CropCenter 2x3 0x1", 420 &image.NRGBA{ 421 Rect: image.Rect(-1, -1, 1, 2), 422 Stride: 2 * 4, 423 Pix: []uint8{ 424 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 425 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 426 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 427 }, 428 }, 429 0, 1, 430 &image.NRGBA{ 431 Rect: image.Rect(0, 0, 0, 0), 432 Stride: 0, 433 Pix: []uint8{}, 434 }, 435 }, 436 { 437 "CropCenter 2x3 5x5", 438 &image.NRGBA{ 439 Rect: image.Rect(-1, -1, 1, 2), 440 Stride: 2 * 4, 441 Pix: []uint8{ 442 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 443 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 444 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 445 }, 446 }, 447 5, 5, 448 &image.NRGBA{ 449 Rect: image.Rect(0, 0, 2, 3), 450 Stride: 2 * 4, 451 Pix: []uint8{ 452 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 453 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 454 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 455 }, 456 }, 457 }, 458 } 459 for _, tc := range testCases { 460 t.Run(tc.name, func(t *testing.T) { 461 got := CropCenter(tc.src, tc.w, tc.h) 462 if !compareNRGBA(got, tc.want, 0) { 463 t.Fatalf("got result %#v want %#v", got, tc.want) 464 } 465 }) 466 } 467 } 468 469 func TestCropAnchor(t *testing.T) { 470 testCases := []struct { 471 name string 472 src image.Image 473 w, h int 474 anchor Anchor 475 want *image.NRGBA 476 }{ 477 { 478 "CropAnchor 4x4 2x2 TopLeft", 479 &image.NRGBA{ 480 Rect: image.Rect(-1, -1, 3, 3), 481 Stride: 4 * 4, 482 Pix: []uint8{ 483 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 484 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 485 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 486 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 487 }, 488 }, 489 2, 2, 490 TopLeft, 491 &image.NRGBA{ 492 Rect: image.Rect(0, 0, 2, 2), 493 Stride: 2 * 4, 494 Pix: []uint8{ 495 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 496 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 497 }, 498 }, 499 }, 500 { 501 "CropAnchor 4x4 2x2 Top", 502 &image.NRGBA{ 503 Rect: image.Rect(-1, -1, 3, 3), 504 Stride: 4 * 4, 505 Pix: []uint8{ 506 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 507 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 508 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 509 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 510 }, 511 }, 512 2, 2, 513 Top, 514 &image.NRGBA{ 515 Rect: image.Rect(0, 0, 2, 2), 516 Stride: 2 * 4, 517 Pix: []uint8{ 518 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 519 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 520 }, 521 }, 522 }, 523 { 524 "CropAnchor 4x4 2x2 TopRight", 525 &image.NRGBA{ 526 Rect: image.Rect(-1, -1, 3, 3), 527 Stride: 4 * 4, 528 Pix: []uint8{ 529 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 530 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 531 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 532 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 533 }, 534 }, 535 2, 2, 536 TopRight, 537 &image.NRGBA{ 538 Rect: image.Rect(0, 0, 2, 2), 539 Stride: 2 * 4, 540 Pix: []uint8{ 541 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 542 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 543 }, 544 }, 545 }, 546 { 547 "CropAnchor 4x4 2x2 Left", 548 &image.NRGBA{ 549 Rect: image.Rect(-1, -1, 3, 3), 550 Stride: 4 * 4, 551 Pix: []uint8{ 552 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 553 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 554 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 555 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 556 }, 557 }, 558 2, 2, 559 Left, 560 &image.NRGBA{ 561 Rect: image.Rect(0, 0, 2, 2), 562 Stride: 2 * 4, 563 Pix: []uint8{ 564 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 565 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 566 }, 567 }, 568 }, 569 { 570 "CropAnchor 4x4 2x2 Center", 571 &image.NRGBA{ 572 Rect: image.Rect(-1, -1, 3, 3), 573 Stride: 4 * 4, 574 Pix: []uint8{ 575 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 576 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 577 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 578 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 579 }, 580 }, 581 2, 2, 582 Center, 583 &image.NRGBA{ 584 Rect: image.Rect(0, 0, 2, 2), 585 Stride: 2 * 4, 586 Pix: []uint8{ 587 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 588 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 589 }, 590 }, 591 }, 592 { 593 "CropAnchor 4x4 2x2 Right", 594 &image.NRGBA{ 595 Rect: image.Rect(-1, -1, 3, 3), 596 Stride: 4 * 4, 597 Pix: []uint8{ 598 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 599 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 600 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 601 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 602 }, 603 }, 604 2, 2, 605 Right, 606 &image.NRGBA{ 607 Rect: image.Rect(0, 0, 2, 2), 608 Stride: 2 * 4, 609 Pix: []uint8{ 610 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 611 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 612 }, 613 }, 614 }, 615 { 616 "CropAnchor 4x4 2x2 BottomLeft", 617 &image.NRGBA{ 618 Rect: image.Rect(-1, -1, 3, 3), 619 Stride: 4 * 4, 620 Pix: []uint8{ 621 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 622 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 623 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 624 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 625 }, 626 }, 627 2, 2, 628 BottomLeft, 629 &image.NRGBA{ 630 Rect: image.Rect(0, 0, 2, 2), 631 Stride: 2 * 4, 632 Pix: []uint8{ 633 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 634 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 635 }, 636 }, 637 }, 638 { 639 "CropAnchor 4x4 2x2 Bottom", 640 &image.NRGBA{ 641 Rect: image.Rect(-1, -1, 3, 3), 642 Stride: 4 * 4, 643 Pix: []uint8{ 644 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 645 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 646 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 647 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 648 }, 649 }, 650 2, 2, 651 Bottom, 652 &image.NRGBA{ 653 Rect: image.Rect(0, 0, 2, 2), 654 Stride: 2 * 4, 655 Pix: []uint8{ 656 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 657 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 658 }, 659 }, 660 }, 661 { 662 "CropAnchor 4x4 2x2 BottomRight", 663 &image.NRGBA{ 664 Rect: image.Rect(-1, -1, 3, 3), 665 Stride: 4 * 4, 666 Pix: []uint8{ 667 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 668 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 669 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 670 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 671 }, 672 }, 673 2, 2, 674 BottomRight, 675 &image.NRGBA{ 676 Rect: image.Rect(0, 0, 2, 2), 677 Stride: 2 * 4, 678 Pix: []uint8{ 679 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 680 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 681 }, 682 }, 683 }, 684 { 685 "CropAnchor 4x4 0x0 BottomRight", 686 &image.NRGBA{ 687 Rect: image.Rect(-1, -1, 3, 3), 688 Stride: 4 * 4, 689 Pix: []uint8{ 690 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 691 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 692 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 693 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 694 }, 695 }, 696 0, 0, 697 BottomRight, 698 &image.NRGBA{ 699 Rect: image.Rect(0, 0, 0, 0), 700 Stride: 0, 701 Pix: []uint8{}, 702 }, 703 }, 704 { 705 "CropAnchor 4x4 100x100 BottomRight", 706 &image.NRGBA{ 707 Rect: image.Rect(-1, -1, 3, 3), 708 Stride: 4 * 4, 709 Pix: []uint8{ 710 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 711 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 712 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 713 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 714 }, 715 }, 716 100, 100, 717 BottomRight, 718 &image.NRGBA{ 719 Rect: image.Rect(0, 0, 4, 4), 720 Stride: 4 * 4, 721 Pix: []uint8{ 722 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 723 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 724 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 725 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 726 }, 727 }, 728 }, 729 { 730 "CropAnchor 4x4 1x100 BottomRight", 731 &image.NRGBA{ 732 Rect: image.Rect(-1, -1, 3, 3), 733 Stride: 4 * 4, 734 Pix: []uint8{ 735 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 736 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 737 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 738 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 739 }, 740 }, 741 1, 100, 742 BottomRight, 743 &image.NRGBA{ 744 Rect: image.Rect(0, 0, 1, 4), 745 Stride: 1 * 4, 746 Pix: []uint8{ 747 0x0c, 0x0d, 0x0e, 0x0f, 748 0x1c, 0x1d, 0x1e, 0x1f, 749 0x2c, 0x2d, 0x2e, 0x2f, 750 0x3c, 0x3d, 0x3e, 0x3f, 751 }, 752 }, 753 }, 754 { 755 "CropAnchor 4x4 0x100 BottomRight", 756 &image.NRGBA{ 757 Rect: image.Rect(-1, -1, 3, 3), 758 Stride: 4 * 4, 759 Pix: []uint8{ 760 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 761 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 762 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 763 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 764 }, 765 }, 766 0, 100, 767 BottomRight, 768 &image.NRGBA{ 769 Rect: image.Rect(0, 0, 0, 0), 770 Stride: 0, 771 Pix: []uint8{}, 772 }, 773 }, 774 } 775 for _, tc := range testCases { 776 t.Run(tc.name, func(t *testing.T) { 777 got := CropAnchor(tc.src, tc.w, tc.h, tc.anchor) 778 if !compareNRGBA(got, tc.want, 0) { 779 t.Fatalf("got result %#v want %#v", got, tc.want) 780 } 781 }) 782 } 783 } 784 785 func TestPaste(t *testing.T) { 786 testCases := []struct { 787 name string 788 src1 image.Image 789 src2 image.Image 790 p image.Point 791 want *image.NRGBA 792 }{ 793 { 794 "Paste 2x3 2x3", 795 &image.NRGBA{ 796 Rect: image.Rect(0, 0, 2, 3), 797 Stride: 2 * 4, 798 Pix: []uint8{ 799 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 800 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 801 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 802 }, 803 }, 804 &image.NRGBA{ 805 Rect: image.Rect(-1, -1, 1, 2), 806 Stride: 2 * 4, 807 Pix: []uint8{ 808 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 809 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 810 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 811 }, 812 }, 813 image.Pt(0, 0), 814 &image.NRGBA{ 815 Rect: image.Rect(0, 0, 2, 3), 816 Stride: 2 * 4, 817 Pix: []uint8{ 818 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 819 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 820 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 821 }, 822 }, 823 }, 824 { 825 "Paste 2x3 2x1", 826 &image.NRGBA{ 827 Rect: image.Rect(-1, -1, 1, 2), 828 Stride: 2 * 4, 829 Pix: []uint8{ 830 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 831 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 832 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 833 }, 834 }, 835 &image.NRGBA{ 836 Rect: image.Rect(1, 1, 3, 2), 837 Stride: 2 * 4, 838 Pix: []uint8{ 839 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 840 }, 841 }, 842 image.Pt(-1, 0), 843 &image.NRGBA{ 844 Rect: image.Rect(0, 0, 2, 3), 845 Stride: 2 * 4, 846 Pix: []uint8{ 847 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 848 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 849 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 850 }, 851 }, 852 }, 853 { 854 "Paste 3x4 4x3 bottom right intersection", 855 &image.NRGBA{ 856 Rect: image.Rect(-1, -1, 2, 3), 857 Stride: 3 * 4, 858 Pix: []uint8{ 859 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 860 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 861 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 862 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 863 }, 864 }, 865 &image.NRGBA{ 866 Rect: image.Rect(1, 1, 5, 4), 867 Stride: 4 * 4, 868 Pix: []uint8{ 869 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 870 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 871 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 872 }, 873 }, 874 image.Pt(0, 1), 875 &image.NRGBA{ 876 Rect: image.Rect(0, 0, 3, 4), 877 Stride: 3 * 4, 878 Pix: []uint8{ 879 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 880 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 881 0x30, 0x31, 0x32, 0x33, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 882 0x40, 0x41, 0x42, 0x43, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 883 }, 884 }, 885 }, 886 { 887 "Paste 3x4 4x3 top left intersection", 888 &image.NRGBA{ 889 Rect: image.Rect(-1, -1, 2, 3), 890 Stride: 3 * 4, 891 Pix: []uint8{ 892 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 893 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 894 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 895 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 896 }, 897 }, 898 &image.NRGBA{ 899 Rect: image.Rect(1, 1, 5, 4), 900 Stride: 4 * 4, 901 Pix: []uint8{ 902 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 903 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 904 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 905 }, 906 }, 907 image.Pt(-3, -2), 908 &image.NRGBA{ 909 Rect: image.Rect(0, 0, 3, 4), 910 Stride: 3 * 4, 911 Pix: []uint8{ 912 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0x18, 0x19, 0x1a, 0x1b, 913 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0x28, 0x29, 0x2a, 0x2b, 914 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 915 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 916 }, 917 }, 918 }, 919 { 920 "Paste 3x4 4x3 no intersection", 921 &image.NRGBA{ 922 Rect: image.Rect(-1, -1, 2, 3), 923 Stride: 3 * 4, 924 Pix: []uint8{ 925 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 926 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 927 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 928 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 929 }, 930 }, 931 &image.NRGBA{ 932 Rect: image.Rect(1, 1, 5, 4), 933 Stride: 4 * 4, 934 Pix: []uint8{ 935 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 936 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 937 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 938 }, 939 }, 940 image.Pt(-20, 20), 941 &image.NRGBA{ 942 Rect: image.Rect(0, 0, 3, 4), 943 Stride: 3 * 4, 944 Pix: []uint8{ 945 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 946 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 947 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 948 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 949 }, 950 }, 951 }, 952 } 953 for _, tc := range testCases { 954 t.Run(tc.name, func(t *testing.T) { 955 got := Paste(tc.src1, tc.src2, tc.p) 956 if !compareNRGBA(got, tc.want, 0) { 957 t.Fatalf("got result %#v want %#v", got, tc.want) 958 } 959 }) 960 } 961 } 962 963 func BenchmarkPaste(b *testing.B) { 964 b.ReportAllocs() 965 for i := 0; i < b.N; i++ { 966 Paste(testdataBranchesJPG, testdataFlowersSmallPNG, image.Pt(100, 100)) 967 } 968 } 969 970 func TestPasteCenter(t *testing.T) { 971 testCases := []struct { 972 name string 973 src1 image.Image 974 src2 image.Image 975 want *image.NRGBA 976 }{ 977 { 978 "PasteCenter 2x3 2x1", 979 &image.NRGBA{ 980 Rect: image.Rect(-1, -1, 1, 2), 981 Stride: 2 * 4, 982 Pix: []uint8{ 983 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 984 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 985 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 986 }, 987 }, 988 &image.NRGBA{ 989 Rect: image.Rect(1, 1, 3, 2), 990 Stride: 2 * 4, 991 Pix: []uint8{ 992 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 993 }, 994 }, 995 &image.NRGBA{ 996 Rect: image.Rect(0, 0, 2, 3), 997 Stride: 2 * 4, 998 Pix: []uint8{ 999 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 1000 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 1001 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 1002 }, 1003 }, 1004 }, 1005 } 1006 for _, tc := range testCases { 1007 t.Run(tc.name, func(t *testing.T) { 1008 got := PasteCenter(tc.src1, tc.src2) 1009 if !compareNRGBA(got, tc.want, 0) { 1010 t.Fatalf("got result %#v want %#v", got, tc.want) 1011 } 1012 }) 1013 } 1014 } 1015 1016 func TestOverlay(t *testing.T) { 1017 testCases := []struct { 1018 name string 1019 src1 image.Image 1020 src2 image.Image 1021 p image.Point 1022 a float64 1023 want *image.NRGBA 1024 }{ 1025 { 1026 "Overlay 2x3 2x1 1.0", 1027 &image.NRGBA{ 1028 Rect: image.Rect(-1, -1, 1, 2), 1029 Stride: 2 * 4, 1030 Pix: []uint8{ 1031 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 1032 0x60, 0x00, 0x90, 0xff, 0xff, 0x00, 0x99, 0x7f, 1033 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 1034 }, 1035 }, 1036 &image.NRGBA{ 1037 Rect: image.Rect(1, 1, 3, 2), 1038 Stride: 2 * 4, 1039 Pix: []uint8{ 1040 0x20, 0x40, 0x80, 0x7f, 0xaa, 0xbb, 0xcc, 0xff, 1041 }, 1042 }, 1043 image.Pt(-1, 0), 1044 1.0, 1045 &image.NRGBA{ 1046 Rect: image.Rect(0, 0, 2, 3), 1047 Stride: 2 * 4, 1048 Pix: []uint8{ 1049 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, 1050 0x40, 0x1f, 0x88, 0xff, 0xaa, 0xbb, 0xcc, 0xff, 1051 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 1052 }, 1053 }, 1054 }, 1055 { 1056 "Overlay 2x2 2x2 0.5", 1057 &image.NRGBA{ 1058 Rect: image.Rect(-1, -1, 1, 1), 1059 Stride: 2 * 4, 1060 Pix: []uint8{ 1061 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 1062 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00, 1063 }, 1064 }, 1065 &image.NRGBA{ 1066 Rect: image.Rect(-1, -1, 1, 1), 1067 Stride: 2 * 4, 1068 Pix: []uint8{ 1069 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 1070 0xff, 0xff, 0x00, 0xff, 0x20, 0x20, 0x20, 0xff, 1071 }, 1072 }, 1073 image.Pt(-1, -1), 1074 0.5, 1075 &image.NRGBA{ 1076 Rect: image.Rect(0, 0, 2, 2), 1077 Stride: 2 * 4, 1078 Pix: []uint8{ 1079 0xff, 0x7f, 0x7f, 0xff, 0x00, 0xff, 0x00, 0xff, 1080 0x7f, 0x7f, 0x7f, 0xff, 0x20, 0x20, 0x20, 0x7f, 1081 }, 1082 }, 1083 }, 1084 { 1085 "Overlay 2x2 2x2 0.5 no intersection", 1086 &image.NRGBA{ 1087 Rect: image.Rect(-1, -1, 1, 1), 1088 Stride: 2 * 4, 1089 Pix: []uint8{ 1090 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 1091 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00, 1092 }, 1093 }, 1094 &image.NRGBA{ 1095 Rect: image.Rect(-1, -1, 1, 1), 1096 Stride: 2 * 4, 1097 Pix: []uint8{ 1098 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 1099 0xff, 0xff, 0x00, 0xff, 0x20, 0x20, 0x20, 0xff, 1100 }, 1101 }, 1102 image.Pt(-10, 10), 1103 0.5, 1104 &image.NRGBA{ 1105 Rect: image.Rect(0, 0, 2, 2), 1106 Stride: 2 * 4, 1107 Pix: []uint8{ 1108 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 1109 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00, 1110 }, 1111 }, 1112 }, 1113 } 1114 for _, tc := range testCases { 1115 t.Run(tc.name, func(t *testing.T) { 1116 got := Overlay(tc.src1, tc.src2, tc.p, tc.a) 1117 if !compareNRGBA(got, tc.want, 0) { 1118 t.Fatalf("got result %#v want %#v", got, tc.want) 1119 } 1120 }) 1121 } 1122 } 1123 1124 func BenchmarkOverlay(b *testing.B) { 1125 b.ReportAllocs() 1126 for i := 0; i < b.N; i++ { 1127 Overlay(testdataBranchesJPG, testdataFlowersSmallPNG, image.Pt(100, 100), 0.5) 1128 } 1129 } 1130 1131 func TestOverlayCenter(t *testing.T) { 1132 testCases := []struct { 1133 name string 1134 src1 image.Image 1135 src2 image.Image 1136 a float64 1137 want *image.NRGBA 1138 }{ 1139 { 1140 "OverlayCenter 2x3 2x1", 1141 &image.NRGBA{ 1142 Rect: image.Rect(-1, -1, 1, 2), 1143 Stride: 2 * 4, 1144 Pix: []uint8{ 1145 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, 1146 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, 1147 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, 1148 }, 1149 }, 1150 &image.NRGBA{ 1151 Rect: image.Rect(1, 1, 3, 2), 1152 Stride: 2 * 4, 1153 Pix: []uint8{ 1154 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 1155 }, 1156 }, 1157 0.5, 1158 &image.NRGBA{ 1159 Rect: image.Rect(0, 0, 2, 3), 1160 Stride: 2 * 4, 1161 Pix: []uint8{ 1162 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, 1163 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 1164 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, 1165 }, 1166 }, 1167 }, 1168 } 1169 for _, tc := range testCases { 1170 t.Run(tc.name, func(t *testing.T) { 1171 got := OverlayCenter(tc.src1, tc.src2, 0.5) 1172 if !compareNRGBA(got, tc.want, 0) { 1173 t.Fatalf("got result %#v want %#v", got, tc.want) 1174 } 1175 }) 1176 } 1177 }