-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathimage.lua
138 lines (127 loc) · 5.17 KB
/
image.lua
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
local ffi = require "ffi"
local IMAGE_WIDTH = 400
local IMAGE_HEIGHT = 60
local image = {}
ffi.cdef[[
typedef void MagickWand;
typedef void PixelWand;
typedef void DrawingWand;
typedef int MagickBooleanType;
typedef int ExceptionType;
typedef int ssize_t;
typedef int CompositeOperator;
typedef enum {
ForgetGravity,
NorthWestGravity,
NorthGravity,
NorthEastGravity,
WestGravity,
CenterGravity,
EastGravity,
SouthWestGravity,
SouthGravity,
SouthEastGravity,
StaticGravitys
} GravityType;
typedef enum {
UndefinedInterpolatePixel,
AverageInterpolatePixel,
Average9InterpolatePixel,
Average16InterpolatePixel,
BackgroundInterpolatePixel,
BilinearInterpolatePixel,
BlendInterpolatePixel,
CatromInterpolatePixel,
IntegerInterpolatePixel,
MeshInterpolatePixel,
NearestInterpolatePixel,
SplineInterpolatePixel
} PixelInterpolateMethod;
void MagickWandGenesis();
MagickWand* NewMagickWand();
MagickWand* DestroyMagickWand(MagickWand* magick_wand);
PixelWand* NewPixelWand();
MagickBooleanType PixelSetColor(PixelWand* pixel_wand,const char* color);
PixelWand* DestroyPixelWand(PixelWand* pixel_wand);
MagickBooleanType MagickNewImage(MagickWand* magick_wand, const size_t columns, const size_t rows, const PixelWand* background);
MagickBooleanType MagickSetFormat(MagickWand* magick_wand, const char* format);
MagickBooleanType MagickSetImageBackgroundColor(MagickWand* magick_wand, const PixelWand* pixel_wand);
DrawingWand* NewDrawingWand();
DrawingWand* DestroyDrawingWand(DrawingWand* drawing_wand);
void DrawSetGravity(DrawingWand*wand, const GravityType gravity);
MagickBooleanType DrawSetFont(DrawingWand* drawing_wand, const char* font_name);
void DrawSetTextKerning(DrawingWand* drawing_wand, const double kerning);
void DrawSetTextInterwordSpacing(DrawingWand* drawing_wand, const double interword_spacing);
void DrawSetFillColor(DrawingWand* drawing_wand, const PixelWand* pixel_wand);
void DrawSetStrokeColor(DrawingWand* drawing_wand, const PixelWand* pixel_wand);
void DrawSetStrokeWidth(DrawingWand* drawing_wand, const double stroke_width);
void DrawSetFontSize(DrawingWand* drawing_wand, const double pointsize);
void DrawAnnotation(DrawingWand* drawing_wand, const double x, const double y, const unsigned char* text);
void DrawCircle(DrawingWand* drawing_wand, const double ox, const double oy, const double px, const double py);
MagickBooleanType MagickDrawImage(MagickWand* magick_wand, const DrawingWand* drawing_wand);
MagickBooleanType MagickWaveImage(MagickWand* magick_wand, const double amplitude, const double wave_length, const PixelInterpolateMethod method);
MagickBooleanType MagickCropImage(MagickWand* magick_wand, const size_t width, const size_t height, const ssize_t x, const ssize_t y);
unsigned char* MagickGetImageBlob(MagickWand* magick_wand, size_t* len);
void* MagickRelinquishMemory(void* ref);
]]
local MagickWand = ffi.load('MagickWand')
function image.create(text, type, background, foreground)
math.randomseed(os.time())
local magick_wand = MagickWand.NewMagickWand()
local pixel_wand = MagickWand.NewPixelWand()
local drawing_wand = MagickWand.NewDrawingWand()
function finalize()
MagickWand.DestroyDrawingWand(drawing_wand)
MagickWand.DestroyPixelWand(pixel_wand)
MagickWand.DestroyMagickWand(magick_wand)
end
MagickWand.PixelSetColor(pixel_wand, background or "white")
if not MagickWand.MagickNewImage(magick_wand, IMAGE_WIDTH, IMAGE_HEIGHT, pixel_wand) then
ngx.log(ngx.ERROR, "Failed to create image")
finalize()
return nil
end
if not MagickWand.MagickSetFormat(magick_wand, type or "png") then
ngx.log(ngx.ERROR, "Failed to set image format")
finalize()
return nil
end
MagickWand.MagickSetImageBackgroundColor(magick_wand, pixel_wand)
if not MagickWand.DrawSetFont(drawing_wand, "fonts/impact.ttf") then
ngx.log(ngx.ERROR, "Failed to load font")
finalize()
return nil
end
MagickWand.DrawSetFontSize(drawing_wand, 20)
MagickWand.DrawSetTextKerning(drawing_wand, -1.5)
MagickWand.DrawSetTextInterwordSpacing(drawing_wand, 20)
MagickWand.DrawSetFillColor(drawing_wand, pixel_wand)
MagickWand.PixelSetColor(pixel_wand, foreground or "black")
MagickWand.DrawSetStrokeColor(drawing_wand, pixel_wand)
MagickWand.DrawSetStrokeWidth(drawing_wand, 0.7)
MagickWand.DrawSetGravity(drawing_wand, MagickWand.CenterGravity)
MagickWand.DrawAnnotation(drawing_wand, 0, 0, text)
for i = 1, 5 do
local x = math.random(20, IMAGE_WIDTH - 20)
local y = math.random(20, IMAGE_HEIGHT - 20)
local diameter = math.random(1, 2)
MagickWand.DrawCircle(drawing_wand, x, y, x + diameter, y + diameter)
end
if not MagickWand.MagickDrawImage(magick_wand, drawing_wand) then
ngx.log(ngx.ERROR, "Failed to draw")
finalize()
return nil
end
for i = 1, 2 do
MagickWand.MagickWaveImage(magick_wand, 2, math.random(30, 60), MagickWand.AverageInterpolatePixel)
end
MagickWand.MagickCropImage(magick_wand, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0)
local len = ffi.new("size_t[1]", 0)
local blob = MagickWand.MagickGetImageBlob(magick_wand, len)
local data = ffi.string(blob, len[0])
MagickWand.MagickRelinquishMemory(blob)
finalize()
return data
end
MagickWand.MagickWandGenesis()
return image