mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-05 11:51:16 -06:00
implement thumbnail support for txt files
This commit is contained in:
106
thumbnails/pkg/preprocessor/preprocessor.go
Normal file
106
thumbnails/pkg/preprocessor/preprocessor.go
Normal file
@@ -0,0 +1,106 @@
|
||||
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{}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user