/
artwork.go
151 lines (136 loc) · 4.13 KB
/
artwork.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package artsparts
import (
"encoding/json"
"fmt"
"image"
"io/ioutil"
"os"
"path/filepath"
"github.com/OpenGLAMTools/ArtsParts/helpers"
"github.com/OpenGLAMTools/ArtsParts/shortlink"
"github.com/disintegration/imaging"
"github.com/pkg/errors"
)
// Artwork is one element like for example a picture. The picture
// should be placed inside a folder. One artwork per folder! The
// foldername is then used as the id.
// The conf file here is stored as JSON, because the content is created
// and edited via a configuration dialog.
// Path contains the part of the url how the artwork can be found:
// /[institution]/[collection]/[artwork]
type Artwork struct {
Timestamp string `json:"timestamp"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
TweetID int64 `json:"tweet"`
HashTag string `json:"hashtag"`
URIPath string `json:"-"`
ShortLink string `json:"shortlink"`
Parts []*Part
fpath string
collection *Collection
}
// NewArtwork loads an artwork configuration and return a pointer.
func NewArtwork(fpath string, coll *Collection) (*Artwork, error) {
artw := &Artwork{
fpath: fpath,
collection: coll,
}
dataFilePath := filepath.Join(fpath, DataFileName)
b, err := ioutil.ReadFile(dataFilePath)
if err != nil {
if !os.IsNotExist(err) {
return artw, err
}
// default values when data file is created
artw.ID = filepath.Base(fpath)
artw.Name = artw.ID
// ensure the data file
err = artw.WriteData()
// return the fresh artwork
return artw, err
}
if err := json.Unmarshal(b, artw); err != nil {
return artw, err
}
artw.URIPath = fmt.Sprintf("/%s/%s/%s", coll.institution.ID, coll.ID, artw.ID)
artw.ShortLink, err = shortlink.GetShort("/artwork" + artw.URIPath)
return artw, err
}
// ImgFile return the filename of the image.
func (artw *Artwork) ImgFile() (string, error) {
fileTypes := []string{".jpg", ".jpeg", ".png"}
ls, err := ioutil.ReadDir(artw.fpath)
if err != nil {
return "", errors.WithMessage(err, "ReadDir in artwork.ImgFile()")
}
for _, f := range ls {
if f.IsDir() {
continue
}
if helpers.StringInSlice(filepath.Ext(f.Name()), fileTypes) {
return f.Name(), nil
}
}
return "", errors.New("No image file found")
}
// AddPart adds a Part to the artwork
func (artw *Artwork) AddPart(p *Part) {
artw.Parts = append(artw.Parts, p)
}
// Artpart creates the part of the artwork. Every number is relative to the size
// of the picture. To get the x value in pixel you need to multiply it to the width
func (artw *Artwork) Artpart(p *Part) (image.Image, error) {
img, err := artw.Image()
if err != nil {
return nil, err
}
bounds := img.Bounds()
imgWidth := float64(bounds.Max.X)
imgHeigth := float64(bounds.Max.Y)
rect := image.Rect(
int(p.X*imgWidth),
int(p.Y*imgHeigth),
int((p.X+p.Width)*imgWidth),
int((p.Y+p.Height)*imgHeigth))
artp := imaging.Crop(img, rect)
return artp, nil
}
// Image returns the Image of the artwork
func (artw *Artwork) Image() (image.Image, error) {
f, err := artw.ImgFile()
if err != nil {
return nil, err
}
return imaging.Open(filepath.Join(artw.fpath, f))
}
// WriteData writes the artw into a file. If the
// file does not exist the file is created.
func (artw *Artwork) WriteData() error {
b, err := artw.Marshal()
if err != nil {
return err
}
return ioutil.WriteFile(artw.dataFilePath(), b, 0777)
}
// Marshal wraps the json marshal func. If the file format
// should be changed it can be done here.
func (artw *Artwork) Marshal() ([]byte, error) {
return json.MarshalIndent(artw, "", " ")
}
// Path returns the stored path to the artwork as string
func (artw *Artwork) Path() string {
return artw.fpath
}
// InstitutionTwitter returns the twitter name of the institution
func (artw *Artwork) InstitutionTwitter() string {
return artw.collection.institution.TwitterName
}
// IsAdminUser returns true, when the given user has admin rights
func (artw *Artwork) IsAdminUser(userName string) bool {
return helpers.StringInSlice(userName, artw.collection.institution.Admins)
}
func (artw *Artwork) dataFilePath() string {
return filepath.Join(artw.fpath, DataFileName)
}