When I call png.Decode(imageFile) it returns a type image.Image. But I can't find a documented way to convert this to an image.NRGBA or image.RGBA on which I can call methods like At().
How can I achieve this?
If you don't need to "convert" the image type, and just want to extract the underlying type from the interface, use a "type assertion":
if img, ok := i.(*image.RGBA); ok {
// img is now an *image.RGBA
}
Or with a type switch:
switch i := i.(type) {
case *image.RGBA:
// i in an *image.RGBA
case *image.NRGBA:
// i in an *image.NRBGA
}
The solution to the question in the title, how to convert an image to image.NRGBA, can be found in the Go Blog: The trick is to create a new, empty image.NRGBA and then to "draw" the original image into the NRGBA image:
import "image/draw"
...
src := ...image to be converted...
b := src.Bounds()
m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
Related
Given a function with a parameter (that is a pointer to a struct) I want to instantiate a type of this parameter.
For example, for this function:
func MyFunction(myStruct *MyStruct) {}
using reflection I want to create a variable that contains exactly same as x := &MyStruct{} would contain.
This is the code example:
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
}
func main () {
reflectedFunction := reflect.TypeOf(MyFunction)
argType := reflectedFunction.In(0)
reflectedParameter := reflect.New(argType)
actual := reflectedParameter.Interface()
fmt.Println(actual)
expected := &MyStruct{}
fmt.Println(expected)
}
func MyFunction(myStruct *MyStruct) {
}
If you execute it, you'll see that they contain different info:
0xc00000e028 // actual
&{} // expected
This question isn't about why I would like to do this, so please avoid recommending not doing it, etc.
In your code, actual is a interface{} value containing a *MyStruct. As the name and documentation indicate, reflectedParameter.Interface() returns an interface{}.
using reflection I want to create a variable that contains exactly same as x := &MyStruct{} would contain.
Then you'll have to type assert it:
actual := reflectedParameter.Elem().Interface().(*MyStruct)
reflect.New creates a pointer to a new zero value of the reflected type. In your example that type is already a *MyStruct, so the value of your actual winds up being a representation of a **MyStruct, as seen in https://play.golang.org/p/Nyuc0mYmgkZ. Taking the .Elem() of that results in the correct type again, but you end up with a nil pointer (*MyStruct)(nil).
You need to take the .Elem() if that first type if you want to create a new pointer value.
reflectedParameter := reflect.New(argType.Elem())
https://play.golang.org/p/QzwTFUH3HTs
reflectedFunction := reflect.TypeOf(MyFunction)
argType := reflectedFunction.In(0)
reflectedParameter := reflect.New(argType.Elem())
actual := reflectedParameter.Interface()
fmt.Printf("%#v\n", actual)
expected := &MyStruct{}
fmt.Printf("%#v\n", expected)
Which prints
&main.MyStruct{}
&main.MyStruct{}
I'm trying to use syscall with user32.dll to get the contents of the clipboard. I expect it to be image data from a Print Screen.
Right now I've got this:
if opened := openClipboard(0); !opened {
fmt.Println("Failed to open Clipboard")
}
handle := getClipboardData(CF_BITMAP)
// get buffer
img, _, err := Decode(buffer)
I need to get the data into a readable buffer using the handle.
I've had some inspiration from AllenDang/w32 and atotto/clipboard on github. The following would work for text, based on atotto's implementation:
text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(handle))[:])
But how can I get a buffer containing image data I can decode?
[Update]
Going by the solution #kostix provided, I hacked together a half working example:
image.RegisterFormat("bmp", "bmp", bmp.Decode, bmp.DecodeConfig)
if opened := w32.OpenClipboard(0); opened == false {
fmt.Println("Error: Failed to open Clipboard")
}
//fmt.Printf("Format: %d\n", w32.EnumClipboardFormats(w32.CF_BITMAP))
handle := w32.GetClipboardData(w32.CF_DIB)
size := globalSize(w32.HGLOBAL(handle))
if handle != 0 {
pData := w32.GlobalLock(w32.HGLOBAL(handle))
if pData != nil {
data := (*[1 << 25]byte)(pData)[:size]
// The data is either in DIB format and missing the BITMAPFILEHEADER
// or there are other issues since it can't be decoded at this point
buffer := bytes.NewBuffer(data)
img, _, err := image.Decode(buffer)
if err != nil {
fmt.Printf("Failed decoding: %s", err)
os.Exit(1)
}
fmt.Println(img.At(0, 0).RGBA())
}
w32.GlobalUnlock(w32.HGLOBAL(pData))
}
w32.CloseClipboard()
AllenDang/w32 contains most of what you'd need, but sometimes you need to implement something yourself, like globalSize():
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procGlobalSize = modkernel32.NewProc("GlobalSize")
)
func globalSize(hMem w32.HGLOBAL) uint {
ret, _, _ := procGlobalSize.Call(uintptr(hMem))
if ret == 0 {
panic("GlobalSize failed")
}
return uint(ret)
}
Maybe someone will come up with a solution to get the BMP data. In the meantime I'll be taking a different route.
#JimB is correct: user32!GetClipboardData() returns a HGLOBAL, and a comment example over there suggests using kernel32!GlobalLock() to a) globally lock that handle, and b) yield a proper pointer to the memory referred to by it.
You will need to kernel32!GlobalUnlock() the handle after you're done with it.
As to converting pointers obtained from Win32 API functions to something readable by Go, the usual trick is casting the pointer to an insanely large slice. To cite the "Turning C arrays into Go slices" of "the Go wiki article on cgo":
To create a Go slice backed by a C array (without copying the original
data), one needs to acquire this length at runtime and use a type
conversion to a pointer to a very big array and then slice it to the
length that you want (also remember to set the cap if you're using Go 1.2 > or later), for example (see http://play.golang.org/p/XuC0xqtAIC for a
runnable example):
import "C"
import "unsafe"
...
var theCArray *C.YourType = C.getTheArray()
length := C.getTheArrayLength()
slice := (*[1 << 30]C.YourType)(unsafe.Pointer(theCArray))[:length:length]
It is important to keep in mind that the Go garbage collector will not
interact with this data, and that if it is freed from the C side of
things, the behavior of any Go code using the slice is nondeterministic.
In your case it will be simpler:
h := GlobalLock()
defer GlobalUnlock(h)
length := somehowGetLengthOfImageInTheClipboard()
slice := (*[1 << 30]byte)(unsafe.Pointer((uintptr(h)))[:length:length]
Then you need to actually read the bitmap.
This depends on the format of the Device-Independent Bitmap (DIB) available for export from the clipboard.
See this and this for a start.
As usually, definitions of BITMAPINFOHEADER etc are easily available online in the MSDN site.
I'm trying to create an animated GIF from a series of arbitrary non-paletted images. In order to create a paletted image, I need to come up with a palette somehow.
// RGBA, etc. images from somewhere else
var frames []image.Image
outGif := &gif.GIF{}
for _, simage := range frames {
// TODO: Convert image to paletted image
// bounds := simage.Bounds()
// palettedImage := image.NewPaletted(bounds, ...)
// Add new frame to animated GIF
outGif.Image = append(outGif.Image, palettedImage)
outGif.Delay = append(outGif.Delay, 0)
}
gif.EncodeAll(w, outGif)
Is there an easy way in golang stdlib to accomplish this?
It seems an automatic way of intelligently generating palettes is missing from the golang stdlib (correct me if I'm wrong here). But there seems to be a stub for providing your own Quantizer, which led me to the gogif project. (Which was the apparent source of image.Gif.)
I was able to borrow the MedianCutQuantizer from that project, defined here:
https://github.com/andybons/gogif/blob/master/mediancut.go
Which results in the following:
var subimages []image.Image // RGBA, etc. images from somewhere else
outGif := &gif.GIF{}
for _, simage := range subimages {
bounds := simage.Bounds()
palettedImage := image.NewPaletted(bounds, nil)
quantizer := gogif.MedianCutQuantizer{NumColor: 64}
quantizer.Quantize(palettedImage, bounds, simage, image.ZP)
// Add new frame to animated GIF
outGif.Image = append(outGif.Image, palettedImage)
outGif.Delay = append(outGif.Delay, 0)
}
gif.EncodeAll(w, outGif)
Instead of generating your own palette, you can also use on of the predefined (https://golang.org/pkg/image/color/palette/)
...
palettedImage := image.NewPaletted(bounds, palette.Plan9)
draw.Draw(palettedImage, palettedImage.Rect, simage, bounds.Min, draw.Over)
...
I am doing some practice with the Go image package with my free time this summer.
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})
}
The problem here is when I run it with the img.Set commented out I get this result
type: *image.RGBA
type: *image.RGBA
but when it's uncommented I get an error saying
img.Set undefined (type image.Image has no field or method Set)
I'm assuming I'm using reflect wrong, I'm still fully grasping the whole interface and type definitions in Go.
To expand on
a previous answer
answer:
png.Decode may create one of several different underlying image types (*image.Gray, *image.RGBA, *image.Paletted, *image.NRGBA, etc).
It returns whatever image it created as an image.Image interface which provides read only access to the data.
However, all (most?) of the actual image types it returns do implement the Set method for simple write access.
The way you can safely test for and use this method is via the existing draw.Image interface from the image/draw package. It's just this:
// 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)
}
So you could do something like:
func drawablePNGImage(r io.Reader) (draw.Image, error) {
img, err := png.Decode(r)
if err != nil {
return nil, err
}
dimg, ok := img.(draw.Image)
if !ok {
return nil, fmt.Errorf("%T is not a drawable image type", img)
}
return dimg, nil
}
Playground (shows an example calling all the image.Image methods as well as Set).
Edit for Go1.17+:
Note that Go1.17 added draw.RGBA64Image with a SetRGBA64 method. As with draw.Image, all of the standard image types implement this. The advantage of this method is that the color values are not boxed in the color.Color interface type so doing many pixel operations can be faster.
Also note that Go1.18 added optimisations to the draw.Draw and draw.DrawMask fallback implementations for images that implement the optional draw.RGBA64Image and image.RGBA64Image interfaces.
reflect.TypeOf(img) gives you the reflection type of the value in the interface img, if its an interface. In this case, img is an interface, an image.Image which contains an *image.RGBA.
You can fix your code by converting img to an *image.RGBA, or more robustly, define an interface type with the right Set method, and convert img to that (the draw.Image interface in "image/draw" works perfectly for this, as noted by #DaveC). The interface type is preferable if you aren't sure that png.Decode will always give you an *image.RGBA for the .png files you have.
img.(*image.RGBA).Set(0, 0, color.RGBA{136, 0, 21, 255})
or
type Setter interface {
Set(x, y int, c color.Color)
}
img.(Setter).Set(0, 0, color.RGBA{136, 0, 21, 255})
or (probably best):
import "image/draw"
...
img.(draw.Image).Set(0, 0, color.RGBA{136, 0, 21, 255})
The compiler is correct, the image.Image type is an interface that does not include the Set() function.
I am not an expert at the image library but my cursory look at the types seems to suggest you can take an Image type and use the Bounds() method to get a image.Rectangle to create a new RGBA type as done previously in your example code.
// 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})
This is a strict answer to your type issue but I don't have any gurantee it accomplishes your end goals.
Given a number like 1.400126761e+09 in Golang, what can I use to cast it to an int? I tried using the strconv library to play around with it and convert it using FormatFloat but that function returns the same thing when I give it the 'e' flag. Any other functions/libraries that will handle this conversion to an int?
Just use int(). For example:
x := float32(3.1)
fmt.Println(int(x))
ParseFloat is not returning the same thing, it's returning a float64 or float32. After you use it, you can just convert to an int as usual:
s := "1.400126761e+09"
f, err := strconv.ParseFloat(s, 64)
if err == nil {
thisisanint := int(f)
fmt.Println(thisisanint)
} else {
fmt.Println(err)
}
Go Playground
I actually was not clear as the variable I was playing with employs the interface{} and simply needed a float64 type assertion before casting it like int(). Hope this helps!