mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 09:20:15 -06:00
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package preprocessor
|
|
|
|
import (
|
|
"bufio"
|
|
"github.com/golang/freetype"
|
|
"github.com/golang/freetype/truetype"
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/image/font"
|
|
"golang.org/x/image/font/gofont/goregular"
|
|
"image"
|
|
"image/draw"
|
|
"io"
|
|
"mime"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
fontSize = 12
|
|
spacing float64 = 1.5
|
|
)
|
|
|
|
type FileConverter interface {
|
|
Convert(r io.Reader) (image.Image, error)
|
|
}
|
|
|
|
type ImageDecoder struct{}
|
|
|
|
func (i ImageDecoder) Convert(r io.Reader) (image.Image, error) {
|
|
img, _, err := image.Decode(r)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, `could not decode the image`)
|
|
}
|
|
return img, nil
|
|
}
|
|
|
|
type TxtToImageConverter struct{}
|
|
|
|
func (t TxtToImageConverter) Convert(r io.Reader) (image.Image, error) {
|
|
img := image.NewRGBA(image.Rect(0, 0, 640, 480))
|
|
draw.Draw(img, img.Bounds(), image.White, image.Point{}, draw.Src)
|
|
|
|
c := freetype.NewContext()
|
|
// Ignoring the error since we are using the embedded Golang font.
|
|
// This shouldn't return an error.
|
|
f, _ := truetype.Parse(goregular.TTF)
|
|
c.SetFont(f)
|
|
c.SetFontSize(fontSize)
|
|
c.SetClip(img.Bounds())
|
|
c.SetDst(img)
|
|
c.SetSrc(image.Black)
|
|
c.SetHinting(font.HintingFull)
|
|
pt := freetype.Pt(10, 10+int(c.PointToFixed(fontSize)>>6))
|
|
|
|
scanner := bufio.NewScanner(r)
|
|
for scanner.Scan() {
|
|
txt := scanner.Text()
|
|
cs := chunks(txt, 80)
|
|
for _, s := range cs {
|
|
_, err := c.DrawString(strings.TrimSpace(s), pt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pt.Y += c.PointToFixed(fontSize * spacing)
|
|
if pt.Y.Round() >= img.Bounds().Dy() {
|
|
return img, scanner.Err()
|
|
}
|
|
}
|
|
|
|
}
|
|
return img, scanner.Err()
|
|
}
|
|
|
|
// Code from https://stackoverflow.com/a/61469854
|
|
// Written By Igor Mikushkin
|
|
func chunks(s string, chunkSize int) []string {
|
|
if chunkSize >= len(s) {
|
|
return []string{s}
|
|
}
|
|
var chunks []string
|
|
chunk := make([]rune, chunkSize)
|
|
length := 0
|
|
for _, r := range s {
|
|
chunk[length] = r
|
|
length++
|
|
if length == chunkSize {
|
|
chunks = append(chunks, string(chunk))
|
|
length = 0
|
|
}
|
|
}
|
|
if length > 0 {
|
|
chunks = append(chunks, string(chunk[:length]))
|
|
}
|
|
return chunks
|
|
}
|
|
|
|
func ForType(mimeType string) FileConverter {
|
|
// We can ignore the error here because we parse it in IsMimeTypeSupported before and if it fails
|
|
// return the service call. So we should only get here when the mimeType parses fine.
|
|
mimeType, _, _ = mime.ParseMediaType(mimeType)
|
|
switch mimeType {
|
|
case "text/plain":
|
|
return TxtToImageConverter{}
|
|
default:
|
|
return ImageDecoder{}
|
|
}
|
|
}
|