Skip to content

Instantly share code, notes, and snippets.

@paulm17
Created March 13, 2019 11:09
Show Gist options
  • Save paulm17/4bd17334660101139a973921924a00b3 to your computer and use it in GitHub Desktop.
Save paulm17/4bd17334660101139a973921924a00b3 to your computer and use it in GitHub Desktop.
error transforming image, Framebuffer contains no pixels
package main
import (
"fmt"
"io/ioutil"
"math"
"os"
"path/filepath"
"strings"
"github.com/discordapp/lilliput"
)
type context struct {
PayloadData payloadData
Decoder lilliput.Decoder
ImageHeader *lilliput.ImageHeader
Dir string
}
type payloadData struct {
FileID string
Filename string
Extension string
}
// EncodeOptions image sizes
var EncodeOptions = map[string]map[int]int{
".jpeg": map[int]int{lilliput.JpegQuality: 85},
".png": map[int]int{lilliput.PngCompression: 7},
".webp": map[int]int{lilliput.WebpQuality: 85},
}
func main() {
p := payloadData{}
p.FileID = "01d5v8kqp4bqwnr33rxz7qzp6b"
p.Filename = "01d5v8kqp4bqwnr33rxz7qzp6b.jpeg"
p.Extension = "jpeg"
c := context{}
c.PayloadData = p
c.Dir = "./upload/dam/"
c.verifyImage()
sizes := []int{150, 600, 1024, 1600}
for _, size := range sizes {
fmt.Sprintf("processing size: %d", size)
err := c.resizeImage(size)
fmt.Println(err)
}
fmt.Println("done")
}
func (c *context) verifyImage() error {
// decoder wants []byte, so read the whole file into a buffer
inputBuf, err := ioutil.ReadFile(c.Dir + c.PayloadData.Filename)
if err != nil {
return fmt.Errorf("failed to read input file, %s", err)
}
decoder, err := lilliput.NewDecoder(inputBuf)
// this error reflects very basic checks,
// mostly just for the magic bytes of the file to match known image formats
if err != nil {
return fmt.Errorf("error decoding image, %s", err)
}
c.Decoder = decoder
header, err := decoder.Header()
// this error is much more comprehensive and reflects
// format errors
if err != nil {
return fmt.Errorf("error reading image header, %s", err)
}
c.ImageHeader = header
return nil
}
func (c *context) resizeImage(outputWidth int) error {
// name of output file, also determines output type
outputFilename := fmt.Sprintf("%d_%s.%s", outputWidth, c.PayloadData.FileID, c.PayloadData.Extension)
// perform stretching resize instead of cropping
stretch := false
// get ready to resize image,
// using 8192x8192 maximum resize buffer size
ops := lilliput.NewImageOps(8192)
defer ops.Close()
// create a buffer to store the output image, 50MB in this case
outputImg := make([]byte, 50*1024*1024)
// use user supplied filename to guess output type if provided
// otherwise don't transcode (use existing type)
outputType := "." + strings.ToLower(c.Decoder.Description())
if outputFilename != "" {
outputType = filepath.Ext(outputFilename)
}
outputHeight := c.ImageHeader.Height()
if outputWidth == 150 {
// Thumbnail
outputHeight = 150
} else if c.ImageHeader.Width() == c.ImageHeader.Height() {
// Image is 1:1
outputHeight = outputWidth
} else {
// Resize height based on width / ratio
floatRatio := float64(c.ImageHeader.Width()) / float64(c.ImageHeader.Height())
floatWidth := float64(outputWidth)
floatDivision := floatWidth / floatRatio
floatHeight := math.Round(floatDivision)
outputHeight = int(floatHeight)
}
resizeMethod := lilliput.ImageOpsFit
if stretch {
resizeMethod = lilliput.ImageOpsResize
}
if outputWidth == c.ImageHeader.Width() && outputHeight == c.ImageHeader.Height() {
resizeMethod = lilliput.ImageOpsNoResize
}
opts := &lilliput.ImageOptions{
FileType: outputType,
Width: outputWidth,
Height: outputHeight,
ResizeMethod: resizeMethod,
NormalizeOrientation: true,
EncodeOptions: EncodeOptions[outputType],
}
// resize and transcode image
outputImg, err := ops.Transform(c.Decoder, opts, outputImg)
if err != nil {
return fmt.Errorf("error transforming image, %s", err)
}
if _, err := os.Stat(c.Dir + outputFilename); !os.IsNotExist(err) {
return fmt.Errorf("output filename %s exists, quitting", outputFilename)
}
err = ioutil.WriteFile(c.Dir+outputFilename, outputImg, 0400)
if err != nil {
return fmt.Errorf("error writing out resized image, %s", err)
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment