英文:
Append images without creating temporary files with Golang and imagemagick. Is it possible?
问题
我想在Golang和imagemagick中追加图像而不创建临时文件。是否可以像这样做?
似乎我不能有多个stdin。
func main() {
var output bytes.Buffer
buff1 := new(bytes.Buffer)
f1, _ := os.Open("image/1.png")
defer f1.Close()
img1, _, _ := image.Decode(f1)
png.Encode(buff1, img1)
buff2 := new(bytes.Buffer)
f2, _ := os.Open("image/2.png")
defer f1.Close()
img2, _, _ := image.Decode(f2)
png.Encode(buff2, img2)
buff3 := new(bytes.Buffer)
f3, _ := os.Open("image/3.png")
defer f1.Close()
img3, _, _ := image.Decode(f3)
png.Encode(buff3, img3)
cmd := exec.Command("convert", []string{"png:-", "png:-", "+append", "png:-"}...)
cmd.Stdin = bytes.NewReader(buff1.Bytes())
// ? buff2.Bytes()
// ? buff3.Bytes()
cmd.Stdout = &output
if err := cmd.Run(); err != nil {
fmt.Println("failed: %w", err)
}
fmt.Println(len(output.Bytes()))
imgPng, _, _ := image.Decode(bytes.NewReader(output.Bytes()))
out, _ := os.Create("result.png")
png.Encode(out, imgPng)
}
英文:
I would like to append images without creating temporary files with Golang and imagemagick. Is it possible to do something like this ?
Seems like i can't have multiple stdin.
func main() {
var output bytes.Buffer
buff1 := new(bytes.Buffer)
f1, _ := os.Open("image/1.png")
defer f1.Close()
img1, _, _ := image.Decode(f1)
png.Encode(buff1, img1)
buff2 := new(bytes.Buffer)
f2, _ := os.Open("image/2.png")
defer f1.Close()
img2, _, _ := image.Decode(f2)
png.Encode(buff2, img2)
buff3 := new(bytes.Buffer)
f3, _ := os.Open("image/3.png")
defer f1.Close()
img3, _, _ := image.Decode(f3)
png.Encode(buff3, img3)
cmd := exec.Command("convert", []string{"png:-", "png:-", "+append", "png:-"}...)
cmd.Stdin = bytes.NewReader(buff1.Bytes())
// ? buff2.Bytes()
// ? buff3.Bytes()
cmd.Stdout = &output
if err := cmd.Run(); err != nil {
fmt.Println("failed: %w", err)
}
fmt.Println(len(output.Bytes()))
imgPng, _, _ := image.Decode(bytes.NewReader(output.Bytes()))
out, _ := os.Create("result.png")
png.Encode(out, imgPng)
}
答案1
得分: 1
你可以在大多数现代Unix操作系统上使用这种方法:
对于每个文件:
- 通过
os.Pipe
创建一个管道。 - 创建一个goroutine将图像数据写入写入管道
*os.File
,并在完成后关闭它。 - 将每个读取管道
*os.File
附加到exec.Cmd.ExtraFiles
。第一个文件/管道可以通过/dev/fd/3
、/dev/fd/4
等访问。
还需要确保在出现错误时通过关闭每个管道*os.File
来释放goroutine。
这个方法相对复杂,而且不完全可移植。更简单的方法是创建临时文件(例如,通过os.CreateTemp
),然后在使用后进行清理。实际上,这些文件可能会存储在内存文件系统中(例如,当/tmp使用tmpfs时)。
英文:
You can use this approach on most modern Unix OSes:
For each file:
- Create a pipe via
os.Pipe
- Create a goroutine to write your image data into the write pipe
*os.File
and close it when finished. - Append each read pipe
*os.File
toexec.Cmd.ExtraFiles
. The first file/pipe will be accessible via/dev/fd/3
, then/dev/fd/4
, etc..
You will also need to ensure the goroutines are released if there is an error by closing each pipe *os.File
afterwards.
This is reasonably complex, and not totally portable. It's a bit simpler to just create temporary files (eg, via os.CreateTemp
) and cleanup afterwards. In practice these files may be stored on a memory filesystem anyway (eg, when /tmp is using tmpfs).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论