通过Martini提供解码后的图像。

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

Serve a decoded image via Martini

问题

我目前正在玩耍golang和Martini等,想要动态地提供一些处理/生成的图像。这是一个最简单的例子:

package main

import (
    "github.com/codegangsta/martini"
    "github.com/nfnt/resize"
    "image"
    "image/jpeg"
    "log"
    "os"
)

func thumb() image.Image {
    file, err := os.Open("test.jpg")
    if err != nil {
        log.Fatal(err)
    }

    img, err := jpeg.Decode(file)
    if err != nil {
        log.Fatal(err)
    }
    file.Close()

    m := resize.Resize(0, 200, img, resize.MitchellNetravali)

    return m
}

func main() {
    m := martini.Classic()
    m.Get("/", func() image.Image {
        return thumb()
    })
    m.Run()
}

这个代码可以正常编译,但是返回的不是一个图像,而是一些"Content-Type:text/plain; charset=utf-8"的内容,看起来像这样:

<*image.RGBA64 Value>

我相当确定我需要再次对图像进行编码,然后提供它。但是我不太确定如何在不将图像保存到磁盘的情况下做到这一点...

提前感谢!

英文:

I am currently playing around with golang and Martini and such and wanted to dynamically serve some manipulated/generated images. Here's a minimal example:

package main

import (
    &quot;github.com/codegangsta/martini&quot;
    &quot;github.com/nfnt/resize&quot;
    &quot;image&quot;
    &quot;image/jpeg&quot;
    &quot;log&quot;
    &quot;os&quot;
)

func thumb() image.Image {
    file, err := os.Open(&quot;test.jpg&quot;)
    if err != nil {
        log.Fatal(err)
    }

    img, err := jpeg.Decode(file)
    if err != nil {
        log.Fatal(err)
    }
    file.Close()
    
    m := resize.Resize(0, 200, img, resize.MitchellNetravali)

    return m
}

func main() {
    m := martini.Classic()
    m.Get(&quot;/&quot;) image.Image {
        return thumb()
    })
    m.Run()
}

That compiles fine, but instead of serving an image, I get some "Content-Type:text/plain; charset=utf-8" that looks like this:

&lt;*image.RGBA64 Value&gt;

I am pretty sure that I need to encode the image again and then serve it. But im not quite sure how to do this without saving the image to the disk...

Thanks in advance!

答案1

得分: 7

你可以直接向ResponseWriter写入内容,因为它实现了io.Writer接口,无需使用缓冲区或将图像复制到磁盘。

你已经接近成功了,只需要设置内容类型,并像你提到的那样将image.Image对象重新编码为jpeg格式。幸运的是,jpeg.Encode()方法需要一个写入器来写入,而且由于Martini具有将其注入到处理程序中的能力,你可以随时使用ResponseWriter来完成这个任务。

注意:你可能希望进行更健壮的错误处理,而不仅仅是我提供的这样简单的处理方式。这只是为了让事情开始进行而已。;)

package main

import (
	"image"
	"image/jpeg"
	"log"
	"net/http"
	"os"

	"github.com/codegangsta/martini"
	"github.com/nfnt/resize"
)

func thumb() image.Image {
	file, err := os.Open("test.jpg")
	if err != nil {
		log.Fatal(err)
	}

	img, err := jpeg.Decode(file)
	if err != nil {
		log.Fatal(err)
	}
	file.Close()

	m := resize.Resize(0, 200, img, resize.MitchellNetravali)

	return m
}

func main() {
	m := martini.Classic()

	m.Get("/", func(res http.ResponseWriter, req *http.Request) {
		res.Header().Set("Content-Type", "image/jpeg")
		err := jpeg.Encode(res, thumb(), &jpeg.Options{100})
		if err != nil {
			res.WriteHeader(500)
		} else {
			res.WriteHeader(200)
		}
	})
	m.Run()
}
英文:

You can write to the ResponseWriter directly because it implements the io.Writer interface, no need to use a buffer or copy the image to disk.

You were almost there, just needed to set the content type and like you mentioned encode the image.Image object back into a jpeg. Luckily, the jpeg.Encode() method needed a writer to write to and you have the ResponseWriter available at your disposal to do just that thanks to Martini having the ability to inject it into your handler.

Note: you will probably want to do a more robust job of error handling than I have provided. This is just to get the ball rolling. 通过Martini提供解码后的图像。

package main

import (
	&quot;image&quot;
	&quot;image/jpeg&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;os&quot;

	&quot;github.com/codegangsta/martini&quot;
	&quot;github.com/nfnt/resize&quot;
)

func thumb() image.Image {
	file, err := os.Open(&quot;test.jpg&quot;)
	if err != nil {
		log.Fatal(err)
	}

	img, err := jpeg.Decode(file)
	if err != nil {
		log.Fatal(err)
	}
	file.Close()

	m := resize.Resize(0, 200, img, resize.MitchellNetravali)

	return m
}

func main() {
	m := martini.Classic()

	m.Get(&quot;/&quot;, func(res http.ResponseWriter, req *http.Request) {
		res.Header().Set(&quot;Content-Type&quot;, &quot;image/jpeg&quot;)
		err := jpeg.Encode(res, thumb(), &amp;jpeg.Options{100})
		if err != nil {
			res.WriteHeader(500)
		} else {
			res.WriteHeader(200)
		}
	})
	m.Run()
}

huangapple
  • 本文由 发表于 2014年3月22日 01:27:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/22565544.html
匿名

发表评论

匿名网友

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

确定