go lang image scale and add watermark
This commit is contained in:
10
image-scale-and-addwatermark/go.mod
Normal file
10
image-scale-and-addwatermark/go.mod
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
module hatter.ink/tool/image-scale-and-addwatermark
|
||||||
|
|
||||||
|
go 1.25.5
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||||
|
golang.org/x/image v0.36.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/x/text v0.34.0 // indirect
|
||||||
6
image-scale-and-addwatermark/go.sum
Normal file
6
image-scale-and-addwatermark/go.sum
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
|
golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
|
||||||
|
golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
|
||||||
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
136
image-scale-and-addwatermark/main.go
Normal file
136
image-scale-and-addwatermark/main.go
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
"image/jpeg"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/nfnt/resize"
|
||||||
|
"golang.org/x/image/font"
|
||||||
|
"golang.org/x/image/font/opentype"
|
||||||
|
"golang.org/x/image/math/fixed"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addWatermark(img *image.RGBA, text string, textColor color.Color, bgColor color.Color) {
|
||||||
|
fontData, err := os.ReadFile("/System/Library/Fonts/Courier.ttc")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error loading font:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ttCollection, err := opentype.ParseCollection(fontData)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error parsing font collection:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ttFont, err := ttCollection.Font(0)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error getting font from collection:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fontSize := 20.0
|
||||||
|
face, err := opentype.NewFace(ttFont, &opentype.FaceOptions{
|
||||||
|
Size: fontSize,
|
||||||
|
DPI: 72,
|
||||||
|
Hinting: font.HintingFull,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error creating face:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算文字尺寸
|
||||||
|
d := &font.Drawer{
|
||||||
|
Dst: img,
|
||||||
|
Src: image.NewUniform(textColor),
|
||||||
|
Face: face,
|
||||||
|
Dot: fixed.Point26_6{},
|
||||||
|
}
|
||||||
|
textBounds := d.MeasureString(text)
|
||||||
|
textWidth := int(textBounds.Ceil())
|
||||||
|
textHeight := int(face.Metrics().Height.Ceil())
|
||||||
|
|
||||||
|
// 设置水印文字的位置为右下角,添加内边距
|
||||||
|
padding := 8
|
||||||
|
x := img.Bounds().Max.X - textWidth - padding
|
||||||
|
y := img.Bounds().Max.Y - padding - textHeight/2 + 4
|
||||||
|
|
||||||
|
// 绘制背景矩形(上下左右居中于文字)
|
||||||
|
bgRect := image.Rect(x-padding/2, y-textHeight/2-padding/2+4, x+textWidth+padding/2, y+textHeight/2+padding/2)
|
||||||
|
draw.Draw(img, bgRect, image.NewUniform(bgColor), image.Point{}, draw.Src)
|
||||||
|
|
||||||
|
// 绘制文字
|
||||||
|
d.Dot = fixed.Point26_6{X: fixed.I(x), Y: fixed.I(y + 8)}
|
||||||
|
d.DrawString(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inputImagePath := "input.jpg" // 输入图片路径
|
||||||
|
outputImagePath := "output.jpg" // 输出图片路径
|
||||||
|
|
||||||
|
maxSize := 1200 // 默认最大尺寸
|
||||||
|
|
||||||
|
file, err := os.Open(inputImagePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error opening file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
img, _, err := image.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error decoding image:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds := img.Bounds()
|
||||||
|
width := bounds.Max.X
|
||||||
|
height := bounds.Max.Y
|
||||||
|
fmt.Printf("Image %s, width: %d, height: %d\n", inputImagePath, width, height)
|
||||||
|
|
||||||
|
var resizedImg image.Image
|
||||||
|
if width > maxSize && height > maxSize {
|
||||||
|
if width < height {
|
||||||
|
resizedImg = resize.Resize(uint(maxSize), 0, img, resize.Lanczos3)
|
||||||
|
} else {
|
||||||
|
resizedImg = resize.Resize(0, uint(maxSize), img, resize.Lanczos3)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resizedImg = img
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将图片转换为 RGBA 格式以便添加水印
|
||||||
|
rgbaImg := image.NewRGBA(resizedImg.Bounds())
|
||||||
|
if rgbaImg.Stride != rgbaImg.Rect.Size().X*4 {
|
||||||
|
fmt.Println("Unsupported image format")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for y := rgbaImg.Rect.Min.Y; y < rgbaImg.Rect.Max.Y; y++ {
|
||||||
|
for x := rgbaImg.Rect.Min.X; x < rgbaImg.Rect.Max.X; x++ {
|
||||||
|
rgbaImg.Set(x, y, resizedImg.At(x, y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加水印(使用柔和的深灰色文字和米白色背景)
|
||||||
|
softTextColor := color.RGBA{R: 60, G: 60, B: 60, A: 255}
|
||||||
|
softBgColor := color.RGBA{R: 250, G: 250, B: 245, A: 255}
|
||||||
|
addWatermark(rgbaImg, "email@example.com", softTextColor, softBgColor)
|
||||||
|
|
||||||
|
outFile, err := os.Create(outputImagePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error creating file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
err = jpeg.Encode(outFile, rgbaImg, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error encoding image:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Image processed and saved as", filepath.Base(outputImagePath))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user