img.lockFocus is inaccessible via ObjC bridge? - objective-c

I'm trying to create a purely JXA-ObjC approach to getting pixel colors from image paths. Here's what I have currently:
ObjC.import('Foundation')
ObjC.import('AppKit')
var c_filePath = $(picturePath)
var c_img = $.NSImage.alloc.initWithContentsOfFile(c_filePath)
if(c_img==$()){
return []
}
var c_point = $.NSMakePoint(x,y)
c_img.lockFocus() //Error - Undefined is not a function...?
var c_color = NSReadPixel(c_point)
c_img.unlockFocus() //Error - Undefined is not a function...?
c_img.release()
var r; var g; var b; var a
c_img.getRegGreenBlueAlpha($(r),$(g),$(b),$(a))
r = ObjC.unwrap(r)
g = ObjC.unwrap(g)
b = ObjC.unwrap(b)
a = ObjC.unwrap(a)
This code is heavily based off of the code found here.
However, as shown above c_img.lockFocus() is undefined according to JXA. Oddly I can get access to c_img.lockFocusFlipped(), however I'm not sure how to use this and/or if it can be used for the same purpose as lockFocus().
Is there an obvious problem here? Or is there a better way to get the pixel colour of an image?
Any help would be grateful.

It looks like I am too used to methods requiring parenthesis. TylerGaw however told me that this is not necessarily the case.
ObjC.import('Foundation')
ObjC.import('AppKit')
var c_filePath = $(picturePath)
var c_img = $.NSImage.alloc.initWithContentsOfFile(c_filePath)
if(c_img==$()){
return []
}
var c_point = $.NSMakePoint(x,y)
c_img.lockFocus
var c_color = NSReadPixel(c_point)
c_img.unlockFocus
c_img.release
appears to work as expected.

Related

Calculate distance between two PFGeopoints in a NSPredicate for a Parse Query

I have a special case when I want to do something like
let predicate = NSPredicate(format:"
DISTANCE(\(UserLocation),photoLocation) <= visibleRadius AND
DISTANCE(\(UserLocation),photoLocation" <= 10)"
var query = PFQuery(className:"Photo", predicate:predicate)
Basically, I want to get all photos that are taken within 10km around my current location if my current location is also within the photo's visible radius
Also, photoLocation and visibleRadius are two columns in the database, I will supply UserLocation as a PFGeoPoint.
Is it possible to achieve this? In my opinion, I don't think that I may call, for example, photoLocation.latitude to get a specific coordinate value. May I?
I'll appreciate you a lot if this can be achieved!!
I found this at the pares.com docs here is the link
let swOfSF = PFGeoPoint(latitude:37.708813, longitude:-122.526398)
let neOfSF = PFGeoPoint(latitude:37.822802, longitude:-122.373962)
var query = PFQuery(className:"PizzaPlaceObject")
query.whereKey("location", withinGeoBoxFromSouthwest:swOfSF, toNortheast:neOfSF)
var pizzaPlacesInSF = query.findObjects()
This code fetch you all the objects that are in a rectangle area defined by the swOfSF & neOfSF objectc, where seOfSF is in the south-west corner and neOfSF is in the north-east corner.
You can make some alterations to the code and get all the objects in rectangle area that your object is in middle
i would recommend that you don't use a radius, because it will take a lot of calculations. Instead use a rectangle area (like in the code i gave you).
just calculate what is the max/min longitude & max/min latitude from your position and fetch all the objects that are in between. you can read about how to fine the min/max longitude & latitude here Link
I managed to solve it using Parse Cloud Code, here is the quick tutorial
Parse.Cloud.define("latestPosts", function(request, response) {
var limit = 20;
var query = new Parse.Query("Post");
var userLocation = request.params.userLocation;
var searchScope = request.params.searchScope;
var afterDate = request.params.afterDate;
var senderUserName = request.params.senderUserName;
query.withinKilometers("Location", userLocation, searchScope);
query.greaterThan("createdAt", afterDate);
query.notEqualTo("senderUserName",senderUserName);
query.ascending("createdAt");
query.find({
success: function(results) {
var finalResults = results.filter(function(el) {
var visibleRadius = el.get("VisibleRadius");
var postLocation = el.get("Location");
return postLocation.kilometersTo(userLocation) <= visibleRadius;
});
if (finalResults.length > limit) {
var slicedFinalResults = results.slice(0, 20);
response.success(slicedFinalResults);
} else {
response.success(finalResults);
}
},
error: function() {
response.error("no new post");
}
});
});
The code above illustrate a basic example of how to use Cloud Code. Except, I have to make sure that all the returned image are in the union of user's search scope and photo's visible circle. There are more techniques such as Promises. But for my purpose, the code above should just suffice.

Can't get additionalSearchFields to work

jsonStoreInit = function(pSuccess, pFailure){
collections={};
collections['objects'] = {};
var options = {};
options.localKeyGen = false;
options.clear = false;
options.username = app.username;
options.password = app.password;
options.additionalSearchFields = {key: 'string'};
WL.JSONStore.init(collections, options)
.then(pSuccess)
.fail(pFailure);
};
putObject = function(pObject) {
var keyValue = pObject.getKey();
var object = {myObject : pObject.getKey()};
var options = {};
//options.additionalSearchFields = {key : keyValue};
WL.JSONStore.get("objects")
.add(object, options);
};
I'm on WL 6.0 FP 1
In the code sample above jsonStoreInit is what I use to init my store including the options.additionalSearchFields.
When I come to add the objects in the putObject funciton it works fine with the additionalSearchFields commented out, but when I uncomment it to add the additional fields I get an error
[wl.jsonstore] {"src":"store","err":21,"msg":"INVALID_ADD_INDEX_KEY","col":"objects","usr":"xxxx","doc":{},"res":{}}
When I look this error message up all I get is
21 INVALID_ADD_INDEX_KEY
Problem with additional search fields.
Which I had kinda figured ... can anyone provide any help on this ...
I don't need to you fix my code but if you could point me to a working example that would be excellent.
Many thanks, ownimage
The person that asked the question solved it, but I'm leaving this answer in case someone is wondering how to pass data that uses additionalSearchFields.
Example:
var data = {hello: 'world'};
WL.JSONStore.get('collection').add(data, {additionalSearchFields: {key: 'value'}})
The example assumes the collection was created with a search field for hello as string and an additional search field for key as string. It also assumes there's a collection initialized called collection.

how to use serialization package

I want to convert my class to a Map so I'm using Serialization package. From the example it looks simple:
var address = new Address();
address.street = 'N 34th';
address.city = 'Seattle';
var serialization = new Serialization()
..addRuleFor(Address);
Map output = serialization.write(address);
I expect to see an output like {'street' : 'N 34th', 'city' : 'Seattle'} but instead it just output something I-don't-know-what-that-is
{"roots":[{"__Ref":true,"rule":3,"object":0}],"data":[[],[],[],[["Seattle","N 34th"]]],"rules":"{\"roots\":[{\"__Ref\":true,\"rule\":1,\"object\":0}],\"data\":[[],[[{\"__Ref\":true,\"rule\":4,\"object\":0},{\"__Ref\":true,\"rule\":3,\"object\":0},{\"__Ref\":true,\"rule\":5,\"object\":0},{\"__Ref\":true,\"rule\":6,\"object\":0}]],[[],[],[\"city\",\"street\"]],[[]],[[]],[[]],[[{\"__Ref\":true,\"rule\":2,\"object\":0},{\"__Ref\":true,\"rule\":2,\"object\":1},\"\",{\"__Ref\":true,\"rule\":2,\"object\":2},{\"__Ref\":true,\"rule\":7,\"object\":0}]],[\"Address\"]],\"rules\":null}"}
Serialization is not supposed to create human-readable output. Maybe JSON output is more what you look for:
import dart:convert;
{
var address = new Address();
..address.street = 'N 34th';
..address.city = 'Seattle';
var encoded = JSON.encode(address, mirrorJson);
}
Map mirrorJson(o) {
Map map = new Map();
InstanceMirror im = reflect(o);
ClassMirror cm = im.type;
var decls = cm.declarations.values.where((dm) => dm is VariableMirror);
decls.forEach((dm) {
var key = MirrorSystem.getName(dm.simpleName);
var val = im.getField(dm.simpleName).reflectee;
map[key] = val;
});
return map;
}
The new Address() creates a full prototype object which is what you are seeing. That being said, they could have done something to avoid part of those, but if you want to restore the object just the way it is, that's necessary.
To see the full content of an object you use the for() instruction in this way:
for(obj in idx) alert(obj[idx]);
You'll see that you get loads of data this way. Without the new Address() it would probably not be that bad.
Serialization won't help you here...
You might give a try to JsonObject library, and maybe go through this in depth explanation how to do what you are trying to do using mirrors.

Small AS2 OOP Issue

I'm working with Actionscript 2 (not ready to upgrade yet, although it's irreverent to the problem) but I'm having trouble with OOP and classes.
I've got a "Tool" class, written like so:
class com.Tool {
public var self:MovieClip;
private static var Type:String;
function Tool(T:String, X:Number, Y:Number) {
Type = T;
self = _root.createEmptyMovieClip("obj"+_root.getNextHighestDepth(), _root.getNextHighestDepth());
self._x = X;
self._y = Y;
self.width = 36;
self.height = 36;
self.onRollOver = function() {
trace(Type);
}
}
}
I create 3 of them in the main script like so:
var toolPan:Tool = new Tool("pan", 0, 0);
var toolSquare:Tool = new Tool("square", 0, 38);
var toolLine:Tool = new Tool("line", 0, 76);
It all works great, except the onRollOver. It's supposed to output the unique "Type" string, but it always outputs "line" (the last Type Tool created) regardless which one I roll over.
Needless to say, I'm still a beginner to all this. But it seems like they're all sharing the same variable :/ How do I make these variables unique to each object created?
Thank you very much!
It's because it's type static, so the value is shared by all instances of that class. Remove it and it should work.
private var Type:String;

creating new variable name instance using this[ ] in actionscript 3

I keep looking this over the internet but I think, as far as I have searched, nothing yet had been posted (if any, please give me some links). Is this a way to make an instance this way. When I tried, there's a compilation error, a syntax error ("expecting identifier before this"). I'm happy to receive help from you guys.
Here's my code.
var mc_Names:Array = [];
function createMovieClip(index:int):void{
var nameOfMc:String = "mc_" + index;
mc_Names[index] = nameOfMc;
var this[mc_Names[index]]:MovieClip = new MovieClip(); **// this is what I'm asking if it is possible**
this[mc_Names[index]].graphics.lineStyle(20,0x00FF00, 0.5);
this[mc_Names[index]].graphics.moveTo(square_mc.x,square_mc.y);
this[mc_Names[index]].graphics.lineTo(mc3.x, mc3.y);
this[mc_Names[index]].x = 0;
this[mc_Names[index]].y = 0;
addChildAt(this[mc_Names[index]], 0);
currentIndex++;
}
Or is there any way to make it more simple or another way of declaring variable instances through this[] to make a dynamic creation of those movieclip instances.
var index:int = 1;
var A:Array = new Array();
A[index] = "mc_1";
A[index] = new MovieClip();
A[index].graphics.lineStyle(20,0x00FF00, 0.5);
A[index].graphics.moveTo(0,0);
A[index].graphics.lineTo(100, 100);
A[index].x = 0;
A[index].y = 0;
addChildAt(A[index], 0);
//it is possible to do this way. Direct substitution... :D