forked from qifengzhang007/gooxml
/
image.go
131 lines (113 loc) · 3.77 KB
/
image.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
// Copyright 2017 Baliance. All rights reserved.
//
// Use of this source code is governed by the terms of the Affero GNU General
// Public License version 3.0 as published by the Free Software Foundation and
// appearing in the file LICENSE included in the packaging of this file. A
// commercial license can be purchased by contacting sales@baliance.com.
package common
import (
"bytes"
"fmt"
"github.com/qifengzhang007/gooxml/schema/soo/pkg/relationships"
"image"
"os"
"github.com/qifengzhang007/gooxml/measurement"
// Add image format support
_ "image/gif"
_ "image/jpeg"
_ "image/png"
)
// Image is a container for image information. It's used as we need format and
// and size information to use images.
// It contains either the filesystem path to the image, or the image itself.
type Image struct {
Size image.Point
Format string
Path string
Data *[]byte
}
// ImageRef is a reference to an image within a document.
type ImageRef struct {
d *DocBase
rels Relationships
img Image
relID string
}
// MakeImageRef constructs an image reference which is a reference to a
// particular image file inside a document. The same image can be used multiple
// times in a document by re-use the ImageRef.
func MakeImageRef(img Image, d *DocBase, docRels Relationships, rel *relationships.Relationship) ImageRef {
if rel != nil {
return ImageRef{img: img, d: d, rels: docRels, relID: rel.IdAttr}
}
return ImageRef{img: img, d: d, rels: docRels, relID: ""}
}
func (i *ImageRef) SetRelID(id string) {
i.relID = id
}
// RelID returns the relationship ID.
func (i ImageRef) RelID() string {
return i.relID
}
// Format returns the format of the underlying image
func (i ImageRef) Format() string {
return i.img.Format
}
// Path returns the path to an image file, if any.
func (i ImageRef) Path() string {
return i.img.Path
}
// Data returns the data of an image file, if any.
func (i ImageRef) Data() *[]byte {
return i.img.Data
}
// Size returns the size of an image
func (i ImageRef) Size() image.Point {
return i.img.Size
}
// RelativeHeight returns the relative height of an image given a fixed width.
// This is used when setting image to a fixed width to calculate the height
// required to keep the same image aspect ratio.
func (i ImageRef) RelativeHeight(w measurement.Distance) measurement.Distance {
hScale := float64(i.Size().Y) / float64(i.Size().X)
return w * measurement.Distance(hScale)
}
// RelativeWidth returns the relative width of an image given a fixed height.
// This is used when setting image to a fixed height to calculate the width
// required to keep the same image aspect ratio.
func (i ImageRef) RelativeWidth(h measurement.Distance) measurement.Distance {
wScale := float64(i.Size().X) / float64(i.Size().Y)
return h * measurement.Distance(wScale)
}
// ImageFromFile reads an image from a file on disk. It doesn't keep the image
// in memory and only reads it to determine the format and size. You can also
// construct an Image directly if the file and size are known.
func ImageFromFile(path string) (Image, error) {
f, err := os.Open(path)
r := Image{}
if err != nil {
return r, fmt.Errorf("error reading image: %s", err)
}
defer f.Close()
imgDec, ifmt, err := image.Decode(f)
if err != nil {
return r, fmt.Errorf("unable to parse image: %s", err)
}
r.Path = path
r.Format = ifmt
r.Size = imgDec.Bounds().Size()
return r, nil
}
// ImageFromBytes returns an Image struct for an in-memory image. You can also
// construct an Image directly if the file and size are known.
func ImageFromBytes(data []byte) (Image, error) {
r := Image{}
imgDec, ifmt, err := image.Decode(bytes.NewReader(data))
if err != nil {
return r, fmt.Errorf("unable to parse image: %s", err)
}
r.Data = &data
r.Format = ifmt
r.Size = imgDec.Bounds().Size()
return r, nil
}