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)) } }
以上所述就是本文的全部内容了,希望大家能够喜欢。