OSDN Git Service

Update Go library to r60.3 release.
[pf3gnuchains/gcc-fork.git] / libgo / go / image / draw / draw.go
1 // Copyright 2009 The Go Authors.  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 draw provides image composition functions.
6 //
7 // See "The Go image/draw package" for an introduction to this package:
8 // http://blog.golang.org/2011/09/go-imagedraw-package.html
9 package draw
10
11 import (
12         "image"
13         "image/ycbcr"
14 )
15
16 // m is the maximum color value returned by image.Color.RGBA.
17 const m = 1<<16 - 1
18
19 // Op is a Porter-Duff compositing operator.
20 type Op int
21
22 const (
23         // Over specifies ``(src in mask) over dst''.
24         Over Op = iota
25         // Src specifies ``src in mask''.
26         Src
27 )
28
29 var zeroColor image.Color = image.AlphaColor{0}
30
31 // A draw.Image is an image.Image with a Set method to change a single pixel.
32 type Image interface {
33         image.Image
34         Set(x, y int, c image.Color)
35 }
36
37 // Draw calls DrawMask with a nil mask.
38 func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
39         DrawMask(dst, r, src, sp, nil, image.ZP, op)
40 }
41
42 // clip clips r against each image's bounds (after translating into the
43 // destination image's co-ordinate space) and shifts the points sp and mp by
44 // the same amount as the change in r.Min.
45 func clip(dst Image, r *image.Rectangle, src image.Image, sp *image.Point, mask image.Image, mp *image.Point) {
46         orig := r.Min
47         *r = r.Intersect(dst.Bounds())
48         *r = r.Intersect(src.Bounds().Add(orig.Sub(*sp)))
49         if mask != nil {
50                 *r = r.Intersect(mask.Bounds().Add(orig.Sub(*mp)))
51         }
52         dx := r.Min.X - orig.X
53         dy := r.Min.Y - orig.Y
54         if dx == 0 && dy == 0 {
55                 return
56         }
57         (*sp).X += dx
58         (*sp).Y += dy
59         (*mp).X += dx
60         (*mp).Y += dy
61 }
62
63 // DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r
64 // in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque.
65 func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
66         clip(dst, &r, src, &sp, mask, &mp)
67         if r.Empty() {
68                 return
69         }
70
71         // Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation.
72         if dst0, ok := dst.(*image.RGBA); ok {
73                 if op == Over {
74                         if mask == nil {
75                                 switch src0 := src.(type) {
76                                 case *image.ColorImage:
77                                         drawFillOver(dst0, r, src0)
78                                         return
79                                 case *image.RGBA:
80                                         drawCopyOver(dst0, r, src0, sp)
81                                         return
82                                 case *image.NRGBA:
83                                         drawNRGBAOver(dst0, r, src0, sp)
84                                         return
85                                 case *ycbcr.YCbCr:
86                                         drawYCbCr(dst0, r, src0, sp)
87                                         return
88                                 }
89                         } else if mask0, ok := mask.(*image.Alpha); ok {
90                                 switch src0 := src.(type) {
91                                 case *image.ColorImage:
92                                         drawGlyphOver(dst0, r, src0, mask0, mp)
93                                         return
94                                 }
95                         }
96                 } else {
97                         if mask == nil {
98                                 switch src0 := src.(type) {
99                                 case *image.ColorImage:
100                                         drawFillSrc(dst0, r, src0)
101                                         return
102                                 case *image.RGBA:
103                                         drawCopySrc(dst0, r, src0, sp)
104                                         return
105                                 case *image.NRGBA:
106                                         drawNRGBASrc(dst0, r, src0, sp)
107                                         return
108                                 case *ycbcr.YCbCr:
109                                         drawYCbCr(dst0, r, src0, sp)
110                                         return
111                                 }
112                         }
113                 }
114                 drawRGBA(dst0, r, src, sp, mask, mp, op)
115                 return
116         }
117
118         x0, x1, dx := r.Min.X, r.Max.X, 1
119         y0, y1, dy := r.Min.Y, r.Max.Y, 1
120         if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
121                 // Rectangles overlap: process backward?
122                 if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
123                         x0, x1, dx = x1-1, x0-1, -1
124                         y0, y1, dy = y1-1, y0-1, -1
125                 }
126         }
127
128         var out *image.RGBA64Color
129         sy := sp.Y + y0 - r.Min.Y
130         my := mp.Y + y0 - r.Min.Y
131         for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
132                 sx := sp.X + x0 - r.Min.X
133                 mx := mp.X + x0 - r.Min.X
134                 for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
135                         ma := uint32(m)
136                         if mask != nil {
137                                 _, _, _, ma = mask.At(mx, my).RGBA()
138                         }
139                         switch {
140                         case ma == 0:
141                                 if op == Over {
142                                         // No-op.
143                                 } else {
144                                         dst.Set(x, y, zeroColor)
145                                 }
146                         case ma == m && op == Src:
147                                 dst.Set(x, y, src.At(sx, sy))
148                         default:
149                                 sr, sg, sb, sa := src.At(sx, sy).RGBA()
150                                 if out == nil {
151                                         out = new(image.RGBA64Color)
152                                 }
153                                 if op == Over {
154                                         dr, dg, db, da := dst.At(x, y).RGBA()
155                                         a := m - (sa * ma / m)
156                                         out.R = uint16((dr*a + sr*ma) / m)
157                                         out.G = uint16((dg*a + sg*ma) / m)
158                                         out.B = uint16((db*a + sb*ma) / m)
159                                         out.A = uint16((da*a + sa*ma) / m)
160                                 } else {
161                                         out.R = uint16(sr * ma / m)
162                                         out.G = uint16(sg * ma / m)
163                                         out.B = uint16(sb * ma / m)
164                                         out.A = uint16(sa * ma / m)
165                                 }
166                                 dst.Set(x, y, out)
167                         }
168                 }
169         }
170 }
171
172 func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
173         sr, sg, sb, sa := src.RGBA()
174         // The 0x101 is here for the same reason as in drawRGBA.
175         a := (m - sa) * 0x101
176         i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
177         i1 := i0 + r.Dx()*4
178         for y := r.Min.Y; y != r.Max.Y; y++ {
179                 for i := i0; i < i1; i += 4 {
180                         dr := uint32(dst.Pix[i+0])
181                         dg := uint32(dst.Pix[i+1])
182                         db := uint32(dst.Pix[i+2])
183                         da := uint32(dst.Pix[i+3])
184
185                         dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8)
186                         dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8)
187                         dst.Pix[i+2] = uint8((db*a/m + sb) >> 8)
188                         dst.Pix[i+3] = uint8((da*a/m + sa) >> 8)
189                 }
190                 i0 += dst.Stride
191                 i1 += dst.Stride
192         }
193 }
194
195 func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
196         sr, sg, sb, sa := src.RGBA()
197         // The built-in copy function is faster than a straightforward for loop to fill the destination with
198         // the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and
199         // then use the first row as the slice source for the remaining rows.
200         i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
201         i1 := i0 + r.Dx()*4
202         for i := i0; i < i1; i += 4 {
203                 dst.Pix[i+0] = uint8(sr >> 8)
204                 dst.Pix[i+1] = uint8(sg >> 8)
205                 dst.Pix[i+2] = uint8(sb >> 8)
206                 dst.Pix[i+3] = uint8(sa >> 8)
207         }
208         firstRow := dst.Pix[i0:i1]
209         for y := r.Min.Y + 1; y < r.Max.Y; y++ {
210                 i0 += dst.Stride
211                 i1 += dst.Stride
212                 copy(dst.Pix[i0:i1], firstRow)
213         }
214 }
215
216 func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
217         dx, dy := r.Dx(), r.Dy()
218         d0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
219         s0 := (sp.Y-src.Rect.Min.Y)*src.Stride + (sp.X-src.Rect.Min.X)*4
220         var (
221                 ddelta, sdelta int
222                 i0, i1, idelta int
223         )
224         if r.Min.Y < sp.Y || r.Min.Y == sp.Y && r.Min.X <= sp.X {
225                 ddelta = dst.Stride
226                 sdelta = src.Stride
227                 i0, i1, idelta = 0, dx*4, +4
228         } else {
229                 // If the source start point is higher than the destination start point, or equal height but to the left,
230                 // then we compose the rows in right-to-left, bottom-up order instead of left-to-right, top-down.
231                 d0 += (dy - 1) * dst.Stride
232                 s0 += (dy - 1) * src.Stride
233                 ddelta = -dst.Stride
234                 sdelta = -src.Stride
235                 i0, i1, idelta = (dx-1)*4, -4, -4
236         }
237         for ; dy > 0; dy-- {
238                 dpix := dst.Pix[d0:]
239                 spix := src.Pix[s0:]
240                 for i := i0; i != i1; i += idelta {
241                         sr := uint32(spix[i+0]) * 0x101
242                         sg := uint32(spix[i+1]) * 0x101
243                         sb := uint32(spix[i+2]) * 0x101
244                         sa := uint32(spix[i+3]) * 0x101
245
246                         dr := uint32(dpix[i+0])
247                         dg := uint32(dpix[i+1])
248                         db := uint32(dpix[i+2])
249                         da := uint32(dpix[i+3])
250
251                         // The 0x101 is here for the same reason as in drawRGBA.
252                         a := (m - sa) * 0x101
253
254                         dpix[i+0] = uint8((dr*a/m + sr) >> 8)
255                         dpix[i+1] = uint8((dg*a/m + sg) >> 8)
256                         dpix[i+2] = uint8((db*a/m + sb) >> 8)
257                         dpix[i+3] = uint8((da*a/m + sa) >> 8)
258                 }
259                 d0 += ddelta
260                 s0 += sdelta
261         }
262 }
263
264 func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
265         n, dy := 4*r.Dx(), r.Dy()
266         d0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
267         s0 := (sp.Y-src.Rect.Min.Y)*src.Stride + (sp.X-src.Rect.Min.X)*4
268         var ddelta, sdelta int
269         if r.Min.Y <= sp.Y {
270                 ddelta = dst.Stride
271                 sdelta = src.Stride
272         } else {
273                 // If the source start point is higher than the destination start point, then we compose the rows
274                 // in bottom-up order instead of top-down. Unlike the drawCopyOver function, we don't have to
275                 // check the x co-ordinates because the built-in copy function can handle overlapping slices.
276                 d0 += (dy - 1) * dst.Stride
277                 s0 += (dy - 1) * src.Stride
278                 ddelta = -dst.Stride
279                 sdelta = -src.Stride
280         }
281         for ; dy > 0; dy-- {
282                 copy(dst.Pix[d0:d0+n], src.Pix[s0:s0+n])
283                 d0 += ddelta
284                 s0 += sdelta
285         }
286 }
287
288 func drawNRGBAOver(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
289         i0 := (r.Min.X - dst.Rect.Min.X) * 4
290         i1 := (r.Max.X - dst.Rect.Min.X) * 4
291         si0 := (sp.X - src.Rect.Min.X) * 4
292         yMax := r.Max.Y - dst.Rect.Min.Y
293
294         y := r.Min.Y - dst.Rect.Min.Y
295         sy := sp.Y - src.Rect.Min.Y
296         for ; y != yMax; y, sy = y+1, sy+1 {
297                 dpix := dst.Pix[y*dst.Stride:]
298                 spix := src.Pix[sy*src.Stride:]
299
300                 for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
301                         // Convert from non-premultiplied color to pre-multiplied color.
302                         sa := uint32(spix[si+3]) * 0x101
303                         sr := uint32(spix[si+0]) * sa / 0xff
304                         sg := uint32(spix[si+1]) * sa / 0xff
305                         sb := uint32(spix[si+2]) * sa / 0xff
306
307                         dr := uint32(dpix[i+0])
308                         dg := uint32(dpix[i+1])
309                         db := uint32(dpix[i+2])
310                         da := uint32(dpix[i+3])
311
312                         // The 0x101 is here for the same reason as in drawRGBA.
313                         a := (m - sa) * 0x101
314
315                         dpix[i+0] = uint8((dr*a/m + sr) >> 8)
316                         dpix[i+1] = uint8((dg*a/m + sg) >> 8)
317                         dpix[i+2] = uint8((db*a/m + sb) >> 8)
318                         dpix[i+3] = uint8((da*a/m + sa) >> 8)
319                 }
320         }
321 }
322
323 func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
324         i0 := (r.Min.X - dst.Rect.Min.X) * 4
325         i1 := (r.Max.X - dst.Rect.Min.X) * 4
326         si0 := (sp.X - src.Rect.Min.X) * 4
327         yMax := r.Max.Y - dst.Rect.Min.Y
328
329         y := r.Min.Y - dst.Rect.Min.Y
330         sy := sp.Y - src.Rect.Min.Y
331         for ; y != yMax; y, sy = y+1, sy+1 {
332                 dpix := dst.Pix[y*dst.Stride:]
333                 spix := src.Pix[sy*src.Stride:]
334
335                 for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
336                         // Convert from non-premultiplied color to pre-multiplied color.
337                         sa := uint32(spix[si+3]) * 0x101
338                         sr := uint32(spix[si+0]) * sa / 0xff
339                         sg := uint32(spix[si+1]) * sa / 0xff
340                         sb := uint32(spix[si+2]) * sa / 0xff
341
342                         dpix[i+0] = uint8(sr >> 8)
343                         dpix[i+1] = uint8(sg >> 8)
344                         dpix[i+2] = uint8(sb >> 8)
345                         dpix[i+3] = uint8(sa >> 8)
346                 }
347         }
348 }
349
350 func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Point) {
351         // A YCbCr image is always fully opaque, and so if the mask is implicitly nil
352         // (i.e. fully opaque) then the op is effectively always Src.
353         var (
354                 yy, cb, cr uint8
355         )
356         x0 := (r.Min.X - dst.Rect.Min.X) * 4
357         x1 := (r.Max.X - dst.Rect.Min.X) * 4
358         y0 := r.Min.Y - dst.Rect.Min.Y
359         y1 := r.Max.Y - dst.Rect.Min.Y
360         switch src.SubsampleRatio {
361         case ycbcr.SubsampleRatio422:
362                 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
363                         dpix := dst.Pix[y*dst.Stride:]
364                         for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
365                                 i := sx / 2
366                                 yy = src.Y[sy*src.YStride+sx]
367                                 cb = src.Cb[sy*src.CStride+i]
368                                 cr = src.Cr[sy*src.CStride+i]
369                                 rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
370                                 dpix[x+0] = rr
371                                 dpix[x+1] = gg
372                                 dpix[x+2] = bb
373                                 dpix[x+3] = 255
374                         }
375                 }
376         case ycbcr.SubsampleRatio420:
377                 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
378                         dpix := dst.Pix[y*dst.Stride:]
379                         for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
380                                 i, j := sx/2, sy/2
381                                 yy = src.Y[sy*src.YStride+sx]
382                                 cb = src.Cb[j*src.CStride+i]
383                                 cr = src.Cr[j*src.CStride+i]
384                                 rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
385                                 dpix[x+0] = rr
386                                 dpix[x+1] = gg
387                                 dpix[x+2] = bb
388                                 dpix[x+3] = 255
389                         }
390                 }
391         default:
392                 // Default to 4:4:4 subsampling.
393                 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
394                         dpix := dst.Pix[y*dst.Stride:]
395                         for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
396                                 yy = src.Y[sy*src.YStride+sx]
397                                 cb = src.Cb[sy*src.CStride+sx]
398                                 cr = src.Cr[sy*src.CStride+sx]
399                                 rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
400                                 dpix[x+0] = rr
401                                 dpix[x+1] = gg
402                                 dpix[x+2] = bb
403                                 dpix[x+3] = 255
404                         }
405                 }
406         }
407 }
408
409 func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage, mask *image.Alpha, mp image.Point) {
410         i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
411         i1 := i0 + r.Dx()*4
412         mi0 := (mp.Y-mask.Rect.Min.Y)*mask.Stride + mp.X - mask.Rect.Min.X
413         sr, sg, sb, sa := src.RGBA()
414         for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 {
415                 for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 {
416                         ma := uint32(mask.Pix[mi])
417                         if ma == 0 {
418                                 continue
419                         }
420                         ma |= ma << 8
421
422                         dr := uint32(dst.Pix[i+0])
423                         dg := uint32(dst.Pix[i+1])
424                         db := uint32(dst.Pix[i+2])
425                         da := uint32(dst.Pix[i+3])
426
427                         // The 0x101 is here for the same reason as in drawRGBA.
428                         a := (m - (sa * ma / m)) * 0x101
429
430                         dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
431                         dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
432                         dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
433                         dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
434                 }
435                 i0 += dst.Stride
436                 i1 += dst.Stride
437                 mi0 += mask.Stride
438         }
439 }
440
441 func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
442         x0, x1, dx := r.Min.X, r.Max.X, 1
443         y0, y1, dy := r.Min.Y, r.Max.Y, 1
444         if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
445                 if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
446                         x0, x1, dx = x1-1, x0-1, -1
447                         y0, y1, dy = y1-1, y0-1, -1
448                 }
449         }
450
451         sy := sp.Y + y0 - r.Min.Y
452         my := mp.Y + y0 - r.Min.Y
453         sx0 := sp.X + x0 - r.Min.X
454         mx0 := mp.X + x0 - r.Min.X
455         sx1 := sx0 + (x1 - x0)
456         i0 := (y0-dst.Rect.Min.Y)*dst.Stride + (x0-dst.Rect.Min.X)*4
457         di := dx * 4
458         for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
459                 for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
460                         ma := uint32(m)
461                         if mask != nil {
462                                 _, _, _, ma = mask.At(mx, my).RGBA()
463                         }
464                         sr, sg, sb, sa := src.At(sx, sy).RGBA()
465                         if op == Over {
466                                 dr := uint32(dst.Pix[i+0])
467                                 dg := uint32(dst.Pix[i+1])
468                                 db := uint32(dst.Pix[i+2])
469                                 da := uint32(dst.Pix[i+3])
470
471                                 // dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
472                                 // We work in 16-bit color, and so would normally do:
473                                 // dr |= dr << 8
474                                 // and similarly for dg, db and da, but instead we multiply a
475                                 // (which is a 16-bit color, ranging in [0,65535]) by 0x101.
476                                 // This yields the same result, but is fewer arithmetic operations.
477                                 a := (m - (sa * ma / m)) * 0x101
478
479                                 dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
480                                 dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
481                                 dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
482                                 dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
483
484                         } else {
485                                 dst.Pix[i+0] = uint8(sr * ma / m >> 8)
486                                 dst.Pix[i+1] = uint8(sg * ma / m >> 8)
487                                 dst.Pix[i+2] = uint8(sb * ma / m >> 8)
488                                 dst.Pix[i+3] = uint8(sa * ma / m >> 8)
489                         }
490                 }
491                 i0 += dy * dst.Stride
492         }
493 }