-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathheif.go
125 lines (113 loc) · 2.72 KB
/
heif.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//go:build heif || darwin
// +build heif darwin
package imagecoding
import (
"image"
"image/color"
"runtime"
"github.com/strukturag/libheif/go/heif"
)
func ConfigHeif(data []byte) (image.Config, string, error) {
if len(data) == 0 {
return image.Config{}, string(Heif), ErrEmptyInput
}
ctx, err := heif.NewContext()
if err != nil {
return image.Config{}, string(Heif), err
}
err = ctx.ReadFromMemory(data)
if err != nil {
return image.Config{}, string(Heif), err
}
img, err := ctx.GetPrimaryImageHandle()
if err != nil {
return image.Config{}, string(Heif), err
}
cfg := image.Config{
ColorModel: color.YCbCrModel,
Width: img.GetWidth(),
Height: img.GetHeight(),
}
runtime.KeepAlive(ctx)
return cfg, string(Heif), nil
}
func DecodeHeif(data []byte) (image.Image, error) {
if len(data) == 0 {
return nil, ErrEmptyInput
}
ctx, err := heif.NewContext()
if err != nil {
return nil, err
}
err = ctx.ReadFromMemory(data)
if err != nil {
return nil, err
}
imgh, err := ctx.GetPrimaryImageHandle()
if err != nil {
return nil, err
}
img, err := imgh.DecodeImage(heif.ColorspaceUndefined, heif.ChromaUndefined, nil)
runtime.KeepAlive(ctx)
if err != nil {
return nil, err
}
goimg, err := img.GetImage()
if err != nil {
return nil, err
}
return goimg, nil
}
func TransformHeif(data []byte, grayscale bool, scale ScaleFunc) (out image.Image, width, height int, scaleFactor float64, err error) {
if len(data) == 0 {
return nil, 0, 0, 0, ErrEmptyInput
}
ctx, err := heif.NewContext()
if err != nil {
return nil, 0, 0, 0, err
}
err = ctx.ReadFromMemory(data)
if err != nil {
return nil, 0, 0, 0, err
}
imgh, err := ctx.GetPrimaryImageHandle()
if err != nil {
return nil, 0, 0, 0, err
}
width = imgh.GetWidth()
height = imgh.GetHeight()
// Calculate scaling factor
scaledW, scaledH, scaleFactor := scale(width, height)
var img *heif.Image
img, err = imgh.DecodeImage(heif.ColorspaceUndefined, heif.ChromaUndefined, nil)
runtime.KeepAlive(ctx)
if err != nil {
return nil, 0, 0, 0, err
}
// Scale if required
if scaleFactor > 1.1 || scaleFactor < 0.9 {
img, err = img.ScaleImage(scaledW, scaledH)
if err != nil {
return nil, 0, 0, 0, err
}
} else {
scaleFactor = 1
}
goimg, err := img.GetImage()
if err != nil {
return nil, 0, 0, 0, err
}
// libheif does not support conversion from YUV/RGB -> Gray Scale
if grayscale {
// Drop the channels we don't need by converting to image.Gray
bounds := goimg.Bounds()
imgGray := image.NewGray(bounds)
for y := 0; y < bounds.Max.Y; y++ {
for x := 0; x < bounds.Max.X; x++ {
imgGray.Set(x, y, color.GrayModel.Convert(goimg.At(x, y)))
}
}
goimg = imgGray
}
return goimg, width, height, scaleFactor, nil
}