将额外的数据写入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?

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.

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)