mirror of
https://github.com/lwch/natpass.git
synced 2024-04-21 12:41:54 +00:00
82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
package vnc
|
|
|
|
import (
|
|
"image"
|
|
"reflect"
|
|
"unsafe"
|
|
)
|
|
|
|
func calcDiff(src, dst *image.RGBA) []image.Rectangle {
|
|
// 宽度必须为2的倍数
|
|
const width = 64
|
|
const height = 64
|
|
size := dst.Bounds()
|
|
ret := make([]image.Rectangle, 0, (size.Max.X*size.Max.Y)/(width*height))
|
|
for y := 0; y < size.Max.Y; y += height {
|
|
for x := 0; x < size.Max.X; x += width {
|
|
dWidth := size.Max.X - x
|
|
dHeight := size.Max.Y - y
|
|
if dWidth > width {
|
|
dWidth = width
|
|
}
|
|
if dHeight > height {
|
|
dHeight = height
|
|
}
|
|
rect := image.Rect(x, y, x+dWidth, y+dHeight)
|
|
if dWidth%2 == 0 {
|
|
if isDiff8(src, dst, rect) {
|
|
ret = append(ret, rect)
|
|
}
|
|
} else {
|
|
if isDiff4(src, dst, rect) {
|
|
ret = append(ret, rect)
|
|
}
|
|
}
|
|
////////
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func isDiff8(src, dst *image.RGBA, rect image.Rectangle) bool {
|
|
sx := src.Bounds().Max.X * 4
|
|
dx := rect.Min.X * 4
|
|
ptr := uintptr(rect.Min.Y*sx + dx)
|
|
srcData := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&src.Pix)).Data)
|
|
dstData := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&dst.Pix)).Data)
|
|
for y := 0; y < rect.Size().Y; y++ {
|
|
next := ptr + uintptr(sx)
|
|
for x := 0; x < rect.Size().X; x += 2 {
|
|
src := (*uint64)(unsafe.Pointer(uintptr(srcData) + ptr))
|
|
dst := (*uint64)(unsafe.Pointer(uintptr(dstData) + ptr))
|
|
if *src != *dst {
|
|
return true
|
|
}
|
|
ptr += 8
|
|
}
|
|
ptr = next
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isDiff4(src, dst *image.RGBA, rect image.Rectangle) bool {
|
|
sx := src.Bounds().Max.X * 4
|
|
dx := rect.Min.X * 4
|
|
ptr := uintptr(rect.Min.Y*sx + dx)
|
|
srcData := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&src.Pix)).Data)
|
|
dstData := unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&dst.Pix)).Data)
|
|
for y := 0; y < rect.Size().Y; y++ {
|
|
next := ptr + uintptr(sx)
|
|
for x := 0; x < rect.Size().X; x++ {
|
|
src := (*uint64)(unsafe.Pointer(uintptr(srcData) + ptr))
|
|
dst := (*uint64)(unsafe.Pointer(uintptr(dstData) + ptr))
|
|
if *src != *dst {
|
|
return true
|
|
}
|
|
ptr += 4
|
|
}
|
|
ptr = next
|
|
}
|
|
return false
|
|
}
|