-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconversion.go
342 lines (286 loc) · 11.1 KB
/
conversion.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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
package vips
/*
#cgo pkg-config: vips
#include "vips.h"
*/
import "C"
import (
"image"
)
// CompassDirection direction on a compass.
type CompassDirection int
const (
// DirectionCentre centre
DirectionCentre = CompassDirection(C.VIPS_COMPASS_DIRECTION_CENTRE)
// DirectionNorth notrh
DirectionNorth = CompassDirection(C.VIPS_COMPASS_DIRECTION_NORTH)
// DirectionEast east
DirectionEast = CompassDirection(C.VIPS_COMPASS_DIRECTION_EAST)
// DirectionSouth south
DirectionSouth = CompassDirection(C.VIPS_COMPASS_DIRECTION_SOUTH)
// DirectionWest west
DirectionWest = CompassDirection(C.VIPS_COMPASS_DIRECTION_WEST)
// DirectionNorthEast north-east
DirectionNorthEast = CompassDirection(C.VIPS_COMPASS_DIRECTION_NORTH_EAST)
// DirectionSouthEast south-east
DirectionSouthEast = CompassDirection(C.VIPS_COMPASS_DIRECTION_SOUTH_EAST)
// DirectionSouthWest south-west
DirectionSouthWest = CompassDirection(C.VIPS_COMPASS_DIRECTION_SOUTH_WEST)
// DirectionNorthWest north-west
DirectionNorthWest = CompassDirection(C.VIPS_COMPASS_DIRECTION_NORTH_WEST)
)
// BlendMode The various Porter-Duff and PDF blend modes. See vips_composite(), for example.
// The Cairo docs have a nice explanation of all the blend modes:
//
// https://www.cairographics.org/operators
// The non-separable modes are not implemented.
type BlendMode int
const (
// BlendModeClear where the second object is drawn, the first is removed
BlendModeClear = BlendMode(C.VIPS_BLEND_MODE_CLEAR)
// BlendModeSource the second object is drawn as if nothing were below
BlendModeSource = BlendMode(C.VIPS_BLEND_MODE_SOURCE)
// BlendModeOver the image shows what you would expect if you held two semi-transparent slides on top of each other
BlendModeOver = BlendMode(C.VIPS_BLEND_MODE_OVER)
// BlendModeIn the first object is removed completely, the second is only drawn where the first was
BlendModeIn = BlendMode(C.VIPS_BLEND_MODE_IN)
// BlendModeOut the second is drawn only where the first isn't
BlendModeOut = BlendMode(C.VIPS_BLEND_MODE_OUT)
// BlendModeAtop this leaves the first object mostly intact, but mixes both objects in the overlapping area
BlendModeAtop = BlendMode(C.VIPS_BLEND_MODE_ATOP)
// BlendModeDest leaves the first object untouched, the second is discarded completely
BlendModeDest = BlendMode(C.VIPS_BLEND_MODE_DEST)
// BlendModeDestOver like OVER, but swaps the arguments
BlendModeDestOver = BlendMode(C.VIPS_BLEND_MODE_DEST_OVER)
// BlendModeDestIn like IN, but swaps the arguments
BlendModeDestIn = BlendMode(C.VIPS_BLEND_MODE_DEST_IN)
// BlendModeDestOut like OUT, but swaps the arguments
BlendModeDestOut = BlendMode(C.VIPS_BLEND_MODE_DEST_OUT)
// BlendModeDestAtop like ATOP, but swaps the arguments
BlendModeDestAtop = BlendMode(C.VIPS_BLEND_MODE_DEST_ATOP)
// BlendModeXor something like a difference operator
BlendModeXor = BlendMode(C.VIPS_BLEND_MODE_XOR)
// BlendModeAdd a bit like adding the two images
BlendModeAdd = BlendMode(C.VIPS_BLEND_MODE_ADD)
// BlendModeSaturate a bit like the darker of the two
BlendModeSaturate = BlendMode(C.VIPS_BLEND_MODE_SATURATE)
// BlendModeMultiply at least as dark as the darker of the two inputs
BlendModeMultiply = BlendMode(C.VIPS_BLEND_MODE_MULTIPLY)
// BlendModeScreen at least as light as the lighter of the inputs
BlendModeScreen = BlendMode(C.VIPS_BLEND_MODE_SCREEN)
// BlendModeOverlay multiplies or screens colors, depending on the lightness
BlendModeOverlay = BlendMode(C.VIPS_BLEND_MODE_OVERLAY)
// BlendModeDarken the darker of each component
BlendModeDarken = BlendMode(C.VIPS_BLEND_MODE_DARKEN)
// BlendModeLighten the lighter of each component
BlendModeLighten = BlendMode(C.VIPS_BLEND_MODE_LIGHTEN)
// BlendModeColourDodge brighten first by a factor second
BlendModeColourDodge = BlendMode(C.VIPS_BLEND_MODE_COLOUR_DODGE)
// BlendModeColourBurn darken first by a factor of second
BlendModeColourBurn = BlendMode(C.VIPS_BLEND_MODE_COLOUR_BURN)
// BlendModeHardLight multiply or screen, depending on lightness
BlendModeHardLight = BlendMode(C.VIPS_BLEND_MODE_HARD_LIGHT)
// BlendModeSoftLight darken or lighten, depending on lightness
BlendModeSoftLight = BlendMode(C.VIPS_BLEND_MODE_SOFT_LIGHT)
// BlendModeDifference difference of the two
BlendModeDifference = BlendMode(C.VIPS_BLEND_MODE_DIFFERENCE)
// BlendModeExclusion somewhat like DIFFERENCE, but lower-contrast
BlendModeExclusion = BlendMode(C.VIPS_BLEND_MODE_EXCLUSION)
)
// Angle Fixed rotate angles.
type Angle int
const (
// AngleD0 no rotate
AngleD0 = Angle(C.VIPS_ANGLE_D0)
// AngleD90 90 degrees clockwise
AngleD90 = Angle(C.VIPS_ANGLE_D90)
// AngleD180 180 degree rotate
AngleD180 = Angle(C.VIPS_ANGLE_D180)
// AngleD270 90 degrees anti-clockwise
AngleD270 = Angle(C.VIPS_ANGLE_D270)
)
// Direction Operations like Flip() need to be told whether to flip left-right or top-bottom.
type Direction int
const (
// DirectionHorizontal left-right
DirectionHorizontal = Direction(C.VIPS_DIRECTION_HORIZONTAL)
// DirectionVertical top-bottom
DirectionVertical = Direction(C.VIPS_DIRECTION_VERTICAL)
)
// Replicate repeats an image many times.
// across: repeat input this many times across
// down: repeat input this many times down
func (th *Image) Replicate(across, down int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_replicate(th.vipsImage, &vipsImage, C.int(across), C.int(down)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Gravity place in within an image of size width by height at a certain gravity.
func (th *Image) Gravity(direction CompassDirection, width, height int) (err error) {
vcd := C.VipsCompassDirection(direction)
var vipsImage *C.VipsImage
if C.vipsimage_gravity(th.vipsImage, &vipsImage, vcd, C.int(width), C.int(height)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Composite ...
func (th *Image) Composite() {
}
// Composite2 composite overlay on top of base with mode. See Composite.
func (th *Image) Composite2(overlay *Image, mode BlendMode, point image.Point) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_composite2(th.vipsImage, overlay.vipsImage, &vipsImage, C.VipsBlendMode(mode),
C.int(point.X), C.int(point.Y)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// AutoRot look at the image metadata and rotate the image to make it upright.
// Note:
//
// vips only supports the four simple rotations, it does not support the various
// mirror modes. If the image is using one of these mirror modes, the image is not
// rotated and the VIPS_META_ORIENTATION tag is not removed.
func (th *Image) AutoRot() (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_autorot(th.vipsImage, &vipsImage) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Embed *Image within an image of size width by height at position x , y .
func (th *Image) Embed(x, y, width, height int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_embed(th.vipsImage, &vipsImage, C.int(x), C.int(y), C.int(width), C.int(height)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// ExtractArea extract an area from an image. The area must fit within *Image.
func (th *Image) ExtractArea(left, top, width, height int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_extract_area(th.vipsImage, &vipsImage, C.int(left), C.int(top), C.int(width), C.int(height)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Crop a synonym for ExtractArea.
func (th *Image) Crop(left, top, width, height int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_crop(th.vipsImage, &vipsImage, C.int(left), C.int(top), C.int(width), C.int(height)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Flip an image left-right or up-down.
func (th *Image) Flip(direction Direction) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_flip(th.vipsImage, &vipsImage, C.VipsDirection(direction)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Grid chop a tall thin image up into a set of tiles, lay the tiles out in a grid.
func (th *Image) Grid(tileHeight, across, down int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_grid(th.vipsImage, &vipsImage, C.int(tileHeight), C.int(across), C.int(down)) != 0 {
return
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Scale search the image for the maximum and minimum value,
// then return the image as unsigned 8-bit, scaled so that
// the maximum value is 255 and the minimum is zero.
func (th *Image) Scale() (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_scale(th.vipsImage, &vipsImage) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// SubSample an image by an integer fraction. This is fast, nearest-neighbour shrink.
func (th *Image) SubSample(xFac, yFac int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_subsample(th.vipsImage, &vipsImage, C.int(xFac), C.int(yFac)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Zoom an image by repeating pixels. This is fast nearest-neighbour zoom.
func (th *Image) Zoom(xFac, yFac int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_zoom(th.vipsImage, &vipsImage, C.int(xFac), C.int(yFac)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Wrap slice an image up and move the segments about so that
// the pixel that was at 0, 0 is now at x , y . If x and y
// are not set, they default to the centre of the image.
func (th *Image) Wrap() (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_wrap(th.vipsImage, &vipsImage) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// ExtractBand extract a band or bands from an image.
// Extracting out of range is an error.
func (th *Image) ExtractBand(band int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_extract_band(th.vipsImage, &vipsImage, C.int(band)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// SmartCrop crop an image down to a specified width and height by removing boring parts.
func (th *Image) SmartCrop(width, height int) (err error) {
var vipsImage *C.VipsImage
if C.vipsimage_smartcrop(th.vipsImage, &vipsImage, C.int(width), C.int(height)) != 0 {
return Error()
}
C.g_object_unref(C.gpointer(th.vipsImage))
th.vipsImage = vipsImage
return
}
// Copy an image, optionally modifying the header.
// VIPS copies images by copying pointers, so this operation is instant, even for very large images.
func (th *Image) Copy() (out *Image, err error) {
var vipsImage *C.VipsImage
if C.vipsimage_copy(th.vipsImage, &vipsImage) != 0 {
err = Error()
return
}
return NewFromVipsImage(vipsImage), nil
}