Screenshot is merged when multiple display screens are connected
kashishm opened this issue · 8 comments
can you try this one and tell me how it works?
package screenshot
import (
// #cgo LDFLAGS: -framework CoreGraphics
// #cgo LDFLAGS: -framework CoreFoundation
// #include <CoreGraphics/CoreGraphics.h>
// #include <CoreFoundation/CoreFoundation.h>
"C"
"image"
"reflect"
"unsafe"
)
func ScreenRect() (image.Rectangle, error) {
displayID := C.CGMainDisplayID()
width := int(C.CGDisplayPixelsWide(displayID))
height := int(C.CGDisplayPixelsHigh(displayID))
return image.Rect(0, 0, width, height), nil
}
func CaptureScreen() (*image.RGBA, error) {
rect, err := ScreenRect()
if err != nil {
return nil, err
}
return CaptureRect(rect)
}
func CaptureRect(rect image.Rectangle) (*image.RGBA, error) {
displayID := C.CGMainDisplayID()
list := make([]C.CGDirectDisplayID, 16)
size := uint32(0)
C.CGGetOnlineDisplayList(C.uint32_t(cap(list)), (*C.CGDirectDisplayID)(unsafe.Pointer(&list[0])), (*C.uint32_t)(&size))
if size > 0 {
displayID = list[0]
}
width := int(C.CGDisplayPixelsWide(displayID))
rawData := C.CGDataProviderCopyData(C.CGImageGetDataProvider(C.CGDisplayCreateImage(displayID)))
length := int(C.CFDataGetLength(rawData))
ptr := unsafe.Pointer(C.CFDataGetBytePtr(rawData))
var slice []byte
hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
hdrp.Data = uintptr(ptr)
hdrp.Len = length
hdrp.Cap = length
imageBytes := make([]byte, length)
for i := 0; i < length; i += 4 {
imageBytes[i], imageBytes[i+2], imageBytes[i+1], imageBytes[i+3] = slice[i+2], slice[i], slice[i+1], slice[i+3]
}
C.CFRelease(rawData)
img := &image.RGBA{Pix: imageBytes, Stride: 4 * width, Rect: rect}
return img, nil
}
Thanks for the quick reply. With the above code also, the screenshot is same.
We have forked this repo and we were using screencapture
for taking screenshots in darwin. It is working fine and can take screenshots for multiple displays as well. Here's the code.
Is there any specific reason for not using it?
Thanks for checking :).
I guess because his code is a using a different binary to take the screenshot, I will try to find how to fix it during the week
The CG framework does have support for multiple displays, but I didn't go so far when I implemented the darwin version (it was simpler to just get the main display). The advantage of using CG over screencapture is you don't need to write to a file and thus you have no issues with file permissions. Also, the library has better chances of outliving the tool.
I can work out a multi display version when I get the time ;)
The problem is not (probably) caused by multiple displays. Today I played with your library and received the same result. Looking deeper into the function CaptureRect() I discovered that display resolution returns screen size (e.g. 1440x900), but returned Image is 2880x1800 on my retina display. This caused corruption of the image. I was able to get correct picture tweaking your function, but 2x bigger. Because I don't know Apple Core framework I wasn't able to scale down the picture to desired resolution.
Hope this help.
15' Retina display has in fact 2880x1800 pixels. So the image is probably correct, and 1440x900 number is wrong.
@pftbest: I don't use native resolution on my 13" notebook, I use 1440x900. So both numbers are correct. Screen resolution is 1440x900 (reported by CGDisplayPixelsWide)
, but screenshot has native display resolution 2560x1600 (reported by CGDisplayCreateImage
- sorry, I mentioned wrong numbers in my original comment).
The image is than iterated using width reported by CGDisplayPixelsWide
with real screen resolution in the function CaptureRect
and this iteration distorts the image. In the original comment from @kashishm the issue is probably that plugging another monitor changes the screen resolution.
Solution should be to rescale the image returned by CGDisplayPixelsWide
to real screen resolution if they are different. When I work with my screen I want to use screen points, not native display resolution.
This problem can also affect other implementations (Linux, Windows, ...).