2013-02-01 16 views
5

का उपयोग कर एक तस्वीर के स्वैप पीएनजी चैनल मैं एक छोटा लिखने की कोशिश कर रहा हूं, जो एक पीएनजी फ़ाइल पढ़ेगा, और एक चैनल को दूसरे (आर, जी, बी) के साथ स्वैप करेगा संभावित विकल्पगोलांग - छवि और छवि/पीएनजी

हालांकि, मुझे रंग से पूर्णांक निकालने का तरीका नहीं पता है। छवि वस्तु द्वारा लौटाया गया ऑब्जेक्ट। (X, y)। इसे वापस लिखना शायद छवि के साथ आसान होगा। सेट (एक्स, वाई, रंग) एक बार मैं स्वैप किए गए चैनलों के साथ नया आरजीबीए रंग बना सकता हूं।

यहाँ मैं अब (आप काफी पिछले पाश करने के लिए छोड़ सकते हैं) हूँ:

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: %v\n", 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 ???? 
    } 
} 
} 

मैं वास्तव में नए जाने के लिए और प्रोग्रामिंग सामान्य रूप में है, तो आपका जवाब में यह विचार करें हूँ। धन्यवाद।

+1

मैं आरजीबीए पीएनजी छवियों का उपयोग कर रहा हूं (वे ब्लेंडर 3 डी से निर्यात किए गए सामान्य मानचित्र हैं)। – Zoltan

उत्तर

7

हमम, जो मैंने सोचा था उससे कठिन था - मुझे आश्चर्य है कि कोई भी बेहतर विचार के साथ आ सकता है!

समस्या यह है कि आप ठोस प्रकार को नहीं जानते हैं कि png.Decode रिटर्न - यह किसी भी छवि प्रकार को वापस कर सकता है। आपके पास केवल image.Image इंटरफ़ेस है जिसमें सेट विधि नहीं है।

दौर है कि प्राप्त करने के लिए, पहले एक इंटरफेस है जो सभी चित्र प्रकार जो पिक्सल सेट कर सकते हैं संतुष्ट

type ImageSet interface { 
    Set(x, y int, c color.Color) 
} 

अगला देख pic कि इंटरफेस (अगर यह नहीं है आतंक जाएगा जाना लागू करता है कि क्या परिभाषित - picSet का उपयोग , ठीक है फार्म का है कि अगर आप परेशान)

// 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, y, newCol) 
    } 
} 

मुझे लगता है कि इस बात का कोई उच्च प्रदर्शन संस्करण एक प्रकार स्विच का उपयोग करने के लिए निर्धारित करने के लिए जो छवि प्रकार यह था होता है, तो 48 बिट के लिए 24 बिट छवियों के लिए uint8s और uint16s साथ हर एक के लिए एक स्वनिर्धारित कोड है छवियों आदि

Here is the complete working उदाहरण यदि आप जाना चाहते हैं। हालांकि यह खेल के मैदान में काम नहीं करता है - आपको इसे डाउनलोड करना होगा।


अद्यतन: बस अपनी टिप्पणी देखा। यदि आप जानते हैं कि आपके पास आरजीबीए छवि है, तो आप अंतर्निहित छवि प्राप्त करने के लिए एक प्रकार का दावा कर सकते हैं जो चीजों को एक बहुत आसान बनाता है।

// 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, y, col) 
    } 
} 
+0

बिल्कुल वही जो मैं खोज रहा था .. बहुत बहुत धन्यवाद! पैलेट की गई छवियों के साथ अतिरिक्त काम के लिए खेद है .. :) मुझे इसे पोस्ट के मुख्य भाग में शामिल करना चाहिए था। बहुत बढ़िया। जिज्ञासा से बाहर: ऐसा लगता है कि मुझे आंतरिक लूप के अंदर एक स्विच/केस टेस्ट लिखना है, यह जांचने के लिए कि हमने किस चैनल को प्रतिस्थापित करना चुना है .. यह महसूस करता है (बहुत) अक्षम .. क्या कोई और तरीका हो सकता है? – Zoltan

+0

केवल 3 संभावित स्विच हैं जो आप कर सकते हैं, इसलिए मैं उन कार्यों को करने के लिए 3 फ़ंक्शन लिखूंगा और काम करने के लिए कार्यों की एक तालिका का उपयोग कर सकता हूं। (या फ़ंक्शन पॉइंटर का चयन करने के लिए स्विच का उपयोग करें)। फिर आप चुने हुए फ़ंक्शन को लूप में पॉइंटर के माध्यम से कॉल कर सकते हैं जो अच्छा और तेज़ होगा। –

+0

वास्तव में .. धन्यवाद फिर से! – Zoltan

संबंधित मुद्दे