-
Notifications
You must be signed in to change notification settings - Fork 1
/
rotate.go
75 lines (70 loc) · 1.96 KB
/
rotate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package imagescaling
import (
"image"
"runtime"
"sync"
)
type RotateMode int
const(
Rotate90Degrees RotateMode = 90
Rotate180Degrees RotateMode = 180
Rotate270Degrees RotateMode = 270
)
func (m *Image) Rotate(r RotateMode) *Image {
if m.err != nil {
return m
}
if m.opImage == nil {
m.opImage = m.image
}
var wImg, hImg int
switch r {
case Rotate90Degrees, Rotate270Degrees:
wImg = m.opImage.Bounds().Dy()
hImg = m.opImage.Bounds().Dx()
case Rotate180Degrees:
wImg = m.opImage.Bounds().Dx()
hImg = m.opImage.Bounds().Dy()
default:
m.err = ERRUNKNOWROTATEMODE
return m
}
rowSize := wImg * 4
m.tempImage = image.NewNRGBA(image.Rect(0, 0, wImg, hImg))
procs := runtime.GOMAXPROCS(0)
if procs > hImg {
procs = hImg
}
c := make(chan int, hImg)
for i:=0; i< hImg; i++{
c <- i
}
close(c)
var wg sync.WaitGroup
for i := 0; i < procs; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for nh := range c {
i := nh * m.tempImage.Stride
switch r {
case Rotate90Degrees:
srcX := nh
m.adjust(srcX, 0, srcX+1, m.opImage.Bounds().Max.Y, m.tempImage.Pix[i:i+rowSize])
reverse(m.tempImage.Pix[i : i+rowSize])
case Rotate180Degrees:
srcY := m.opImage.Bounds().Max.Y - nh - 1
m.adjust(0, srcY, m.opImage.Bounds().Max.X, srcY+1, m.tempImage.Pix[i:i+rowSize])
reverse(m.tempImage.Pix[i : i+rowSize])
case Rotate270Degrees:
srcX := hImg - nh - 1
m.adjust(srcX, 0, srcX+1, m.opImage.Bounds().Max.Y, m.tempImage.Pix[i:i+rowSize])
}
}
}()
}
wg.Wait()
m.opImage = m.tempImage
m.tempImage = nil
return m
}