-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtransform.go
More file actions
89 lines (81 loc) · 2.67 KB
/
transform.go
File metadata and controls
89 lines (81 loc) · 2.67 KB
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package xtx
import (
"image"
"image/color"
"golang.org/x/image/draw"
)
// Resize scales img to the given width and height using bilinear
// interpolation. For aspect-ratio-preserving variants,
// use ResizeToWidth or ResizeToHeight.
func Resize(img image.Image, width, height int) *image.RGBA {
if width < 1 {
width = 1
}
if height < 1 {
height = 1
}
dst := image.NewRGBA(image.Rect(0, 0, width, height))
draw.ApproxBiLinear.Scale(dst, dst.Bounds(), img, img.Bounds(), draw.Over, nil)
return dst
}
// ResizeToWidth scales img so its width equals targetWidth, maintaining
// the original aspect ratio. Uses bilinear interpolation.
func ResizeToWidth(img image.Image, targetWidth int) *image.RGBA {
bounds := img.Bounds()
srcW, srcH := bounds.Dx(), bounds.Dy()
if srcW == targetWidth {
// Convert to RGBA if needed.
dst := image.NewRGBA(bounds)
draw.Draw(dst, bounds, img, bounds.Min, draw.Src)
return dst
}
targetHeight := srcH * targetWidth / srcW
return Resize(img, targetWidth, targetHeight)
}
// ResizeToHeight scales img so its height equals targetHeight, maintaining
// the original aspect ratio. Uses bilinear interpolation.
func ResizeToHeight(img image.Image, targetHeight int) *image.RGBA {
bounds := img.Bounds()
srcW, srcH := bounds.Dx(), bounds.Dy()
if srcH == targetHeight {
dst := image.NewRGBA(bounds)
draw.Draw(dst, bounds, img, bounds.Min, draw.Src)
return dst
}
targetWidth := srcW * targetHeight / srcH
return Resize(img, targetWidth, targetHeight)
}
// RotateCW rotates an image 90° clockwise.
// A W×H image becomes H×W.
func RotateCW(img image.Image) *image.RGBA {
bounds := img.Bounds()
w, h := bounds.Dx(), bounds.Dy()
dst := image.NewRGBA(image.Rect(0, 0, h, w))
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
// Source (x,y) → destination (h-1-(y-minY), x-minX)
dst.Set(h-1-(y-bounds.Min.Y), x-bounds.Min.X, img.At(x, y))
}
}
return dst
}
// RotateCCW rotates an image 90° counter-clockwise.
// A W×H image becomes H×W.
func RotateCCW(img image.Image) *image.RGBA {
bounds := img.Bounds()
w, h := bounds.Dx(), bounds.Dy()
dst := image.NewRGBA(image.Rect(0, 0, h, w))
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
// Source (x,y) → destination (y-minY, w-1-(x-minX))
dst.Set(y-bounds.Min.Y, w-1-(x-bounds.Min.X), img.At(x, y))
}
}
return dst
}
// NewWhitePage creates a new RGBA image of the given dimensions filled with white.
func NewWhitePage(w, h int) *image.RGBA {
page := image.NewRGBA(image.Rect(0, 0, w, h))
draw.Draw(page, page.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
return page
}