修正无法解屏的问题

This commit is contained in:
lwch
2021-11-01 18:30:37 +08:00
parent 2b6a5d2ce2
commit 94bece1bbb
8 changed files with 95 additions and 56 deletions
+5
View File
@@ -146,6 +146,11 @@ func main() {
os.Exit(1)
}
// for test
// work := worker.NewWorker()
// work.TestCapture()
// return
dir, err := filepath.Abs(*conf)
runtime.Assert(err)
+6 -1
View File
@@ -9,6 +9,11 @@ import (
// SendVNCImage send vnc image data
func (conn *Conn) SendVNCImage(to string, toIdx uint32, id string, screen, rect image.Rectangle,
encode network.VncImageEncoding, data []byte) {
dup := func(data []byte) []byte {
ret := make([]byte, len(data))
copy(ret, data)
return ret
}
var msg network.Msg
msg.To = to
msg.ToIdx = toIdx
@@ -25,7 +30,7 @@ func (conn *Conn) SendVNCImage(to string, toIdx uint32, id string, screen, rect
RectHeight: uint32(rect.Dy()),
},
Encode: encode,
Data: data,
Data: dup(data),
},
}
select {
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"image"
"image/jpeg"
"natpass/code/client/tunnel/vnc/define"
"natpass/code/client/tunnel/vnc/vncnetwork"
"os"
@@ -13,6 +14,7 @@ import (
"unicode/utf16"
"unsafe"
"github.com/lwch/logging"
"golang.org/x/sys/windows"
)
@@ -137,14 +139,8 @@ func (p *Process) Capture(timeout time.Duration) (*image.RGBA, error) {
p.chWrite <- &msg
trans := func(data *vncnetwork.ImageData) *image.RGBA {
img := image.NewRGBA(image.Rect(0, 0, int(data.GetWidth()), int(data.GetHeight())))
switch data.GetBits() {
case 8:
// TODO
case 24:
// TODO
case 32:
copy(img.Pix, data.GetData())
}
copy(img.Pix, data.GetData())
// dumpImage(img)
return img
}
if timeout > 0 {
@@ -159,3 +155,17 @@ func (p *Process) Capture(timeout time.Duration) (*image.RGBA, error) {
return trans(data), nil
}
}
func dumpImage(img image.Image) {
f, err := os.Create(`C:\Users\lwch\Pictures\debug.jpeg`)
if err != nil {
logging.Error("debug: %v", err)
return
}
defer f.Close()
err = jpeg.Encode(f, img, nil)
if err != nil {
logging.Error("encode: %v", err)
return
}
}
-37
View File
@@ -1,37 +0,0 @@
package worker
import (
"natpass/code/client/tunnel/vnc/vncnetwork"
"github.com/gorilla/websocket"
"google.golang.org/protobuf/proto"
)
func captureError(conn *websocket.Conn, msg string) {
var m vncnetwork.VncMsg
m.XType = vncnetwork.VncMsg_capture_data
m.Payload = &vncnetwork.VncMsg_Data{
Data: &vncnetwork.ImageData{
Ok: false,
Msg: msg,
},
}
data, _ := proto.Marshal(&m)
conn.WriteMessage(websocket.BinaryMessage, data)
}
func captureOK(conn *websocket.Conn, bits, width, height int, data []byte) {
var msg vncnetwork.VncMsg
msg.XType = vncnetwork.VncMsg_capture_data
msg.Payload = &vncnetwork.VncMsg_Data{
Data: &vncnetwork.ImageData{
Ok: true,
Bits: uint32(bits),
Width: uint32(width),
Height: uint32(height),
Data: data,
},
}
data, _ = proto.Marshal(&msg)
conn.WriteMessage(websocket.BinaryMessage, data)
}
@@ -3,25 +3,36 @@ package worker
import (
"errors"
"natpass/code/client/tunnel/vnc/define"
"natpass/code/client/tunnel/vnc/vncnetwork"
"syscall"
"unsafe"
"github.com/gorilla/websocket"
"github.com/lwch/logging"
)
func (worker *Worker) runCapture(conn *websocket.Conn) {
func (worker *Worker) runCapture() vncnetwork.ImageData {
err := worker.capture()
if err != nil {
logging.Error("capture: %v", err.Error())
captureError(conn, err.Error())
return
return vncnetwork.ImageData{
Ok: false,
Msg: err.Error(),
}
}
data := make([]byte, worker.info.width*worker.info.height*worker.info.bits/8)
for i := 0; i < len(data); i++ {
data[i] = *(*uint8)(unsafe.Pointer(worker.buffer + uintptr(i)))
}
captureOK(conn, worker.info.bits, worker.info.width, worker.info.height, data)
// BGR => RGB
for i := 0; i < len(data); i += (worker.info.bits / 8) {
data[i], data[i+2] = data[i+2], data[i]
}
return vncnetwork.ImageData{
Ok: true,
Bits: uint32(worker.info.bits),
Width: uint32(worker.info.width),
Height: uint32(worker.info.height),
Data: data,
}
}
func (worker *Worker) capture() error {
@@ -43,6 +54,7 @@ func (worker *Worker) capture() error {
return errors.New("update buffer: " + err.Error())
}
}
logging.Info("width=%d, height=%d, bits=%d", info.width, info.height, info.bits)
memDC, _, err := syscall.Syscall(define.FuncCreateCompatibleDC, 1, worker.hdc, 0, 0)
if memDC == 0 {
return errors.New("create dc: " + err.Error())
@@ -59,7 +71,7 @@ func (worker *Worker) capture() error {
return errors.New("select object: " + err.Error())
}
defer syscall.Syscall(define.FuncSelectObject, 2, memDC, oldDC, 0)
ok, _, err := syscall.Syscall9(define.FuncBitBlt, 0, memDC, 0, 0,
ok, _, err := syscall.Syscall9(define.FuncBitBlt, 9, memDC, 0, 0,
uintptr(worker.info.width), uintptr(worker.info.height), worker.hdc, 0, 0, define.SRCCOPY)
if ok == 0 {
return errors.New("bitblt: " + err.Error())
@@ -92,6 +104,9 @@ func (worker *Worker) copyImageData(bitmap uintptr) {
hdr.BiHeight = int32(-worker.info.height)
hdr.BiCompression = define.BI_RGB
hdr.BiSizeImage = 0
syscall.Syscall9(define.FuncGetDIBits, 7, worker.hdc, bitmap, 0, uintptr(worker.info.height),
lines, _, err := syscall.Syscall9(define.FuncGetDIBits, 7, worker.hdc, bitmap, 0, uintptr(worker.info.height),
worker.buffer, uintptr(unsafe.Pointer(&hdr)), define.DIB_RGB_COLORS, 0, 0)
if lines == 0 {
logging.Error("get bits: %v", err)
}
}
+2 -1
View File
@@ -5,5 +5,6 @@ package worker
import "github.com/gorilla/websocket"
func (worker *Worker) runCapture(conn *websocket.Conn) {
func (worker *Worker) runCapture() vncnetwork.ImageData {
return vncnetwork.ImageData{}
}
+37 -1
View File
@@ -1,7 +1,10 @@
package worker
import (
"image"
"image/jpeg"
"natpass/code/client/tunnel/vnc/vncnetwork"
"os"
"github.com/gorilla/websocket"
"github.com/lwch/logging"
@@ -42,7 +45,40 @@ func (worker *Worker) Do(conn *websocket.Conn) {
}
switch msg.GetXType() {
case vncnetwork.VncMsg_capture_req:
worker.runCapture(conn)
data := worker.runCapture()
// if data.Ok {
// dumpImage(data.Data, int(data.Width), int(data.Height))
// }
if !data.Ok {
logging.Error("capture: %s", data.Msg)
}
msg.XType = vncnetwork.VncMsg_capture_data
msg.Payload = &vncnetwork.VncMsg_Data{
Data: &data,
}
enc, _ := proto.Marshal(&msg)
conn.WriteMessage(websocket.BinaryMessage, enc)
}
}
}
func (worker *Worker) TestCapture() {
msg := worker.runCapture()
dumpImage(msg.Data, int(msg.Width), int(msg.Height))
}
func dumpImage(data []byte, width, height int) {
f, err := os.Create(`C:\Users\lwch\Pictures\debug.jpeg`)
if err != nil {
logging.Error("debug: %v", err)
return
}
defer f.Close()
img := image.NewRGBA(image.Rect(0, 0, width, height))
copy(img.Pix, data)
err = jpeg.Encode(f, img, nil)
if err != nil {
logging.Error("encode: %v", err)
return
}
}
@@ -92,6 +92,10 @@ func (worker *Worker) updateInfo() error {
worker.info.bits = int(bits)
worker.info.width = int(width)
worker.info.height = int(height)
if worker.info.bits != 32 {
worker.info.bits = 32
logging.Info("reset bits to 32")
}
return nil
}