使用Golang和ImageMagick在不创建临时文件的情况下追加图像,这是否可能?

huangapple go评论73阅读模式
英文:

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 to exec.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).

huangapple
  • 本文由 发表于 2021年9月23日 14:27:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/69294973.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定