英文:
Looking for better way to save an in memory image to file
问题
代码的目标是下载一张图片,将其粘贴到一个更大的父图片上,并保存结果。
经过多次失败后,我最终得到了以下可以工作的代码。
然而,是否有比使用bytes.Buffer
和writer
更好的方法来将目标图片保存到文件或传递给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 (
"image"
"image/draw"
"image/jpeg"
"os"
// "image/color"
// "io/ioutil"
// "fmt"
"bufio"
"bytes"
"log"
"net/http"
)
func main() {
// Fetch an image.
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()
// 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(&imageBuf, target, nil)
if err != nil {
log.Panic(err)
}
// Write to file.
fo, err := os.Create("img.jpg")
if err != nil {
panic(err)
}
fw := bufio.NewWriter(fo)
fw.Write(imageBuf.Bytes())
}
答案1
得分: 12
jpeg.Encode()
函数需要一个 io.Writer
对象来将编码后的图像写入(以 JPEG 格式)。*os.File
和 http.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
英文:
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("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)
}
To serve it as an image:
// w is of type http.ResponseWriter:
if err := jpeg.Encode(w, target, nil); err != nil {
log.Printf("failed to encode: %v", 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论