Files
fscan/mylib/grdp/core/rle.go
T
ZacharyZcR 71b92d4408 feat: v2.1.0 核心重构与功能增强
## 架构重构
- 全局变量消除,迁移至 Config/State 对象
- SMB 插件融合(smb/smb2/smbghost/smbinfo)
- 服务探测重构,实现 Nmap 风格 fallback 机制
- 输出系统重构,TXT 实时刷盘 + 双写机制
- i18n 框架升级至 go-i18n

## 性能优化
- 正则表达式预编译
- 内存优化 map[string]struct{}
- 并发指纹匹配
- SOCKS5 连接复用
- 滑动窗口调度 + 自适应线程池

## 新功能
- Web 管理界面
- 多格式 POC 适配(xray/afrog)
- 增强指纹库(3139条)
- Favicon hash 指纹识别
- 插件选择性编译(Build Tags)
- fscan-lab 靶场环境
- 默认端口扩展(62→133)

## 构建系统
- 添加 no_local tag 支持排除本地插件
- 多版本构建:fscan/fscan-nolocal/fscan-web
- CI 添加 snapshot 模式支持仅测试构建

## Bug 修复
- 修复 120+ 个问题,包括 RDP panic、批量扫描漏报、
  JSON 输出格式、Redis 检测、Context 超时等

## 测试增强
- 单元测试覆盖率 74-100%
- 并发安全测试
- 集成测试(Web/端口/服务/SSH/ICMP)
2026-01-11 20:16:23 +08:00

1086 lines
22 KiB
Go

package core
import (
"github.com/shadow1ng/fscan/mylib/grdp/glog"
"unsafe"
)
func CVAL(p *[]uint8) int {
a := int((*p)[0])
*p = (*p)[1:]
return a
}
func CVAL2(p *[]uint8, v *uint16) {
*v = *((*uint16)(unsafe.Pointer(&(*p)[0])))
*p = (*p)[2:]
}
func CVAL3(p *[]uint8, v *[3]uint8) {
(*v)[0] = (*p)[0]
(*v)[1] = (*p)[1]
(*v)[2] = (*p)[2]
*p = (*p)[3:]
}
func REPEAT(f func(), count *int, x *int, width int) {
for (*count & ^0x7) != 0 && ((*x + 8) < width) {
for i := 0; i < 8; i++ {
f()
*count = *count - 1
*x = *x + 1
}
}
for (*count > 0) && (*x < width) {
f()
*count = *count - 1
*x = *x + 1
}
}
/* 1 byte bitmap decompress */
func decompress1(output *[]uint8, width, height int, input []uint8, size int) bool {
var (
prevline, line, count int
offset, code int
x int = width
opcode int
lastopcode int8 = -1
insertmix, bicolour, isfillormix bool
mixmask, mask uint8
colour1, colour2 uint8
mix uint8 = 0xff
fom_mask uint8
)
out := *output
for len(input) != 0 {
fom_mask = 0
code = CVAL(&input)
opcode = code >> 4
/* Handle different opcode forms */
switch opcode {
case 0xc, 0xd, 0xe:
opcode -= 6
count = int(code & 0xf)
offset = 16
case 0xf:
opcode = code & 0xf
if opcode < 9 {
count = int(CVAL(&input))
count |= int(CVAL(&input) << 8)
} else {
count = 1
if opcode < 0xb {
count = 8
}
}
offset = 0
default:
opcode >>= 1
count = int(code & 0x1f)
offset = 32
}
/* Handle strange cases for counts */
if offset != 0 {
isfillormix = ((opcode == 2) || (opcode == 7))
if count == 0 {
if isfillormix {
count = int(CVAL(&input)) + 1
} else {
count = int(CVAL(&input) + offset)
}
} else if isfillormix {
count <<= 3
}
}
/* Read preliminary data */
switch opcode {
case 0: /* Fill */
if (lastopcode == int8(opcode)) && !((x == width) && (prevline == 0)) {
insertmix = true
}
break
case 8: /* Bicolour */
colour1 = uint8(CVAL(&input))
colour2 = uint8(CVAL(&input))
break
case 3: /* Colour */
colour2 = uint8(CVAL(&input))
break
case 6: /* SetMix/Mix */
fallthrough
case 7: /* SetMix/FillOrMix */
mix = uint8(CVAL(&input))
opcode -= 5
break
case 9: /* FillOrMix_1 */
mask = 0x03
opcode = 0x02
fom_mask = 3
break
case 0x0a: /* FillOrMix_2 */
mask = 0x05
opcode = 0x02
fom_mask = 5
break
}
lastopcode = int8(opcode)
mixmask = 0
/* Output body */
for count > 0 {
if x >= width {
if height <= 0 {
return false
}
x = 0
height--
prevline = line
line = height * width
}
switch opcode {
case 0: /* Fill */
if insertmix {
if prevline == 0 {
out[x+line] = mix
} else {
out[x+line] = out[prevline+x] ^ mix
}
insertmix = false
count--
x++
}
if prevline == 0 {
REPEAT(func() {
out[x+line] = 0
}, &count, &x, width)
} else {
REPEAT(func() {
out[x+line] = out[prevline+x]
}, &count, &x, width)
}
break
case 1: /* Mix */
if prevline == 0 {
REPEAT(func() {
out[x+line] = mix
}, &count, &x, width)
} else {
REPEAT(func() {
out[x+line] = out[prevline+x] ^ mix
}, &count, &x, width)
}
break
case 2: /* Fill or Mix */
if prevline == 0 {
REPEAT(func() {
mixmask <<= 1
if mixmask == 0 {
mask = fom_mask
if fom_mask == 0 {
mask = uint8(CVAL(&input))
mixmask = 1
}
}
if mask&mixmask != 0 {
out[x+line] = mix
} else {
out[x+line] = 0
}
}, &count, &x, width)
} else {
REPEAT(func() {
mixmask = mixmask << 1
if mixmask == 0 {
mask = fom_mask
if fom_mask == 0 {
mask = uint8(CVAL(&input))
mixmask = 1
}
}
if mask&mixmask != 0 {
out[x+line] = out[prevline+x] ^ mix
} else {
out[x+line] = out[prevline+x]
}
}, &count, &x, width)
}
break
case 3: /* Colour */
REPEAT(func() {
out[x+line] = colour2
}, &count, &x, width)
break
case 4: /* Copy */
REPEAT(func() {
out[x+line] = uint8(CVAL(&input))
}, &count, &x, width)
break
case 8: /* Bicolour */
REPEAT(func() {
if bicolour {
out[x+line] = colour2
bicolour = false
} else {
out[x+line] = colour1
bicolour = true
count++
}
}, &count, &x, width)
break
case 0xd: /* White */
REPEAT(func() {
out[x+line] = 0xff
}, &count, &x, width)
break
case 0xe: /* Black */
REPEAT(func() {
out[x+line] = 0
}, &count, &x, width)
break
default:
glog.Debugf("bitmap opcode 0x%x\n", opcode)
return false
}
}
}
return true
}
/* 2 byte bitmap decompress */
func decompress2(output *[]uint8, width, height int, input []uint8, size int) bool {
var (
prevline, line, count int
offset, code int
x int = width
opcode int
lastopcode int = -1
insertmix, bicolour, isfillormix bool
mixmask, mask uint8
colour1, colour2 uint16
mix uint16 = 0xffff
fom_mask uint8
)
out := make([]uint16, width*height)
for len(input) != 0 {
fom_mask = 0
code = CVAL(&input)
opcode = code >> 4
/* Handle different opcode forms */
switch opcode {
case 0xc, 0xd, 0xe:
opcode -= 6
count = code & 0xf
offset = 16
break
case 0xf:
opcode = code & 0xf
if opcode < 9 {
count = CVAL(&input)
count |= CVAL(&input) << 8
} else {
count = 1
if opcode < 0xb {
count = 8
}
}
offset = 0
break
default:
opcode >>= 1
count = code & 0x1f
offset = 32
break
}
/* Handle strange cases for counts */
if offset != 0 {
isfillormix = ((opcode == 2) || (opcode == 7))
if count == 0 {
if isfillormix {
count = CVAL(&input) + 1
} else {
count = CVAL(&input) + offset
}
} else if isfillormix {
count <<= 3
}
}
/* Read preliminary data */
switch opcode {
case 0: /* Fill */
if (lastopcode == opcode) && !((x == width) && (prevline == 0)) {
insertmix = true
}
break
case 8: /* Bicolour */
CVAL2(&input, &colour1)
CVAL2(&input, &colour2)
break
case 3: /* Colour */
CVAL2(&input, &colour2)
break
case 6: /* SetMix/Mix */
fallthrough
case 7: /* SetMix/FillOrMix */
CVAL2(&input, &mix)
opcode -= 5
break
case 9: /* FillOrMix_1 */
mask = 0x03
opcode = 0x02
fom_mask = 3
break
case 0x0a: /* FillOrMix_2 */
mask = 0x05
opcode = 0x02
fom_mask = 5
break
}
lastopcode = opcode
mixmask = 0
/* Output body */
for count > 0 {
if x >= width {
if height <= 0 {
return false
}
x = 0
height--
prevline = line
line = height * width
}
switch opcode {
case 0: /* Fill */
if insertmix {
if prevline == 0 {
out[x+line] = mix
} else {
out[x+line] = out[prevline+x] ^ mix
}
insertmix = false
count--
x++
}
if prevline == 0 {
REPEAT(func() {
out[x+line] = 0
}, &count, &x, width)
} else {
REPEAT(func() {
out[x+line] = out[prevline+x]
}, &count, &x, width)
}
break
case 1: /* Mix */
if prevline == 0 {
REPEAT(func() {
out[x+line] = mix
}, &count, &x, width)
} else {
REPEAT(func() {
out[x+line] = out[prevline+x] ^ mix
}, &count, &x, width)
}
break
case 2: /* Fill or Mix */
if prevline == 0 {
REPEAT(func() {
mixmask <<= 1
if mixmask == 0 {
mask = fom_mask
if fom_mask == 0 {
mask = uint8(CVAL(&input))
mixmask = 1
}
}
if mask&mixmask != 0 {
out[x+line] = mix
} else {
out[x+line] = 0
}
}, &count, &x, width)
} else {
REPEAT(func() {
mixmask = mixmask << 1
if mixmask == 0 {
mask = fom_mask
if fom_mask == 0 {
mask = uint8(CVAL(&input))
mixmask = 1
}
}
if mask&mixmask != 0 {
out[x+line] = out[prevline+x] ^ mix
} else {
out[x+line] = out[prevline+x]
}
}, &count, &x, width)
}
break
case 3: /* Colour */
REPEAT(func() {
out[x+line] = colour2
}, &count, &x, width)
break
case 4: /* Copy */
REPEAT(func() {
var a uint16
CVAL2(&input, &a)
out[x+line] = a
}, &count, &x, width)
break
case 8: /* Bicolour */
REPEAT(func() {
if bicolour {
out[x+line] = colour2
bicolour = false
} else {
out[x+line] = colour1
bicolour = true
count++
}
}, &count, &x, width)
break
case 0xd: /* White */
REPEAT(func() {
out[x+line] = 0xffff
}, &count, &x, width)
break
case 0xe: /* Black */
REPEAT(func() {
out[x+line] = 0
}, &count, &x, width)
break
default:
glog.Debugf("bitmap opcode 0x%x\n", opcode)
return false
}
}
}
j := 0
for _, v := range out {
(*output)[j], (*output)[j+1] = PutUint16BE(v)
//(*output)[j+1], (*output)[j] = PutUint16BE(v)
j += 2
}
return true
}
//func decompress2(output *[]uint8, width, height int, input []uint8, size int) bool {
// var (
// prevline, line int
// opcode, count, offset, code int
// x int = width
// lastopcode int = -1
// insertmix, bicolour, isfillormix bool
// mixmask, mask uint8
// colour1, colour2 uint16
// mix uint16 = 0xffff
// fom_mask uint8
// )
//
// out := make([]uint16, width*height)
// for len(input) != 0 {
// fom_mask = 0
// code = CVAL(&input)
// opcode = code >> 4
// /* Handle different opcode forms */
// switch opcode {
// case 0xc, 0xd, 0xe:
// opcode -= 6
// count = code & 0xf
// offset = 16
// break
// case 0xf:
// opcode = code & 0xf
// if opcode < 9 {
// count = CVAL(&input)
// count |= CVAL(&input) << 8
// } else {
// count = 1
// if opcode < 0xb {
// count = 8
// }
// }
// offset = 0
// break
// default:
// opcode >>= 1
// count = code & 0x1f
// offset = 32
// break
// }
//
// /* Handle strange cases for counts */
// if offset != 0 {
// isfillormix = ((opcode == 2) || (opcode == 7))
// if count == 0 {
// if isfillormix {
// count = CVAL(&input) + 1
// } else {
// count = CVAL(&input) + offset
// }
// } else if isfillormix {
// count <<= 3
// }
// }
// /* Read preliminary data */
// switch opcode {
// case 0: /* Fill */
// if (lastopcode == opcode) && !((x == width) && (prevline == 0)) {
// insertmix = true
// }
// break
// case 8: /* Bicolour */
// CVAL2(&input, &colour1)
// CVAL2(&input, &colour2)
// break
// case 3: /* Colour */
// CVAL2(&input, &colour2)
// break
// case 6: /* SetMix/Mix */
// fallthrough
// case 7: /* SetMix/FillOrMix */
// CVAL2(&input, &mix)
// opcode -= 5
// break
// case 9: /* FillOrMix_1 */
// mask = 0x03
// opcode = 0x02
// fom_mask = 3
// break
// case 0x0a: /* FillOrMix_2 */
// mask = 0x05
// opcode = 0x02
// fom_mask = 5
// break
// }
// lastopcode = opcode
// mixmask = 0
// /* Output body */
// for count > 0 {
// if x >= width {
// if height <= 0 {
// return false
// }
//
// x = 0
// height--
// prevline = line
// line = height * width
// }
// switch opcode {
// case 0: /* Fill */
// if insertmix {
// if prevline == 0 {
// out[x+line] = mix
// } else {
// out[x+line] = out[prevline+x] ^ mix
// }
// insertmix = false
// count--
// x++
// }
// if prevline == 0 {
// REPEAT(func() {
// out[x+line] = 0
// }, &count, &x, width)
// } else {
// REPEAT(func() {
// out[x+line] = out[prevline+x]
// }, &count, &x, width)
// }
// break
// case 1: /* Mix */
// if prevline == 0 {
// REPEAT(func() {
// out[x+line] = mix
// }, &count, &x, width)
// } else {
// REPEAT(func() {
// out[x+line] = out[prevline+x] ^ mix
// }, &count, &x, width)
// }
// break
// case 2: /* Fill or Mix */
// if prevline == 0 {
// REPEAT(func() {
// mixmask <<= 1
// if mixmask == 0 {
// mask = fom_mask
// if fom_mask == 0 {
// mask = uint8(CVAL(&input))
// mixmask = 1
// }
// }
// if mask&mixmask != 0 {
// out[x+line] = mix
// } else {
// out[x+line] = 0
// }
// }, &count, &x, width)
// } else {
// REPEAT(func() {
// mixmask = mixmask << 1
// if mixmask == 0 {
// mask = fom_mask
// if fom_mask == 0 {
// mask = uint8(CVAL(&input))
// mixmask = 1
// }
// }
// if mask&mixmask != 0 {
// out[x+line] = out[prevline+x] ^ mix
// } else {
// out[x+line] = out[prevline+x]
// }
// }, &count, &x, width)
// }
// break
// case 3: /* Colour */
// REPEAT(func() {
// out[x+line] = colour2
// }, &count, &x, width)
// break
// case 4: /* Copy */
// REPEAT(func() {
// var a uint16
// CVAL2(&input, &a)
// out[x+line] = a
// }, &count, &x, width)
//
// break
// case 8: /* Bicolour */
// REPEAT(func() {
// if bicolour {
// out[x+line] = colour2
// bicolour = false
// } else {
// out[x+line] = colour1
// bicolour = true
// count++
// }
// }, &count, &x, width)
//
// break
// case 0xd: /* White */
// REPEAT(func() {
// out[x+line] = 0xffff
// }, &count, &x, width)
// break
// case 0xe: /* Black */
// REPEAT(func() {
// out[x+line] = 0
// }, &count, &x, width)
// break
// default:
// glog.Debugf("bitmap opcode 0x%x\n", opcode)
// return false
// }
// }
// }
// j := 0
// for _, v := range out {
// (*output)[j], (*output)[j+1] = PutUint16BE(v)
// j += 2
// }
// return true
//}
// /* 3 byte bitmap decompress */
func decompress3(output *[]uint8, width, height int, input []uint8, size int) bool {
var (
prevline, line, count int
opcode, offset, code int
x int = width
lastopcode int = -1
insertmix, bicolour, isfillormix bool
mixmask, mask uint8
colour1 = [3]uint8{0, 0, 0}
colour2 = [3]uint8{0, 0, 0}
mix = [3]uint8{0xff, 0xff, 0xff}
fom_mask uint8
)
out := *output
for len(input) != 0 {
fom_mask = 0
code = CVAL(&input)
opcode = code >> 4
/* Handle different opcode forms */
switch opcode {
case 0xc, 0xd, 0xe:
opcode -= 6
count = code & 0xf
offset = 16
break
case 0xf:
opcode = code & 0xf
if opcode < 9 {
count = CVAL(&input)
count |= CVAL(&input) << 8
} else {
count = 1
if opcode < 0xb {
count = 8
}
}
offset = 0
break
default:
opcode >>= 1
count = code & 0x1f
offset = 32
break
}
/* Handle strange cases for counts */
if offset != 0 {
isfillormix = ((opcode == 2) || (opcode == 7))
if count == 0 {
if isfillormix {
count = CVAL(&input) + 1
} else {
count = CVAL(&input) + offset
}
} else if isfillormix {
count <<= 3
}
}
/* Read preliminary data */
switch opcode {
case 0: /* Fill */
if (lastopcode == opcode) && !((x == width) && (prevline == 0)) {
insertmix = true
}
break
case 8: /* Bicolour */
CVAL3(&input, &colour1)
CVAL3(&input, &colour2)
break
case 3: /* Colour */
CVAL3(&input, &colour2)
break
case 6: /* SetMix/Mix */
fallthrough
case 7: /* SetMix/FillOrMix */
CVAL3(&input, &mix)
opcode -= 5
break
case 9: /* FillOrMix_1 */
mask = 0x03
opcode = 0x02
fom_mask = 3
break
case 0x0a: /* FillOrMix_2 */
mask = 0x05
opcode = 0x02
fom_mask = 5
break
}
lastopcode = opcode
mixmask = 0
/* Output body */
for count > 0 {
if x >= width {
if height <= 0 {
return false
}
x = 0
height--
prevline = line
line = height * width * 3
}
switch opcode {
case 0: /* Fill */
if insertmix {
if prevline == 0 {
out[3*x+line] = mix[0]
out[3*x+line+1] = mix[1]
out[3*x+line+2] = mix[2]
} else {
out[3*x+line] = out[prevline+3*x] ^ mix[0]
out[3*x+line+1] = out[prevline+3*x+1] ^ mix[1]
out[3*x+line+2] = out[prevline+3*x+2] ^ mix[2]
}
insertmix = false
count--
x++
}
if prevline == 0 {
REPEAT(func() {
out[3*x+line] = 0
out[3*x+line+1] = 0
out[3*x+line+2] = 0
}, &count, &x, width)
} else {
REPEAT(func() {
out[3*x+line] = out[prevline+3*x]
out[3*x+line+1] = out[prevline+3*x+1]
out[3*x+line+2] = out[prevline+3*x+2]
}, &count, &x, width)
}
break
case 1: /* Mix */
if prevline == 0 {
REPEAT(func() {
out[3*x+line] = mix[0]
out[3*x+line+1] = mix[1]
out[3*x+line+2] = mix[2]
}, &count, &x, width)
} else {
REPEAT(func() {
out[3*x+line] = out[prevline+3*x] ^ mix[0]
out[3*x+line+1] = out[prevline+3*x+1] ^ mix[1]
out[3*x+line+2] = out[prevline+3*x+2] ^ mix[2]
}, &count, &x, width)
}
break
case 2: /* Fill or Mix */
if prevline == 0 {
REPEAT(func() {
mixmask = mixmask << 1
if mixmask == 0 {
mask = fom_mask
if fom_mask == 0 {
mask = uint8(CVAL(&input))
mixmask = 1
}
}
if mask&mixmask != 0 {
out[3*x+line] = mix[0]
out[3*x+line+1] = mix[1]
out[3*x+line+2] = mix[2]
} else {
out[3*x+line] = 0
out[3*x+line+1] = 0
out[3*x+line+2] = 0
}
}, &count, &x, width)
} else {
REPEAT(func() {
mixmask = mixmask << 1
if mixmask == 0 {
mask = fom_mask
if fom_mask == 0 {
mask = uint8(CVAL(&input))
mixmask = 1
}
}
if mask&mixmask != 0 {
out[3*x+line] = out[prevline+3*x] ^ mix[0]
out[3*x+line+1] = out[prevline+3*x+1] ^ mix[1]
out[3*x+line+2] = out[prevline+3*x+2] ^ mix[2]
} else {
out[3*x+line] = out[prevline+3*x]
out[3*x+line+1] = out[prevline+3*x+1]
out[3*x+line+2] = out[prevline+3*x+2]
}
}, &count, &x, width)
}
break
case 3: /* Colour */
REPEAT(func() {
out[3*x+line] = colour2[0]
out[3*x+line+1] = colour2[1]
out[3*x+line+2] = colour2[2]
}, &count, &x, width)
break
case 4: /* Copy */
REPEAT(func() {
out[3*x+line] = uint8(CVAL(&input))
out[3*x+line+1] = uint8(CVAL(&input))
out[3*x+line+2] = uint8(CVAL(&input))
}, &count, &x, width)
break
case 8: /* Bicolour */
REPEAT(func() {
if bicolour {
out[3*x+line] = colour2[0]
out[3*x+line+1] = colour2[1]
out[3*x+line+2] = colour2[2]
bicolour = false
} else {
out[3*x+line] = colour1[0]
out[3*x+line+1] = colour1[1]
out[3*x+line+2] = colour1[2]
bicolour = true
count++
}
}, &count, &x, width)
break
case 0xd: /* White */
REPEAT(func() {
out[3*x+line] = 0xff
out[3*x+line+1] = 0xff
out[3*x+line+2] = 0xff
}, &count, &x, width)
break
case 0xe: /* Black */
REPEAT(func() {
out[3*x+line] = 0
out[3*x+line+1] = 0
out[3*x+line+2] = 0
}, &count, &x, width)
break
default:
glog.Debugf("bitmap opcode 0x%x\n", opcode)
return false
}
}
}
return true
}
/* decompress a colour plane */
func processPlane(in *[]uint8, width, height int, output *[]uint8, j int) int {
var (
indexw int
indexh int
code int
collen int
replen int
color uint8
x uint8
revcode int
lastline int
thisline int
)
ln := len(*in)
lastline = 0
indexh = 0
i := 0
for indexh < height {
thisline = j + (width * height * 4) - ((indexh + 1) * width * 4)
color = 0
indexw = 0
i = thisline
if lastline == 0 {
for indexw < width {
code = CVAL(in)
replen = int(code & 0xf)
collen = int((code >> 4) & 0xf)
revcode = (replen << 4) | collen
if (revcode <= 47) && (revcode >= 16) {
replen = revcode
collen = 0
}
for collen > 0 {
color = uint8(CVAL(in))
(*output)[i] = uint8(color)
i += 4
indexw++
collen--
}
for replen > 0 {
(*output)[i] = uint8(color)
i += 4
indexw++
replen--
}
}
} else {
for indexw < width {
code = CVAL(in)
replen = int(code & 0xf)
collen = int((code >> 4) & 0xf)
revcode = (replen << 4) | collen
if (revcode <= 47) && (revcode >= 16) {
replen = revcode
collen = 0
}
for collen > 0 {
x = uint8(CVAL(in))
if x&1 != 0 {
x = x >> 1
x = x + 1
color = -x
} else {
x = x >> 1
color = x
}
x = (*output)[indexw*4+lastline] + color
(*output)[i] = uint8(x)
i += 4
indexw++
collen--
}
for replen > 0 {
x = (*output)[indexw*4+lastline] + color
(*output)[i] = uint8(x)
i += 4
indexw++
replen--
}
}
}
indexh++
lastline = thisline
}
return ln - len(*in)
}
/* 4 byte bitmap decompress */
func decompress4(output *[]uint8, width, height int, input []uint8, size int) bool {
var (
code int
onceBytes, total int
)
code = CVAL(&input)
if code != 0x10 {
return false
}
total = 1
onceBytes = processPlane(&input, width, height, output, 3)
total += onceBytes
onceBytes = processPlane(&input, width, height, output, 2)
total += onceBytes
onceBytes = processPlane(&input, width, height, output, 1)
total += onceBytes
onceBytes = processPlane(&input, width, height, output, 0)
total += onceBytes
return size == total
}
/* main decompress function */
func Decompress(input []uint8, width, height int, Bpp int) []uint8 {
size := width * height * Bpp
output := make([]uint8, size)
glog.Debug("decompress, bmp tpye =", Bpp)
switch Bpp {
case 1:
decompress1(&output, width, height, input, size)
case 2:
decompress2(&output, width, height, input, size)
case 3:
decompress3(&output, width, height, input, size)
case 4:
decompress4(&output, width, height, input, size)
default:
glog.Debugf("Bpp %d\n", Bpp)
}
return output
}