go语言实现将重要数据写入图片中
原理:将数据的二进制形式写入图像红色通道数据二进制的低位
只支持png格式的输出
写入数据
go run shadow.go -in="c.jpg" -data="hide me" -out="out.png"
读取数据
go run shadow.go -in="out.png"
代码如下:
package main import ( "errors" "flag" "fmt" "image" "image/color" _ "image/jpeg" "image/png" "log" "math" "os" ) var FLAG = [4]byte{0x13, 0x14, 0x52, 0x00} //shadow flag. //byte to 8 bits func Byte2bits(b byte) (a [8]byte) { var c uint8 = 7 var i uint8 for i = 0; i < 8; i++ { a[i] = b >> (c - i) & 1 } return } //8 bits to byte. func Bits2Byte(a [8]byte) (b byte) { for i := 0; i < 8; i++ { b += a[i] * uint8(math.Pow(2, float64(7-i))) } return } //uint32 to 4 bytes. func Uint32ToBytes(i uint32) (b [4]byte) { b[0] = uint8(i >> 24) b[1] = uint8(i >> 16 & 0xffff) b[2] = uint8(i >> 8 & 0xff) b[3] = uint8(i & 0xff) return } //4 bytes to uint32. func Bytes2Uint32(b [4]byte) (i uint32) { var j uint32 for ; j < 4; j++ { i += uint32(b[j]) << (24 - j*8) } return } func BuildShadowHeader(length uint32) (b [8]byte) { var i int for ; i < 4; i++ { b[i] = FLAG[i] } a := Uint32ToBytes(length) for ; i < 8; i++ { b[i] = a[i-4] } return } func WriteShadow(b []byte, im image.Image) (out image.Image, err error) { max := im.Bounds().Max.X*im.Bounds().Max.Y/8 - 64 b_len := len(b) if len(b) > max { return nil, errors.New("image does not have enough space for shadow.") } head := BuildShadowHeader(uint32(b_len)) var bb byte var bs [8]byte var i int out, err = SetImage(im, func(index, x, y int, in, out image.Image) { rgba := readRGBAColor(im.At(x, y)) if index < b_len*8+64 { if index < 64 { bb = head[index/8] } else { bb = b[index/8-8] } bs = Byte2bits(bb) i = index % 8 if bs[i] != rgba.R&1 { if bs[i] == 0 { rgba.R -= 1 } else { rgba.R += 1 } } } if v := out.(*image.RGBA); v != nil { v.SetRGBA(x, y, rgba) } }) if err != nil { return nil, err } return } func ReadShadowData(im image.Image) (b []byte, err error) { head, err := ReadShadowHeader(im) if err != nil { return nil, err } length := int(ReadShadowLength(head)) var bk []byte = make([]byte, length*8) b = make([]byte, length) _, err = SetImage(im, func(index, x, y int, in, out image.Image) { if index >= 64 && index < length*8+64 { R := readRGBAColor(im.At(x, y)).R bk[index-64] = uint8(R & 1) } }) var bb [8]byte var bs []byte for i := 0; i < length; i++ { bs = bk[8*i : 8*(i+1)] for j := 0; j < 8; j++ { bb[j] = bs[j] } b[i] = Bits2Byte(bb) } return } func ReadShadowHeader(im image.Image) (b [8]byte, err error) { var bm [64]byte _, err = SetImage(im, func(index, x, y int, in, out image.Image) { rgba := readRGBAColor(im.At(x, y)) if index < 64 { bm[index] = uint8(rgba.R & 1) } }) if err != nil { return } var bb [8]byte var bs []byte for i := 0; i < 8; i++ { bs = bm[8*i : 8*(i+1)] for j := 0; j < 8; j++ { bb[j] = bs[j] } b[i] = Bits2Byte(bb) } return } func ReadShadowFlag(b [8]byte) (a [4]byte) { for i := 0; i < 4; i++ { a[i] = b[i] } return } func ReadShadowLength(b [8]byte) uint32 { var bb [4]byte for i := 4; i < 8; i++ { bb[i-4] = b[i] } return Bytes2Uint32(bb) } func OpenImage(path string) (image.Image, error) { im_read, err := os.Open(path) defer im_read.Close() if err != nil { return nil, err } im, _, err := image.Decode(im_read) if err != nil { return nil, err } return im, nil } //modify image func SetImage(im image.Image, f func(index, x, y int, in, out image.Image)) (out image.Image, err error) { if f == nil { return im, nil } index := 0 bounds := im.Bounds() out = image.NewRGBA(bounds) var m *image.RGBA = out.(*image.RGBA) for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { m.Set(x, y, im.At(x, y)) f(index, x, y, im, out) index += 1 } } return out, nil } //conert any color to RABGA color. func readRGBAColor(from_color color.Color) color.RGBA { return color.RGBAModel.Convert(from_color).(color.RGBA) } //only write to jpeg formats. func WriteImage(path string, im image.Image) error { out, err := os.OpenFile(path, os.O_CREATE, os.ModePerm) defer out.Close() if err != nil { return err } err = png.Encode(out, im) if err != nil { return err } return nil } var read_in string var write_out string var data string func init() { flag.StringVar(&read_in, "in", "", "image path read in.") flag.StringVar(&write_out, "out", "out.jpg", "image path write out.") flag.StringVar(&data, "data", "", "data to shadow.") } func errHandle(err error) { if err != nil { log.Fatal(err) } } func main() { flag.Parse() if read_in == "" { fmt.Println("Options:") flag.PrintDefaults() return } im, err := OpenImage(read_in) errHandle(err) if data != "" { out, err := WriteShadow([]byte(data), im) errHandle(err) err = WriteImage(write_out, out) errHandle(err) } else { head, err := ReadShadowHeader(im) errHandle(err) _flag := ReadShadowFlag(head) if _flag != FLAG { fmt.Println("image doesn't have shadow data.") return } data, err := ReadShadowData(im) errHandle(err) fmt.Println("shadow:", string(data)) } }
以上所述就是本文的全部内容了,希望大家能够喜欢。
相关推荐
cleanerxiaoqiang 2020-06-16
zrtlin 2020-11-09
xuebingnan 2020-11-05
wikiwater 2020-10-27
heheeheh 2020-10-19
Crazyshark 2020-09-15
softwear 2020-08-21
ZGCdemo 2020-08-16
jczwilliam 2020-08-16
littleFatty 2020-08-16
idning 2020-08-03
jinxiutong 2020-07-26
lanzhusiyu 2020-07-19
Skyline 2020-07-04
xiaofanguan 2020-06-25
Aveiox 2020-06-23