github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/convert/convert.go (about) 1 // Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package convert implements some image convert functions. 6 package convert 7 8 import ( 9 "fmt" 10 "image" 11 "image/color" 12 13 image_ext "github.com/chai2010/gopkg/image" 14 color_ext "github.com/chai2010/gopkg/image/color" 15 ) 16 17 func ColorModel(m image.Image, model color.Model) image.Image { 18 if model == nil { 19 return m 20 } 21 switch model { 22 case color.GrayModel: 23 return Gray(m) 24 case color.Gray16Model: 25 return Gray16(m) 26 case color_ext.Gray32fModel: 27 return Gray32f(m) 28 case color_ext.RGBModel: 29 return RGB(m) 30 case color_ext.RGB48Model: 31 return RGB48(m) 32 case color_ext.RGB96fModel: 33 return RGB96f(m) 34 case color.RGBAModel: 35 return RGBA(m) 36 case color.RGBA64Model: 37 return RGBA64(m) 38 case color_ext.RGBA128fModel: 39 return RGBA128f(m) 40 } 41 panic(fmt.Sprintf("image/convert: unsupport colorModel %T", model)) 42 } 43 44 func Color(m image.Image, isColor bool) image.Image { 45 if isColor { 46 return convertToColor(m) 47 } else { 48 return convertToGray(m) 49 } 50 } 51 52 func Gray(m image.Image) *image.Gray { 53 if gray, ok := m.(*image.Gray); ok { 54 return gray 55 } 56 b := m.Bounds() 57 gray := image.NewGray(b) 58 switch m := m.(type) { 59 case *image.Gray16: 60 for y := b.Min.Y; y < b.Max.Y; y++ { 61 for x := b.Min.X; x < b.Max.X; x++ { 62 v := m.Gray16At(x, y) 63 gray.SetGray(x, y, color.Gray{uint8(v.Y >> 8)}) 64 } 65 } 66 case *image.RGBA: 67 for y := b.Min.Y; y < b.Max.Y; y++ { 68 for x := b.Min.X; x < b.Max.X; x++ { 69 gray.SetGray(x, y, color.GrayModel.Convert(m.RGBAAt(x, y)).(color.Gray)) 70 } 71 } 72 case *image.RGBA64: 73 for y := b.Min.Y; y < b.Max.Y; y++ { 74 for x := b.Min.X; x < b.Max.X; x++ { 75 gray.SetGray(x, y, color.GrayModel.Convert(m.RGBA64At(x, y)).(color.Gray)) 76 } 77 } 78 case *image.YCbCr: 79 for y := b.Min.Y; y < b.Max.Y; y++ { 80 copy( 81 gray.Pix[y*gray.Stride:][:gray.Stride], 82 m.Y[y*m.YStride:][:m.YStride], 83 ) 84 } 85 default: 86 for y := b.Min.Y; y < b.Max.Y; y++ { 87 for x := b.Min.X; x < b.Max.X; x++ { 88 gray.Set(x, y, m.At(x, y)) 89 } 90 } 91 } 92 return gray 93 } 94 95 func Gray16(m image.Image) *image.Gray16 { 96 if gray16, ok := m.(*image.Gray16); ok { 97 return gray16 98 } 99 b := m.Bounds() 100 gray16 := image.NewGray16(b) 101 switch m := m.(type) { 102 case *image.Gray: 103 for y := b.Min.Y; y < b.Max.Y; y++ { 104 for x := b.Min.X; x < b.Max.X; x++ { 105 v := m.GrayAt(x, y) 106 gray16.SetGray16(x, y, color.Gray16{uint16(v.Y) << 8}) 107 } 108 } 109 case *image.RGBA: 110 for y := b.Min.Y; y < b.Max.Y; y++ { 111 for x := b.Min.X; x < b.Max.X; x++ { 112 gray16.SetGray16(x, y, 113 color.Gray16Model.Convert(m.RGBAAt(x, y)).(color.Gray16), 114 ) 115 } 116 } 117 case *image.RGBA64: 118 for y := b.Min.Y; y < b.Max.Y; y++ { 119 for x := b.Min.X; x < b.Max.X; x++ { 120 gray16.SetGray16(x, y, 121 color.Gray16Model.Convert(m.RGBA64At(x, y)).(color.Gray16), 122 ) 123 } 124 } 125 case *image.YCbCr: 126 for y := b.Min.Y; y < b.Max.Y; y++ { 127 for x := b.Min.X; x < b.Max.X; x++ { 128 v := m.Y[m.YOffset(x, y)] 129 gray16.SetGray16(x, y, color.Gray16{uint16(v) << 8}) 130 } 131 } 132 default: 133 for y := b.Min.Y; y < b.Max.Y; y++ { 134 for x := b.Min.X; x < b.Max.X; x++ { 135 gray16.Set(x, y, m.At(x, y)) 136 } 137 } 138 } 139 return gray16 140 } 141 142 func Gray32f(m image.Image) *image_ext.Gray32f { 143 if gray32f, ok := m.(*image_ext.Gray32f); ok { 144 return gray32f 145 } 146 b := m.Bounds() 147 gray32f := image_ext.NewGray32f(b) 148 for y := b.Min.Y; y < b.Max.Y; y++ { 149 for x := b.Min.X; x < b.Max.X; x++ { 150 gray32f.Set(x, y, m.At(x, y)) 151 } 152 } 153 return gray32f 154 } 155 156 func RGB(m image.Image) *image_ext.RGB { 157 if rgb, ok := m.(*image_ext.RGB); ok { 158 return rgb 159 } 160 b := m.Bounds() 161 rgb := image_ext.NewRGB(b) 162 switch m := m.(type) { 163 case *image.Gray: 164 for y := b.Min.Y; y < b.Max.Y; y++ { 165 for x := b.Min.X; x < b.Max.X; x++ { 166 v := m.GrayAt(x, y) 167 rgb.SetRGB(x, y, color_ext.RGB{ 168 R: v.Y, 169 G: v.Y, 170 B: v.Y, 171 }) 172 } 173 } 174 case *image.Gray16: 175 for y := b.Min.Y; y < b.Max.Y; y++ { 176 for x := b.Min.X; x < b.Max.X; x++ { 177 v := m.Gray16At(x, y) 178 rgb.SetRGB(x, y, color_ext.RGB{ 179 R: uint8(v.Y >> 8), 180 G: uint8(v.Y >> 8), 181 B: uint8(v.Y >> 8), 182 }) 183 } 184 } 185 default: 186 for y := b.Min.Y; y < b.Max.Y; y++ { 187 for x := b.Min.X; x < b.Max.X; x++ { 188 rgb.Set(x, y, m.At(x, y)) 189 } 190 } 191 } 192 return rgb 193 } 194 195 func RGB48(m image.Image) *image_ext.RGB48 { 196 if rgb48, ok := m.(*image_ext.RGB48); ok { 197 return rgb48 198 } 199 b := m.Bounds() 200 rgb48 := image_ext.NewRGB48(b) 201 switch m := m.(type) { 202 case *image.Gray: 203 for y := b.Min.Y; y < b.Max.Y; y++ { 204 for x := b.Min.X; x < b.Max.X; x++ { 205 v := m.GrayAt(x, y) 206 rgb48.SetRGB48(x, y, color_ext.RGB48{ 207 R: uint16(v.Y) >> 8, 208 G: uint16(v.Y) >> 8, 209 B: uint16(v.Y) >> 8, 210 }) 211 } 212 } 213 case *image.Gray16: 214 for y := b.Min.Y; y < b.Max.Y; y++ { 215 for x := b.Min.X; x < b.Max.X; x++ { 216 v := m.Gray16At(x, y) 217 rgb48.SetRGB48(x, y, color_ext.RGB48{ 218 R: v.Y, 219 G: v.Y, 220 B: v.Y, 221 }) 222 } 223 } 224 default: 225 for y := b.Min.Y; y < b.Max.Y; y++ { 226 for x := b.Min.X; x < b.Max.X; x++ { 227 rgb48.Set(x, y, m.At(x, y)) 228 } 229 } 230 } 231 return rgb48 232 } 233 234 func RGB96f(m image.Image) *image_ext.RGB96f { 235 if rgb96f, ok := m.(*image_ext.RGB96f); ok { 236 return rgb96f 237 } 238 b := m.Bounds() 239 rgb96f := image_ext.NewRGB96f(b) 240 switch m := m.(type) { 241 case *image.Gray: 242 for y := b.Min.Y; y < b.Max.Y; y++ { 243 for x := b.Min.X; x < b.Max.X; x++ { 244 v := m.GrayAt(x, y) 245 rgb96f.SetRGB96f(x, y, color_ext.RGB96f{ 246 R: float32(uint16(v.Y) >> 8), 247 G: float32(uint16(v.Y) >> 8), 248 B: float32(uint16(v.Y) >> 8), 249 }) 250 } 251 } 252 case *image.Gray16: 253 for y := b.Min.Y; y < b.Max.Y; y++ { 254 for x := b.Min.X; x < b.Max.X; x++ { 255 v := m.Gray16At(x, y) 256 rgb96f.SetRGB96f(x, y, color_ext.RGB96f{ 257 R: float32(v.Y), 258 G: float32(v.Y), 259 B: float32(v.Y), 260 }) 261 } 262 } 263 default: 264 for y := b.Min.Y; y < b.Max.Y; y++ { 265 for x := b.Min.X; x < b.Max.X; x++ { 266 rgb96f.Set(x, y, m.At(x, y)) 267 } 268 } 269 } 270 return rgb96f 271 } 272 273 func RGBA(m image.Image) *image.RGBA { 274 if rgba, ok := m.(*image.RGBA); ok { 275 return rgba 276 } 277 b := m.Bounds() 278 rgba := image.NewRGBA(b) 279 switch m := m.(type) { 280 case *image.Gray: 281 for y := b.Min.Y; y < b.Max.Y; y++ { 282 for x := b.Min.X; x < b.Max.X; x++ { 283 v := m.GrayAt(x, y) 284 rgba.SetRGBA(x, y, color.RGBA{ 285 R: v.Y, 286 G: v.Y, 287 B: v.Y, 288 A: 0xFF, 289 }) 290 } 291 } 292 case *image.Gray16: 293 for y := b.Min.Y; y < b.Max.Y; y++ { 294 for x := b.Min.X; x < b.Max.X; x++ { 295 v := m.Gray16At(x, y) 296 rgba.SetRGBA(x, y, color.RGBA{ 297 R: uint8(v.Y >> 8), 298 G: uint8(v.Y >> 8), 299 B: uint8(v.Y >> 8), 300 A: 0xFF, 301 }) 302 } 303 } 304 default: 305 for y := b.Min.Y; y < b.Max.Y; y++ { 306 for x := b.Min.X; x < b.Max.X; x++ { 307 rgba.Set(x, y, m.At(x, y)) 308 } 309 } 310 } 311 return rgba 312 } 313 314 func RGBA64(m image.Image) *image.RGBA64 { 315 if rgba64, ok := m.(*image.RGBA64); ok { 316 return rgba64 317 } 318 b := m.Bounds() 319 rgba64 := image.NewRGBA64(b) 320 switch m := m.(type) { 321 case *image.Gray: 322 for y := b.Min.Y; y < b.Max.Y; y++ { 323 for x := b.Min.X; x < b.Max.X; x++ { 324 v := m.GrayAt(x, y) 325 rgba64.SetRGBA64(x, y, color.RGBA64{ 326 R: uint16(v.Y) >> 8, 327 G: uint16(v.Y) >> 8, 328 B: uint16(v.Y) >> 8, 329 A: 0xFFFF, 330 }) 331 } 332 } 333 case *image.Gray16: 334 for y := b.Min.Y; y < b.Max.Y; y++ { 335 for x := b.Min.X; x < b.Max.X; x++ { 336 v := m.Gray16At(x, y) 337 rgba64.SetRGBA64(x, y, color.RGBA64{ 338 R: v.Y, 339 G: v.Y, 340 B: v.Y, 341 A: 0xFFFF, 342 }) 343 } 344 } 345 case *image.RGBA: 346 for y := b.Min.Y; y < b.Max.Y; y++ { 347 for x := b.Min.X; x < b.Max.X; x++ { 348 v := m.RGBAAt(x, y) 349 rgba64.SetRGBA64(x, y, color.RGBA64{ 350 R: uint16(v.R) >> 8, 351 G: uint16(v.G) >> 8, 352 B: uint16(v.B) >> 8, 353 A: uint16(v.A) >> 8, 354 }) 355 } 356 } 357 default: 358 for y := b.Min.Y; y < b.Max.Y; y++ { 359 for x := b.Min.X; x < b.Max.X; x++ { 360 rgba64.Set(x, y, m.At(x, y)) 361 } 362 } 363 } 364 return rgba64 365 } 366 367 func RGBA128f(m image.Image) *image_ext.RGBA128f { 368 if rgba128f, ok := m.(*image_ext.RGBA128f); ok { 369 return rgba128f 370 } 371 b := m.Bounds() 372 rgba128f := image_ext.NewRGBA128f(b) 373 switch m := m.(type) { 374 case *image.Gray: 375 for y := b.Min.Y; y < b.Max.Y; y++ { 376 for x := b.Min.X; x < b.Max.X; x++ { 377 v := m.GrayAt(x, y) 378 rgba128f.SetRGBA128f(x, y, color_ext.RGBA128f{ 379 R: float32(uint16(v.Y) >> 8), 380 G: float32(uint16(v.Y) >> 8), 381 B: float32(uint16(v.Y) >> 8), 382 A: 0xFFFF, 383 }) 384 } 385 } 386 case *image.Gray16: 387 for y := b.Min.Y; y < b.Max.Y; y++ { 388 for x := b.Min.X; x < b.Max.X; x++ { 389 v := m.Gray16At(x, y) 390 rgba128f.SetRGBA128f(x, y, color_ext.RGBA128f{ 391 R: float32(v.Y), 392 G: float32(v.Y), 393 B: float32(v.Y), 394 A: 0xFFFF, 395 }) 396 } 397 } 398 case *image.RGBA: 399 for y := b.Min.Y; y < b.Max.Y; y++ { 400 for x := b.Min.X; x < b.Max.X; x++ { 401 v := m.RGBAAt(x, y) 402 rgba128f.SetRGBA128f(x, y, color_ext.RGBA128f{ 403 R: float32(uint16(v.R) >> 8), 404 G: float32(uint16(v.G) >> 8), 405 B: float32(uint16(v.B) >> 8), 406 A: float32(uint16(v.A) >> 8), 407 }) 408 } 409 } 410 default: 411 for y := b.Min.Y; y < b.Max.Y; y++ { 412 for x := b.Min.X; x < b.Max.X; x++ { 413 rgba128f.Set(x, y, m.At(x, y)) 414 } 415 } 416 } 417 return rgba128f 418 } 419 420 func Paletted(m image.Image, p color.Palette) *image.Paletted { 421 if m, ok := m.(*image.Paletted); ok { 422 if len(m.Palette) == len(p) { 423 if &m.Palette[0] == &p[0] { 424 return m 425 } 426 isEqual := true 427 for i, c := range m.Palette { 428 r0, g0, b0, a0 := c.RGBA() 429 r1, g1, b1, a1 := p[i].RGBA() 430 if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { 431 isEqual = false 432 break 433 } 434 } 435 if isEqual { 436 return m 437 } 438 } 439 } 440 b := m.Bounds() 441 paletted := image.NewPaletted(b, p) 442 for y := b.Min.Y; y < b.Max.Y; y++ { 443 for x := b.Min.X; x < b.Max.X; x++ { 444 paletted.Set(x, y, m.At(x, y)) 445 } 446 } 447 return paletted 448 } 449 450 func YCbCr(m image.Image, subsampleRatio image.YCbCrSubsampleRatio) *image.YCbCr { 451 if m, ok := m.(*image.YCbCr); ok { 452 if m.SubsampleRatio == subsampleRatio { 453 return m 454 } 455 } 456 b := m.Bounds() 457 yCbCr := image_ext.NewYCbCr(b, subsampleRatio) 458 for y := b.Min.Y; y < b.Max.Y; y++ { 459 for x := b.Min.X; x < b.Max.X; x++ { 460 yCbCr.Set(x, y, m.At(x, y)) 461 } 462 } 463 return (*image.YCbCr)(yCbCr) 464 } 465 466 func convertToColor(m image.Image) image.Image { 467 switch m := m.(type) { 468 case *image.Gray: 469 b := m.Bounds() 470 rgb := image_ext.NewRGB(b) 471 for y := b.Min.Y; y < b.Max.Y; y++ { 472 for x := b.Min.X; x < b.Max.X; x++ { 473 v := m.GrayAt(x, y) 474 rgb.SetRGB(x, y, color_ext.RGB{ 475 R: v.Y, 476 G: v.Y, 477 B: v.Y, 478 }) 479 } 480 } 481 return rgb 482 case *image.Gray16: 483 b := m.Bounds() 484 rgb48 := image_ext.NewRGB48(b) 485 for y := b.Min.Y; y < b.Max.Y; y++ { 486 for x := b.Min.X; x < b.Max.X; x++ { 487 v := m.Gray16At(x, y) 488 rgb48.SetRGB48(x, y, color_ext.RGB48{ 489 R: v.Y, 490 G: v.Y, 491 B: v.Y, 492 }) 493 } 494 } 495 return rgb48 496 case *image_ext.Gray32f: 497 b := m.Bounds() 498 rgb96f := image_ext.NewRGB96f(b) 499 for y := b.Min.Y; y < b.Max.Y; y++ { 500 for x := b.Min.X; x < b.Max.X; x++ { 501 v := m.Gray32fAt(x, y) 502 rgb96f.SetRGB96f(x, y, color_ext.RGB96f{ 503 R: v.Y, 504 G: v.Y, 505 B: v.Y, 506 }) 507 } 508 } 509 return rgb96f 510 case *image.YCbCr: 511 b := m.Bounds() 512 rgb := image_ext.NewRGB(b) 513 for y := b.Min.Y; y < b.Max.Y; y++ { 514 for x := b.Min.X; x < b.Max.X; x++ { 515 v := m.YCbCrAt(x, y) 516 rr, gg, bb := color.YCbCrToRGB(v.Y, v.Cb, v.Cr) 517 rgb.SetRGB(x, y, color_ext.RGB{ 518 R: rr, 519 G: gg, 520 B: bb, 521 }) 522 } 523 } 524 return rgb 525 case *image.Paletted: 526 switch m.Palette[0].(type) { 527 case color.Gray: 528 b := m.Bounds() 529 rgb := image_ext.NewRGB(b) 530 for y := b.Min.Y; y < b.Max.Y; y++ { 531 for x := b.Min.X; x < b.Max.X; x++ { 532 v := m.At(x, y).(color.Gray) 533 rgb.SetRGB(x, y, color_ext.RGB{ 534 R: v.Y, 535 G: v.Y, 536 B: v.Y, 537 }) 538 } 539 } 540 return rgb 541 case color.Gray16: 542 b := m.Bounds() 543 rgb48 := image_ext.NewRGB48(b) 544 for y := b.Min.Y; y < b.Max.Y; y++ { 545 for x := b.Min.X; x < b.Max.X; x++ { 546 v := m.At(x, y).(color.Gray16) 547 rgb48.SetRGB48(x, y, color_ext.RGB48{ 548 R: v.Y, 549 G: v.Y, 550 B: v.Y, 551 }) 552 } 553 } 554 return rgb48 555 case color_ext.Gray32f: 556 b := m.Bounds() 557 rgb96f := image_ext.NewRGB96f(b) 558 for y := b.Min.Y; y < b.Max.Y; y++ { 559 for x := b.Min.X; x < b.Max.X; x++ { 560 v := m.At(x, y).(color_ext.Gray32f) 561 rgb96f.SetRGB96f(x, y, color_ext.RGB96f{ 562 R: v.Y, 563 G: v.Y, 564 B: v.Y, 565 }) 566 } 567 } 568 return rgb96f 569 case color.YCbCr: 570 b := m.Bounds() 571 rgb := image_ext.NewRGB(b) 572 for y := b.Min.Y; y < b.Max.Y; y++ { 573 for x := b.Min.X; x < b.Max.X; x++ { 574 v := m.At(x, y).(color.YCbCr) 575 rr, gg, bb := color.YCbCrToRGB(v.Y, v.Cb, v.Cr) 576 rgb.SetRGB(x, y, color_ext.RGB{ 577 R: rr, 578 G: gg, 579 B: bb, 580 }) 581 } 582 } 583 return rgb 584 } 585 } 586 return m 587 } 588 589 func convertToGray(m image.Image) image.Image { 590 switch m := m.(type) { 591 case *image_ext.RGB: 592 b := m.Bounds() 593 gray := image.NewGray(b) 594 for y := b.Min.Y; y < b.Max.Y; y++ { 595 for x := b.Min.X; x < b.Max.X; x++ { 596 gray.SetGray(x, y, 597 color.GrayModel.Convert(m.RGBAt(x, y)).(color.Gray), 598 ) 599 } 600 } 601 return gray 602 case *image_ext.RGB48: 603 b := m.Bounds() 604 gray16 := image.NewGray16(b) 605 for y := b.Min.Y; y < b.Max.Y; y++ { 606 for x := b.Min.X; x < b.Max.X; x++ { 607 gray16.SetGray16(x, y, 608 color.Gray16Model.Convert(m.RGB48At(x, y)).(color.Gray16), 609 ) 610 } 611 } 612 return gray16 613 case *image_ext.RGB96f: 614 b := m.Bounds() 615 gray32f := image_ext.NewGray32f(b) 616 for y := b.Min.Y; y < b.Max.Y; y++ { 617 for x := b.Min.X; x < b.Max.X; x++ { 618 gray32f.SetGray32f(x, y, 619 color_ext.Gray32fModel.Convert(m.RGB96fAt(x, y)).(color_ext.Gray32f), 620 ) 621 } 622 } 623 return gray32f 624 case *image.RGBA: 625 b := m.Bounds() 626 gray := image.NewGray(b) 627 for y := b.Min.Y; y < b.Max.Y; y++ { 628 for x := b.Min.X; x < b.Max.X; x++ { 629 gray.SetGray(x, y, 630 color.RGBAModel.Convert(m.RGBAAt(x, y)).(color.Gray), 631 ) 632 } 633 } 634 return gray 635 case *image.RGBA64: 636 b := m.Bounds() 637 gray16 := image.NewGray16(b) 638 for y := b.Min.Y; y < b.Max.Y; y++ { 639 for x := b.Min.X; x < b.Max.X; x++ { 640 gray16.SetGray16(x, y, 641 color.Gray16Model.Convert(m.RGBA64At(x, y)).(color.Gray16), 642 ) 643 } 644 } 645 return gray16 646 case *image_ext.RGBA128f: 647 b := m.Bounds() 648 gray32f := image_ext.NewGray32f(b) 649 for y := b.Min.Y; y < b.Max.Y; y++ { 650 for x := b.Min.X; x < b.Max.X; x++ { 651 gray32f.SetGray32f(x, y, 652 color_ext.Gray32fModel.Convert(m.RGBA128fAt(x, y)).(color_ext.Gray32f), 653 ) 654 } 655 } 656 return gray32f 657 case *image.YCbCr: 658 b := m.Bounds() 659 gray := image.NewGray(b) 660 for y := b.Min.Y; y < b.Max.Y; y++ { 661 copy(gray.Pix[y*gray.Stride:][:b.Dx()], m.Y[y*m.YStride:]) 662 } 663 return gray 664 case *image.Paletted: 665 switch m.Palette[0].(type) { 666 case color_ext.RGB, color.RGBA, color.YCbCr: 667 b := m.Bounds() 668 gray := image.NewGray(b) 669 for y := b.Min.Y; y < b.Max.Y; y++ { 670 for x := b.Min.X; x < b.Max.X; x++ { 671 gray.SetGray(x, y, 672 color.GrayModel.Convert(m.At(x, y)).(color.Gray), 673 ) 674 } 675 } 676 return gray 677 case color_ext.RGB48, color.RGBA64: 678 b := m.Bounds() 679 gray16 := image.NewGray16(b) 680 for y := b.Min.Y; y < b.Max.Y; y++ { 681 for x := b.Min.X; x < b.Max.X; x++ { 682 gray16.SetGray16(x, y, 683 color.Gray16Model.Convert(m.At(x, y)).(color.Gray16), 684 ) 685 } 686 } 687 return gray16 688 case color_ext.RGB96f, color_ext.RGBA128f: 689 b := m.Bounds() 690 gray32f := image_ext.NewGray32f(b) 691 for y := b.Min.Y; y < b.Max.Y; y++ { 692 for x := b.Min.X; x < b.Max.X; x++ { 693 gray32f.SetGray32f(x, y, 694 color_ext.Gray32fModel.Convert(m.At(x, y)).(color_ext.Gray32f), 695 ) 696 } 697 } 698 return gray32f 699 } 700 } 701 return m 702 }