Golang – 使用Image和Image / PNG交换图片的PNG频道
我正在尝试写一个短的,它将读取一个PNG文件,并交换一个通道与另一个(R,G,B)是可能的选择.
然而,我无法找到如何从image.At(x,y)返回的color.Color对象中提取整数.一旦我可以使用交换的通道构造新的RGBA颜色,使用image.Set(x,y,color)将其写回可能会更容易. 我现在在这里(你可以跳到最后一个循环): package main import ( "flag" "fmt" //"image" "image/color" "image/png" "os" ) type Choice struct { value string valid bool } func (c *Choice) validate() { goodchoices := []string{"R","G","B"} for _,v := range goodchoices { if c.value == v { c.valid = true } } } func main() { var fname string var c1 Choice var c2 Choice flag.StringVar(&c1.value,"c1","","The color channel to swap - R or G or B ") flag.StringVar(&c2.value,"c2","The color channel to swap with - R or G or B ") flag.StringVar(&fname,"f","A .png image (normal map)") flag.Parse() c1.validate() c2.validate() if c1.valid == true && c2.valid == true { fmt.Println("We could proceed..") fmt.Println("Swapping channels:",c1.value,"<->",c2.value,"In",fname) //for testing } else { fmt.Println("Invalid channel... Please use R,G or B.") return } file,err := os.Open(fname) if err != nil { fmt.Println(err) return } defer file.Close() pic,err := png.Decode(file) if err != nil { fmt.Fprintf(os.Stderr,"%s: %vn",fname,err) return } b := pic.Bounds() for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { col := pic.At(x,y) ???? How do I swap the channels in col ???? } } } 我是Go和编程的新手,所以请在你的答案中考虑一下.谢谢. 解决方法
嗯,这比我想象的要难 – 我想知道是否有人能想出更好的主意!
问题是你不知道png.Decode返回的具体类型 – 它可能返回任何图像类型.您只有一个image.Image接口,它没有Set方法. 为了解决这个问题,首先要定义一个可以设置像素的所有图像类型都满足的接口 type ImageSet interface { Set(x,y int,c color.Color) } 接下来看看pic是否实现了该接口(如果没有,则会发生恐慌 – 使用picSet,如果困扰你,请使用ok表单) // Get an interface which can set pixels picSet := pic.(ImageSet) 现在你的循环看起来像这样 – 我只交换了红色和绿色,所以你可以看到这个想法. for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { col := pic.At(x,y) r,g,b,a := col.RGBA() // Swap green and red newCol := color.RGBA{uint8(g>>8),uint8(r>>8),uint8(b>>8),uint8(a>>8)} picSet.Set(x,newCol) } } 我怀疑这个高性能版本必须使用类型开关来确定它是哪种图像类型,然后为每个图像类型定制代码,其中uint8s用于24位图像,uint16s用于48位图像等. Here is the complete working例如果你想要去.虽然它在游乐场不起作用 – 你必须下载它. 更新:刚刚注意到您的评论.如果你知道你有一个RGBA图像,那么你可以使用一个类型断言来获取底层图像,这使得事情变得更加容易. // Get an image.RGBA if it is one rgba,ok := pic.(*image.RGBA) if !ok { fmt.Println("That wasn't an RGBA!") return } for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { // Note type assertion to get a color.RGBA col := rgba.At(x,y).(color.RGBA) // Swap green and red col.G,col.R = col.R,col.G rgba.Set(x,col) } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |