欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

go语言实现将重要数据写入图片中

程序员文章站 2022-11-15 12:59:41
原理:将数据的二进制形式写入图像红色通道数据二进制的低位 只支持png格式的输出 写入数据 go run shadow.go -in="c.jpg" -data="h...

原理:将数据的二进制形式写入图像红色通道数据二进制的低位
只支持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))
    }
}

以上所述就是本文的全部内容了,希望大家能够喜欢。