text: 
  module.exports = function(RED) {
      "use strict";
      var ExifImage = require('exif').ExifImage;
  
      function convertDegreesMinutesSecondsToDecimals(degrees, minutes, seconds) {
          var result;
          result = degrees + (minutes / 60) + (seconds / 3600);
          return result;
      }
  
      function ExifNode(n) {
          RED.nodes.createNode(this,n);
          var node = this;
  
          /***
           * Extracts GPS location information from Exif data. If enough information is
           * provided, convert the Exif data into a pair of single floating point number
           * latitude/longitude data pairs. Populates msg.location with these.
           * Assumes that the msg object will always have exifData available as msg.exif.
           * Assume that the GPS data saved into Exif provides a valid value
           */
          function addMsgLocationDataFromExifGPSData(msg) {
              var gpsData = msg.exif.gps; // declaring variable purely to make checks more readable
              if (gpsData.GPSAltitude) {
                  /* istanbul ignore else */
                  if (!msg.location) { msg.location = {}; }
                  msg.location.alt = gpsData.GPSAltitude;
              }
              if (gpsData.GPSLatitudeRef && gpsData.GPSLatitude && gpsData.GPSLongitudeRef && gpsData.GPSLongitude) { // location can be determined, OK
                  // The data provided in Exif is in degrees, minutes, seconds, this is to be converted into a single floating point degree
                  if (gpsData.GPSLatitude.length === 3) { // OK to convert latitude
                      if (gpsData.GPSLongitude.length === 3) { // OK to convert longitude
  
                          var latitude = convertDegreesMinutesSecondsToDecimals(gpsData.GPSLatitude[0], gpsData.GPSLatitude[1], gpsData.GPSLatitude[2]);
                          latitude = Math.round(latitude * 100000)/100000;    // 5dp is approx 1m resolution...
                          // (N)orth means positive latitude, (S)outh means negative latitude
                          if (gpsData.GPSLatitudeRef.toString() === 'S' || gpsData.GPSLatitudeRef.toString() === 's') {
                              latitude = latitude * -1;
                          }
  
                          var longitude = convertDegreesMinutesSecondsToDecimals(gpsData.GPSLongitude[0], gpsData.GPSLongitude[1], gpsData.GPSLongitude[2]);
                          longitude = Math.round(longitude * 100000)/100000;  // 5dp is approx 1m resolution...
                          // (E)ast means positive longitude, (W)est means negative longitude
                          if (gpsData.GPSLongitudeRef.toString() === 'W' || gpsData.GPSLongitudeRef.toString() === 'w') {
                              longitude = longitude * -1;
                          }
                          // Create location property if not exists
                          if (!msg.location) { msg.location = {}; }
                          msg.location.lat = latitude;
                          msg.location.lon = longitude;
                          return;
                      }
                      else {
                          node.log("Invalid longitude data, no location information has been added to the message.");
                      }
                  }
                  else {
                      node.log("Invalid latitude data, no location information has been added to the message.");
                  }
              }
              else {
                  node.log("The location of this image cannot be determined safely so no location information has been added to the message.");
              }
          }
  
          this.on("input", function(msg) {
              try {
                  if (msg.payload) {
                      if (Buffer.isBuffer(msg.payload)) {
                          new ExifImage({ image : msg.payload }, function (error, exifData) {
                              if (error) {
                                  node.log(error.toString());
                              }
                              else {
                                  if (exifData) {
                                      msg.exif = exifData;
                                      if ((exifData.hasOwnProperty("gps")) && (Object.keys(exifData.gps).length !== 0)) {
                                          addMsgLocationDataFromExifGPSData(msg);
                                      }
                                      //else { node.log("The incoming image did not contain Exif GPS data."); }
                                  }
                                  else {
                                      node.warn("The incoming image did not contain any Exif data, nothing to do.");
                                  }
                              }
                              node.send(msg);
                          });
                      }
                      else {
                          node.error("Invalid payload received, the Exif node cannot proceed, no messages sent.",msg);
                          return;
                      }
                  }
                  else {
                      node.error("No payload received, the Exif node cannot proceed, no messages sent.",msg);
                      return;
                  }
              }
              catch (error) {
                  node.error("An error occurred while extracting Exif information. Please check the log for details.",msg);
                  node.log('Error: '+error.message);
                  return;
              }
          });
      }
      RED.nodes.registerType("exif",ExifNode);
  }
  