2015-05-14 48 views
1

今年夏天我正在做一些Go圖像包和我的空閒時間練習。使用Image.Image或* image.RGBA的Set()方法

package main 

import (

    "os" 
    "image" 
    "image/png" 
    "image/color" 
    "log" 
    "fmt" 
    "reflect" 

) 

func main(){ 

    file , err := os.OpenFile("C:/Sources/go3x3.png", os.O_RDWR, os.FileMode(0777)) 
    if err != nil { 
     log.Fatal(err) 
    } 

    img , err := png.Decode(file) 
    if err != nil { 
     log.Fatal(err) 
    } 


    img.At(0,0).RGBA() 
    fmt.Println("type:", reflect.TypeOf(img)) 

    m := image.NewRGBA(image.Rect(0, 0, 640, 480)) 
    fmt.Println("type:", reflect.TypeOf(m)) 
    m.Set(5, 5, color.RGBA{255, 0, 0, 255}) 
    img.Set(0, 0, color.RGBA{136, 0, 21, 255}) 
} 

這裏的問題是,當我註釋掉img.Set運行它,我得到這樣的結果

type: *image.RGBA 
type: *image.RGBA 

,但是當它註釋掉我得到一個錯誤說

img.Set undefined (type image.Image has no field or method Set) 

我假設我使用反射錯誤,我仍然完全掌握Go中的整個界面和類型定義。

回答

2

reflect.TypeOf(img)爲您提供接口img中的值的反射類型,如果它是一個接口。在這種情況下,img的接口,image.Image其中包含*image.RGBA

可以通過轉換img*image.RGBA解決您的代碼,或更有力,定義與右Set方法的接口類型,並轉換img到(該draw.Image接口"image/draw"完全適用於這一點,因爲通過@注意DaveC)。如果您不確定png.Decode將始終爲您提供.png文件的*image.RGBA,則該接口類型更可取。

img.(*image.RGBA).Set(0, 0, color.RGBA{136, 0, 21, 255}) 

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

img.(Setter).Set(0, 0, color.RGBA{136, 0, 21, 255}) 

或(可能是最好的):

import "image/draw" 

... 

img.(draw.Image).Set(0, 0, color.RGBA{136, 0, 21, 255}) 
+0

該接口稍微好一些的版本已經作爲'draw.Image'存在。請參閱[我的答案](http://stackoverflow.com/a/30243259/55504)瞭解使用它的一種方法。 –

+0

@DaveC啊是的。我要更新我的答案並讚揚你。 –

0

編譯器是正確的,則image.Image類型是一個接口,不包括set()函數。

我不是圖像庫的專家,但粗略地看看這些類型似乎建議您可以採用圖像類型並使用Bounds()方法來獲得image.Rectangle以創建一個新的RGBA類型,如以前在您的示例中所做的那樣碼。

// Your current image manipulation 
m := image.NewRGBA(image.Rect(0, 0, 640, 480)) 
fmt.Println("type:", reflect.TypeOf(m)) 
m.Set(5, 5, color.RGBA{255, 0, 0, 255}) 

// You can create a image.RGBA type by passing the image.Rectangle 
// returned from image.Image.Bounds() 
m = image.NewRGBA(img.Bounds()) 
m.Set(0, 0, color.RGBA{136, 0, 21, 255}) 

這是對您的類型問題的嚴格回答,但我沒有任何保證它會實現您的最終目標。

3

爲了擴展 Anonymous' answer

png.Decode可以創建幾個不同的基礎的圖像類型(*image.Gray*image.RGBA*image.Paletted*image.NRGBA等)中的一個。 它返回它創建的任何圖像作爲image.Image接口,其中提供對數據的只讀訪問

但是,它返回的所有(最?)實際圖像類型都實現了用於簡單寫入訪問的Set方法。 您可以安全地測試和使用此方法的方式是通過image/draw包中的現有draw.Image接口。這只是這樣的:

// From image/draw: 
// Image is an image.Image with a Set method to change a single pixel. 
type Image interface { 
     image.Image 
     Set(x, y int, c color.Color) 
} 

所以,你可以這樣做:

​​3210

Playground(顯示了一個例子呼籲所有image.Image方法以及Set)。

相關問題