I would probably prefer to use pressly/chi, but I guess it makes no difference. I imagine given an input URL like this example.com/Jd8saD.jpg?resize=420x320&fit=crop&rotate=90
, then it would go to the following GET function because of r.Get("/:image", ImageGET)
:
function ImageGET(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("resize") != "" {
// do something
}
if r.URL.Query().Get("crop") != "" {
// do something
}
if r.URL.Query().Get("watermark") != "" {
// do something
}
etc
}
Now, my question is, how should I design whatever function does the image processing so that it will process everything properly and efficiently? I don't expect you to write code that will handle the resizing, but how would these functions look like? Perhaps:
function Resize(size string) (imgfile?, error) {
// the resize stuff
}
What would that returned imgfile
even be? A struct containing some relevant img info?
Likely,
imgfile
will satisfy the image.Image
interface and not the data saved on disk (ie. the actual jpg file)
Image is a finite rectangular grid of color.Color values taken from a color model.
Lots of 3rd party golang image libraries use image.Image
to manipulate images.
I would use a standard image.Image
interface retrieved (read to memory) by a filename in the imageGET
function and modified according to the queries. You can see also the jpeg golang library from the standard lib.
function ImageGET(w http.ResponseWriter, r *http.Request) {
// GetJPEGImageFromFileSystem must decode os.File content and
// return a golang image.Image interface
img, _ := GetJPEGImageFromFileSystem(r.URL.Query().Get("filename"))
if r.URL.Query().Get("resize") != "" {
// If resizing, write over the image.Image in Memory,
// but not the image File on disk
img, _ = Resize(img, r.URL.Query().GET("resize"))
}
// etc...
}
function Resize(img image.Image, size string) (image.Image, error) {
// the resize stuff -- or, alternatively just call a dependency in the original handler to resize
return resizedImage, nil
}
Now, my question is, how should I design whatever function does the image processing so that it will process everything properly and efficiently?
Depends on the package you are using for your stuff and what you want to do with it. If you look for example to the imaging package you see that they return always: *image.NRGBA
That type implements the image.Image
interface.
At the next step you can use the Encode function.
func Encode(w io.Writer, img image.Image, format Format) error
As you see that function uses a io.Writer.
function ImageGET(w http.ResponseWriter, r *http.Request) {
// ...
imaging.Encode(w,img,imaging.PNG)
// ...
So you just need to use the writer from the your handler there and ready.
So to keep your function correct just return the image.Image
interface.