[Verification] Code compiles without errors. TCT pass rate 29/63.
Change-Id: If33a3907a28dbcd9a68a81d1c9f2b21279d4119f
Signed-off-by: Rafal Lelusz <r.lelusz@samsung.com>
'rational.h',
'exif_gps_location.cc',
'exif_gps_location.h',
+ 'get_exif_info.cc',
+ 'get_exif_info.h',
],
'conditions': [
[ 'tizen == 1', {
-// 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.
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, [
{
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);
}
};
native_.call('Exif_getExifInfo', callArgs, callback);
};
-
ExifManager.prototype.saveExifInfo = function() {
var args = validator_.validateArgs(arguments, [
{
native_.call('Exif_getThumbnail', {'uri': args.uri}, callback);
};
-// this function passes ExifInformation_exposureProgram_attribute test:
tizen.ExifInformation = function() {
validator_.isConstructorCall(this, tizen.ExifInformation);
}
]);
- 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) {
return uri_;
},
set: function(v) {
- uri_ = v ? converter_.toString(v, true) : uri_;
+ uri_ = v ? converter_.toString(v) : uri_;
},
enumerable: true
},
return width_;
},
set: function(v) {
- width_ = v ? converter_.toLong(v, true) : width_;
+ width_ = (!type_.isUndefined(v)) ? converter_.toLong(v, true) : width_;
},
enumerable: true
},
return height_;
},
set: function(v) {
- height_ = v ? converter_.toLong(v, true) : height_;
+ height_ = (!type_.isUndefined(v)) ? converter_.toLong(v, true) : height_;
},
enumerable: true
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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: {
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_;
}
}
});
}
}
-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) {
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();
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);
#include "exif_util.h"
#include "jpeg_file.h"
#include "exif_information.h"
+#include "get_exif_info.h"
namespace extension {
namespace exif {
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>());
}
get, get_response,
std::shared_ptr<JsonValue>(new JsonValue(JsonObject())));
- LoggerD("ExifInstance::getExifInfo() END (c++)");
+ LoggerD("exit");
}
void ExifInstance::saveExifInfo(const picojson::value& args,
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_
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
return result;
}
-
std::string ExifUtil::timeTToExifGpsDateStamp(time_t time) {
int year, month, day, hour, min, sec;
extractFromTimeT(time, year, month, day, hour, min, sec);
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);
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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__