Permalink
Browse files

extent async isSolid to return pixel value - an integer for both imag…

…es and grids - beware 32 bit limits
  • Loading branch information...
Dane Springmeyer
Dane Springmeyer committed Oct 26, 2012
1 parent 823ecff commit fa1aee2590ca9432780d17fa325aed75c0e09f5e
Showing with 108 additions and 23 deletions.
  1. +36 −6 src/mapnik_grid_view.cpp
  2. +36 −6 src/mapnik_image_view.cpp
  3. +8 −4 test/grid_view.test.js
  4. +1 −1 test/image.test.js
  5. +27 −6 test/image_view.test.js
View
@@ -104,9 +104,11 @@ Handle<Value> GridView::height(const Arguments& args)
typedef struct {
uv_work_t request;
GridView* g;
- std::string error_name;
Persistent<Function> cb;
+ bool error;
+ std::string error_name;
bool result;
+ mapnik::grid_view::value_type pixel;
} is_solid_grid_view_baton_t;
@@ -128,6 +130,8 @@ Handle<Value> GridView::isSolid(const Arguments& args)
closure->request.data = closure;
closure->g = g;
closure->result = true;
+ closure->pixel = 0;
+ closure->error = false;
closure->cb = Persistent<Function>::New(Handle<Function>::Cast(callback));
uv_queue_work(uv_default_loop(), &closure->request, EIO_IsSolid, EIO_AfterIsSolid);
g->Ref();
@@ -140,6 +144,7 @@ void GridView::EIO_IsSolid(uv_work_t* req)
if (view->width() > 0 && view->height() > 0)
{
mapnik::grid_view::value_type first_pixel = view->getRow(0)[0];
+ closure->pixel = first_pixel;
for (unsigned y = 0; y < view->height(); ++y)
{
mapnik::grid_view::value_type const * row = view->getRow(y);
@@ -153,15 +158,40 @@ void GridView::EIO_IsSolid(uv_work_t* req)
}
}
}
+ else
+ {
+ closure->error = true;
+ closure->error_name = "image does not have valid dimensions";
+ }
}
void GridView::EIO_AfterIsSolid(uv_work_t* req)
{
HandleScope scope;
is_solid_grid_view_baton_t *closure = static_cast<is_solid_grid_view_baton_t *>(req->data);
TryCatch try_catch;
- Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(Boolean::New(closure->result)) };
- closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
+ if (closure->error) {
+ Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
+ closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
+ }
+ else
+ {
+ if (closure->result)
+ {
+ Local<Value> argv[3] = { Local<Value>::New(Null()),
+ Local<Value>::New(Boolean::New(closure->result)),
+ Local<Value>::New(Number::New(closure->pixel)),
+ };
+ closure->cb->Call(Context::GetCurrent()->Global(), 3, argv);
+ }
+ else
+ {
+ Local<Value> argv[2] = { Local<Value>::New(Null()),
+ Local<Value>::New(Boolean::New(closure->result))
+ };
+ closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
+ }
+ }
if (try_catch.HasCaught())
{
FatalException(try_catch);
@@ -439,8 +469,9 @@ void GridView::EIO_AfterEncode(uv_work_t* req)
if (closure->error) {
Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
- } else {
-
+ }
+ else
+ {
// convert key order to proper javascript array
Local<Array> keys_a = Array::New(closure->key_order.size());
std::vector<std::string>::iterator it;
@@ -459,7 +490,6 @@ void GridView::EIO_AfterEncode(uv_work_t* req)
feature_data,
closure->key_order);
}
-
// Create the return hash.
Local<Object> json = Object::New();
Local<Array> grid_array = Array::New(closure->lines.size());
View
@@ -92,9 +92,11 @@ Handle<Value> ImageView::New(Image * JSImage ,
typedef struct {
uv_work_t request;
ImageView* im;
- std::string error_name;
Persistent<Function> cb;
+ bool error;
+ std::string error_name;
bool result;
+ mapnik::image_view<mapnik::image_data_32>::pixel_type pixel;
} is_solid_image_view_baton_t;
Handle<Value> ImageView::isSolid(const Arguments& args)
@@ -115,6 +117,8 @@ Handle<Value> ImageView::isSolid(const Arguments& args)
closure->request.data = closure;
closure->im = im;
closure->result = true;
+ closure->pixel = 0;
+ closure->error = false;
closure->cb = Persistent<Function>::New(Handle<Function>::Cast(callback));
uv_queue_work(uv_default_loop(), &closure->request, EIO_IsSolid, EIO_AfterIsSolid);
im->Ref();
@@ -127,11 +131,12 @@ void ImageView::EIO_IsSolid(uv_work_t* req)
image_view_ptr view = closure->im->get();
if (view->width() > 0 && view->height() > 0)
{
- mapnik::image_view<mapnik::image_data_32>::pixel_type const* first_row = view->getRow(0);
- mapnik::image_view<mapnik::image_data_32>::pixel_type const first_pixel = first_row[0];
+ typedef mapnik::image_view<mapnik::image_data_32>::pixel_type pixel_type;
+ pixel_type const first_pixel = view->getRow(0)[0];
+ closure->pixel = first_pixel;
for (unsigned y = 0; y < view->height(); ++y)
{
- mapnik::image_view<mapnik::image_data_32>::pixel_type const * row = view->getRow(y);
+ pixel_type const * row = view->getRow(y);
for (unsigned x = 0; x < view->width(); ++x)
{
if (first_pixel != row[x])
@@ -142,15 +147,40 @@ void ImageView::EIO_IsSolid(uv_work_t* req)
}
}
}
+ else
+ {
+ closure->error = true;
+ closure->error_name = "image does not have valid dimensions";
+ }
}
void ImageView::EIO_AfterIsSolid(uv_work_t* req)
{
HandleScope scope;
is_solid_image_view_baton_t *closure = static_cast<is_solid_image_view_baton_t *>(req->data);
TryCatch try_catch;
- Local<Value> argv[2] = { Local<Value>::New(Null()), Local<Value>::New(Boolean::New(closure->result)) };
- closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
+ if (closure->error) {
+ Local<Value> argv[1] = { Exception::Error(String::New(closure->error_name.c_str())) };
+ closure->cb->Call(Context::GetCurrent()->Global(), 1, argv);
+ }
+ else
+ {
+ if (closure->result)
+ {
+ Local<Value> argv[3] = { Local<Value>::New(Null()),
+ Local<Value>::New(Boolean::New(closure->result)),
+ Local<Value>::New(Number::New(closure->pixel)),
+ };
+ closure->cb->Call(Context::GetCurrent()->Global(), 3, argv);
+ }
+ else
+ {
+ Local<Value> argv[2] = { Local<Value>::New(Null()),
+ Local<Value>::New(Boolean::New(closure->result))
+ };
+ closure->cb->Call(Context::GetCurrent()->Global(), 2, argv);
+ }
+ }
if (try_catch.HasCaught())
{
FatalException(try_catch);
View
@@ -14,12 +14,14 @@ describe('mapnik.GridView ', function() {
});
it('should be solid', function() {
- assert.equal(view.isSolid(), true);
+ assert.equal(view.isSolidSync(), true);
});
it('should be solid (async)', function(done) {
- view.isSolid(function(err,solid) {
+ view.isSolid(function(err,solid,pixel) {
assert.equal(solid, true);
+ assert.equal(pixel, -2147483648);
+ assert.equal(pixel, mapnik.Grid.base_mask);
done();
});
});
@@ -30,6 +32,7 @@ describe('mapnik.GridView ', function() {
assert.equal(pixel, 0);
} else {
assert.equal(pixel, -2147483648);
+ assert.equal(pixel, mapnik.Grid.base_mask);
}
});
@@ -43,11 +46,12 @@ describe('mapnik.GridView ', function() {
var grid = new mapnik.Grid(map.width, map.height, {key: '__id__'});
map.render(grid, options, function(err, grid) {
var view = grid.view(0, 0, 256, 256);
- assert.equal(view.isSolid(), false);
+ assert.equal(view.isSolidSync(), false);
// hit alaska (USA is id 207)
assert.equal(view.getPixel(25, 100), 207);
- view.isSolid(function(err,solid){
+ view.isSolid(function(err,solid,pixel){
assert.equal(solid, false);
+ assert.equal(pixel, undefined);
done();
});
});
View
@@ -106,7 +106,7 @@ describe('mapnik.Image ', function() {
gray.background = new mapnik.Color('white');
gray.setGrayScaleToAlpha();
var gray_view = gray.view(0, 0, gray.width(), gray.height());
- assert.equal(gray_view.isSolid(), true);
+ assert.equal(gray_view.isSolidSync(), true);
var pixel = gray_view.getPixel(0, 0);
assert.equal(pixel.r, 255);
assert.equal(pixel.g, 255);
View
@@ -18,7 +18,7 @@ describe('mapnik.ImageView ', function() {
it('should be initialized properly', function() {
var im = new mapnik.Image(256, 256);
var view = im.view(0, 0, 256, 256);
- assert.equal(view.isSolid(), true);
+ assert.equal(view.isSolidSync(), true);
var pixel = view.getPixel(0, 0);
assert.equal(pixel.r, 0);
assert.equal(pixel.g, 0);
@@ -28,7 +28,7 @@ describe('mapnik.ImageView ', function() {
im = new mapnik.Image(256, 256);
im.background = new mapnik.Color(2, 2, 2, 2);
view = im.view(0, 0, 256, 256);
- assert.equal(view.isSolid(), true);
+ assert.equal(view.isSolidSync(), true);
pixel = view.getPixel(0, 0);
assert.equal(pixel.r, 2);
assert.equal(pixel.g, 2);
@@ -40,19 +40,40 @@ describe('mapnik.ImageView ', function() {
it('isSolid async works if true', function(done) {
var im = new mapnik.Image(256, 256);
var view = im.view(0, 0, 256, 256);
- assert.equal(view.isSolid(), true);
- view.isSolid(function(err,solid) {
+ assert.equal(view.isSolidSync(), true);
+ view.isSolid(function(err,solid,pixel) {
assert.equal(solid, true);
+ assert.equal(pixel, 0);
+ done();
+ });
+ });
+
+ it('isSolid async works if true and white', function(done) {
+ var im = new mapnik.Image(256, 256);
+ var color = new mapnik.Color('white');
+ im.background = color
+ var view = im.view(0, 0, 256, 256);
+ assert.equal(view.isSolidSync(), true);
+ view.isSolid(function(err,solid,pixel) {
+ assert.equal(solid, true);
+ assert.equal(pixel, 4294967295);
+ // NOTE: shifts are 32 bit signed ints in js, so creating the unsigned
+ // rgba for white is not possible using normal bit ops
+ // var rgba = (color.a << 24) | (color.b << 16) | (color.g << 8) | (color.r);
+ // how about this? (from tilelive source)
+ var rgba = color.a*(1<<24) + ((color.b<<16) | (color.g<<8) | color.r);
+ assert.equal(pixel, rgba);
done();
});
});
it('isSolid async works if false', function(done) {
var im = new mapnik.Image.open('./test/support/a.png');
var view = im.view(0, 0, im.width(), im.height());
- assert.equal(view.isSolid(), false);
- view.isSolid(function(err,solid) {
+ assert.equal(view.isSolidSync(), false);
+ view.isSolid(function(err,solid,pixel) {
assert.equal(solid, false);
+ assert.equal(pixel, undefined);
done();
});
});

0 comments on commit fa1aee2

Please sign in to comment.