英文:
writing extra data into io.Writer
问题
我正在尝试弄清楚如何更改jpeg.Encode
API(http://golang.org/pkg/image/jpeg/#Encode)的行为,该API接受一个io.Writer
作为参数,并将文件写入其中。
我需要在写入文件的前两个字节之后插入一组字节,并且我认为可以在不将所有内容保存在内存中的情况下完成。我对Golang还不熟悉,我找到了io.Pipe
,它连接了一个读取器和一个写入器,但我不知道如何将其用于我所需的情况。
有人可以帮忙吗?
编辑:我应该只是实现自己的io.Writer
接口吗?
英文:
I am trying to figure out how to change the behaviour of jpeg.Encode
API (http://golang.org/pkg/image/jpeg/#Encode) that takes an io.Writer
as a parameter and writes the file to it.
I need to insert a set of bytes after the first two bytes written in to the file, and I think it is possible to do without keeping everything in memory. I am new to Golang, I found io.Pipe
that connects a reader and a writer, but I do not understand how to use it for what I need.
Could someone help?
EDIT: should I just implement my own io.Writer
interface?
答案1
得分: 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() {
// 蓝色矩形,从Nigel Tao的帖子中借来
// 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) // 在位置2添加三个字节
jpeg.Encode(bi, img, nil)
file.Close()
fmt.Println("已写入!")
}
话虽如此,编辑流以自定义图像对我来说似乎有点破坏性。
英文:
If you know upfront the bytes you need to add in the stream (whatever the stream, image or not), building a Writer object for this specific purpose is not really hard.
Here is an example:
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!")
}
That said, editing a stream to customize an image seems really hackish to me.
答案2
得分: 2
除非您能直接获取具有正确内容的图像(即您需要的额外字节),否则您确实需要提供自己的Writer。
第一种策略例如在signer/signer.go
中进行了说明:您可以修改图像以添加所需的信息(在jianfengye/image-sign
项目中的情况是添加签名)。
但是,如果您无法将这些信息添加到图像中,则需要提供一个Writer来管理所需的写入操作。jpeg/writer.go
已经实现了这一点,它使用自己的内部writer
类型。
一旦jpeg writer 开始写入图像,它将调用您自己的Writer,然后您可以决定是否添加这些额外的字节。
_, e.err = e.w.Write(p)
英文:
Unless you manage to get an Image directly with the right content (meaning the extra bytes you need), you would have indeed to provide your own Writer.
The first strategy is illustrated for instance in signer/signer.go
: you modify an image in order to add the information you want (in the case of the jianfengye/image-sign
project: a signature)
But if you cannot add those to the Image, then you need to provide a Writer which will manage the expected writing.
jpeg/writer.go
does already that, with its own internal writer
type.
Once the jpeg writer starts to write the Image, it will call your own Writer, which can then decide to add those extra bytes or not.
_, e.err = e.w.Write(p)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论