OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [image/] [draw/] [draw.go] - Blame information for rev 747

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.