将额外数据写入io.Writer

时间:2014-12-31 06:30:27

标签: go

我正在尝试弄清楚如何更改jpeg.Encode API(http://golang.org/pkg/image/jpeg/#Encode)的行为,该行为将io.Writer作为参数并将文件写入其中。

我需要在写入文件的前两个字节之后插入一组字节,我认为可以不将所有内容保存在内存中。我是Golang的新手,我发现io.Pipe连接了读者和作家,但我不明白如何将它用于我需要的东西。

有人可以帮忙吗?

编辑:我应该实现自己的io.Writer界面吗?

2 个答案:

答案 0 :(得分:6)

如果您事先知道需要在流中添加的字节(无论是否为流,图像),为此特定目的构建Writer对象并不是很难。

以下是一个例子:

package main

import (
    "fmt"
    "image"
    "image/draw"
    "image/jpeg"
    "image/color"
    "os"
    "io"
)

type ByteInserter struct {
    n   int
    b   []byte
    pos int
    w   io.Writer
}

func NewByteInserter(w io.Writer) *ByteInserter {
    return &ByteInserter{w:w}
}

func (bi* ByteInserter) Set( b[]byte, pos int ) {
    bi.b = b
    bi.pos = pos
}

func (bi *ByteInserter) Write( p []byte ) (n int, err error) {
    if bi.n>bi.pos || bi.n+len(p)<=bi.pos {
        n, err = bi.w.Write(p)
        bi.n += n
    } else {
        cut := bi.pos-bi.n
        if cut > 0 {
            n,err = bi.w.Write(p[:cut])
            bi.n += n
            if err != nil {
                return
            }
        }
        _,err = bi.w.Write(bi.b)
        if err != nil {
            return
        }
        n2 := 0
        n2, err = bi.w.Write(p[cut:])
        bi.n += n2
        n += n2
    }
    return
}

func main() {

    // Blue rectangle, stolen from Nigel Tao's post
    // http://blog.golang.org/go-imagedraw-package
    img := image.NewRGBA(image.Rect(0, 0, 640, 480))
    blue := color.RGBA{0, 0, 255, 255}
    draw.Draw(img, img.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)

    file, err := os.Create("file.jpg")
    if err != nil {
        panic(err)
    }

    bi := NewByteInserter(file)
    bi.Set( []byte("XXX"), 2 )   // Three bytes added at position 2
    jpeg.Encode(bi,img,nil)
    file.Close()

    fmt.Println("Written!")
}

那就是说,编辑一个流来自定义图像对我来说似乎真的很骇人。

答案 1 :(得分:2)

除非您设法直接使用正确的内容获取图像(意味着您需要额外的字节),否则您确实应该提供自己的Writer。

第一个策略例如在signer/signer.go中说明:您修改图像以添加所需信息(在jianfengye/image-sign项目的情况下:签名)

但是如果你不能将它们添加到图像中,那么你需要提供一个能够管理预期书写的Writer。
jpeg/writer.go已经拥有了internal writer type

一旦jpeg作者starts to write the Image,它将call your own Writer,然后可以决定是否添加这些额外的字节。

_, e.err = e.w.Write(p)