1
2
3
4
5
6
7
8
9 package draw
10
11 import (
12 "image"
13 "image/color"
14 "image/internal/imageutil"
15 )
16
17
18 const m = 1<<16 - 1
19
20
21 type Image interface {
22 image.Image
23 Set(x, y int, c color.Color)
24 }
25
26
27
28
29
30 type RGBA64Image interface {
31 image.RGBA64Image
32 Set(x, y int, c color.Color)
33 SetRGBA64(x, y int, c color.RGBA64)
34 }
35
36
37 type Quantizer interface {
38
39
40 Quantize(p color.Palette, m image.Image) color.Palette
41 }
42
43
44 type Op int
45
46 const (
47
48 Over Op = iota
49
50 Src
51 )
52
53
54
55 func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
56 DrawMask(dst, r, src, sp, nil, image.Point{}, op)
57 }
58
59
60 type Drawer interface {
61
62
63 Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
64 }
65
66
67
68 var FloydSteinberg Drawer = floydSteinberg{}
69
70 type floydSteinberg struct{}
71
72 func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
73 clip(dst, &r, src, &sp, nil, nil)
74 if r.Empty() {
75 return
76 }
77 drawPaletted(dst, r, src, sp, true)
78 }
79
80
81
82
83 func clip(dst Image, r *image.Rectangle, src image.Image, sp *image.Point, mask image.Image, mp *image.Point) {
84 orig := r.Min
85 *r = r.Intersect(dst.Bounds())
86 *r = r.Intersect(src.Bounds().Add(orig.Sub(*sp)))
87 if mask != nil {
88 *r = r.Intersect(mask.Bounds().Add(orig.Sub(*mp)))
89 }
90 dx := r.Min.X - orig.X
91 dy := r.Min.Y - orig.Y
92 if dx == 0 && dy == 0 {
93 return
94 }
95 sp.X += dx
96 sp.Y += dy
97 if mp != nil {
98 mp.X += dx
99 mp.Y += dy
100 }
101 }
102
103 func processBackward(dst image.Image, r image.Rectangle, src image.Image, sp image.Point) bool {
104 return dst == src &&
105 r.Overlaps(r.Add(sp.Sub(r.Min))) &&
106 (sp.Y < r.Min.Y || (sp.Y == r.Min.Y && sp.X < r.Min.X))
107 }
108
109
110 func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
111 DrawMask(dst, r, src, sp, nil, image.Point{}, op)
112 }
113
114
115
116 func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
117 clip(dst, &r, src, &sp, mask, &mp)
118 if r.Empty() {
119 return
120 }
121
122
123
124
125
126
127
128
129 switch dst0 := dst.(type) {
130 case *image.RGBA:
131 if op == Over {
132 if mask == nil {
133 switch src0 := src.(type) {
134 case *image.Uniform:
135 sr, sg, sb, sa := src0.RGBA()
136 if sa == 0xffff {
137 drawFillSrc(dst0, r, sr, sg, sb, sa)
138 } else {
139 drawFillOver(dst0, r, sr, sg, sb, sa)
140 }
141 return
142 case *image.RGBA:
143 drawCopyOver(dst0, r, src0, sp)
144 return
145 case *image.NRGBA:
146 drawNRGBAOver(dst0, r, src0, sp)
147 return
148 case *image.YCbCr:
149
150
151
152
153 if imageutil.DrawYCbCr(dst0, r, src0, sp) {
154 return
155 }
156 case *image.Gray:
157 drawGray(dst0, r, src0, sp)
158 return
159 case *image.CMYK:
160 drawCMYK(dst0, r, src0, sp)
161 return
162 }
163 } else if mask0, ok := mask.(*image.Alpha); ok {
164 switch src0 := src.(type) {
165 case *image.Uniform:
166 drawGlyphOver(dst0, r, src0, mask0, mp)
167 return
168 case *image.RGBA:
169 drawRGBAMaskOver(dst0, r, src0, sp, mask0, mp)
170 return
171 case *image.Gray:
172 drawGrayMaskOver(dst0, r, src0, sp, mask0, mp)
173 return
174
175
176 case image.RGBA64Image:
177 drawRGBA64ImageMaskOver(dst0, r, src0, sp, mask0, mp)
178 return
179 }
180 }
181 } else {
182 if mask == nil {
183 switch src0 := src.(type) {
184 case *image.Uniform:
185 sr, sg, sb, sa := src0.RGBA()
186 drawFillSrc(dst0, r, sr, sg, sb, sa)
187 return
188 case *image.RGBA:
189 d0 := dst0.PixOffset(r.Min.X, r.Min.Y)
190 s0 := src0.PixOffset(sp.X, sp.Y)
191 drawCopySrc(
192 dst0.Pix[d0:], dst0.Stride, r, src0.Pix[s0:], src0.Stride, sp, 4*r.Dx())
193 return
194 case *image.NRGBA:
195 drawNRGBASrc(dst0, r, src0, sp)
196 return
197 case *image.YCbCr:
198 if imageutil.DrawYCbCr(dst0, r, src0, sp) {
199 return
200 }
201 case *image.Gray:
202 drawGray(dst0, r, src0, sp)
203 return
204 case *image.CMYK:
205 drawCMYK(dst0, r, src0, sp)
206 return
207 }
208 }
209 }
210 drawRGBA(dst0, r, src, sp, mask, mp, op)
211 return
212 case *image.Paletted:
213 if op == Src && mask == nil {
214 if src0, ok := src.(*image.Uniform); ok {
215 colorIndex := uint8(dst0.Palette.Index(src0.C))
216 i0 := dst0.PixOffset(r.Min.X, r.Min.Y)
217 i1 := i0 + r.Dx()
218 for i := i0; i < i1; i++ {
219 dst0.Pix[i] = colorIndex
220 }
221 firstRow := dst0.Pix[i0:i1]
222 for y := r.Min.Y + 1; y < r.Max.Y; y++ {
223 i0 += dst0.Stride
224 i1 += dst0.Stride
225 copy(dst0.Pix[i0:i1], firstRow)
226 }
227 return
228 } else if !processBackward(dst, r, src, sp) {
229 drawPaletted(dst0, r, src, sp, false)
230 return
231 }
232 }
233 case *image.NRGBA:
234 if op == Src && mask == nil {
235 if src0, ok := src.(*image.NRGBA); ok {
236 d0 := dst0.PixOffset(r.Min.X, r.Min.Y)
237 s0 := src0.PixOffset(sp.X, sp.Y)
238 drawCopySrc(
239 dst0.Pix[d0:], dst0.Stride, r, src0.Pix[s0:], src0.Stride, sp, 4*r.Dx())
240 return
241 }
242 }
243 case *image.NRGBA64:
244 if op == Src && mask == nil {
245 if src0, ok := src.(*image.NRGBA64); ok {
246 d0 := dst0.PixOffset(r.Min.X, r.Min.Y)
247 s0 := src0.PixOffset(sp.X, sp.Y)
248 drawCopySrc(
249 dst0.Pix[d0:], dst0.Stride, r, src0.Pix[s0:], src0.Stride, sp, 8*r.Dx())
250 return
251 }
252 }
253 }
254
255 x0, x1, dx := r.Min.X, r.Max.X, 1
256 y0, y1, dy := r.Min.Y, r.Max.Y, 1
257 if processBackward(dst, r, src, sp) {
258 x0, x1, dx = x1-1, x0-1, -1
259 y0, y1, dy = y1-1, y0-1, -1
260 }
261
262
263
264
265
266
267
268
269 if dst0, _ := dst.(RGBA64Image); dst0 != nil {
270 if src0, _ := src.(image.RGBA64Image); src0 != nil {
271 if mask == nil {
272 sy := sp.Y + y0 - r.Min.Y
273 my := mp.Y + y0 - r.Min.Y
274 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
275 sx := sp.X + x0 - r.Min.X
276 mx := mp.X + x0 - r.Min.X
277 for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
278 if op == Src {
279 dst0.SetRGBA64(x, y, src0.RGBA64At(sx, sy))
280 } else {
281 srgba := src0.RGBA64At(sx, sy)
282 a := m - uint32(srgba.A)
283 drgba := dst0.RGBA64At(x, y)
284 dst0.SetRGBA64(x, y, color.RGBA64{
285 R: uint16((uint32(drgba.R)*a)/m) + srgba.R,
286 G: uint16((uint32(drgba.G)*a)/m) + srgba.G,
287 B: uint16((uint32(drgba.B)*a)/m) + srgba.B,
288 A: uint16((uint32(drgba.A)*a)/m) + srgba.A,
289 })
290 }
291 }
292 }
293 return
294
295 } else if mask0, _ := mask.(image.RGBA64Image); mask0 != nil {
296 sy := sp.Y + y0 - r.Min.Y
297 my := mp.Y + y0 - r.Min.Y
298 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
299 sx := sp.X + x0 - r.Min.X
300 mx := mp.X + x0 - r.Min.X
301 for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
302 ma := uint32(mask0.RGBA64At(mx, my).A)
303 switch {
304 case ma == 0:
305 if op == Over {
306
307 } else {
308 dst0.SetRGBA64(x, y, color.RGBA64{})
309 }
310 case ma == m && op == Src:
311 dst0.SetRGBA64(x, y, src0.RGBA64At(sx, sy))
312 default:
313 srgba := src0.RGBA64At(sx, sy)
314 if op == Over {
315 drgba := dst0.RGBA64At(x, y)
316 a := m - (uint32(srgba.A) * ma / m)
317 dst0.SetRGBA64(x, y, color.RGBA64{
318 R: uint16((uint32(drgba.R)*a + uint32(srgba.R)*ma) / m),
319 G: uint16((uint32(drgba.G)*a + uint32(srgba.G)*ma) / m),
320 B: uint16((uint32(drgba.B)*a + uint32(srgba.B)*ma) / m),
321 A: uint16((uint32(drgba.A)*a + uint32(srgba.A)*ma) / m),
322 })
323 } else {
324 dst0.SetRGBA64(x, y, color.RGBA64{
325 R: uint16(uint32(srgba.R) * ma / m),
326 G: uint16(uint32(srgba.G) * ma / m),
327 B: uint16(uint32(srgba.B) * ma / m),
328 A: uint16(uint32(srgba.A) * ma / m),
329 })
330 }
331 }
332 }
333 }
334 return
335 }
336 }
337 }
338
339
340
341
342
343
344 var out color.RGBA64
345 sy := sp.Y + y0 - r.Min.Y
346 my := mp.Y + y0 - r.Min.Y
347 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
348 sx := sp.X + x0 - r.Min.X
349 mx := mp.X + x0 - r.Min.X
350 for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
351 ma := uint32(m)
352 if mask != nil {
353 _, _, _, ma = mask.At(mx, my).RGBA()
354 }
355 switch {
356 case ma == 0:
357 if op == Over {
358
359 } else {
360 dst.Set(x, y, color.Transparent)
361 }
362 case ma == m && op == Src:
363 dst.Set(x, y, src.At(sx, sy))
364 default:
365 sr, sg, sb, sa := src.At(sx, sy).RGBA()
366 if op == Over {
367 dr, dg, db, da := dst.At(x, y).RGBA()
368 a := m - (sa * ma / m)
369 out.R = uint16((dr*a + sr*ma) / m)
370 out.G = uint16((dg*a + sg*ma) / m)
371 out.B = uint16((db*a + sb*ma) / m)
372 out.A = uint16((da*a + sa*ma) / m)
373 } else {
374 out.R = uint16(sr * ma / m)
375 out.G = uint16(sg * ma / m)
376 out.B = uint16(sb * ma / m)
377 out.A = uint16(sa * ma / m)
378 }
379
380
381
382
383 dst.Set(x, y, &out)
384 }
385 }
386 }
387 }
388
389 func drawFillOver(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
390
391 a := (m - sa) * 0x101
392 i0 := dst.PixOffset(r.Min.X, r.Min.Y)
393 i1 := i0 + r.Dx()*4
394 for y := r.Min.Y; y != r.Max.Y; y++ {
395 for i := i0; i < i1; i += 4 {
396 dr := &dst.Pix[i+0]
397 dg := &dst.Pix[i+1]
398 db := &dst.Pix[i+2]
399 da := &dst.Pix[i+3]
400
401 *dr = uint8((uint32(*dr)*a/m + sr) >> 8)
402 *dg = uint8((uint32(*dg)*a/m + sg) >> 8)
403 *db = uint8((uint32(*db)*a/m + sb) >> 8)
404 *da = uint8((uint32(*da)*a/m + sa) >> 8)
405 }
406 i0 += dst.Stride
407 i1 += dst.Stride
408 }
409 }
410
411 func drawFillSrc(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
412 sr8 := uint8(sr >> 8)
413 sg8 := uint8(sg >> 8)
414 sb8 := uint8(sb >> 8)
415 sa8 := uint8(sa >> 8)
416
417
418
419 i0 := dst.PixOffset(r.Min.X, r.Min.Y)
420 i1 := i0 + r.Dx()*4
421 for i := i0; i < i1; i += 4 {
422 dst.Pix[i+0] = sr8
423 dst.Pix[i+1] = sg8
424 dst.Pix[i+2] = sb8
425 dst.Pix[i+3] = sa8
426 }
427 firstRow := dst.Pix[i0:i1]
428 for y := r.Min.Y + 1; y < r.Max.Y; y++ {
429 i0 += dst.Stride
430 i1 += dst.Stride
431 copy(dst.Pix[i0:i1], firstRow)
432 }
433 }
434
435 func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
436 dx, dy := r.Dx(), r.Dy()
437 d0 := dst.PixOffset(r.Min.X, r.Min.Y)
438 s0 := src.PixOffset(sp.X, sp.Y)
439 var (
440 ddelta, sdelta int
441 i0, i1, idelta int
442 )
443 if r.Min.Y < sp.Y || r.Min.Y == sp.Y && r.Min.X <= sp.X {
444 ddelta = dst.Stride
445 sdelta = src.Stride
446 i0, i1, idelta = 0, dx*4, +4
447 } else {
448
449
450 d0 += (dy - 1) * dst.Stride
451 s0 += (dy - 1) * src.Stride
452 ddelta = -dst.Stride
453 sdelta = -src.Stride
454 i0, i1, idelta = (dx-1)*4, -4, -4
455 }
456 for ; dy > 0; dy-- {
457 dpix := dst.Pix[d0:]
458 spix := src.Pix[s0:]
459 for i := i0; i != i1; i += idelta {
460 s := spix[i : i+4 : i+4]
461 sr := uint32(s[0]) * 0x101
462 sg := uint32(s[1]) * 0x101
463 sb := uint32(s[2]) * 0x101
464 sa := uint32(s[3]) * 0x101
465
466
467 a := (m - sa) * 0x101
468
469 d := dpix[i : i+4 : i+4]
470 d[0] = uint8((uint32(d[0])*a/m + sr) >> 8)
471 d[1] = uint8((uint32(d[1])*a/m + sg) >> 8)
472 d[2] = uint8((uint32(d[2])*a/m + sb) >> 8)
473 d[3] = uint8((uint32(d[3])*a/m + sa) >> 8)
474 }
475 d0 += ddelta
476 s0 += sdelta
477 }
478 }
479
480
481
482
483 func drawCopySrc(
484 dstPix []byte, dstStride int, r image.Rectangle,
485 srcPix []byte, srcStride int, sp image.Point,
486 bytesPerRow int) {
487
488 d0, s0, ddelta, sdelta, dy := 0, 0, dstStride, srcStride, r.Dy()
489 if r.Min.Y > sp.Y {
490
491
492
493
494
495 d0 = (dy - 1) * dstStride
496 s0 = (dy - 1) * srcStride
497 ddelta = -dstStride
498 sdelta = -srcStride
499 }
500 for ; dy > 0; dy-- {
501 copy(dstPix[d0:d0+bytesPerRow], srcPix[s0:s0+bytesPerRow])
502 d0 += ddelta
503 s0 += sdelta
504 }
505 }
506
507 func drawNRGBAOver(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
508 i0 := (r.Min.X - dst.Rect.Min.X) * 4
509 i1 := (r.Max.X - dst.Rect.Min.X) * 4
510 si0 := (sp.X - src.Rect.Min.X) * 4
511 yMax := r.Max.Y - dst.Rect.Min.Y
512
513 y := r.Min.Y - dst.Rect.Min.Y
514 sy := sp.Y - src.Rect.Min.Y
515 for ; y != yMax; y, sy = y+1, sy+1 {
516 dpix := dst.Pix[y*dst.Stride:]
517 spix := src.Pix[sy*src.Stride:]
518
519 for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
520
521 s := spix[si : si+4 : si+4]
522 sa := uint32(s[3]) * 0x101
523 sr := uint32(s[0]) * sa / 0xff
524 sg := uint32(s[1]) * sa / 0xff
525 sb := uint32(s[2]) * sa / 0xff
526
527 d := dpix[i : i+4 : i+4]
528 dr := uint32(d[0])
529 dg := uint32(d[1])
530 db := uint32(d[2])
531 da := uint32(d[3])
532
533
534 a := (m - sa) * 0x101
535
536 d[0] = uint8((dr*a/m + sr) >> 8)
537 d[1] = uint8((dg*a/m + sg) >> 8)
538 d[2] = uint8((db*a/m + sb) >> 8)
539 d[3] = uint8((da*a/m + sa) >> 8)
540 }
541 }
542 }
543
544 func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
545 i0 := (r.Min.X - dst.Rect.Min.X) * 4
546 i1 := (r.Max.X - dst.Rect.Min.X) * 4
547 si0 := (sp.X - src.Rect.Min.X) * 4
548 yMax := r.Max.Y - dst.Rect.Min.Y
549
550 y := r.Min.Y - dst.Rect.Min.Y
551 sy := sp.Y - src.Rect.Min.Y
552 for ; y != yMax; y, sy = y+1, sy+1 {
553 dpix := dst.Pix[y*dst.Stride:]
554 spix := src.Pix[sy*src.Stride:]
555
556 for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
557
558 s := spix[si : si+4 : si+4]
559 sa := uint32(s[3]) * 0x101
560 sr := uint32(s[0]) * sa / 0xff
561 sg := uint32(s[1]) * sa / 0xff
562 sb := uint32(s[2]) * sa / 0xff
563
564 d := dpix[i : i+4 : i+4]
565 d[0] = uint8(sr >> 8)
566 d[1] = uint8(sg >> 8)
567 d[2] = uint8(sb >> 8)
568 d[3] = uint8(sa >> 8)
569 }
570 }
571 }
572
573 func drawGray(dst *image.RGBA, r image.Rectangle, src *image.Gray, sp image.Point) {
574 i0 := (r.Min.X - dst.Rect.Min.X) * 4
575 i1 := (r.Max.X - dst.Rect.Min.X) * 4
576 si0 := (sp.X - src.Rect.Min.X) * 1
577 yMax := r.Max.Y - dst.Rect.Min.Y
578
579 y := r.Min.Y - dst.Rect.Min.Y
580 sy := sp.Y - src.Rect.Min.Y
581 for ; y != yMax; y, sy = y+1, sy+1 {
582 dpix := dst.Pix[y*dst.Stride:]
583 spix := src.Pix[sy*src.Stride:]
584
585 for i, si := i0, si0; i < i1; i, si = i+4, si+1 {
586 p := spix[si]
587 d := dpix[i : i+4 : i+4]
588 d[0] = p
589 d[1] = p
590 d[2] = p
591 d[3] = 255
592 }
593 }
594 }
595
596 func drawCMYK(dst *image.RGBA, r image.Rectangle, src *image.CMYK, sp image.Point) {
597 i0 := (r.Min.X - dst.Rect.Min.X) * 4
598 i1 := (r.Max.X - dst.Rect.Min.X) * 4
599 si0 := (sp.X - src.Rect.Min.X) * 4
600 yMax := r.Max.Y - dst.Rect.Min.Y
601
602 y := r.Min.Y - dst.Rect.Min.Y
603 sy := sp.Y - src.Rect.Min.Y
604 for ; y != yMax; y, sy = y+1, sy+1 {
605 dpix := dst.Pix[y*dst.Stride:]
606 spix := src.Pix[sy*src.Stride:]
607
608 for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
609 s := spix[si : si+4 : si+4]
610 d := dpix[i : i+4 : i+4]
611 d[0], d[1], d[2] = color.CMYKToRGB(s[0], s[1], s[2], s[3])
612 d[3] = 255
613 }
614 }
615 }
616
617 func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
618 i0 := dst.PixOffset(r.Min.X, r.Min.Y)
619 i1 := i0 + r.Dx()*4
620 mi0 := mask.PixOffset(mp.X, mp.Y)
621 sr, sg, sb, sa := src.RGBA()
622 for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 {
623 for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 {
624 ma := uint32(mask.Pix[mi])
625 if ma == 0 {
626 continue
627 }
628 ma |= ma << 8
629
630
631 a := (m - (sa * ma / m)) * 0x101
632
633 d := dst.Pix[i : i+4 : i+4]
634 d[0] = uint8((uint32(d[0])*a + sr*ma) / m >> 8)
635 d[1] = uint8((uint32(d[1])*a + sg*ma) / m >> 8)
636 d[2] = uint8((uint32(d[2])*a + sb*ma) / m >> 8)
637 d[3] = uint8((uint32(d[3])*a + sa*ma) / m >> 8)
638 }
639 i0 += dst.Stride
640 i1 += dst.Stride
641 mi0 += mask.Stride
642 }
643 }
644
645 func drawGrayMaskOver(dst *image.RGBA, r image.Rectangle, src *image.Gray, sp image.Point, mask *image.Alpha, mp image.Point) {
646 x0, x1, dx := r.Min.X, r.Max.X, 1
647 y0, y1, dy := r.Min.Y, r.Max.Y, 1
648 if r.Overlaps(r.Add(sp.Sub(r.Min))) {
649 if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
650 x0, x1, dx = x1-1, x0-1, -1
651 y0, y1, dy = y1-1, y0-1, -1
652 }
653 }
654
655 sy := sp.Y + y0 - r.Min.Y
656 my := mp.Y + y0 - r.Min.Y
657 sx0 := sp.X + x0 - r.Min.X
658 mx0 := mp.X + x0 - r.Min.X
659 sx1 := sx0 + (x1 - x0)
660 i0 := dst.PixOffset(x0, y0)
661 di := dx * 4
662 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
663 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
664 mi := mask.PixOffset(mx, my)
665 ma := uint32(mask.Pix[mi])
666 ma |= ma << 8
667 si := src.PixOffset(sx, sy)
668 sy := uint32(src.Pix[si])
669 sy |= sy << 8
670 sa := uint32(0xffff)
671
672 d := dst.Pix[i : i+4 : i+4]
673 dr := uint32(d[0])
674 dg := uint32(d[1])
675 db := uint32(d[2])
676 da := uint32(d[3])
677
678
679
680
681
682
683
684 a := (m - (sa * ma / m)) * 0x101
685
686 d[0] = uint8((dr*a + sy*ma) / m >> 8)
687 d[1] = uint8((dg*a + sy*ma) / m >> 8)
688 d[2] = uint8((db*a + sy*ma) / m >> 8)
689 d[3] = uint8((da*a + sa*ma) / m >> 8)
690 }
691 i0 += dy * dst.Stride
692 }
693 }
694
695 func drawRGBAMaskOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point, mask *image.Alpha, mp image.Point) {
696 x0, x1, dx := r.Min.X, r.Max.X, 1
697 y0, y1, dy := r.Min.Y, r.Max.Y, 1
698 if dst == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
699 if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
700 x0, x1, dx = x1-1, x0-1, -1
701 y0, y1, dy = y1-1, y0-1, -1
702 }
703 }
704
705 sy := sp.Y + y0 - r.Min.Y
706 my := mp.Y + y0 - r.Min.Y
707 sx0 := sp.X + x0 - r.Min.X
708 mx0 := mp.X + x0 - r.Min.X
709 sx1 := sx0 + (x1 - x0)
710 i0 := dst.PixOffset(x0, y0)
711 di := dx * 4
712 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
713 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
714 mi := mask.PixOffset(mx, my)
715 ma := uint32(mask.Pix[mi])
716 ma |= ma << 8
717 si := src.PixOffset(sx, sy)
718 sr := uint32(src.Pix[si+0])
719 sg := uint32(src.Pix[si+1])
720 sb := uint32(src.Pix[si+2])
721 sa := uint32(src.Pix[si+3])
722 sr |= sr << 8
723 sg |= sg << 8
724 sb |= sb << 8
725 sa |= sa << 8
726 d := dst.Pix[i : i+4 : i+4]
727 dr := uint32(d[0])
728 dg := uint32(d[1])
729 db := uint32(d[2])
730 da := uint32(d[3])
731
732
733
734
735
736
737
738 a := (m - (sa * ma / m)) * 0x101
739
740 d[0] = uint8((dr*a + sr*ma) / m >> 8)
741 d[1] = uint8((dg*a + sg*ma) / m >> 8)
742 d[2] = uint8((db*a + sb*ma) / m >> 8)
743 d[3] = uint8((da*a + sa*ma) / m >> 8)
744 }
745 i0 += dy * dst.Stride
746 }
747 }
748
749 func drawRGBA64ImageMaskOver(dst *image.RGBA, r image.Rectangle, src image.RGBA64Image, sp image.Point, mask *image.Alpha, mp image.Point) {
750 x0, x1, dx := r.Min.X, r.Max.X, 1
751 y0, y1, dy := r.Min.Y, r.Max.Y, 1
752 if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
753 if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
754 x0, x1, dx = x1-1, x0-1, -1
755 y0, y1, dy = y1-1, y0-1, -1
756 }
757 }
758
759 sy := sp.Y + y0 - r.Min.Y
760 my := mp.Y + y0 - r.Min.Y
761 sx0 := sp.X + x0 - r.Min.X
762 mx0 := mp.X + x0 - r.Min.X
763 sx1 := sx0 + (x1 - x0)
764 i0 := dst.PixOffset(x0, y0)
765 di := dx * 4
766 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
767 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
768 mi := mask.PixOffset(mx, my)
769 ma := uint32(mask.Pix[mi])
770 ma |= ma << 8
771 srgba := src.RGBA64At(sx, sy)
772 d := dst.Pix[i : i+4 : i+4]
773 dr := uint32(d[0])
774 dg := uint32(d[1])
775 db := uint32(d[2])
776 da := uint32(d[3])
777
778
779
780
781
782
783
784 a := (m - (uint32(srgba.A) * ma / m)) * 0x101
785
786 d[0] = uint8((dr*a + uint32(srgba.R)*ma) / m >> 8)
787 d[1] = uint8((dg*a + uint32(srgba.G)*ma) / m >> 8)
788 d[2] = uint8((db*a + uint32(srgba.B)*ma) / m >> 8)
789 d[3] = uint8((da*a + uint32(srgba.A)*ma) / m >> 8)
790 }
791 i0 += dy * dst.Stride
792 }
793 }
794
795 func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
796 x0, x1, dx := r.Min.X, r.Max.X, 1
797 y0, y1, dy := r.Min.Y, r.Max.Y, 1
798 if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
799 if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
800 x0, x1, dx = x1-1, x0-1, -1
801 y0, y1, dy = y1-1, y0-1, -1
802 }
803 }
804
805 sy := sp.Y + y0 - r.Min.Y
806 my := mp.Y + y0 - r.Min.Y
807 sx0 := sp.X + x0 - r.Min.X
808 mx0 := mp.X + x0 - r.Min.X
809 sx1 := sx0 + (x1 - x0)
810 i0 := dst.PixOffset(x0, y0)
811 di := dx * 4
812
813
814
815
816
817
818
819 if src0, _ := src.(image.RGBA64Image); src0 != nil {
820 if mask == nil {
821 if op == Over {
822 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
823 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
824 srgba := src0.RGBA64At(sx, sy)
825 d := dst.Pix[i : i+4 : i+4]
826 dr := uint32(d[0])
827 dg := uint32(d[1])
828 db := uint32(d[2])
829 da := uint32(d[3])
830 a := (m - uint32(srgba.A)) * 0x101
831 d[0] = uint8((dr*a/m + uint32(srgba.R)) >> 8)
832 d[1] = uint8((dg*a/m + uint32(srgba.G)) >> 8)
833 d[2] = uint8((db*a/m + uint32(srgba.B)) >> 8)
834 d[3] = uint8((da*a/m + uint32(srgba.A)) >> 8)
835 }
836 i0 += dy * dst.Stride
837 }
838 } else {
839 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
840 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
841 srgba := src0.RGBA64At(sx, sy)
842 d := dst.Pix[i : i+4 : i+4]
843 d[0] = uint8(srgba.R >> 8)
844 d[1] = uint8(srgba.G >> 8)
845 d[2] = uint8(srgba.B >> 8)
846 d[3] = uint8(srgba.A >> 8)
847 }
848 i0 += dy * dst.Stride
849 }
850 }
851 return
852
853 } else if mask0, _ := mask.(image.RGBA64Image); mask0 != nil {
854 if op == Over {
855 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
856 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
857 ma := uint32(mask0.RGBA64At(mx, my).A)
858 srgba := src0.RGBA64At(sx, sy)
859 d := dst.Pix[i : i+4 : i+4]
860 dr := uint32(d[0])
861 dg := uint32(d[1])
862 db := uint32(d[2])
863 da := uint32(d[3])
864 a := (m - (uint32(srgba.A) * ma / m)) * 0x101
865 d[0] = uint8((dr*a + uint32(srgba.R)*ma) / m >> 8)
866 d[1] = uint8((dg*a + uint32(srgba.G)*ma) / m >> 8)
867 d[2] = uint8((db*a + uint32(srgba.B)*ma) / m >> 8)
868 d[3] = uint8((da*a + uint32(srgba.A)*ma) / m >> 8)
869 }
870 i0 += dy * dst.Stride
871 }
872 } else {
873 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
874 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
875 ma := uint32(mask0.RGBA64At(mx, my).A)
876 srgba := src0.RGBA64At(sx, sy)
877 d := dst.Pix[i : i+4 : i+4]
878 d[0] = uint8(uint32(srgba.R) * ma / m >> 8)
879 d[1] = uint8(uint32(srgba.G) * ma / m >> 8)
880 d[2] = uint8(uint32(srgba.B) * ma / m >> 8)
881 d[3] = uint8(uint32(srgba.A) * ma / m >> 8)
882 }
883 i0 += dy * dst.Stride
884 }
885 }
886 return
887 }
888 }
889
890
891
892
893
894
895 for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
896 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
897 ma := uint32(m)
898 if mask != nil {
899 _, _, _, ma = mask.At(mx, my).RGBA()
900 }
901 sr, sg, sb, sa := src.At(sx, sy).RGBA()
902 d := dst.Pix[i : i+4 : i+4]
903 if op == Over {
904 dr := uint32(d[0])
905 dg := uint32(d[1])
906 db := uint32(d[2])
907 da := uint32(d[3])
908
909
910
911
912
913
914
915 a := (m - (sa * ma / m)) * 0x101
916
917 d[0] = uint8((dr*a + sr*ma) / m >> 8)
918 d[1] = uint8((dg*a + sg*ma) / m >> 8)
919 d[2] = uint8((db*a + sb*ma) / m >> 8)
920 d[3] = uint8((da*a + sa*ma) / m >> 8)
921
922 } else {
923 d[0] = uint8(sr * ma / m >> 8)
924 d[1] = uint8(sg * ma / m >> 8)
925 d[2] = uint8(sb * ma / m >> 8)
926 d[3] = uint8(sa * ma / m >> 8)
927 }
928 }
929 i0 += dy * dst.Stride
930 }
931 }
932
933
934 func clamp(i int32) int32 {
935 if i < 0 {
936 return 0
937 }
938 if i > 0xffff {
939 return 0xffff
940 }
941 return i
942 }
943
944
945
946
947
948 func sqDiff(x, y int32) uint32 {
949
950
951
952 d := uint32(x - y)
953 return (d * d) >> 2
954 }
955
956 func drawPaletted(dst Image, r image.Rectangle, src image.Image, sp image.Point, floydSteinberg bool) {
957
958
959
960
961
962
963
964
965 palette, pix, stride := [][4]int32(nil), []byte(nil), 0
966 if p, ok := dst.(*image.Paletted); ok {
967 palette = make([][4]int32, len(p.Palette))
968 for i, col := range p.Palette {
969 r, g, b, a := col.RGBA()
970 palette[i][0] = int32(r)
971 palette[i][1] = int32(g)
972 palette[i][2] = int32(b)
973 palette[i][3] = int32(a)
974 }
975 pix, stride = p.Pix[p.PixOffset(r.Min.X, r.Min.Y):], p.Stride
976 }
977
978
979
980
981 var quantErrorCurr, quantErrorNext [][4]int32
982 if floydSteinberg {
983 quantErrorCurr = make([][4]int32, r.Dx()+2)
984 quantErrorNext = make([][4]int32, r.Dx()+2)
985 }
986 pxRGBA := func(x, y int) (r, g, b, a uint32) { return src.At(x, y).RGBA() }
987
988
989
990 switch src0 := src.(type) {
991 case *image.RGBA:
992 pxRGBA = func(x, y int) (r, g, b, a uint32) { return src0.RGBAAt(x, y).RGBA() }
993 case *image.NRGBA:
994 pxRGBA = func(x, y int) (r, g, b, a uint32) { return src0.NRGBAAt(x, y).RGBA() }
995 case *image.YCbCr:
996 pxRGBA = func(x, y int) (r, g, b, a uint32) { return src0.YCbCrAt(x, y).RGBA() }
997 }
998
999
1000 out := color.RGBA64{A: 0xffff}
1001 for y := 0; y != r.Dy(); y++ {
1002 for x := 0; x != r.Dx(); x++ {
1003
1004
1005 sr, sg, sb, sa := pxRGBA(sp.X+x, sp.Y+y)
1006 er, eg, eb, ea := int32(sr), int32(sg), int32(sb), int32(sa)
1007 if floydSteinberg {
1008 er = clamp(er + quantErrorCurr[x+1][0]/16)
1009 eg = clamp(eg + quantErrorCurr[x+1][1]/16)
1010 eb = clamp(eb + quantErrorCurr[x+1][2]/16)
1011 ea = clamp(ea + quantErrorCurr[x+1][3]/16)
1012 }
1013
1014 if palette != nil {
1015
1016
1017
1018 bestIndex, bestSum := 0, uint32(1<<32-1)
1019 for index, p := range palette {
1020 sum := sqDiff(er, p[0]) + sqDiff(eg, p[1]) + sqDiff(eb, p[2]) + sqDiff(ea, p[3])
1021 if sum < bestSum {
1022 bestIndex, bestSum = index, sum
1023 if sum == 0 {
1024 break
1025 }
1026 }
1027 }
1028 pix[y*stride+x] = byte(bestIndex)
1029
1030 if !floydSteinberg {
1031 continue
1032 }
1033 er -= palette[bestIndex][0]
1034 eg -= palette[bestIndex][1]
1035 eb -= palette[bestIndex][2]
1036 ea -= palette[bestIndex][3]
1037
1038 } else {
1039 out.R = uint16(er)
1040 out.G = uint16(eg)
1041 out.B = uint16(eb)
1042 out.A = uint16(ea)
1043
1044
1045
1046
1047 dst.Set(r.Min.X+x, r.Min.Y+y, &out)
1048
1049 if !floydSteinberg {
1050 continue
1051 }
1052 sr, sg, sb, sa = dst.At(r.Min.X+x, r.Min.Y+y).RGBA()
1053 er -= int32(sr)
1054 eg -= int32(sg)
1055 eb -= int32(sb)
1056 ea -= int32(sa)
1057 }
1058
1059
1060 quantErrorNext[x+0][0] += er * 3
1061 quantErrorNext[x+0][1] += eg * 3
1062 quantErrorNext[x+0][2] += eb * 3
1063 quantErrorNext[x+0][3] += ea * 3
1064 quantErrorNext[x+1][0] += er * 5
1065 quantErrorNext[x+1][1] += eg * 5
1066 quantErrorNext[x+1][2] += eb * 5
1067 quantErrorNext[x+1][3] += ea * 5
1068 quantErrorNext[x+2][0] += er * 1
1069 quantErrorNext[x+2][1] += eg * 1
1070 quantErrorNext[x+2][2] += eb * 1
1071 quantErrorNext[x+2][3] += ea * 1
1072 quantErrorCurr[x+2][0] += er * 7
1073 quantErrorCurr[x+2][1] += eg * 7
1074 quantErrorCurr[x+2][2] += eb * 7
1075 quantErrorCurr[x+2][3] += ea * 7
1076 }
1077
1078
1079 if floydSteinberg {
1080 quantErrorCurr, quantErrorNext = quantErrorNext, quantErrorCurr
1081 clear(quantErrorNext)
1082 }
1083 }
1084 }
1085
View as plain text