291 lines
7.0 KiB
Go
291 lines
7.0 KiB
Go
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("任务完成!")
|
||
},
|
||
}
|