star/image/image.go
2025-06-13 13:05:50 +08:00

291 lines
7.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package image
import (
"encoding/hex"
"fmt"
"image"
"image/color"
"sort"
"b612.me/starlog"
"github.com/spf13/cobra"
)
var useHex bool
var useAlpha bool
var useCount int
var ckt uint8
var fromRgb string
var toRgb string
func init() {
Cmd.AddCommand(imgMirrorCmd, imgRgbCountCmd, imgReplaceCmd, imgReverseCmd, CmdExifRead)
imgRgbCountCmd.Flags().BoolVarP(&useHex, "hex", "x", false, "使用十六进制表示")
imgRgbCountCmd.Flags().BoolVarP(&useAlpha, "alpha", "a", false, "统计alpha通道")
imgRgbCountCmd.Flags().IntVarP(&useCount, "count", "c", 10, "显示数量")
imgReplaceCmd.Flags().Uint8VarP(&ckt, "ckt", "k", 30, "颜色比较阈值")
imgReplaceCmd.Flags().StringVarP(&fromRgb, "from", "f", "dfdfdf", "需要替换的颜色")
imgReplaceCmd.Flags().StringVarP(&toRgb, "to", "t", "ffffff", "替换为的颜色")
}
var Cmd = &cobra.Command{
Use: "image",
Short: "图像处理",
Long: "简单的图像处理工具",
Run: func(this *cobra.Command, args []string) {
this.Help()
},
}
var imgMirrorCmd = &cobra.Command{
Use: "mirror",
Short: "图像镜像翻转",
Long: "图像镜像翻转<水平>",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要转换的图像!")
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
size := img.Bounds()
nimg := image.NewRGBA(size)
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
nimg.Set(size.Dx()-x, y, img.At(x, y))
}
}
if err := SavePhoto(v, nimg); err != nil {
starlog.Errorln(err, v)
continue
} else {
fmt.Println(v, "转换已完成!")
}
}
fmt.Println("任务完成!")
},
}
var imgAlpha = &cobra.Command{
Use: "alpha",
Short: "设置透明度",
Long: "设置alpha通道透明度",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要转换的图像!")
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
img = SetAlpha(img, 4)
if err := SavePhoto(v, img); err != nil {
starlog.Errorln(err, v)
continue
} else {
fmt.Println(v, "转换已完成!")
}
}
fmt.Println("任务完成!")
},
}
var imgRgbCountCmd = &cobra.Command{
Use: "rgbcount",
Short: "统计最多的rgb值",
Long: "统计最多的RGB值",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要统计的图像!")
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
size := img.Bounds()
colorMap := make(map[string]int)
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
color := img.At(x, y)
r, g, b, a := color.RGBA()
var key string
if useAlpha {
if !useHex {
key = fmt.Sprintf("%d,%d,%d,%d", uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
} else {
key = fmt.Sprintf("%x%x%x%x", uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
}
} else {
if !useHex {
key = fmt.Sprintf("%d,%d,%d", uint8(r>>8), uint8(g>>8), uint8(b>>8))
} else {
key = fmt.Sprintf("%x%x%x", uint8(r>>8), uint8(g>>8), uint8(b>>8))
}
}
if _, ok := colorMap[key]; ok {
colorMap[key]++
} else {
colorMap[key] = 1
}
}
}
colorSlice := make([]struct {
string
int
}, 0, len(colorMap))
for k, v := range colorMap {
colorSlice = append(colorSlice, struct {
string
int
}{k, v})
}
sort.Slice(colorSlice, func(i, j int) bool {
return colorSlice[i].int > colorSlice[j].int
})
fmt.Println(v)
for i := 0; i < useCount && i < len(colorSlice); i++ {
fmt.Printf("%d. %s: %d\n", i+1, colorSlice[i].string, colorSlice[i].int)
}
fmt.Println("----------------")
}
fmt.Println("任务完成!")
},
}
var imgReplaceCmd = &cobra.Command{
Use: "replace",
Short: "图像RGB替换",
Long: "图像RGB替换",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要转换的图像!")
return
}
r, g, b, err := HexToRGB(fromRgb)
if err != nil {
starlog.Errorln(err)
return
}
nr, ng, nb, err := HexToRGB(toRgb)
if err != nil {
starlog.Errorln(err)
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
size := img.Bounds()
nimg := image.NewRGBA(size)
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
mR, mG, mB, ma := img.At(x, y).RGBA()
mr, mg, mb := uint8(mR>>8), uint8(mG>>8), uint8(mB>>8)
nimg.Set(x, y, img.At(x, y))
if mr-r < ckt || r-mr < ckt {
if mg-g < ckt || g-mg < ckt {
if mb-b < ckt || b-mb < ckt {
nimg.Set(x, y, color.NRGBA{nr, ng, nb, uint8(ma >> 8)})
}
}
}
}
}
if err := SavePhoto("new-"+v, nimg); err != nil {
starlog.Errorln(err, v)
continue
} else {
fmt.Println(v, "转换已完成!")
}
}
fmt.Println("任务完成!")
},
}
func HexToRGB(hexStr string) (uint8, uint8, uint8, error) {
// 检查输入长度是否为6
if len(hexStr) != 6 {
return 0, 0, 0, fmt.Errorf("invalid hex color string: %s", hexStr)
}
// 将16进制字符串解码为字节数组
decoded, err := hex.DecodeString(hexStr)
if err != nil {
return 0, 0, 0, fmt.Errorf("failed to decode hex string: %v", err)
}
// 解码结果应该有3个字节
if len(decoded) != 3 {
return 0, 0, 0, fmt.Errorf("invalid hex color format: %s", hexStr)
}
// 返回三个通道值
return decoded[0], decoded[1], decoded[2], nil
}
var imgReverseCmd = &cobra.Command{
Use: "reverse",
Short: "图像反色",
Long: "图像反色",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要转换的图像!")
return
}
for _, v := range args {
img, err := OpenImage(v)
if err != nil {
starlog.Errorln(err, v)
continue
}
size := img.Bounds()
nimg := image.NewRGBA(size)
for x := 0; x < size.Dx(); x++ {
for y := 0; y < size.Dy(); y++ {
r, g, b, a := img.At(x, y).RGBA()
nimg.Set(x, y, color.NRGBA{uint8(255 - r>>8), uint8(255 - g>>8), uint8(255 - b>>8), uint8(a >> 8)})
}
}
if err := SavePhoto("reverse-"+v, nimg); err != nil {
starlog.Errorln(err, v)
continue
} else {
fmt.Println(v, "转换已完成!")
}
}
fmt.Println("任务完成!")
},
}
var CmdExifRead = &cobra.Command{
Use: "exifread",
Short: "读取图像Exif信息",
Long: "读取图像Exif信息输出为表格格式",
Run: func(this *cobra.Command, args []string) {
if len(args) == 0 {
starlog.Errorln("请指定需要读取Exif信息的图像")
return
}
for _, v := range args {
if err := Exif(v); err != nil {
starlog.Errorln(err, v)
continue
}
fmt.Println(v, "Exif信息读取完成")
}
fmt.Println("任务完成!")
},
}