Flickr Integration Complete!

It really didn't take too long! What I outlined in the previous post is exactly what it does:

  • Check flickr for my photos that were tagged with "jtccom". Download the 2048 pixel wide version of it
  • Write JS + Node part of my website which shows, in a queue like manner, an image that hasn't been processed
  • Clicking on the image shows a box of where I clicked, where it would be cropped, according to the sizes defined for the header
  • Send request to the server, which uses GraphicsMagick to crop it and then create different scaled images based on the sizes defined for the site

Here are some screenshots:

At first, you are prompted with the next image which hasn't been processed


Next, you select the point where you want to crop it. Sizes are pre-determined, so there's no dragging and resizing a bounding box, it knows all the sizes and the size of the images, so it just does it for you


Click the process button when you've made your crop selection


Wait a second or two while Node.js and gm (GraphicsMagick) processes your photos.

And GraphicsMagick code in node.js, which is really helpful, and I was able to get it to work on Windows

this.handlePost = function(site, query, finishedCallback){ var tmpdir = path.normalize(site.path + site.config.tempDownloadFolder); var processeddir = path.normalize(site.path + site.config.processedFolder); var form = query.form; var sizes = site.config.imageWidths; var heights = site.config.imageHeights; var filename = form.image.substring(form.image.lastIndexOf("/")+1); var fileParts = filename.split("."); sizes.sort(function(a,b){ return b - a; }); heights.sort(function(a,b){ return b - a; }); var x1 = parseInt(form.x1, 10), x2 = parseInt(form.x2, 10), y1 = parseInt(form.y1, 10), y2 = parseInt(form.y2, 10); var w = x2 - x1, h = y2 - y1; // process first size, use that for base of resizes var croppedPath = processeddir + fileParts[0] + "-" + sizes[0] + "." + fileParts[1]; gm(tmpdir + filename).crop(w, h, x1, y1).write(croppedPath, function(err){ var sync = new SyncArray(sizes); sync.forEach(function(size, index, array, finishedOne){ if (index > 0){ var scaled = processeddir + fileParts[0] + "-" + size + "." + fileParts[1]; gm(croppedPath).resize(size, heights[index]).write(scaled, function(x){ finishedOne(); }); } else finishedOne(); }, function(){ finishedCallback({ content: JSON.stringify({ success: true }), headers: {"Content-Type": "application/json"} }); }); }); }

Again, it uses my custom built webserver and the SyncArray object that I also wrote.

Flickr code was pretty simple too. Here's that, accessing the Flickr API (no auth) with Node.js

var http = require("http"), querystring = require("querystring"), SyncArray = require("syncarray").SyncArray; this.getPhotosByTag = function(apiKey, user, tag, callback){ var self = this; var method = "flickr.photos.search"; var qs = { method: method, api_key: apiKey, user_id: user, tags: tag, format: "json", nojsoncallback: 1 }; var req = { host: "api.flickr.com", path: "/services/rest/?" + querystring.stringify(qs) }; http.get(req, function(res){ var json = ""; res.on("data", function(d){ json += d; }).on("end", function(){ var photos = JSON.parse(json).photos.photo; if (photos.length > 0){ var sync = new SyncArray(photos); sync.forEach(function(photo, index, array, finishedOne){ self.getPhotoSizes(apiKey, photo.id, function(sizes){ photo.url = sizes.filter(function(s){ return s.label == "Large 2048"; })[0].source; finishedOne(); }) }, function(){ console.log("url = " + photos[0].url) callback(photos); }) } else callback([]); }); }); } this.getPhotoSizes = function(apiKey, photoId, callback){ var method = "flickr.photos.getSizes"; var qs = { method: method, api_key: apiKey, photo_id: photoId, format: "json", nojsoncallback: 1 }; var req = { host: "api.flickr.com", path: "/services/rest/?" + querystring.stringify(qs) }; http.get(req, function(res){ res.setEncoding("utf8"); var json = ""; res.on("data", function(d){ json += d; }).on("end", function(){ var sizes = JSON.parse(json).sizes.size; console.log(sizes.length); callback(sizes); }); }); }

The next step is to update the front end css to include all sizes of a version of the image, and switch between them using the respond.js and media queries. That should be simple, but it's late and I'm going to bed!!

Enjoy! Leave a comment.

Prettier Site

I updated the site by incorporating a random picture that I've taken, pre-cropped, into the header.

As a developer and overall lazy person, finding and cropping 10 images to the size that I want was way too much. I will have to rectify this. I got a flickr API key. Here are my plans:

  1. Obtain Flickr API Key - Done
  2. Take Pictures
  3. Upload them to flickr the normal way
  4. Add a tag to them specifying that they are suitable for the website, like jtccom
  5. Write a service that checks for new photos of mine with that tag, download them, flag them as new
  6. Write an admin interface to show new images, and for now, let me click the important part of the image, so it can crop to the size I need around the specified point. Sizes will be pre-determined (3 sizes for the 3 different breakpoints I have defined in my responsive design (not much to it).
  7. Continuously have an inflow of beautiful headers that will display on my web page

It shouldn't be that bad. Nothing I've mentioned above has me too concerned. It should be fun! For now, though, I have 10 canned images that don't populate directly from flickr. They are random so you have have to refresh more than just 10 times to see them all. Enjoy!