go语言实现将重要数据写入图片中
原理:将数据的二进制形式写入图像红色通道数据二进制的低位
只支持png格式的输出
写入数据
gorunshadow.go-in="c.jpg"-data="hideme"-out="out.png"
读取数据
gorunshadow.go-in="out.png"
packagemain
import(
"errors"
"flag"
"fmt"
"image"
"image/color"
_"image/jpeg"
"image/png"
"log"
"math"
"os"
)
varFLAG=[4]byte{0x13,0x14,0x52,0x00}//shadowflag.
//byteto8bits
funcByte2bits(bbyte)(a[8]byte){
varcuint8=7
variuint8
fori=0;i<8;i++{
a[i]=b>>(c-i)&1
}
return
}
//8bitstobyte.
funcBits2Byte(a[8]byte)(bbyte){
fori:=0;i<8;i++{
b+=a[i]*uint8(math.Pow(2,float64(7-i)))
}
return
}
//uint32to4bytes.
funcUint32ToBytes(iuint32)(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
}
//4bytestouint32.
funcBytes2Uint32(b[4]byte)(iuint32){
varjuint32
for;j<4;j++{
i+=uint32(b[j])<<(24-j*8)
}
return
}
funcBuildShadowHeader(lengthuint32)(b[8]byte){
variint
for;i<4;i++{
b[i]=FLAG[i]
}
a:=Uint32ToBytes(length)
for;i<8;i++{
b[i]=a[i-4]
}
return
}
funcWriteShadow(b[]byte,imimage.Image)(outimage.Image,errerror){
max:=im.Bounds().Max.X*im.Bounds().Max.Y/8-64
b_len:=len(b)
iflen(b)>max{
returnnil,errors.New("imagedoesnothaveenoughspaceforshadow.")
}
head:=BuildShadowHeader(uint32(b_len))
varbbbyte
varbs[8]byte
variint
out,err=SetImage(im,func(index,x,yint,in,outimage.Image){
rgba:=readRGBAColor(im.At(x,y))
ifindex<b_len*8+64{
ifindex<64{
bb=head[index/8]
}else{
bb=b[index/8-8]
}
bs=Byte2bits(bb)
i=index%8
ifbs[i]!=rgba.R&1{
ifbs[i]==0{
rgba.R-=1
}else{
rgba.R+=1
}
}
}
ifv:=out.(*image.RGBA);v!=nil{
v.SetRGBA(x,y,rgba)
}
})
iferr!=nil{
returnnil,err
}
return
}
funcReadShadowData(imimage.Image)(b[]byte,errerror){
head,err:=ReadShadowHeader(im)
iferr!=nil{
returnnil,err
}
length:=int(ReadShadowLength(head))
varbk[]byte=make([]byte,length*8)
b=make([]byte,length)
_,err=SetImage(im,func(index,x,yint,in,outimage.Image){
ifindex>=64&&index<length*8+64{
R:=readRGBAColor(im.At(x,y)).R
bk[index-64]=uint8(R&1)
}
})
varbb[8]byte
varbs[]byte
fori:=0;i<length;i++{
bs=bk[8*i:8*(i+1)]
forj:=0;j<8;j++{
bb[j]=bs[j]
}
b[i]=Bits2Byte(bb)
}
return
}
funcReadShadowHeader(imimage.Image)(b[8]byte,errerror){
varbm[64]byte
_,err=SetImage(im,func(index,x,yint,in,outimage.Image){
rgba:=readRGBAColor(im.At(x,y))
ifindex<64{
bm[index]=uint8(rgba.R&1)
}
})
iferr!=nil{
return
}
varbb[8]byte
varbs[]byte
fori:=0;i<8;i++{
bs=bm[8*i:8*(i+1)]
forj:=0;j<8;j++{
bb[j]=bs[j]
}
b[i]=Bits2Byte(bb)
}
return
}
funcReadShadowFlag(b[8]byte)(a[4]byte){
fori:=0;i<4;i++{
a[i]=b[i]
}
return
}
funcReadShadowLength(b[8]byte)uint32{
varbb[4]byte
fori:=4;i<8;i++{
bb[i-4]=b[i]
}
returnBytes2Uint32(bb)
}
funcOpenImage(pathstring)(image.Image,error){
im_read,err:=os.Open(path)
deferim_read.Close()
iferr!=nil{
returnnil,err
}
im,_,err:=image.Decode(im_read)
iferr!=nil{
returnnil,err
}
returnim,nil
}
//modifyimage
funcSetImage(imimage.Image,ffunc(index,x,yint,in,outimage.Image))(outimage.Image,errerror){
iff==nil{
returnim,nil
}
index:=0
bounds:=im.Bounds()
out=image.NewRGBA(bounds)
varm*image.RGBA=out.(*image.RGBA)
fory:=bounds.Min.Y;y<bounds.Max.Y;y++{
forx:=bounds.Min.X;x<bounds.Max.X;x++{
m.Set(x,y,im.At(x,y))
f(index,x,y,im,out)
index+=1
}
}
returnout,nil
}
//conertanycolortoRABGAcolor.
funcreadRGBAColor(from_colorcolor.Color)color.RGBA{
returncolor.RGBAModel.Convert(from_color).(color.RGBA)
}
//onlywritetojpegformats.
funcWriteImage(pathstring,imimage.Image)error{
out,err:=os.OpenFile(path,os.O_CREATE,os.ModePerm)
deferout.Close()
iferr!=nil{
returnerr
}
err=png.Encode(out,im)
iferr!=nil{
returnerr
}
returnnil
}
varread_instring
varwrite_outstring
vardatastring
funcinit(){
flag.StringVar(&read_in,"in","","imagepathreadin.")
flag.StringVar(&write_out,"out","out.jpg","imagepathwriteout.")
flag.StringVar(&data,"data","","datatoshadow.")
}
funcerrHandle(errerror){
iferr!=nil{
log.Fatal(err)
}
}
funcmain(){
flag.Parse()
ifread_in==""{
fmt.Println("Options:")
flag.PrintDefaults()
return
}
im,err:=OpenImage(read_in)
errHandle(err)
ifdata!=""{
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("imagedoesn'thaveshadowdata.")
return
}
data,err:=ReadShadowData(im)
errHandle(err)
fmt.Println("shadow:",string(data))
}
}
以上所述就是本文的全部内容了,希望大家能够喜欢。