-
Notifications
You must be signed in to change notification settings - Fork 164
Expand file tree
/
Copy pathmapnik_image_open.cpp
More file actions
164 lines (150 loc) · 4.9 KB
/
mapnik_image_open.cpp
File metadata and controls
164 lines (150 loc) · 4.9 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
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
// mapnik
#include <mapnik/image.hpp> // for image types
#include <mapnik/image_any.hpp> // for image_any
#include <mapnik/image_reader.hpp> // for get_image_reader, etc
#include <mapnik/image_util.hpp> // for save_to_string, guess_type, etc
//
#include "mapnik_image.hpp"
namespace detail {
struct AsyncOpen : Napi::AsyncWorker
{
using Base = Napi::AsyncWorker;
AsyncOpen(std::string const& filename, Napi::Function const& callback)
: Base(callback),
filename_(filename) {}
void Execute() override
{
auto type = mapnik::type_from_filename(filename_);
if (type)
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename_, *type));
if (reader.get())
{
try
{
image_ = std::make_shared<mapnik::image_any>(reader->read(0, 0, reader->width(), reader->height()));
if (!reader->has_alpha()) mapnik::set_premultiplied_alpha(*image_, true);
}
catch (std::exception const& ex)
{
SetError(ex.what());
}
}
else
SetError("Can't create image reader");
}
else
{
SetError("Can't determine image type from filename");
}
}
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);
}
private:
std::string filename_;
image_ptr image_;
};
} // namespace detail
/**
* Load in a pre-existing image as an image object
* @name openSync
* @memberof Image
* @instance
* @param {string} path - path to the image you want to load
* @returns {mapnik.Image} new image object based on existing image
* @example
* var img = new mapnik.Image.open('./path/to/image.jpg');
*/
Napi::Value Image::openSync(Napi::CallbackInfo const& info)
{
Napi::Env env = info.Env();
Napi::EscapableHandleScope scope(env);
if (info.Length() < 1)
{
Napi::Error::New(env, "must provide a string argument").ThrowAsJavaScriptException();
return env.Undefined();
}
if (!info[0].IsString())
{
Napi::TypeError::New(env, "Argument must be a string").ThrowAsJavaScriptException();
return env.Undefined();
}
try
{
std::string filename = info[0].As<Napi::String>();
auto type = mapnik::type_from_filename(filename);
if (type)
{
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename, *type));
if (reader.get())
{
image_ptr imagep = std::make_shared<mapnik::image_any>(reader->read(0, 0, reader->width(), reader->height()));
if (!reader->has_alpha())
{
mapnik::set_premultiplied_alpha(*imagep, true);
}
Napi::Value arg = Napi::External<image_ptr>::New(env, &imagep);
Napi::Object obj = constructor.New({arg});
return scope.Escape(obj);
}
}
Napi::TypeError::New(env, ("Unsupported image format:" + filename)).ThrowAsJavaScriptException();
return env.Undefined();
}
catch (std::exception const& ex)
{
Napi::Error::New(env, ex.what()).ThrowAsJavaScriptException();
return env.Undefined();
}
}
/**
* Load in a pre-existing image as an image object
* @name open
* @memberof Image
* @static
* @param {string} path - path to the image you want to load
* @param {Function} callback -
* @example
* mapnik.Image.open('./path/to/image.jpg', function(err, img) {
* if (err) throw err;
* // img is now an Image object
* });
*/
Napi::Value Image::open(Napi::CallbackInfo const& info)
{
Napi::Env env = info.Env();
if (info.Length() == 1)
{
return openSync(info);
}
if (info.Length() < 2)
{
Napi::Error::New(env, "must provide a string argument").ThrowAsJavaScriptException();
return env.Undefined();
}
if (!info[0].IsString())
{
Napi::TypeError::New(env, "Argument must be a string").ThrowAsJavaScriptException();
return env.Undefined();
}
// ensure callback is a function
Napi::Value callback_val = info[info.Length() - 1];
if (!callback_val.IsFunction())
{
Napi::TypeError::New(env, "last argument must be a callback function").ThrowAsJavaScriptException();
return env.Undefined();
}
Napi::Function callback = callback_val.As<Napi::Function>();
std::string filename = info[0].As<Napi::String>();
auto* worker = new detail::AsyncOpen(filename, callback);
worker->Queue();
return env.Undefined();
}