Using the Set() method of an image.Image or *image.RGBA - image

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.

Related

Type mismatch with projection on a []byte property

I have a struct as follows
type MyEntity struct {
PF []byte `json:"-" datastore:"_pf"`
}
Querying without a Projection works fine. However, when I query with projection on "_pf" field, I get "type mismatch: string versus []uint8" error. I implemented the PropertyLoadSaver and examined the prop.Value for "_pf" property and found that some rows return []byte type and some return string. So, why is projected query failing with this error while non-projected queries are fine? At the moment I am resolving this by implementing PropertyLoadSaver interface and explicitly checking types and converting string type to []byte type to solve this problem.
Here is the complete test case. This is reproduced on cloud datastore emulator. Use appropriate value for datastoreProject variable below. Rest all should directly work. You can see the behavior by inserting both entities or one of the types of the entities. The error that is displayed is
panic: datastore: cannot load field "_pf" into a "tests.MyEntity": type mismatch: string versus []uint8 [recovered]
panic: datastore: cannot load field "_pf" into a "tests.MyEntity": type mismatch: string versus []uint8
Following is the code.
type MyEntity struct {
PF []byte `json:"-" datastore:"_pf"`
}
func TestPackedField(t *testing.T) {
e1 := &MyEntity{PF: []byte{83, 0, 0, 0, 93, 150, 154, 206, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 3}} // returns []byte on projection
e2 := &MyEntity{PF: []byte{83, 0, 0, 0, 93, 120, 79, 87, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 3}} // returns string on projection
ctx := context.Background()
conn, err := datastore.NewClient(ctx, datastoreProject)
if err != nil {
panic(err)
}
bkey := datastore.NameKey("Bytes", "bytearray", nil)
if true {
conn.Put(ctx, bkey, e1)
}
skey := datastore.NameKey("Bytes", "string", nil)
if true {
conn.Put(ctx, skey, e2)
}
q1 := datastore.NewQuery("Bytes").Order("-_pf").Limit(2)
var elfull []*MyEntity
if _, err := conn.GetAll(ctx, q1, &elfull); err != nil {
panic(err)
}
q2 := datastore.NewQuery("Bytes").Project("_pf").Order("-_pf").Limit(2)
var elprojected []*MyEntity
if _, err := conn.GetAll(ctx, q2, &elprojected); err != nil {
conn.Delete(ctx, bkey)
conn.Delete(ctx, skey)
panic(err)
}
}
In order to understand why this works fine on normal queries and not on projection queries you might want firstly to read about what is the actual difference between those two. As it is mentioned in this post:
Whereas "regular" (which I'm taking to mean SELECT * ...) queries against Cloud Datastore typically use indexes that only contain a sorted subset of the properties of the queried entities, plus pointers to the full entities, projection queries run against indexes that contain all the fields requested by the query. So it appears the significant latency gain comes from the elimination of the need to fetch the queried entities once the set of entities matching the query has been discerned via the index.
So, basically, when you do your projection query, your queried entities are not fetched.
As I was reading through this official documentation, I found some really interesting phrases related to your question :
A field of slice type corresponds to a Datastore array property, except for []byte, which corresponds to a Datastore blob. If a non-array value is loaded into a slice field, the result will be a slice with one element, containing the value.
Key Field
If the struct contains a *datastore.Key field tagged with the name "key", its value will be ignored on Put. When reading the Entity back into the Go struct, the field will be populated with the *datastore.Key value used to query for the Entity.
What I understood from here is that maybe in your case, the fields are populated with the key value for that query ( string ).
Another interesting thing that I have discoverd is that according to the properties and values type documentation the type []byte is not indexed. And as it is told here, unindexed properties cannot be projected. So projected queries should not work for this particular use case at all.

Getting window geometry in Go for Windows

I want to create a tool with Go that lets me resize multiple windows on my screen. As an example lets assume that I want to find my Firefox window and my Atom (text editor) window and place them, so that they take up exactly half of my screen (FF left, Atom right).
So far I realized, that I need to use the Windows API for that. I created a method that gives me all handles and the titles of all windows, but I'm struggling with geometry information. I understand that the api call GetWindowRect will help, but how can I get the information out of a pointer to a rect?
Follow up question 1: what other information can I get about the windows?
Follow up question 2: How do I resize the window so that it takes exactly half my screen size? I guess, I need another call to get the monitor dimensions.
What I have so far is the code below. The main program finds all handles and displays those containing 'Atom' in the title. The windows package contains the code accessing the windows API.
My current result is that I get 2 handles for atom (why not just 1?). I guess, I have to learn more about the Windows API, too. Are there good summaries to understand the basics?
main.go:
package main
import (
"resizer/windows"
"fmt"
"log"
"strings"
)
func main() {
const title = "Atom"
m := windows.GetAllWindows()
fmt.Printf("Map of windows: \n")
for handle := range m {
if strings.Contains(m[handle].Title(), title) {
fmt.Printf("'%v'\n", m[handle])
}
}
}
windows.go:
package windows
import (
"fmt"
"log"
"syscall"
"unsafe"
)
var (
user32 = syscall.MustLoadDLL("user32.dll")
procEnumWindows = user32.MustFindProc("EnumWindows")
procGetWindowTextW = user32.MustFindProc("GetWindowTextW")
)
// Window represents any Window that is opened in the Windows OS
type Window struct {
handle syscall.Handle
title string
}
// Title returns the title of the window
func (w Window) Title() string {
return w.title
}
// GetAllWindows finds all currently opened windows
func GetAllWindows() map[syscall.Handle]Window {
m := make(map[syscall.Handle]Window)
cb := syscall.NewCallback(func(h syscall.Handle, p uintptr) uintptr {
bytes := make([]uint16, 200)
_, err := GetWindowText(h, &bytes[0], int32(len(bytes)))
title := "||| no title found |||"
if err == nil {
title = syscall.UTF16ToString(bytes)
}
m[h] = Window{h, title}
return 1 // continue enumeration
})
EnumWindows(cb, 0)
return m
}
// EnumWindows loops through all windows and calls a callback function on each
func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
// GetWindowText gets the title of a Window given by a certain handle
func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) {
r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
len = int32(r0)
if len == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
GetWindowRect() writes the geometry to the RECT structure you pass the pointer to in. It operates exactly like the GetWindowText() call you already have; the difference is you have to provide the RECT structure yourself.
You should be able to just get away with copying the structure verbatim. To substitute data types, use this page. The definition for RECT says all the fields are LONG, which that page says is "[a] 32-bit signed integer". So this should suffice:
type RECT struct {
left int32 // or Left, Top, etc. if this type is to be exported
top int32
right int32
bottom int32
}
(Most likely irrelevant, but it's worth pointing out that RECT operates identically to image.Rectangle, with left and top being Min and right and bottom being Max. They are not identical because image.Rectangle uses int, so you may want to consider providing conversion functions if you want to use image's geometry functions to manipulate rectangles instead of GDI's.)

How to load image resource from windows `syscall` in golang?

I am writing a golang program using go-bindata to embed the image resources, and use the Asset(string) ([]byte, error) function to access resources. But my existing library codes go like this:
func NewIconFromFile(filePath string) (uintptr, error) {
absFilePath, err := filepath.Abs(filePath)
if err != nil {
return 0, err
}
hicon, _, _ := LoadImage.Call(
0,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(absFilePath))),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE|LR_LOADFROMFILE)
if hicon == 0 {
return 0, errors.New("load image failed: " + filePath)
}
return hicon, nil
}
How can I rewrite this functions to:
func NewIconFromRawBytes(imgBytes []byte) (uintptr, error)
so it can support for loading images from []byte ? Any helps? thanks.
Edit: There is a similar c++ version question, how can I port it to golang.
LoadImage() deals with Windows resources, which are built into Windows executables directly. go-bindata doesn't seem to deal in these, and doing this with Go directly isn't trivial.
If you want to be able to write a NewIconFromRawBytes() that creates an HICON from memory, you'll need to use the confusingly-named CreateIconFromResourceEx() function. If you do that, you may want to keep the info in the answer here in mind.
If, however, this is an image instead of an icon and you want an HBITMAP out of it, you have a bit more work to do involving the CreateDIBSection() function. The answer here shows what to do, though understanding it may be a bit harder. Of important note is that CreateDIBSection() allocates the image memory for you, so you'll have to copy it from Go to the memory location provided.
Side note: if you have a *image.RGBA or *image.NRGBA, you'll need to flip the bytes around if you want to shove that into an HBITMAP, as Windows expects the bytes in BGRA order, not RGBA order.

Golang Iris Web - Serve 1x1 pixel

I'm new to Golang and trying to use a framework called iris.
My problem is how to serve 1x1 gif pixel, not using c.HTML context, but the way the browser title becomes 1x1 image gif. The image will be used for tracking.
Any help will be deeply appreciated.
Attention: I'm not really familiar with iris so the solution maybe not idiomatic.
package main
import (
"github.com/kataras/iris"
"image"
"image/color"
"image/gif"
)
func main() {
iris.Get("/", func(ctx *iris.Context) {
img := image.NewRGBA(image.Rect(0, 0, 1, 1)) //We create a new image of size 1x1 pixels
img.Set(0, 0, color.RGBA{255, 0, 0, 255}) //set the first and only pixel to some color, in this case red
err := gif.Encode(ctx.Response.BodyWriter(), img, nil) //encode the rgba image to gif, using gif.encode and write it to the response
if err != nil {
panic(err) //if we encounter some problems panic
}
ctx.SetContentType("image/gif") //set the content type so the browser can identify that our response is actually an gif image
})
iris.Listen(":8080")
}
Links for better understanding:
https://golang.org/pkg/image/
https://golang.org/pkg/image/gif
https://golang.org/pkg/image/color
https://golang.org/pkg/image/
https://godoc.org/github.com/valyala/fasthttp#Response

Convert image.Image to image.NRGBA

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)

Resources