最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go語言實現將重要數據寫入圖片中

 更新時間:2015年03月20日 09:43:57   投稿:hebedich  
本文給大家分享的是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))
    }
}

以上所述就是本文的全部內容了,希望大家能夠喜歡。

相關文章

  • golang 輸出重定向:fmt Log,子進程Log,第三方庫logrus的詳解

    golang 輸出重定向:fmt Log,子進程Log,第三方庫logrus的詳解

    這篇文章主要介紹了golang 輸出重定向:fmt Log,子進程Log,第三方庫logrus的詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang設計模式之生成器模式講解和代碼示例

    Golang設計模式之生成器模式講解和代碼示例

    生成器是一種創(chuàng)建型設計模式,使你能夠分步驟創(chuàng)建復雜對象,與其他創(chuàng)建型模式不同,生成器不要求產品擁有通用接口,這使得用相同的創(chuàng)建過程生成不同的產品成為可能,本文就通過代碼示例為大家詳細介紹Golang生成器模式,感興趣的同學可以參考下
    2023-06-06
  • 關于go語言載入json可能遇到的一個坑

    關于go語言載入json可能遇到的一個坑

    Go 語言從新手到大神,每個人多少都會踩一些坑,那么下面這篇文章主要給大家介紹了關于go語言載入json可能遇到的一個坑,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-07-07
  • golang結構化日志log/slog包之slog.Record的用法簡介

    golang結構化日志log/slog包之slog.Record的用法簡介

    這篇文章主要為大家詳細介紹了golang結構化日志log/slog包中slog.Record結構體的使用方法和需要注意的點,文中的示例代碼講解詳細,需要的可以學習一下
    2023-10-10
  • Golang中的同步工具sync.WaitGroup詳解

    Golang中的同步工具sync.WaitGroup詳解

    這篇文章主要詳細為大家介紹了Golang中的同步工具sync.WaitGroup,文中有詳細的代碼示例,具有很好的參考價值,希望對大家有所幫助,一起跟隨小編過來看看吧
    2023-05-05
  • GoFrame?gredis緩存DoVar及Conn連接對象的自動序列化

    GoFrame?gredis緩存DoVar及Conn連接對象的自動序列化

    這篇文章主要為大家介紹了GoFrame?gredis干貨DoVar?Conn連接對象自動序列化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 詳解go語言判斷管道是否關閉的常見誤區(qū)

    詳解go語言判斷管道是否關閉的常見誤區(qū)

    這篇文章主要想和大家一起探討一下在Go語言中,我們是否可以使用讀取管道時的第二個返回值來判斷管道是否關閉,文中的示例代碼講解詳細,有興趣的可以了解下
    2023-10-10
  • 詳解go基于viper實現配置文件熱更新及其源碼分析

    詳解go基于viper實現配置文件熱更新及其源碼分析

    這篇文章主要介紹了詳解go基于viper實現配置文件熱更新及其源碼分析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • Golang?中的?條件變量(sync.Cond)詳解

    Golang?中的?條件變量(sync.Cond)詳解

    這篇文章主要介紹了Golang?中的?條件變量(sync.Cond)詳解的相關資料,需要的朋友可以參考下
    2022-12-12
  • 利用go語言編寫一個并發(fā)包

    利用go語言編寫一個并發(fā)包

    這篇文章主要為大家詳細介紹了如何利用go語言編寫一個并發(fā)包,適合大部分并發(fā)任務,開箱即用,文中的示例代碼講解詳細,有需要的小伙伴可以參考下
    2023-10-10

最新評論

金溪县| 文化| 天峻县| 华阴市| 尚志市| 万源市| 武乡县| 望都县| 淳化县| 诏安县| 长丰县| 穆棱市| 乐昌市| 卓资县| 黄平县| 新巴尔虎右旗| 湖南省| 芦溪县| 兴义市| 海伦市| 惠州市| 西林县| 阜阳市| 五台县| 双流县| 广平县| 溧阳市| 祁阳县| 徐汇区| 浠水县| 阿巴嘎旗| 唐河县| 马尔康县| 松溪县| 镇赉县| 石台县| 六枝特区| 衡阳县| 宕昌县| 蒲城县| 皮山县|