寻找更好的方法将内存中的图像保存到文件中。

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

Looking for better way to save an in memory image to file

问题

代码的目标是下载一张图片,将其粘贴到一个更大的父图片上,并保存结果。

经过多次失败后,我最终得到了以下可以工作的代码。

然而,是否有比使用bytes.Bufferwriter更好的方法来将目标图片保存到文件或传递给http响应?

package main

import (
	"image"
	"image/draw"
	"image/jpeg"
	"os"
	"bufio"
	"bytes"
	"log"
	"net/http"
)

func main() {
	// 获取一张图片。
	resp, err := http.Get("http://katiebrookekennels.com/wp-content/uploads/2014/10/dog-bone4.jpg")
	if err != nil {
		log.Panic(err)
	}
	defer resp.Body.Close()

	// 在内存中保留一份副本。
	myImage, err := jpeg.Decode(resp.Body)

	if err != nil {
		log.Panic(err)
	}

	// 准备父图片,确定子图片的位置。
	target := image.NewRGBA(image.Rect(0, 0, 800, 800))
	// 绘制白色图层。
	draw.Draw(target, target.Bounds(), image.White, image.ZP, draw.Src)
	// 绘制子图片。
	draw.Draw(target, myImage.Bounds(), myImage, image.Point{0, 0}, draw.Src)

	// 编码为jpeg格式。
	var imageBuf bytes.Buffer
	err = jpeg.Encode(&imageBuf, target, nil)

	if err != nil {
		log.Panic(err)
	}

	// 写入文件。
	fo, err := os.Create("img.jpg")
	if err != nil {
		panic(err)
	}
	fw := bufio.NewWriter(fo)

	fw.Write(imageBuf.Bytes())
}
英文:

The goal of the code is to download an image, stick it to a larger parent image and save the result.

After quite a few failures I ended up with the following code that does work.

However, is there a better way than using bytes.Buffer and a writer to save the target image to a file / pass it to an httpResponse?

<!-- language: go -->

package main

import (
	&quot;image&quot;
	&quot;image/draw&quot;
	&quot;image/jpeg&quot;
	&quot;os&quot;
	// &quot;image/color&quot;
	// &quot;io/ioutil&quot;
	// &quot;fmt&quot;
	&quot;bufio&quot;
	&quot;bytes&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)

func main() {
	// Fetch an image.
	resp, err := http.Get(&quot;http://katiebrookekennels.com/wp-content/uploads/2014/10/dog-bone4.jpg&quot;)
	if err != nil {
		log.Panic(err)
	}
	defer resp.Body.Close()

	// Keep an in memory copy.
	myImage, err := jpeg.Decode(resp.Body)

	if err != nil {
		log.Panic(err)
	}

	// Prepare parent image where we want to position child image.
	target := image.NewRGBA(image.Rect(0, 0, 800, 800))
	// Draw white layer.
	draw.Draw(target, target.Bounds(), image.White, image.ZP, draw.Src)
	// Draw child image.
	draw.Draw(target, myImage.Bounds(), myImage, image.Point{0, 0}, draw.Src)

	// Encode to jpeg.
	var imageBuf bytes.Buffer
	err = jpeg.Encode(&amp;imageBuf, target, nil)

	if err != nil {
		log.Panic(err)
	}

	// Write to file.
	fo, err := os.Create(&quot;img.jpg&quot;)
	if err != nil {
		panic(err)
	}
	fw := bufio.NewWriter(fo)

	fw.Write(imageBuf.Bytes())
}

答案1

得分: 12

jpeg.Encode() 函数需要一个 io.Writer 对象来将编码后的图像写入(以 JPEG 格式)。*os.Filehttp.ResponseWriter 也都实现了 io.Writer 接口,因此你可以直接传递一个文件或者 HTTP 响应的写入器,而不是使用 bytes.Buffer

将图像直接保存到文件中的示例代码如下:

f, err := os.Create("img.jpg")
if err != nil {
    panic(err)
}
defer f.Close()
if err = jpeg.Encode(f, target, nil); err != nil {
    log.Printf("failed to encode: %v", err)
}

将图像作为响应返回的示例代码如下:

// w 是类型为 http.ResponseWriter 的对象:
if err := jpeg.Encode(w, target, nil); err != nil {
    log.Printf("failed to encode: %v", err)
}

你可以在以下问题中找到一些示例代码(保存/加载 JPEG 和 PNG 图像):

https://stackoverflow.com/questions/28992396/draw-a-rectangle-in-golang/29004191#29004191

https://stackoverflow.com/questions/38299930/how-to-add-a-simple-text-label-to-an-image-in-go/38300583#38300583

https://stackoverflow.com/questions/36573413/change-color-of-a-single-pixel-go-lang-image/36577076#36577076

英文:

jpeg.Encode() expects an io.Writer to write the encoded image to (in JPEG format). Both *os.File and http.ResponseWriter implement io.Writer too, so instead of a bytes.Buffer, you can directly pass a file or HTTP response writer too.

To save an image directly to a file:

f, err := os.Create(&quot;img.jpg&quot;)
if err != nil {
    panic(err)
}
defer f.Close()
if err = jpeg.Encode(f, target, nil); err != nil {
    log.Printf(&quot;failed to encode: %v&quot;, err)
}

To serve it as an image:

// w is of type http.ResponseWriter:
if err := jpeg.Encode(w, target, nil); err != nil {
    log.Printf(&quot;failed to encode: %v&quot;, err)
}

You can see some examples in these questions (saving/loading JPEG and PNG images):

https://stackoverflow.com/questions/28992396/draw-a-rectangle-in-golang/29004191#29004191

https://stackoverflow.com/questions/38299930/how-to-add-a-simple-text-label-to-an-image-in-go/38300583#38300583

https://stackoverflow.com/questions/36573413/change-color-of-a-single-pixel-go-lang-image/36577076#36577076

huangapple
  • 本文由 发表于 2016年10月8日 07:42:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/39927182.html
匿名

发表评论

匿名网友

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

确定