Posts tagged "photoshop"

Leveraging C/C++ libraries in the CS SDK using Alchemy

This post is going to walk through creating a CS Extension which checks grammar in InDesign. To achieve this, we’ll be using an Adobe Labs technology called Alchemy. If you’re not familiar, Alchemy is a tool that lets you compile C/C++ code into ActionScript bytecode. That means you can efficiently call into your C/C++ code from a pure ActionScript solution. This is especially exciting in the context of the Creative Suite because many developers already have a huge amount of existing code in C/C++. Here’s a brief demo:

 

 

Getting up and running with Alchemy

The following links should be enough to get you going:

Defining the interface

After Alchemy is set up, we next need to download an open-source C library called Link Grammar, you can get the source from here. While the library has plenty of features, we’ll just be using it to tell whether a sentence is grammatically correct or not. To call into this C library from ActionScript we need to define an interface that Alchemy can understand. We define this interface in the C code’s main function. Link Grammar defines a sample main in src/parse.c; replace it with this one, which defines the interface to Alchemy. Here are some magical lines to note:

AS3_Val setupFunction = AS3_Function( NULL, setup );
AS3_Val isThisGrammarFunction = AS3_Function( NULL, isThisGrammar );
AS3_Val result = AS3_Object( “setup: AS3ValType, isThisGrammar:AS3ValType”,

setupFunction, isThisGrammarFunction);

AS3_Release( setupFunction );
AS3_Release( isThisGrammarFunction );
AS3_LibInit( result );

 

This tells Alchemy that we have two C functions we want to expose to ActionScript; setup and isThisGrammar. Now all we have to do is flesh out these functions. For example, here’s our isThisGrammar function:

static AS3_Val isThisGrammar(void* self, AS3_Val args) {

Sentence sent;
int num_linkages;
char* val = NULL;
AS3_ArrayValue( args, “StrType”, &val );
sent = sentence_create(val, dict);
num_linkages = sentence_parse(sent, opts);
if (num_linkages > 0) {

sentence_delete(sent);
return AS3_True();

}
sentence_delete(sent);
return AS3_False();

}

 

This function first reads in a string passed from ActionScript and stores it in the variable val. We then pass val into the Link Grammar library. Based on the result, we return a Boolean to ActionScript telling it whether or not this sentence is grammatically correct. Notice, because we’re in C-land we have to keep in mind memory management (e.g. releasing the sentences when we’re done).

 

Compiling the library

Now that our interface is defined, let’s compile the C code into a swc. Since Alchemy uses a modified version of gcc, we pass it the compiler flag “-swc”. In the Link Grammar Makefile, we need only to change the rule which builds the binary so that it reads:

 

${BIN}/parse: ${OBJECTS}

${CC} ${CLDFLAGS} ${OBJECTS} -swc -o parse.swc

 

Running “make” from the command line will generate parse.swc. Easy as that!

 

From the ActionScript side

In most Alchemy use cases, all we have to do is initialize the C library and then call into the interfaces we defined:

var loader:CLibInit = new CLibInit();
var lib:Object = loader.init();
lib.setup();

 

However, it’s slightly more complex in our case. Alchemy requires that you pass any files needed by the C code as a byte array to the loader before calling your interfaces. Because the C code requires access to the file system (to read the dictionary, grammar rules, etc.), we’re going to need a function something like this:

private function supplyFile( loader:CLibInit, file:File, fileName:String):void {

var bytes:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(bytes, 0, stream.bytesAvailable);
stream.close();
loader.supplyFile(fileName, bytes);

}

 

And that’s all there is to it. To compile the CS Extension, generate the swc and copy it into the libs/ folder. At runtime, make sure you have the contents of Link Grammar’s data/ folder (which includes 4.0.dict, words/, etc.) copied onto the desktop.

 

 

Attached Files:

Localizing Adobe Creative Suite 5 Extensions

If you are developing extensions for Creative Suite CS5, you might want to adapt your software to your audience based on their language or specific region. The Creative Suite host applications have been localised to many languages and now you can also localise your extensions so your users will be able to interact with them in their native or preferred language.
Adding multiple locale support doesn’t have to increase your engineering effort. This cookbook recipe explains you how you can localise not only your extension user interface but also the extension configuration.
There is also a sample that puts in practice the steps explained in the cookbook recipe. This image below shows how the same extension can be localised to different languages and also how we can change it’s configuration based on specific locales. The same sample extension is running in an English version of Illustrator, a Japanese version of Flash Pro and a Spanish version of Photoshop.
localised_extension.jpg
If you are using Extension Builder, you can download the “Localised” sample by selecting:
File > Import > Other > Adobe Creative Suite Extension Builder > Remote Creative Suite SDK Samples > Localised

Geolocation inside the Creative Suite

As part of the Creative Suite Developer Summit we’ve been showing off some sample code that illustrates just how easy certain workflows become when you move into Flash. One of these, that was shown at the session on Connecting the Creative Suite to Web Services (go here to watch), illustrates how you can connect up the Creative Suite to Google Maps and Flickr.

This sample shows an extension built to run in Photoshop, InDesign and Bridge CS5 (and could easily be extended to any product in the Suite). It connects to Google Maps to show location information, and Flickr to show relevant images – with the data used to power those searches customised based on the application the extension runs in. So, in Photoshop this will check the geolocation of the current image (extracted via XMP) and show the images taken nearby. In InDesign it will instead take the location from the machine’s IP address and search based on keywords using the user’s last sentence. Bridge provides a combination of both, where location comes from the XMP and the keywords come from the image tags.

The best part of this is how cheap integration is with these external systems. Google Maps Flex SDK, for example, requires a single MXML entry to create a map, with an additional call into that object being enough to change the positioning of the map;

<maps:Map xmlns:maps=”com.google.maps.*”
    id=”map” width=”263″ height=”229″
    url=”http://code.google.com/apis/maps/”
    key=”SUPER_SECRET_API_KEY”
    x=”30″ y=”10″/>

this.map.setCenter(location,15, MapType.NORMAL_MAP_TYPE);

For Flickr there are plenty of SDK options available, including one for ActionScript, but for the purposes of this I’ve chosen to roll my own calls. This uses a network communications library provided with Extension Builder, which lets us use the minimal amount of code to make a quick call across the network to retrieve the relevant data;

var request:HttpRequest = new HttpRequest(HttpRequest.GET, “http://api.flickr.com”, “/services/rest/”);
request.setParam(“method”, “flickr.photos.search”);
request.setParam(“api_key”, FLICKR_KEY);
request.setParam(“lat”, latLon.lat());
request.setParam(“lon”, latLon.lng());
request.perform(function(response:HttpResponse):void
{
    if (response.succeeded() || response.get_Status() == 0)
    {
        if (response.isParseable())
        {
            // success: XML or JSON response
            var xml:XML = new XML(response.getBodyText());
            for each (var photo:XML in xml.photos.photo) {
            }
        }
    }
});

If you’d like to try this out, you can grab the Extension Builder project here. You’ll need to drop the Google Maps Flex SWC (available here) into the libs folder, and enter your own API key for both the Maps service and Flickr.

I’ve also made it available as a ZXP (here), and as a zip for Bridge (here) the contents of which should be unzipped into your Bridge CS5 user startup scripts folder.