Skip to content

Commit

Permalink
transform: optimize arbitrary angle rotation for multiples of 90 degrees
Browse files Browse the repository at this point in the history
  • Loading branch information
disintegration committed Aug 6, 2017
1 parent 01751ce commit a585802
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 0 deletions.
13 changes: 13 additions & 0 deletions transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,19 @@ func Rotate270(img image.Image) *image.NRGBA {
// The angle parameter is the rotation angle in degrees.
// The bgColor parameter specifies the color of the uncovered zone after the rotation.
func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA {
angle = angle - math.Floor(angle/360)*360

switch angle {
case 0:
return Clone(img)
case 90:
return Rotate90(img)
case 180:
return Rotate180(img)
case 270:
return Rotate270(img)
}

src := toNRGBA(img)
srcW := src.Bounds().Max.X
srcH := src.Bounds().Max.Y
Expand Down
164 changes: 164 additions & 0 deletions transform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,170 @@ func TestRotate(t *testing.T) {
},
},
},
{
"Rotate -360*10",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff,
},
},
-360 * 10,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff,
},
},
},
{
"Rotate -360*10 + 90",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
},
},
-360*10 + 90,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 1),
Stride: 2 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
},
},
},
{
"Rotate -360*10 + 180",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
},
},
-360*10 + 180,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff,
},
},
},
{
"Rotate -360*10 + 270",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
},
},
-360*10 + 270,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
},
},
},
{
"Rotate 360*10",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff,
},
},
360 * 10,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff,
},
},
},
{
"Rotate 360*10 + 90",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
},
},
360*10 + 90,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 1),
Stride: 2 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
},
},
},
{
"Rotate 360*10 + 180",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
},
},
360*10 + 180,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 1, 2),
Stride: 1 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff,
0xff, 0x00, 0x00, 0xff,
},
},
},
{
"Rotate 360*10 + 270",
&image.NRGBA{
Rect: image.Rect(-1, -1, 0, 1),
Stride: 1 * 4,
Pix: []uint8{
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
},
},
360*10 + 270,
color.Black,
&image.NRGBA{
Rect: image.Rect(0, 0, 2, 1),
Stride: 2 * 4,
Pix: []uint8{
0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
},
},
},
}
for _, test := range testCases {
got := Rotate(test.src, test.angle, test.bg)
Expand Down

0 comments on commit a585802

Please sign in to comment.