-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathjpegtran.go
191 lines (157 loc) · 4 KB
/
jpegtran.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package mozjpegbin
import (
"errors"
"fmt"
"github.com/nickalie/go-binwrapper"
"io"
)
type cropInfo struct {
x int
y int
width int
height int
}
// JpegTran wraps jpegtran tool from mozjpeg
type JpegTran struct {
*binwrapper.BinWrapper
optimize bool
progressive bool
crop *cropInfo
inputFile string
input io.Reader
outputFile string
output io.Writer
copy string
}
// NewJpegTran creates new JpegTran instance
func NewJpegTran() *JpegTran {
bin := &JpegTran{
BinWrapper: createBinWrapper(),
copy: "none",
optimize: true,
}
bin.ExecPath("jpegtran")
return bin
}
// Optimize perform optimization of entropy encoding parameters
func (c *JpegTran) Optimize(optimize bool) *JpegTran {
c.optimize = optimize
return c
}
// Progressive create progressive JPEG file
func (c *JpegTran) Progressive(progressive bool) *JpegTran {
c.progressive = progressive
return c
}
// Crop to a rectangular region of width and height, starting at point x,y
func (c *JpegTran) Crop(x, y, width, height int) *JpegTran {
c.crop = &cropInfo{x, y, width, height}
return c
}
// InputFile sets image file to convert.
// Input or InputImage called before will be ignored.
func (c *JpegTran) InputFile(file string) *JpegTran {
c.input = nil
c.inputFile = file
return c
}
// Input sets reader to convert.
// InputFile or InputImage called before will be ignored.
func (c *JpegTran) Input(reader io.Reader) *JpegTran {
c.inputFile = ""
c.input = reader
return c
}
// OutputFile specify the name of the output jpeg file.
// Output called before will be ignored.
func (c *JpegTran) OutputFile(file string) *JpegTran {
c.output = nil
c.outputFile = file
return c
}
// Output specify writer to write jpeg file content.
// OutputFile called before will be ignored.
func (c *JpegTran) Output(writer io.Writer) *JpegTran {
c.outputFile = ""
c.output = writer
return c
}
// CopyNone copy no extra markers from source file. This setting suppresses all comments and other metadata in the source file
func (c *JpegTran) CopyNone() *JpegTran {
c.copy = "none"
return c
}
// CopyComments copy only comment markers. This setting copies comments from the source file but discards any other metadata.
func (c *JpegTran) CopyComments() *JpegTran {
c.copy = "comments"
return c
}
// CopyAll copy all extra markers. This setting preserves miscellaneous markers found in the source file, such as JFIF thumbnails, Exif data, and Photoshop settings. In some files, these extra markers can be sizable. Note that this option will copy thumbnails as-is; they will not be transformed.
func (c *JpegTran) CopyAll() *JpegTran {
c.copy = "all"
return c
}
// Run starts jpegtran with specified parameters.
func (c *JpegTran) Run() error {
defer c.BinWrapper.Reset()
if c.optimize {
c.Arg("-optimize")
}
if c.progressive {
c.Arg("-progressive")
}
if c.crop != nil {
c.Arg("-crop", fmt.Sprintf("%dx%d+%d+%d", c.crop.width, c.crop.height, c.crop.x, c.crop.y))
}
c.Arg("-copy", c.copy)
output, err := c.getOutput()
if err != nil {
return err
}
if output != "" {
c.Arg("-outfile", output)
}
err = c.setInput()
if err != nil {
return err
}
if c.output != nil {
c.SetStdOut(c.output)
}
err = c.BinWrapper.Run()
if err != nil {
return errors.New(err.Error() + ". " + string(c.StdErr()))
}
return nil
}
// Version returns jpegtran version.
func (c *JpegTran) Version() (string, error) {
return version(c.BinWrapper)
}
// Reset resets all parameters to default values
func (c *JpegTran) Reset() *JpegTran {
c.optimize = true
c.progressive = false
c.copy = "none"
c.crop = nil
return c
}
func (c *JpegTran) setInput() error {
if c.input != nil {
c.StdIn(c.input)
} else if c.inputFile != "" {
c.Arg(c.inputFile)
} else {
return errors.New("Undefined input")
}
return nil
}
func (c *JpegTran) getOutput() (string, error) {
if c.output != nil {
return "", nil
} else if c.outputFile != "" {
return c.outputFile, nil
} else {
return "", errors.New("Undefined output")
}
}