Develop a Golang serverless function that processes images uploaded to Azure Blob Storage by resizing them to specific dimensions and saving the resized images back to the storage account.
PLAINFORMAT
package main

import (
	"bytes"
	"context"
	"fmt"
	"image"
	_ "image/jpeg"
	_ "image/png"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/Azure/azure-storage-blob-go/azblob"
	"github.com/nfnt/resize"
)

func main() {
}

// ImageResizeFunction is the entry point for our Azure Function.
func ImageResizeFunction(ctx context.Context, req *http.Request) (interface{}, error) {
	blobURL := req.URL.Query().Get("bloburl")
	if blobURL == "" {
		return nil, fmt.Errorf("missing 'bloburl' query parameter")
	}

	resizedWidth := 100 // Set your desired width here
	resizedHeight := 100 // Set your desired height here

	// Download the image from Blob Storage
	imageBytes, err := downloadImage(blobURL)
	if err != nil {
		return nil, err
	}

	// Resize the image
	resizedImageBytes, err := resizeImage(imageBytes, resizedWidth, resizedHeight)
	if err != nil {
		return nil, err
	}

	// Upload the resized image back to Blob Storage
	err = uploadResizedImage(resizedImageBytes, blobURL)
	if err != nil {
		return nil, err
	}

	return "Image resized and uploaded successfully", nil
}

func downloadImage(blobURL string) ([]byte, error) {
	url, _ := url.Parse(blobURL)
	blobURLParts := azblob.NewBlobURLParts(*url)
	blockBlobURL := azblob.NewBlockBlobURL(*url, getPipeline())

	resp, err := blockBlobURL.Download(context.Background(), 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
	if err != nil {
		return nil, err
	}
	defer resp.Body(azblob.RetryReaderOptions{}).Close()

	body, err := ioutil.ReadAll(resp.Body(azblob.RetryReaderOptions{}))
	if err != nil {
		return nil, err
	}

	return body, nil
}

func resizeImage(imageBytes []byte, width int, height int) ([]byte, error) {
	img, _, err := image.Decode(bytes.NewReader(imageBytes))
	if err != nil {
		return nil, err
	}

	resizedImg := resize.Resize(uint(width), uint(height), img, resize.Lanczos3)

	buf := new(bytes.Buffer)
	err = jpeg.Encode(buf, resizedImg, nil)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func uploadResizedImage(resizedImageBytes []byte, originalBlobURL string) error {
	url, _ := url.Parse(originalBlobURL)
	blobURLParts := azblob.NewBlobURLParts(*url)
	containerURL := azblob.NewContainerURL(blobURLParts.ContainerURL(), getPipeline())

	newBlobName := fmt.Sprintf("%s_resized_%dx%d.jpg", strings.TrimSuffix(blobURLParts.BlobName, filepath.Ext(blobURLParts.BlobName)), resizedWidth, resizedHeight)
	blockBlobURL := containerURL.NewBlockBlobURL(newBlobName)

	_, err := blockBlobURL.Upload(context.Background(), bytes.NewReader(resizedImageBytes), azblob.BlobHTTPHeaders{ContentType: "image/jpeg"}, azblob.Metadata{}, azblob.BlobAccessConditions{})
	return err
}

func getPipeline() azblob.Pipeline {
	accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT"), os.Getenv("AZURE_STORAGE_ACCESS_KEY")
	credential, _ := azblob.NewSharedKeyCredential(accountName, accountKey)
	return azblob.NewPipeline(credential, azblob.PipelineOptions{})
}