-
Notifications
You must be signed in to change notification settings - Fork 164
Expand file tree
/
Copy pathmapnik_image_filter.cpp
More file actions
129 lines (118 loc) · 3.47 KB
/
mapnik_image_filter.cpp
File metadata and controls
129 lines (118 loc) · 3.47 KB
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
#include <mapnik/image_any.hpp> // for image_any
#include <mapnik/image_util.hpp> // for save_to_string, guess_type, etc
#include <mapnik/image_filter_types.hpp>
#include <mapnik/image_filter.hpp> // filter_visitor
#include "mapnik_image.hpp"
namespace detail {
// AsyncWorker
struct AsyncFilter : Napi::AsyncWorker
{
using Base = Napi::AsyncWorker;
AsyncFilter(image_ptr const& image, std::string const& filter, Napi::Function const& callback)
: Base(callback),
image_(image),
filter_(filter)
{
}
void Execute() override
{
try
{
mapnik::filter::filter_image(*image_, filter_); // NOLINT
}
catch (std::exception const& ex)
{
SetError(ex.what());
;
}
}
std::vector<napi_value> GetResult(Napi::Env env) override
{
if (image_)
{
Napi::Value arg = Napi::External<image_ptr>::New(env, &image_);
Napi::Object obj = Image::constructor.New({arg});
return {env.Null(), napi_value(obj)};
}
return Base::GetResult(env);
}
image_ptr image_;
std::string filter_;
};
} // namespace detail
/**
* Apply a filter to this image. This changes all pixel values. (synchronous)
*
* @name filterSync
* @instance
* @memberof Image
* @param {string} filter - can be `blur`, `emboss`, `sharpen`,
* `sobel`, or `gray`.
* @example
* var img = new mapnik.Image(5, 5);
* img.filter('blur');
* // your custom code with `img` having blur applied
*/
Napi::Value Image::filterSync(Napi::CallbackInfo const& info)
{
Napi::Env env = info.Env();
if (info.Length() < 1)
{
Napi::TypeError::New(env, "expects one argument: string filter argument").ThrowAsJavaScriptException();
return env.Undefined();
}
if (!info[0].IsString())
{
Napi::TypeError::New(env, "A string is expected for filter argument").ThrowAsJavaScriptException();
return env.Undefined();
}
std::string filter = info[0].As<Napi::String>();
try
{
mapnik::filter::filter_image(*image_, filter);
}
catch (std::exception const& ex)
{
Napi::Error::New(env, ex.what()).ThrowAsJavaScriptException();
}
return env.Undefined();
}
/**
* Apply a filter to this image. Changes all pixel values.
*
* @name filter
* @instance
* @memberof Image
* @param {string} filter - can be `blur`, `emboss`, `sharpen`,
* `sobel`, or `gray`.
* @param {Function} callback - `function(err, img)`
* @example
* var img = new mapnik.Image(5, 5);
* img.filter('sobel', function(err, img) {
* if (err) throw err;
* // your custom `img` with sobel filter
* // https://en.wikipedia.org/wiki/Sobel_operator
* });
*/
Napi::Value Image::filter(Napi::CallbackInfo const& info)
{
if (info.Length() < 2)
{
return filterSync(info);
}
Napi::Env env = info.Env();
if (!info[info.Length() - 1].IsFunction())
{
Napi::TypeError::New(env, "last argument must be a callback function").ThrowAsJavaScriptException();
return env.Undefined();
}
if (!info[0].IsString())
{
Napi::TypeError::New(env, "A string is expected for filter argument").ThrowAsJavaScriptException();
return env.Undefined();
}
Napi::Function callback = info[info.Length() - 1].As<Napi::Function>();
auto* worker = new detail::AsyncFilter{image_, info[0].As<Napi::String>(), callback};
worker->Queue();
return env.Undefined();
}