我正在尝试弄清楚如何更改jpeg.Encode
API(http://golang.org/pkg/image/jpeg/#Encode)的行为,该行为将io.Writer
作为参数并将文件写入其中。
我需要在写入文件的前两个字节之后插入一组字节,我认为可以不将所有内容保存在内存中。我是Golang的新手,我发现io.Pipe
连接了读者和作家,但我不明白如何将它用于我需要的东西。
有人可以帮忙吗?
编辑:我应该实现自己的io.Writer
界面吗?
答案 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)