[Exif] Implement getExifInfo().
authorRafal Lelusz <r.lelusz@samsung.com>
Tue, 20 Jan 2015 13:25:27 +0000 (14:25 +0100)
committerPawel Sikorski <p.sikorski@samsung.com>
Wed, 21 Jan 2015 13:35:30 +0000 (22:35 +0900)
[Verification] Code compiles without errors. TCT pass rate 29/63.

Change-Id: If33a3907a28dbcd9a68a81d1c9f2b21279d4119f
Signed-off-by: Rafal Lelusz <r.lelusz@samsung.com>
src/exif/exif.gyp
src/exif/exif_api.js
src/exif/exif_information.cc
src/exif/exif_information.h
src/exif/exif_instance.cc
src/exif/exif_instance.h
src/exif/exif_util.cc
src/exif/exif_util.h
src/exif/get_exif_info.cc [new file with mode: 0644]
src/exif/get_exif_info.h [new file with mode: 0644]

index 6346ac80bf11c02e792ed3b0a80a14dbc5613575..9cc39a591bd51adce802ca1637518e06e900cab7 100644 (file)
@@ -28,6 +28,8 @@
         'rational.h',
         'exif_gps_location.cc',
         'exif_gps_location.h',
+        'get_exif_info.cc',
+        'get_exif_info.h',
       ],
       'conditions': [
         [ 'tizen == 1', {
index e890c49b12abb655d86daaf36aad6a4654a6817d..df9687be7133df0cda9fcbe69d91c1ec769e9335 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -82,6 +82,74 @@ function _getJsonFromExifInformation(exifInfo) {
   return json;
 }
 
+function _calculateDegDecimal(degrees, minutes, seconds) {
+  return parseInt(degrees) + parseInt(minutes) / 60.0 + parseInt(seconds) / 3600.0;
+}
+
+function _calculateExifInfo(exifInfoNative) {
+  // copy all properties that share name from
+  // exifInfoNative to exifInfo
+  var exifInfo = new tizen.ExifInformation(exifInfoNative);
+
+  // copy all remaining properties that do not share name or need extra calculations
+  if (exifInfoNative.originalTimeSeconds) {
+    exifInfo.originalTime = new Date(exifInfoNative.originalTimeSeconds * 1000);
+  }
+
+  if (parseInt(exifInfoNative.whiteBalanceValue) === 0) {  // 0=AUTO
+    exifInfo.whiteBalance = WhiteBalanceMode.AUTO;
+  } else if (parseInt(exifInfoNative.whiteBalanceValue) === 1) {  // 1=MANUAL
+    exifInfo.whiteBalance = WhiteBalanceMode.MANUAL;
+  }
+
+  // gpsLocation
+  if (exifInfoNative.gpsLatitudeDegrees &&
+      exifInfoNative.gpsLongitudeDegrees &&
+      exifInfoNative.gpsLatitudeRef &&
+      exifInfoNative.gpsLongitudeRef) {
+    exifInfo.gpsLocation = new tizen.SimpleCoordinates();
+    exifInfo.gpsLocation.latitude = _calculateDegDecimal(exifInfoNative.gpsLatitudeDegrees,
+        exifInfoNative.gpsLatitudeMinutes, exifInfoNative.gpsLatitudeSeconds);
+    exifInfo.gpsLocation.longitude = _calculateDegDecimal(exifInfoNative.gpsLongitudeDegrees,
+        exifInfoNative.gpsLongitudeMinutes, exifInfoNative.gpsLongitudeSeconds);
+
+    if (exifInfoNative.gpsLatitudeRef === 'SOUTH') {
+      exifInfo.gpsLocation.latitude = -exifInfo.gpsLocation.latitude;
+    } else if (exifInfoNative.gpsLatitudeRef !== 'NORTH') {
+      exifInfo.gpsLocation.latitude = null;  // invalid gpsLatitudeRef
+    }
+
+    if (exifInfoNative.gpsLongitudeRef === 'WEST') {
+      exifInfo.gpsLocation.longitude = -exifInfo.gpsLocation.longitude;
+    } else if (exifInfoNative.gpsLongitudeRef !== 'EAST') {
+      exifInfo.gpsLocation.longitude = null;  // invalid gpsLongitudeRef
+    }
+  }
+
+  // gpsAltitude
+  if (exifInfoNative.gpsAltitude && exifInfoNative.gpsAltitudeRef) {
+    if (parseInt(exifInfoNative.gpsAltitudeRef) === 0) {  // 0=ABOVE SEA LEVEL
+      exifInfo.gpsAltitude = exifInfoNative.gpsAltitude;
+    } else if (parseInt(exifInfoNative.gpsAltitudeRef) === 1) {  // 1=BELOW SEA LEVEL
+      exifInfo.gpsAltitude = -exifInfoNative.gpsAltitude;
+    }
+  }
+
+  // gpsTime
+  if (exifInfoNative.gpsExifDate) {
+    var dateSplit = exifInfoNative.gpsExifDate.split(':');
+    exifInfo.gpsTime = new Date(
+        dateSplit[0],  // year
+        dateSplit[1],  // month
+        dateSplit[2],  // day
+        exifInfoNative.gpsExifTimeHours,
+        exifInfoNative.gpsExifTimeMinutes,
+        exifInfoNative.gpsExifTimeSeconds);
+  }
+
+  return exifInfo;
+}
+
 ExifManager.prototype.getExifInfo = function() {
   var args = validator_.validateArgs(arguments, [
     {
@@ -112,7 +180,15 @@ ExifManager.prototype.getExifInfo = function() {
     if (native_.isFailure(result)) {
       native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
     } else {
-      var exifInfo = native_.getResultObject(result);
+
+      // call to c++ code. Fields that do not exist are undefined.
+      var exifInfoNative = native_.getResultObject(result);
+
+      // calculate ExifInformation struct. All fields are initially null.
+      // Fields that do not exist in jpg EXIF must remain null.
+      var exifInfo = _calculateExifInfo(exifInfoNative);
+
+      // make successCalback and pass exifInfo
       args.successCallback(exifInfo);
     }
   };
@@ -120,7 +196,6 @@ ExifManager.prototype.getExifInfo = function() {
   native_.call('Exif_getExifInfo', callArgs, callback);
 };
 
-
 ExifManager.prototype.saveExifInfo = function() {
   var args = validator_.validateArgs(arguments, [
     {
@@ -193,7 +268,6 @@ ExifManager.prototype.getThumbnail = function() {
   native_.call('Exif_getThumbnail', {'uri': args.uri}, callback);
 };
 
-// this function passes ExifInformation_exposureProgram_attribute test:
 tizen.ExifInformation = function() {
   validator_.isConstructorCall(this, tizen.ExifInformation);
 
@@ -206,25 +280,40 @@ tizen.ExifInformation = function() {
     }
   ]);
 
-  var uri_ = null;
-  var width_ = null;
-  var height_ = null;
-  var deviceMaker_ = null;
-  var deviceModel_ = null;
-  var originalTime_ = null;
-  var orientation_ = null;
-  var fNumber_ = null;
-  var isoSpeedRatings_ = null;
-  var exposureTime_ = null;
-  var exposureProgram_ = null;
-  var flash_ = null;
-  var focalLength_ = null;
-  var whiteBalance_ = null;
-  var gpsLocation_ = null;
-  var gpsAltitude_ = null;
-  var gpsProcessingMethod_ = null;
-  var gpsTime_ = null;
-  var userComment_ = null;
+  var uri_ = null,
+      width_ = null,
+      height_ = null,
+      deviceMaker_ = null,
+      deviceModel_ = null,
+      originalTime_ = null,
+      orientation_ = null,
+      fNumber_ = null,
+      isoSpeedRatings_ = null,
+      exposureTime_ = null,
+      exposureProgram_ = null,
+      flash_ = null,
+      focalLength_ = null,
+      whiteBalance_ = null,
+      gpsLocation_ = null,
+      gpsAltitude_ = null,
+      gpsProcessingMethod_ = null,
+      gpsTime_ = null,
+      userComment_ = null;
+
+  function _validateISOSpeedRatings(v) {
+    var valid = false;
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        var data = v[i]; // todo: uncomment when array conversion is implemented.
+        //if (!type_.isNumber(data)) {
+        //  return false;
+        //}
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
 
   var exifInitDict = args.ExifInitDict;
   if (exifInitDict) {
@@ -240,7 +329,7 @@ tizen.ExifInformation = function() {
         return uri_;
       },
       set: function(v) {
-        uri_ = v ? converter_.toString(v, true) : uri_;
+        uri_ = v ? converter_.toString(v) : uri_;
       },
       enumerable: true
     },
@@ -249,7 +338,7 @@ tizen.ExifInformation = function() {
         return width_;
       },
       set: function(v) {
-        width_ = v ? converter_.toLong(v, true) : width_;
+        width_ = (!type_.isUndefined(v)) ? converter_.toLong(v, true) : width_;
       },
       enumerable: true
     },
@@ -258,7 +347,7 @@ tizen.ExifInformation = function() {
         return height_;
       },
       set: function(v) {
-        height_ = v ? converter_.toLong(v, true) : height_;
+        height_ = (!type_.isUndefined(v)) ? converter_.toLong(v, true) : height_;
       },
       enumerable: true
     },
@@ -266,8 +355,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return deviceMaker_;
       },
-      set: function(val) {
-        deviceMaker_ = val ? converter_.toString(val, true) : deviceMaker_;
+      set: function(v) {
+        deviceMaker_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : deviceMaker_;
       },
       enumerable: true
     },
@@ -275,8 +365,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return deviceModel_;
       },
-      set: function(val) {
-        deviceModel_ = val ? converter_.toString(val, true) : deviceModel_;
+      set: function(v) {
+        deviceModel_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : deviceModel_;
       },
       enumerable: true
     },
@@ -284,8 +375,10 @@ tizen.ExifInformation = function() {
       get: function() {
         return originalTime_;
       },
-      set: function(val) {
-        originalTime_ = val instanceof Date ? val : originalTime_;
+      set: function(v) {
+        if (!type_.isUndefined(v)) {
+          if (v === null || v instanceof Date) originalTime_ = v;
+        }
       },
       enumerable: true
     },
@@ -294,8 +387,8 @@ tizen.ExifInformation = function() {
         return orientation_;
       },
       set: function(v) {
-        orientation_ = v ? converter_.toEnum(v, Object.keys(ImageContentOrientation), true) :
-            orientation_;
+        orientation_ = (!type_.isUndefined(v)) ?
+            converter_.toEnum(v, Object.keys(ImageContentOrientation), true) : orientation_;
       },
       enumerable: true
     },
@@ -303,8 +396,8 @@ tizen.ExifInformation = function() {
       get: function() {
         return fNumber_;
       },
-      set: function(val) {
-        fNumber_ = val ? converter_.toDouble(val, true) : fNumber_;
+      set: function(v) {
+        fNumber_ = (!type_.isUndefined(v)) ? converter_.toDouble(v, true) : fNumber_;
       },
       enumerable: true
     },
@@ -312,8 +405,11 @@ tizen.ExifInformation = function() {
       get: function() {
         return isoSpeedRatings_;
       },
-      set: function(val) {
-        isoSpeedRatings_ = type_.isArray(val) ? val : isoSpeedRatings_;
+      set: function(v) {
+        // todo: convert string array into unsigned short array
+        if (!type_.isUndefined(v)) {
+          if (v === null || _validateISOSpeedRatings(v)) isoSpeedRatings_ = v;
+        }
       },
       enumerable: true
     },
@@ -321,8 +417,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return exposureTime_;
       },
-      set: function(val) {
-        exposureTime_ = val ? converter_.toString(val, true) : exposureTime_;
+      set: function(v) {
+        exposureTime_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : exposureTime_;
       },
       enumerable: true
     },
@@ -331,8 +428,8 @@ tizen.ExifInformation = function() {
         return exposureProgram_;
       },
       set: function(v) {
-        exposureProgram_ = v ? converter_.toEnum(v, Object.keys(ExposureProgram), true) :
-            exposureProgram_;
+        exposureProgram_ = (!type_.isUndefined(v)) ?
+            converter_.toEnum(v, Object.keys(ExposureProgram), true) : exposureProgram_;
       },
       enumerable: true
     },
@@ -340,8 +437,8 @@ tizen.ExifInformation = function() {
       get: function() {
         return flash_;
       },
-      set: function(val) {
-        flash_ = converter_.toBoolean(val, true);
+      set: function(v) {
+        flash_ = (!type_.isUndefined(v)) ? converter_.toBoolean(v, true) : flash_;
       },
       enumerable: true
     },
@@ -349,8 +446,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return focalLength_;
       },
-      set: function(val) {
-        focalLength_ = val ? converter_.toDouble(val, true) : focalLength_;
+      set: function(v) {
+        focalLength_ = (!type_.isUndefined(v)) ?
+            converter_.toDouble(v, true) : focalLength_;
       },
       enumerable: true
     },
@@ -359,8 +457,8 @@ tizen.ExifInformation = function() {
         return whiteBalance_;
       },
       set: function(v) {
-        whiteBalance_ = v ? converter_.toEnum(v, Object.keys(WhiteBalanceMode), true) :
-            whiteBalance_;
+        whiteBalance_ = (!type_.isUndefined(v)) ?
+            converter_.toEnum(v, Object.keys(WhiteBalanceMode), true) : whiteBalance_;
       },
       enumerable: true
     },
@@ -368,8 +466,10 @@ tizen.ExifInformation = function() {
       get: function() {
         return gpsLocation_;
       },
-      set: function(val) {
-        gpsLocation_ = val instanceof tizen.SimpleCoordinates ? val : gpsLocation_;
+      set: function(v) {
+        if (!type_.isUndefined(v)) {
+          if (v === null || v instanceof tizen.SimpleCoordinates) gpsLocation_ = v;
+        }
       },
       enumerable: true
     },
@@ -377,8 +477,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return gpsAltitude_;
       },
-      set: function(val) {
-        gpsAltitude_ = val ? converter_.toDouble(val, true) : gpsAltitude_;
+      set: function(v) {
+        gpsAltitude_ = (!type_.isUndefined(v)) ?
+            converter_.toDouble(v, true) : gpsAltitude_;
       },
       enumerable: true
     },
@@ -386,8 +487,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return gpsProcessingMethod_;
       },
-      set: function(val) {
-        gpsProcessingMethod_ = val ? converter_.toString(val, true) : gpsProcessingMethod_;
+      set: function(v) {
+        gpsProcessingMethod_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : gpsProcessingMethod_;
       },
       enumerable: true
     },
@@ -396,8 +498,10 @@ tizen.ExifInformation = function() {
       get: function() {
         return gpsTime_;
       },
-      set: function(val) {
-        gpsTime_ = val instanceof tizen.TZDate ? val : gpsTime_;
+      set: function(v) {
+        if (!type_.isUndefined(v)) {
+          if (v === null || v instanceof Date) gpsTime_ = v;
+        }
       }
     },
     userComment: {
@@ -405,8 +509,9 @@ tizen.ExifInformation = function() {
       get: function() {
         return userComment_;
       },
-      set: function(val) {
-        userComment_ = val ? converter_.toString(val, true) : userComment_;
+      set: function(v) {
+        userComment_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : userComment_;
       }
     }
   });
index b1aba683b2f8e56abe6b5d1e1233cfe6e11aeac8..63c8f8fa7a0b0cf842c480b60e311fdc3ceb7bb6 100644 (file)
@@ -596,488 +596,6 @@ void ExifInformation::set(std::string attributeName, const picojson::value& v) {
   }
 }
 
-bool getGCSPositionFromEntry(ExifEntry *entry, ExifData* exif_data,
-                             GCSPosition& out_pos) {
-  // RATIONAL - 3
-  if (EXIF_FORMAT_RATIONAL == entry->format &&
-      entry->components >= 3 &&
-      entry->data) {
-    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-    out_pos.degrees = Rational(exif_get_rational(entry->data, order));
-    out_pos.minutes = Rational(exif_get_rational(
-        entry->data +   ExifTypeInfo::RationalSize, order));
-    out_pos.seconds = Rational(exif_get_rational(
-        entry->data + 2*ExifTypeInfo::RationalSize, order));
-    return true;
-  } else {
-    return false;
-  }
-}
-
-bool getRationalsFromEntry(ExifEntry *entry, ExifData* exif_data,
-                           unsigned long required_count,
-                           Rationals& out_rationals) {
-  if (EXIF_FORMAT_RATIONAL == entry->format &&
-      entry->components >= required_count &&
-      entry->data) {
-    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-    unsigned char* ptr = entry->data;
-
-    for (unsigned long i = 0; i < required_count; ++i) {
-      out_rationals.push_back(Rational(exif_get_rational(ptr, order)));
-      ptr += ExifTypeInfo::RationalSize;
-    }
-
-    return true;
-  } else {
-    return false;
-  }
-}
-
-Rational getRationalFromEntry(ExifEntry *entry, ExifData* exif_data) {
-  if (EXIF_FORMAT_RATIONAL == entry->format &&
-      entry->components >= 1 &&
-      entry->data) {
-    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-    return Rational(exif_get_rational(entry->data, order));
-  } else {
-    return Rational::createInvalid();
-  }
-}
-
-bool decomposeExifUndefined(ExifEntry* entry, std::string& type,
-                            std::string& value) {
-  if (!entry || !entry->data) {
-    LoggerW("exif entry is NULL/empty");
-    return false;
-  }
-
-  if (entry->size < EXIF_UNDEFINED_TYPE_LENGTH) {
-    LoggerW("entry size is invalid %d < EXIF_UNDEFINED_TYPE_LENGTH",
-        entry->size);
-    return false;
-  }
-
-  const char* ptr = reinterpret_cast<const char*>(entry->data);
-  type = std::string(ptr, EXIF_UNDEFINED_TYPE_LENGTH);
-  ptr += EXIF_UNDEFINED_TYPE_LENGTH;
-  value = std::string(ptr, entry->size - EXIF_UNDEFINED_TYPE_LENGTH);
-  return true;
-}
-
-void ExifInformation::processEntry(ExifEntry* entry, ExifData* exif_data) {
-  char buf[2000];
-  exif_entry_get_value(entry, buf, sizeof(buf));
-  ExifUtil::printExifEntryInfo(entry, exif_data);
-
-  const ExifIfd cur_ifd = exif_entry_get_ifd(entry);
-  if (EXIF_IFD_INTEROPERABILITY == cur_ifd || EXIF_IFD_1 == cur_ifd) {
-    return;
-  }
-
-  switch (static_cast<unsigned int>(entry->tag)) {
-    case EXIF_TAG_IMAGE_WIDTH: {
-      // SHORT or LONG - 1
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation width to: [%s]", buf);
-      setWidth(atol(buf));
-      break;
-    }
-    case EXIF_TAG_IMAGE_LENGTH: {
-      // SHORT or LONG - 1
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation height to: [%s]", buf);
-      setHeight(atol(buf));
-      break;
-    }
-    case EXIF_TAG_MAKE: {
-      // ASCII - Any
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation maker to: [%s]", buf);
-      setDeviceMaker(std::string(buf));
-      break;
-    }
-    case EXIF_TAG_MODEL: {
-      // ASCII - Any
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation model to: [%s]", buf);
-      setDeviceModel(std::string(buf));
-      break;
-    }
-    case EXIF_TAG_DATE_TIME_ORIGINAL: {
-      // ASCII - 20
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      const time_t time = ExifUtil::exifDateTimeOriginalToTimeT(
-          reinterpret_cast<const char*>(entry->data));
-      LoggerD("Setting ExifInformation time original to: [%s] time_t:%d", buf,
-          static_cast<int>(time));
-      setOriginalTime(time);
-    }
-    case EXIF_TAG_ORIENTATION: {
-      // SHORT - 1
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-      const ExifShort orient(exif_get_short(entry->data, order));
-
-      if (orient < EXIF_ORIENTATION_NORMAL ||
-          orient >= EXIF_ORIENTATION_NOT_VALID) {
-        LoggerW("Couldn't set ExifInformation - orientation"
-            " is not valid: %d (%s)", orient, buf);
-      } else {
-        LoggerD("Setting ExifInformation orientation to: %d [%s]", orient, buf);
-        setOrientation(static_cast<ImageOrientation>(orient));
-      }
-      break;
-    }
-    case EXIF_TAG_FNUMBER:
-    {
-      // RATIONAL - 1
-      Rational fnumber = getRationalFromEntry(entry, exif_data);
-      if (fnumber.isValid()) {
-        LoggerD("Setting ExifInformation fnumber to: %f (%s)",
-            fnumber.toDouble(),
-            fnumber.toString().c_str());
-        setFNumber(fnumber);
-      } else {
-        LoggerW("Couldn't set ExifInformation - fnumber is not valid: %s",
-            fnumber.toString().c_str());
-      }
-      break;
-    }
-    case EXIF_TAG_ISO_SPEED_RATINGS: {
-      // SHORT - Any
-      if (EXIF_FORMAT_SHORT == entry->format &&
-          entry->components > 0 &&
-          entry->data) {
-        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-        unsigned char* read_ptr = entry->data;
-        const size_t size_per_member =
-            ExifUtil::getSizeOfExifFormatType(entry->format);
-
-        for (unsigned long i = 0; i < entry->components; ++i) {
-          ExifShort iso_rating = exif_get_short(read_ptr, order);
-
-          LoggerD("Appending ExifInformation speed ratings with: %d",
-              static_cast<int>(iso_rating));
-
-          read_ptr += size_per_member;
-        }
-      } else {
-        LoggerE("iso speed ratings: format or components count is invalid!");
-        throw common::TypeMismatchException("iso speed ratings: format or"
-            " components count is invalid!");
-      }
-      break;
-    }
-    case EXIF_TAG_EXPOSURE_TIME: {
-      // RATIONAL - 1
-      if (EXIF_FORMAT_RATIONAL == entry->format &&
-          entry->components > 0 &&
-          entry->data) {
-        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-        const Rational exp_time(exif_get_rational(entry->data, order));
-
-        if (exp_time.isValid()) {
-          LoggerD("Setting ExifInformation exposure time to: %s (%s)",
-              exp_time.toString().c_str(),
-              exp_time.toExposureTimeString().c_str());
-          setExposureTime(exp_time);
-        } else {
-          LoggerD("Couldn't set ExifInformation"
-              " - exposure time is not valid: %s",
-              exp_time.toString().c_str());
-        }
-      } else {
-        LoggerE("exposure time: format or components count is invalid!");
-        throw common::TypeMismatchException("exposure time: format or"
-            " components count is invalid!");
-      }
-      break;
-    }
-    case EXIF_TAG_EXPOSURE_PROGRAM: {
-      // SHORT - 1
-      exif_entry_get_value(entry, buf, sizeof(buf));
-
-      const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-      const ExifShort exp_program = exif_get_short(entry->data, order);
-      if (exp_program >= EXIF_EXPOSURE_PROGRAM_NOT_VALID) {
-        LoggerW("ExposureProgram: %d (%s) is not valid!", exp_program, buf);
-      } else {
-        LoggerD("Setting ExifInformation exposure program to: %d [%s]",
-            exp_program, buf);
-        setExposureProgram(static_cast<ExposureProgram>(exp_program));
-      }
-      break;
-    }
-    case EXIF_TAG_FLASH: {
-      // SHORT - 1
-      exif_entry_get_value(entry, buf, sizeof(buf));
-
-      const ExifByteOrder order = exif_data_get_byte_order(exif_data);
-      const ExifShort flash = exif_get_short(entry->data, order);
-
-      LoggerD("Setting ExifInformation flash to: [%s] flash=%d", buf, flash);
-      setFlash(flash != 0);
-      break;
-    }
-    case EXIF_TAG_FOCAL_LENGTH: {
-      // RATIONAL - 1
-      Rational flength = getRationalFromEntry(entry, exif_data);
-      if (flength.isValid()) {
-        LoggerD("Setting ExifInformation focal length to: %f (%s)",
-            flength.toDouble(), flength.toString().c_str());
-        setFocalLength(flength);
-      } else {
-        LoggerW("Couldn't set ExifInformation - focal length is not valid: %s",
-            flength.toString().c_str());
-      }
-      break;
-    }
-    case EXIF_TAG_WHITE_BALANCE: {
-      // SHORT - 1
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation white balance to: [%s]", buf);
-      if (entry->data[0]) {
-        setWhiteBalanceMode(EXIF_WHITE_BALANCE_MODE_MANUAL);
-      } else {
-        setWhiteBalanceMode(EXIF_WHITE_BALANCE_MODE_AUTO);
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_LONGITUDE: {
-      // RATIONAL - 3
-      GCSPosition longitude;
-      if (getGCSPositionFromEntry(entry, exif_data, longitude)) {
-        m_gps_location.setLongitude(longitude);
-        LoggerD("Setting ExifInformation gps longitude to: %s; %s; %s valid:%d",
-            longitude.degrees.toString().c_str(),
-            longitude.minutes.toString().c_str(),
-            longitude.seconds.toString().c_str(),
-            longitude.isValid());
-      } else {
-        exif_entry_get_value(entry, buf, sizeof(buf));
-        LoggerW("Couldn't set longitude pos - data is not valid: [%s]", buf);
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_LONGITUDE_REF: {
-      // ASCII - 2
-      if (entry->size < 1) {
-        LoggerW("Longtitude ref entry do not contain enought data!");
-        break;
-      }
-
-      const char ref = static_cast<char>(entry->data[0]);
-      if ('E' == ref || 'e' == ref) {      // East
-        m_gps_location.setLongitudeRef(GPS_LOCATION_EAST);
-        LoggerD("Setting ExifInformation gps longitude REF to: EAST");
-      } else if ('W' == ref || 'w' == ref) {   // West
-        m_gps_location.setLongitudeRef(GPS_LOCATION_WEST);
-        LoggerD("Setting ExifInformation gps longitude REF to: WEST");
-      } else {
-        LoggerW("Unknown longitude ref: %c (0x%x)", ref, static_cast<int>(ref));
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_LATITUDE: {
-      // RATIONAL - 3
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation latitude to: [%s], tag->%s",
-          buf, exif_tag_get_name(entry->tag) );
-
-      GCSPosition latitude;
-      if (getGCSPositionFromEntry(entry, exif_data, latitude)) {
-        m_gps_location.setLatitude(latitude);
-        LoggerD("Setting ExifInformation gps latitude to: %s; %s; %s valid:%d",
-            latitude.degrees.toString().c_str(),
-            latitude.minutes.toString().c_str(),
-            latitude.seconds.toString().c_str(),
-            latitude.isValid());
-      } else {
-        LoggerW("Couldn't set latitude pos - data is not valid!");
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_LATITUDE_REF: {
-      // ASCII - 2
-      if (entry->size < 1) {
-        LoggerW("Latitude ref entry do not contain enought data!");
-        break;
-      }
-
-      const char ref = static_cast<char>(entry->data[0]);
-      if ('N' == ref || 'n' == ref) {      // North
-        m_gps_location.setLatitudeRef(GPS_LOCATION_NORTH);
-        LoggerD("Setting ExifInformation gps latitude REF to: NORTH");
-      } else if ('S' == ref || 's' == ref) {   // South
-        m_gps_location.setLatitudeRef(GPS_LOCATION_SOUTH);
-        LoggerD("Setting ExifInformation gps latitude REF to: SOUTH");
-      } else {
-        LoggerW("Unknown latitude ref: %c (0x%x)", ref, static_cast<int>(ref));
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_ALTITUDE: {
-      // RATIONAL - 1
-      Rational gps_altitude = getRationalFromEntry(entry, exif_data);
-      if (gps_altitude.isValid()) {
-        LoggerD("Setting ExifInformation gps altitude to: %f (%s)",
-            gps_altitude.toDouble(), gps_altitude.toString().c_str());
-        setGpsAltitude(gps_altitude);
-      } else {
-        LoggerW("Couldn't set ExifInformation - gps altitude is not valid: %s",
-            gps_altitude.toString().c_str());
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_ALTITUDE_REF: {
-      // BYTE - 1
-      const ExifByte altitude_ref = static_cast<ExifByte>(entry->data[0]);
-      if (static_cast<ExifByte>(GPS_ALTITUDE_REF_ABOVE_SEA) == altitude_ref ||
-          static_cast<ExifByte>(GPS_ALTITUDE_REF_BELOW_SEA) == altitude_ref) {
-        setGpsAltitudeRef(static_cast<GpsAltitudeRef>(altitude_ref));
-        LoggerD("Setting ExifInformation gps altitude ref to: %d (%s)",
-            static_cast<int>(altitude_ref),
-            (altitude_ref > 0) ? "below sea" : "above sea");
-      } else {
-        LoggerW("GPS altitude ref is invalid:%d should be 0 or 1!",
-            static_cast<int>(altitude_ref));
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_PROCESSING_METHOD: {
-      // UNDEFINED - Any
-      std::string type, value;
-      if (decomposeExifUndefined(entry, type, value)) {
-        LoggerD("Extracted GPSProcessingMethod: [%s], len:%d, type:%s",
-            value.c_str(), value.length(), type.c_str());
-        setGpsProcessingMethod(type, value);
-
-        LoggerD("Setting ExifInformation processing method"
-            " to: [%s], len:%d, type:%s",
-            m_gps_processing_method.c_str(),
-            m_gps_processing_method.length(),
-            m_gps_processing_method_type.c_str());
-      } else {
-        LoggerW("GPSProcessingMethod tag contains invalid values!");
-      }
-      break;
-    }
-    case EXIF_TAG_GPS_DATE_STAMP: {
-      // ASCII - 11
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation gps date stamp to: [%s]", buf);
-      // m_exif_gps_time.setDate(buf);
-      break;
-    }
-    case EXIF_TAG_GPS_TIME_STAMP: {
-      // Rational - 3
-      exif_entry_get_value(entry, buf, sizeof(buf));
-      LoggerD("Setting ExifInformation gps time stamp to: [%s]", buf);
-
-      Rationals time;
-      if (getRationalsFromEntry(entry, exif_data, 3, time)) {
-        // m_exif_gps_time.setTime(time);
-      }
-      break;
-    }
-    case EXIF_TAG_USER_COMMENT: {
-      // UNDEFINED - Any
-      std::string type, value;
-      if (decomposeExifUndefined(entry, type, value)) {
-        LoggerD("Extracted UserComment: [%s], len:%d, type:%s",
-            value.c_str(), value.length(), type.c_str());
-        setUserComment(type, value);
-
-        LoggerD("Setting ExifInformation user comment"
-            " to: [%s], len:%d, type:%s",
-            m_user_comment.c_str(),
-            m_user_comment.length(),
-            m_user_comment_type.c_str());
-      } else {
-        LoggerW("UserComment tag contains invalid values!");
-      }
-
-      break;
-    }
-    default: {
-      LoggerD("Field of tag:%x.H [%s] is not supported, value: [%s]",
-          entry->tag,
-          exif_tag_get_name_in_ifd(entry->tag, cur_ifd),
-          exif_entry_get_value(entry, buf, sizeof(buf)));
-    }
-  }
-}
-
-struct ExifInfoAndDataHolder {
-  ExifInformationPtr exif_info;
-  ExifData* exif_data;
-};
-
-void ExifInformation::contentForeachFunctionProxy(ExifEntry *entry,
-                                                  void *user_data) {
-  ExifInfoAndDataHolder* holder =
-      static_cast<ExifInfoAndDataHolder*>(user_data);
-  if (!holder) {
-    LoggerE("holder is NULL");
-  }
-
-  if (!holder->exif_info) {
-    LoggerE("exif_info is NULL!");
-    return;
-  }
-
-  if (!holder->exif_data) {
-    LoggerE("exif_data is NULL!");
-    return;
-  }
-
-  try {
-    holder->exif_info->processEntry(entry, holder->exif_data);
-  }
-  /*catch(const BasePlatformException &err) {
-    LoggerE("processEntry thrown exception: %s : %s", err.getName().c_str(),
-          err.getMessage().c_str());
-  }*/
-  catch(...) {
-    LoggerE("Unsupported error while processing Exif entry.");
-  }
-}
-
-void ExifInformation::dataForeachFunction(ExifContent *content,
-                                          void *user_data) {
-  exif_content_foreach_entry(content, contentForeachFunctionProxy, user_data);
-}
-
-
-ExifInformationPtr ExifInformation::loadFromURI(const std::string& uri) {
-  ExifInformationPtr exif_info(new ExifInformation());
-  exif_info->setUri(uri);
-
-  const std::string file_path = ExifUtil::convertUriToPath(uri);
-  ExifData* ed = exif_data_new_from_file(file_path.c_str());
-  if (!ed) {
-    LoggerE("Error reading exif from file %s", file_path.c_str());
-    // throw NotFoundException("Error reading exif from file");
-  }
-
-  LoggerD("exif_data_foreach_content START");
-
-  ExifInfoAndDataHolder holder;
-  holder.exif_info = exif_info;
-  holder.exif_data = ed;
-  exif_data_foreach_content(ed, dataForeachFunction,
-      static_cast<void*>(&holder));
-
-  LoggerD("exif_data_foreach_content END");
-
-  exif_data_unref(ed);
-  ed = NULL;
-
-  return exif_info;
-}
-
-
 void ExifInformation::removeNulledAttributesFromExifData(ExifData* exif_data) {
   LoggerD("Entered");
   if (!exif_data) {
index 62ca1dd14ce2790b544639e77bcaffe2beebaa97..4c95d96e1bd65c64ae4b762f0e59b544c70e4de2 100644 (file)
@@ -117,7 +117,6 @@ class ExifInformation {
   explicit ExifInformation(const picojson::value& args);
   ~ExifInformation();
 
-  static ExifInformationPtr loadFromURI(const std::string& uri);
   void saveToFile(const std::string& file_path);
 
   const std::string& getUri();
@@ -210,10 +209,6 @@ class ExifInformation {
   void set(std::string attributeName, const picojson::value& args);
 
  private:
-  void processEntry(ExifEntry* entry, ExifData* exif_data);
-  static void contentForeachFunctionProxy(ExifEntry* entry, void* user_data);
-  static void dataForeachFunction(ExifContent* content, void* user_data);
-
   void removeNulledAttributesFromExifData(ExifData* exif_data);
   void updateAttributesInExifData(ExifData* exif_data);
 
index 9d5720caf19450d465f4c5e57758ff5050edb4f7..23650d30b2c23de4c185ddc87350ca9d90d4cdd2 100644 (file)
@@ -19,6 +19,7 @@
 #include "exif_util.h"
 #include "jpeg_file.h"
 #include "exif_information.h"
+#include "get_exif_info.h"
 
 namespace extension {
 namespace exif {
@@ -49,76 +50,18 @@ ExifInstance::~ExifInstance() { }
 
 void ExifInstance::getExifInfo(const picojson::value& args,
                                picojson::object& out) {
-  LoggerD("ExifInstance::getExifInfo() in c++ A");
+  LoggerD("enter");
 
   const std::string& uri = args.get("uri").get<std::string>();
 
   const double callback_id = args.get("callbackId").get<double>();
   auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
     try {
-      // uri = file:///opt/usr/media/Images/exif.jpg
-      // file_path = /opt/usr/media/Images/exif.jpg
       const std::string file_path = ExifUtil::convertUriToPath(uri);
       LoggerD("file_path = %s\n", file_path.c_str());
 
-      LoggerD("ExifInformation::loadFromURI... %s", file_path.c_str());
-      ExifInformationPtr exif_info = ExifInformation::loadFromURI(uri);
-      if (!exif_info) {
-        LoggerE("ExifInformation::loadFromURI failed for %s",
-            file_path.c_str());
-      }
-
-      unsigned long width = exif_info->getWidth();
-      LoggerD("width = %d", width);
-      unsigned long height = exif_info->getHeight();
-      LoggerD("height = %d", height);
-      const std::string& device_maker = exif_info->getDeviceMaker();
-      LoggerD("device_maker = %s", device_maker.c_str());
-      const std::string& device_model = exif_info->getDeviceModel();
-      LoggerD("device_model = %s", device_model.c_str());
-      const time_t original_time = exif_info->getOriginalTime();
-      LoggerD("original_time = %s", asctime(localtime(&original_time)));
-      //...
-
-      /* todo: all fields that need to be implemented:
-      DOMString uri;
-      unsigned long width;
-      unsigned long height;
-      DOMString deviceMaker;
-      DOMString deviceModel;
-      Date originalTime;
-      ImageContentOrientation orientation;
-      double fNumber;
-      unsigned short[] isoSpeedRatings;
-      DOMString exposureTime;
-      ExposureProgram exposureProgram;
-      boolean flash;
-      double focalLength;
-      WhiteBalanceMode whiteBalance;
-      SimpleCoordinates gpsLocation;
-      double gpsAltitude;
-      DOMString gpsProcessingMethod;
-      Date gpsTime;
-      DOMString userComment;
-*/
-
-      JsonValue result = JsonValue(JsonObject());
-      JsonObject& result_obj = result.get<JsonObject>();
-      std::ostringstream ss_width;
-      ss_width << width;
-      result_obj.insert(std::make_pair("width", ss_width.str().c_str()));
-      std::ostringstream ss_height;
-      ss_height << height;
-      result_obj.insert(std::make_pair("height", ss_height.str().c_str()));
-      result_obj.insert(std::make_pair("device_maker", device_maker.c_str()));
-      result_obj.insert(std::make_pair("device_model", device_model.c_str()));
-      // todo: convert to js type: Date
-      result_obj.insert(std::make_pair("original_time",
-          asctime(localtime(&original_time))));
-
-      // todo: implement remaining fields
-
-      ReportSuccess(result, response->get<picojson::object>());
+      JsonValue result_direct = GetExifInfo::LoadFromURI(uri);
+      ReportSuccess(result_direct, response->get<picojson::object>());
     } catch (const common::PlatformException& e) {
       ReportError(e, response->get<picojson::object>());
     }
@@ -136,7 +79,7 @@ void ExifInstance::getExifInfo(const picojson::value& args,
       get, get_response,
       std::shared_ptr<JsonValue>(new JsonValue(JsonObject())));
 
-  LoggerD("ExifInstance::getExifInfo() END (c++)");
+  LoggerD("exit");
 }
 
 void ExifInstance::saveExifInfo(const picojson::value& args,
index 3bde59dc2030e8bc391dcd65dd23b3cad94b9a15..1cf86a49ff060ff1de06d3a1ee34b2c4ffe49e51 100644 (file)
@@ -20,7 +20,7 @@ class ExifInstance : public common::ParsedInstance {
   void saveExifInfo(const picojson::value& args, picojson::object& out);
   void getThumbnail(const picojson::value& args, picojson::object& out);
 };
+
 }  // namespace exif
 }  // namespace extension
-
 #endif  // EXIF_EXIF_INSTANCE_H_
index ecc3b4107169fa93de4ac3e4c3979c0772ef4249..5dfb100922612d8e1a023527f83c91db154d59d9 100644 (file)
@@ -219,38 +219,6 @@ bool ExifUtil::isValidAbsoluteURI(const std::string& uri) {
   return 0 == uri.find(URI_ABSOLUTE_PREFIX);
 }
 
-void ExifUtil::getURIInfo(const std::string& uri,
-    // const Filesystem::NodeType expected_type,
-    const std::string& required_permission,
-    bool& out_exists,
-    // Filesystem::NodeType& out_type,
-    bool& out_permission_granted) {
-  const std::string absolute_path = ExifUtil::convertUriToPath(uri);
-  out_exists = false;
-  out_permission_granted = false;
-
-  try {
-    // Filesystem::PathPtr path = Filesystem::Path::create(absolute_path);
-    // Filesystem::NodePtr node = Filesystem::Node::resolve(path);
-    // out_type = node->getType();
-    // out_exists = true;
-
-    // if (expected_type == out_type) {
-    //  out_permission_granted = node->checkPermission(path,
-    //      required_permission,
-    //      expected_type);
-    // }
-  }
-  /* catch (const common::BasePlatformException &err) {
-     LoggerE("Couldn't resolve path: %s, got:%s (%s)", absolute_path.c_str(),
-        (err.getName()).c_str(), (err.getMessage()).c_str());
-  }
-  */
-  catch(...) {
-    LoggerE("Couldn't resolve path: %s", absolute_path.c_str());
-  }
-}
-
 // Example:
 // in: uri = file:///opt/usr/media/Images/exif.jpg
 // out: path = /opt/usr/media/Images/exif.jpg
@@ -323,7 +291,6 @@ const Rationals ExifUtil::timeTToExifGpsTimeStamp(time_t time) {
   return result;
 }
 
-
 std::string ExifUtil::timeTToExifGpsDateStamp(time_t time) {
   int year, month, day, hour, min, sec;
   extractFromTimeT(time, year, month, day, hour, min, sec);
index 7ccb081224fb20244c93b867c6166e8c68bb7c3e..9e773723e3e578f25cac4e7d462b534072be3382 100644 (file)
@@ -119,10 +119,6 @@ class ExifUtil {
   static const std::string& exposureProgramToString(ExposureProgram value);
 
   static bool isValidAbsoluteURI(const std::string& uri);
-  static void getURIInfo(const std::string& uri,
-      const std::string& required_permission,
-      bool& out_exists,
-      bool& out_permission_granted);
 
   static std::string convertUriToPath(const std::string& str);
   static std::string ltrim(const std::string& s);
diff --git a/src/exif/get_exif_info.cc b/src/exif/get_exif_info.cc
new file mode 100644 (file)
index 0000000..e929d45
--- /dev/null
@@ -0,0 +1,518 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2015 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "get_exif_info.h"
+
+#include <math.h>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+#include "exif_util.h"
+
+namespace extension {
+namespace exif {
+
+struct ExifDataHolder {
+  ExifData* exif_data;
+  JsonObject* result_obj_ptr;
+};
+
+Rational GetRationalFromEntry(ExifEntry *entry, ExifData* exif_data) {
+  if (EXIF_FORMAT_RATIONAL == entry->format
+      && entry->components >= 1
+      && entry->data) {
+    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+    return Rational(exif_get_rational(entry->data, order));
+  } else {
+    return Rational::createInvalid();
+  }
+}
+
+bool GetRationalsFromEntry(ExifEntry* entry, ExifData* exif_data,
+                           unsigned long required_count,
+                           Rationals& out_rationals) {
+  if (EXIF_FORMAT_RATIONAL == entry->format &&
+      entry->components >= required_count &&
+      entry->data) {
+    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+    unsigned char* ptr = entry->data;
+
+    for (unsigned long i = 0; i < required_count; ++i) {
+      out_rationals.push_back(Rational(exif_get_rational(ptr, order)));
+      ptr += ExifTypeInfo::RationalSize;
+    }
+
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool GetGCSPositionFromEntry(ExifEntry* entry, ExifData* exif_data,
+                             GCSPosition& out_pos) {
+  // RATIONAL - 3
+  if (EXIF_FORMAT_RATIONAL == entry->format &&
+      entry->components >= 3 &&
+      entry->data) {
+    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+    out_pos.degrees = Rational(exif_get_rational(entry->data, order));
+    out_pos.minutes = Rational(exif_get_rational(
+        entry->data +   ExifTypeInfo::RationalSize, order));
+    out_pos.seconds = Rational(exif_get_rational(
+        entry->data + 2*ExifTypeInfo::RationalSize, order));
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool DecomposeExifUndefined(ExifEntry* entry, std::string& type, std::string& value) {
+  if (!entry || !entry->data) {
+    LoggerW("exif entry is NULL/empty");
+    return false;
+  }
+
+  if (entry->size < EXIF_UNDEFINED_TYPE_LENGTH) {
+    LoggerW("entry size is invalid %d < EXIF_UNDEFINED_TYPE_LENGTH", entry->size);
+    return false;
+  }
+
+  const char* ptr = reinterpret_cast<const char*>(entry->data);
+  type = std::string(ptr, EXIF_UNDEFINED_TYPE_LENGTH);
+  ptr += EXIF_UNDEFINED_TYPE_LENGTH;
+  value = std::string(ptr, entry->size - EXIF_UNDEFINED_TYPE_LENGTH);
+  return true;
+}
+
+void GetExifInfo::ProcessEntry(ExifEntry* entry, ExifData* exif_data,
+                               JsonObject* result_obj) {
+  char buf[2000];
+  exif_entry_get_value(entry, buf, sizeof(buf));
+  ExifUtil::printExifEntryInfo(entry, exif_data);
+
+  const ExifIfd cur_ifd = exif_entry_get_ifd(entry);
+  if (EXIF_IFD_INTEROPERABILITY == cur_ifd || EXIF_IFD_1 == cur_ifd) {
+    return;
+  }
+
+  std::pair<std::string, std::string> pair;
+  switch (static_cast<unsigned int>(entry->tag)) {
+    case EXIF_TAG_IMAGE_WIDTH: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation width to: [%s]", buf);
+      pair = std::make_pair("width", std::string(buf));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_IMAGE_LENGTH: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation height to: [%s]", buf);
+      pair = std::make_pair("height", std::string(buf));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_MAKE: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation maker to: [%s]", buf);
+      pair = std::make_pair("deviceMaker", std::string(buf));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_MODEL: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation model to: [%s]", buf);
+      pair = std::make_pair("deviceModel", std::string(buf));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_DATE_TIME_ORIGINAL: {
+      // ASCII - 20
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      const time_t time = ExifUtil::exifDateTimeOriginalToTimeT(
+          reinterpret_cast<const char*>(entry->data));
+      LoggerD("Setting ExifInformation time original to: [%s] time_t:%d", buf,
+          static_cast<int>(time));
+      // convert time_t (number of seconds) to string
+      pair = std::make_pair("originalTimeSeconds",
+          std::to_string(static_cast<int>(time)));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_ORIENTATION: {
+      // SHORT - 1
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+      const ExifShort orient(exif_get_short(entry->data, order));
+
+      std::string orientation = ExifUtil::orientationToString(
+          static_cast<ImageOrientation>(orient));
+      pair = std::make_pair("orientation", orientation);
+      result_obj->insert(pair);
+
+      if (orient < EXIF_ORIENTATION_NORMAL || orient >= EXIF_ORIENTATION_NOT_VALID) {
+        LoggerW("Couldn't set ExifInformation - orientation is not valid: %d (%s)",
+            orient, buf);
+      } else {
+        LoggerD("Setting ExifInformation orientation to: %d [%s]", orient, buf);
+      }
+      break;
+    }
+    case EXIF_TAG_FNUMBER:
+    {
+      // RATIONAL - 1
+      Rational fnumber = GetRationalFromEntry(entry, exif_data);
+      if (fnumber.isValid()) {
+        LoggerD("Setting ExifInformation fnumber to: %f (%s)", fnumber.toDouble(),
+          fnumber.toString().c_str());
+        pair = std::make_pair("fNumber", std::to_string(fnumber.toDouble()));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("Couldn't set ExifInformation - fnumber is not valid: %s",
+            fnumber.toString().c_str());
+      }
+      break;
+    }
+    case EXIF_TAG_ISO_SPEED_RATINGS: {
+      // SHORT - Any
+      if (EXIF_FORMAT_SHORT == entry->format &&
+          entry->components > 0 &&
+          entry->data) {
+        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+        unsigned char* read_ptr = entry->data;
+        const size_t size_per_member =
+            ExifUtil::getSizeOfExifFormatType(entry->format);
+
+        JsonArray array = picojson::array();
+        for (unsigned long i = 0; i < entry->components; ++i) {
+          ExifShort iso_rating = exif_get_short(read_ptr, order);
+          array.push_back(picojson::value(std::to_string(iso_rating)));
+
+          LoggerD("Appending ExifInformation speed ratings with: %d",
+              static_cast<int>(iso_rating));
+
+          read_ptr += size_per_member;
+        }
+        std::pair<std::string, JsonArray> pair_array;
+        pair_array = std::make_pair("isoSpeedRatings", array);
+        result_obj->insert(pair_array);
+      } else {
+        LoggerE("iso speed ratings: format or components count is invalid!");
+        throw common::TypeMismatchException("iso speed ratings: format or"
+            " components count is invalid!");
+      }
+      break;
+    }
+    case EXIF_TAG_EXPOSURE_TIME: {
+      // RATIONAL - 1
+      if (EXIF_FORMAT_RATIONAL == entry->format &&
+          entry->components > 0 &&
+          entry->data) {
+        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+        const Rational exp_time(exif_get_rational(entry->data, order));
+
+        if (exp_time.isValid()) {
+          LoggerD("Setting ExifInformation exposure time to: %s (%s)",
+              exp_time.toString().c_str(),
+              exp_time.toExposureTimeString().c_str());
+          pair = std::make_pair("exposureTime", std::to_string(exp_time.toDouble()));
+          result_obj->insert(pair);
+        } else {
+          LoggerD("Couldn't set ExifInformation - exposure time is not valid: %s",
+              exp_time.toString().c_str());
+        }
+      } else {
+        LoggerE("exposure time: format or components count is invalid!");
+        throw common::TypeMismatchException("exposure time: format or"
+            " components count is invalid!");
+      }
+      break;
+    }
+    case EXIF_TAG_EXPOSURE_PROGRAM: {
+      // SHORT - 1
+      exif_entry_get_value(entry, buf, sizeof(buf));
+
+      const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+      const ExifShort exp_program = exif_get_short(entry->data, order);
+      if (exp_program >= EXIF_EXPOSURE_PROGRAM_NOT_VALID) {
+        LoggerW("ExposureProgram: %d (%s) is not valid!", exp_program, buf);
+      } else {
+        LoggerD("Setting ExifInformation exposure program to: %d [%s]",
+            exp_program, buf);
+        std::string exp_program_string =
+            ExifUtil::exposureProgramToString(static_cast<ExposureProgram>(exp_program));
+        pair = std::make_pair("exposureProgram", exp_program_string);
+        result_obj->insert(pair);
+      }
+      break;
+    }
+    case EXIF_TAG_FLASH: {
+      // SHORT - 1
+      exif_entry_get_value(entry, buf, sizeof(buf));
+
+      const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+      const ExifShort flash = exif_get_short(entry->data, order);
+
+      LoggerD("Setting ExifInformation flash to: [%s] flash=%d", buf, flash);
+      pair = std::make_pair("flash", (flash != 0) ? std::string("true") : std::string("false"));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_FOCAL_LENGTH: {
+      // RATIONAL - 1
+      Rational flength = GetRationalFromEntry(entry, exif_data);
+      if (flength.isValid()) {
+        LoggerD("Setting ExifInformation focal length to: %f (%s)",
+            flength.toDouble(), flength.toString().c_str());
+        pair = std::make_pair("focalLength", std::to_string(flength.toDouble()));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("Couldn't set ExifInformation - focal length is not valid: %s",
+            flength.toString().c_str());
+      }
+      break;
+    }
+    case EXIF_TAG_WHITE_BALANCE: {
+      // SHORT - 1
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation white balance to: [%s]", buf);
+      pair = std::make_pair("whiteBalanceValue",
+          std::to_string(static_cast<int>(entry->data[0])));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_GPS_LONGITUDE: {
+      // RATIONAL - 3
+      GCSPosition longitude;
+      if (GetGCSPositionFromEntry(entry, exif_data, longitude)) {
+        pair = std::make_pair("gpsLongitudeDegrees", std::to_string(longitude.degrees.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLongitudeMinutes", std::to_string(longitude.minutes.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLongitudeSeconds", std::to_string(longitude.seconds.toDouble()));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps longitude to: %s; %s; %s valid:%d",
+            longitude.degrees.toString().c_str(),
+            longitude.minutes.toString().c_str(),
+            longitude.seconds.toString().c_str(),
+            longitude.isValid());
+      } else {
+        LoggerW("Couldn't set longitude pos - data is not valid.");
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_LONGITUDE_REF: {
+      // ASCII - 2
+      if (entry->size < 1) {
+        LoggerW("Longitude ref entry do not contain enough data!");
+        break;
+      }
+
+      const char ref = static_cast<char>(entry->data[0]);
+      if ('E' == ref || 'e' == ref) {      // East
+        pair = std::make_pair("gpsLongitudeRef", std::string("EAST"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps longitude REF to: EAST");
+      } else if ('W' == ref || 'w' == ref) {   // West
+        pair = std::make_pair("gpsLongitudeRef", std::string("WEST"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps longitude REF to: WEST");
+      } else {
+        LoggerW("Unknown longitude ref: %c (0x%x)", ref, static_cast<int>(ref));
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_LATITUDE: {
+      // RATIONAL - 3
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation latitude to: [%s], tag->%s",
+          buf, exif_tag_get_name(entry->tag) );
+
+      GCSPosition latitude;
+      if (GetGCSPositionFromEntry(entry, exif_data, latitude)) {
+        pair = std::make_pair("gpsLatitudeDegrees", std::to_string(latitude.degrees.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLatitudeMinutes", std::to_string(latitude.minutes.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLatitudeSeconds", std::to_string(latitude.seconds.toDouble()));
+        result_obj->insert(pair);
+
+        LoggerD("Setting ExifInformation gps latitude to: %s; %s; %s valid:%d",
+            latitude.degrees.toString().c_str(),
+            latitude.minutes.toString().c_str(),
+            latitude.seconds.toString().c_str(),
+            latitude.isValid());
+      } else {
+        LoggerW("Couldn't set latitude pos - data is not valid!");
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_LATITUDE_REF: {
+      // ASCII - 2
+      if (entry->size < 1) {
+        LoggerW("Latitude ref entry do not contain enough data!");
+        break;
+      }
+
+      const char ref = static_cast<char>(entry->data[0]);
+      if ('N' == ref || 'n' == ref) {      // North
+        pair = std::make_pair("gpsLatitudeRef", std::string("NORTH"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps latitude REF to: NORTH");
+      } else if ('S' == ref || 's' == ref) {   // South
+        pair = std::make_pair("gpsLatitudeRef", std::string("SOUTH"));
+        LoggerD("Setting ExifInformation gps latitude REF to: SOUTH");
+      } else {
+        LoggerW("Unknown latitude ref: %c (0x%x)", ref, static_cast<int>(ref));
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_ALTITUDE: {
+      // RATIONAL - 1
+      Rational gps_altitude = GetRationalFromEntry(entry, exif_data);
+      if (gps_altitude.isValid()) {
+        LoggerD("Setting ExifInformation gps altitude to: %f (%s)",
+            gps_altitude.toDouble(), gps_altitude.toString().c_str());
+        pair = std::make_pair("gpsAltitude", std::to_string(gps_altitude.toDouble()));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("Couldn't set ExifInformation - gps altitude is not valid: %s",
+            gps_altitude.toString().c_str());
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_ALTITUDE_REF: {
+      // BYTE - 1
+      const ExifByte altitude_ref = static_cast<ExifByte>(entry->data[0]);
+      pair = std::make_pair("gpsAltitudeRef", std::to_string(static_cast<int>(altitude_ref)));
+      LoggerD("Setting ExifInformation gps altitude ref to: %d (%s)",
+            static_cast<int>(altitude_ref),
+            (altitude_ref > 0) ? "below sea level" : "above sea level");
+
+      break;
+    }
+    case EXIF_TAG_GPS_PROCESSING_METHOD: {
+      // UNDEFINED - Any
+      std::string type, value;
+      if (DecomposeExifUndefined(entry, type, value)) {
+        LoggerD("Extracted GPSProcessingMethod: [%s], len:%d, type:%s",
+            value.c_str(), value.length(), type.c_str());
+        pair = std::make_pair("gpsProcessingMethod", value);
+        result_obj->insert(pair);
+      } else {
+        LoggerW("GPSProcessingMethod tag contains invalid values!");
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_DATE_STAMP: {
+      // ASCII - 11
+      pair = std::make_pair("gpsExifDate", std::string(buf));
+      result_obj->insert(pair);
+      LoggerD("Setting ExifInformation gps date stamp to %s", pair.second.c_str());
+      break;
+    }
+    case EXIF_TAG_GPS_TIME_STAMP: {
+      // Rational - 3
+      LoggerD("Setting ExifInformation gps time stamp to: [%s]", buf);
+
+      Rationals time;
+      if (GetRationalsFromEntry(entry, exif_data, 3, time)) {
+        pair = std::make_pair("gpsExifTimeHours", std::to_string(time[0].toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsExifTimeMinutes", std::to_string(time[1].toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsExifTimeSeconds", std::to_string(time[2].toDouble()));
+        result_obj->insert(pair);
+      }
+      break;
+    }
+    case EXIF_TAG_USER_COMMENT: {
+      // UNDEFINED - Any
+      std::string type, value;
+      if (DecomposeExifUndefined(entry, type, value)) {
+        LoggerD("Extracted UserComment: [%s], len:%d, type:%s",
+            value.c_str(), value.length(), type.c_str());
+
+        pair = std::make_pair("userComment", value);
+        result_obj->insert(pair);
+      } else {
+        LoggerW("UserComment tag contains invalid values!");
+      }
+      break;
+    }
+  }
+}
+
+void GetExifInfo::ContentForeachFunctionProxy(ExifEntry *entry, void *user_data) {
+  ExifDataHolder* holder = static_cast<ExifDataHolder*>(user_data);
+  if (!holder) {
+    LoggerE("holder is NULL");
+  }
+
+  if (!holder->exif_data) {
+    LoggerE("exif_data is NULL!");
+    return;
+  }
+
+  JsonObject* result_obj_ptr = holder->result_obj_ptr;
+
+  try {
+    ProcessEntry(entry, holder->exif_data, result_obj_ptr);
+  }
+  catch(...) {
+    LoggerE("Unsupported error while processing Exif entry.");
+  }
+}
+
+void GetExifInfo::DataForeachFunction(ExifContent *content, void *user_data) {
+  exif_content_foreach_entry(content, ContentForeachFunctionProxy, user_data);
+}
+
+JsonValue GetExifInfo::LoadFromURI(const std::string& uri) {
+  const std::string file_path = ExifUtil::convertUriToPath(uri);
+  ExifData* ed = exif_data_new_from_file(file_path.c_str());
+  if (!ed) {
+    LoggerE("Error reading exif from file %s", file_path.c_str());
+    throw common::NotFoundException("Error reading exif from file");
+  }
+
+  LoggerD("loadFromURI_into_json exif_data_foreach_content START");
+
+  JsonValue result = JsonValue(JsonObject());
+  JsonObject& result_obj = result.get<JsonObject>();
+
+  ExifDataHolder holder;
+  holder.exif_data = ed;
+  holder.result_obj_ptr = &result_obj;
+  exif_data_foreach_content(ed, DataForeachFunction, static_cast<void*>(&holder));
+
+  LoggerD("loadFromURI_into_json exif_data_foreach_content END");
+
+  exif_data_unref(ed);
+  ed = NULL;
+
+  // uri is not taken from jgp Exif, so we add it here
+  holder.result_obj_ptr->insert(std::make_pair("uri", uri));
+
+  return result;
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/src/exif/get_exif_info.h b/src/exif/get_exif_info.h
new file mode 100644 (file)
index 0000000..47a2334
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2015 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WEBAPI_PLUGINS_EXIF_GET_EXIF_INFO_H_
+#define WEBAPI_PLUGINS_EXIF_GET_EXIF_INFO_H_
+
+#include <libexif/exif-loader.h>
+#include <string>
+
+#include "exif_gps_location.h"
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+namespace extension {
+namespace exif {
+
+extern const size_t EXIF_UNDEFINED_TYPE_LENGTH;
+
+class GetExifInfo {
+ public:
+  static void ProcessEntry(ExifEntry* entry, ExifData* exif_data,
+                           JsonObject* result_obj);
+  static JsonValue LoadFromURI(const std::string& uri);
+
+ private:
+  GetExifInfo() { }  // private ctor - class can not be created
+
+  static void ContentForeachFunctionProxy(ExifEntry* entry, void* user_data);
+  static void DataForeachFunction(ExifContent* content, void* user_data);
+};
+
+typedef std::shared_ptr<GetExifInfo> GetExifInfoPtr;
+
+}  //  namespace exif
+}  //  namespace extension
+
+#endif  // WEBAPI_PLUGINS_EXIF_GET_EXIF_INFO_H__