00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00032
00033 #ifdef HAVE_CONFIG_H
00034 #include "autoconfig.h"
00035 #endif
00036
00037 #ifdef HAVE_LIBEXIF
00038
00039 #include "libexif_handler.h"
00040 #include "tools.h"
00041 #include "config_manager.h"
00042 #include "mem_io_handler.h"
00043
00044 using namespace zmm;
00045 using namespace mxml;
00046
00047 LibExifHandler::LibExifHandler() : MetadataHandler()
00048 {
00049 }
00050
00051 static int getTagFromString(String tag)
00052 {
00053 if (tag == "EXIF_TAG_INTEROPERABILITY_INDEX")
00054 return EXIF_TAG_INTEROPERABILITY_INDEX;
00055 if (tag == "EXIF_TAG_INTEROPERABILITY_VERSION")
00056 return EXIF_TAG_INTEROPERABILITY_VERSION;
00057 if (tag == "EXIF_TAG_IMAGE_WIDTH")
00058 return EXIF_TAG_IMAGE_WIDTH;
00059 if (tag == "EXIF_TAG_IMAGE_LENGTH")
00060 return EXIF_TAG_IMAGE_LENGTH;
00061 if (tag == "EXIF_TAG_BITS_PER_SAMPLE")
00062 return EXIF_TAG_BITS_PER_SAMPLE;
00063 if (tag == "EXIF_TAG_COMPRESSION")
00064 return EXIF_TAG_COMPRESSION;
00065 if (tag == "EXIF_TAG_PHOTOMETRIC_INTERPRETATION")
00066 return EXIF_TAG_PHOTOMETRIC_INTERPRETATION;
00067 if (tag == "EXIF_TAG_FILL_ORDER")
00068 return EXIF_TAG_FILL_ORDER;
00069 if (tag == "EXIF_TAG_DOCUMENT_NAME")
00070 return EXIF_TAG_DOCUMENT_NAME;
00071 if (tag == "EXIF_TAG_IMAGE_DESCRIPTION")
00072 return EXIF_TAG_IMAGE_DESCRIPTION;
00073 if (tag == "EXIF_TAG_MAKE")
00074 return EXIF_TAG_MAKE;
00075 if (tag == "EXIF_TAG_MODEL")
00076 return EXIF_TAG_MODEL;
00077 if (tag == "EXIF_TAG_STRIP_OFFSETS")
00078 return EXIF_TAG_STRIP_OFFSETS;
00079 if (tag == "EXIF_TAG_ORIENTATION")
00080 return EXIF_TAG_ORIENTATION;
00081 if (tag == "EXIF_TAG_SAMPLES_PER_PIXEL")
00082 return EXIF_TAG_SAMPLES_PER_PIXEL;
00083 if (tag == "EXIF_TAG_ROWS_PER_STRIP")
00084 return EXIF_TAG_ROWS_PER_STRIP;
00085 if (tag == "EXIF_TAG_STRIP_BYTE_COUNTS")
00086 return EXIF_TAG_STRIP_BYTE_COUNTS;
00087 if (tag == "EXIF_TAG_X_RESOLUTION")
00088 return EXIF_TAG_X_RESOLUTION;
00089 if (tag == "EXIF_TAG_Y_RESOLUTION")
00090 return EXIF_TAG_Y_RESOLUTION;
00091 if (tag == "EXIF_TAG_PLANAR_CONFIGURATION")
00092 return EXIF_TAG_PLANAR_CONFIGURATION;
00093 if (tag == "EXIF_TAG_RESOLUTION_UNIT")
00094 return EXIF_TAG_RESOLUTION_UNIT;
00095 if (tag == "EXIF_TAG_TRANSFER_FUNCTION")
00096 return EXIF_TAG_TRANSFER_FUNCTION;
00097 if (tag == "EXIF_TAG_SOFTWARE")
00098 return EXIF_TAG_SOFTWARE;
00099 if (tag == "EXIF_TAG_DATE_TIME")
00100 return EXIF_TAG_DATE_TIME;
00101 if (tag == "EXIF_TAG_ARTIST")
00102 return EXIF_TAG_ARTIST;
00103 if (tag == "EXIF_TAG_WHITE_POINT")
00104 return EXIF_TAG_WHITE_POINT;
00105 if (tag == "EXIF_TAG_PRIMARY_CHROMATICITIES")
00106 return EXIF_TAG_PRIMARY_CHROMATICITIES;
00107 if (tag == "EXIF_TAG_TRANSFER_RANGE")
00108 return EXIF_TAG_TRANSFER_RANGE;
00109 if (tag == "EXIF_TAG_JPEG_PROC")
00110 return EXIF_TAG_JPEG_PROC;
00111 if (tag == "EXIF_TAG_JPEG_INTERCHANGE_FORMAT")
00112 return EXIF_TAG_JPEG_INTERCHANGE_FORMAT;
00113 if (tag == "EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH")
00114 return EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH;
00115 if (tag == "EXIF_TAG_YCBCR_COEFFICIENTS")
00116 return EXIF_TAG_YCBCR_COEFFICIENTS;
00117 if (tag == "EXIF_TAG_YCBCR_SUB_SAMPLING")
00118 return EXIF_TAG_YCBCR_SUB_SAMPLING;
00119 if (tag == "EXIF_TAG_YCBCR_POSITIONING")
00120 return EXIF_TAG_YCBCR_POSITIONING;
00121 if (tag == "EXIF_TAG_REFERENCE_BLACK_WHITE")
00122 return EXIF_TAG_REFERENCE_BLACK_WHITE;
00123 if (tag == "EXIF_TAG_RELATED_IMAGE_FILE_FORMAT")
00124 return EXIF_TAG_RELATED_IMAGE_FILE_FORMAT;
00125 if (tag == "EXIF_TAG_RELATED_IMAGE_WIDTH")
00126 return EXIF_TAG_RELATED_IMAGE_WIDTH;
00127 if (tag == "EXIF_TAG_RELATED_IMAGE_LENGTH")
00128 return EXIF_TAG_RELATED_IMAGE_LENGTH;
00129 if (tag == "EXIF_TAG_CFA_REPEAT_PATTERN_DIM")
00130 return EXIF_TAG_CFA_REPEAT_PATTERN_DIM;
00131 if (tag == "EXIF_TAG_CFA_PATTERN")
00132 return EXIF_TAG_CFA_PATTERN;
00133 if (tag == "EXIF_TAG_BATTERY_LEVEL")
00134 return EXIF_TAG_BATTERY_LEVEL;
00135 if (tag == "EXIF_TAG_COPYRIGHT")
00136 return EXIF_TAG_COPYRIGHT;
00137 if (tag == "EXIF_TAG_EXPOSURE_TIME")
00138 return EXIF_TAG_EXPOSURE_TIME;
00139 if (tag == "EXIF_TAG_FNUMBER")
00140 return EXIF_TAG_FNUMBER;
00141 if (tag == "EXIF_TAG_IPTC_NAA")
00142 return EXIF_TAG_IPTC_NAA;
00143 if (tag == "EXIF_TAG_EXIF_IFD_POINTER")
00144 return EXIF_TAG_EXIF_IFD_POINTER;
00145 if (tag == "EXIF_TAG_INTER_COLOR_PROFILE")
00146 return EXIF_TAG_INTER_COLOR_PROFILE;
00147 if (tag == "EXIF_TAG_EXPOSURE_PROGRAM")
00148 return EXIF_TAG_EXPOSURE_PROGRAM;
00149 if (tag == "EXIF_TAG_SPECTRAL_SENSITIVITY")
00150 return EXIF_TAG_SPECTRAL_SENSITIVITY;
00151 if (tag == "EXIF_TAG_GPS_INFO_IFD_POINTER")
00152 return EXIF_TAG_GPS_INFO_IFD_POINTER;
00153 if (tag == "EXIF_TAG_ISO_SPEED_RATINGS")
00154 return EXIF_TAG_ISO_SPEED_RATINGS;
00155 if (tag == "EXIF_TAG_OECF")
00156 return EXIF_TAG_OECF;
00157 if (tag == "EXIF_TAG_EXIF_VERSION")
00158 return EXIF_TAG_EXIF_VERSION;
00159 if (tag == "EXIF_TAG_DATE_TIME_ORIGINAL")
00160 return EXIF_TAG_DATE_TIME_ORIGINAL;
00161 if (tag == "EXIF_TAG_DATE_TIME_DIGITIZED")
00162 return EXIF_TAG_DATE_TIME_DIGITIZED;
00163 if (tag == "EXIF_TAG_COMPONENTS_CONFIGURATION")
00164 return EXIF_TAG_COMPONENTS_CONFIGURATION;
00165 if (tag == "EXIF_TAG_COMPRESSED_BITS_PER_PIXEL")
00166 return EXIF_TAG_COMPRESSED_BITS_PER_PIXEL;
00167 if (tag == "EXIF_TAG_SHUTTER_SPEED_VALUE")
00168 return EXIF_TAG_SHUTTER_SPEED_VALUE;
00169 if (tag == "EXIF_TAG_APERTURE_VALUE")
00170 return EXIF_TAG_APERTURE_VALUE;
00171 if (tag == "EXIF_TAG_BRIGHTNESS_VALUE")
00172 return EXIF_TAG_BRIGHTNESS_VALUE;
00173 if (tag == "EXIF_TAG_EXPOSURE_BIAS_VALUE")
00174 return EXIF_TAG_EXPOSURE_BIAS_VALUE;
00175 if (tag == "EXIF_TAG_MAX_APERTURE_VALUE")
00176 return EXIF_TAG_MAX_APERTURE_VALUE;
00177 if (tag == "EXIF_TAG_SUBJECT_DISTANCE")
00178 return EXIF_TAG_SUBJECT_DISTANCE;
00179 if (tag == "EXIF_TAG_METERING_MODE")
00180 return EXIF_TAG_METERING_MODE;
00181 if (tag == "EXIF_TAG_LIGHT_SOURCE")
00182 return EXIF_TAG_LIGHT_SOURCE;
00183 if (tag == "EXIF_TAG_FLASH")
00184 return EXIF_TAG_FLASH;
00185 if (tag == "EXIF_TAG_FOCAL_LENGTH")
00186 return EXIF_TAG_FOCAL_LENGTH;
00187 if (tag == "EXIF_TAG_SUBJECT_AREA")
00188 return EXIF_TAG_SUBJECT_AREA;
00189 if (tag == "EXIF_TAG_MAKER_NOTE")
00190 return EXIF_TAG_MAKER_NOTE;
00191 if (tag == "EXIF_TAG_USER_COMMENT")
00192 return EXIF_TAG_USER_COMMENT;
00193
00194
00195 if (tag == "EXIF_TAG_SUB_SEC_TIME_ORIGINAL")
00196 return EXIF_TAG_SUB_SEC_TIME_ORIGINAL;
00197 if (tag == "EXIF_TAG_SUB_SEC_TIME_DIGITIZED")
00198 return EXIF_TAG_SUB_SEC_TIME_DIGITIZED;
00199 if (tag == "EXIF_TAG_FLASH_PIX_VERSION")
00200 return EXIF_TAG_FLASH_PIX_VERSION;
00201 if (tag == "EXIF_TAG_COLOR_SPACE")
00202 return EXIF_TAG_COLOR_SPACE;
00203 if (tag == "EXIF_TAG_PIXEL_X_DIMENSION")
00204 return EXIF_TAG_PIXEL_X_DIMENSION;
00205 if (tag == "EXIF_TAG_PIXEL_Y_DIMENSION")
00206 return EXIF_TAG_PIXEL_Y_DIMENSION;
00207 if (tag == "EXIF_TAG_RELATED_SOUND_FILE")
00208 return EXIF_TAG_RELATED_SOUND_FILE;
00209 if (tag == "EXIF_TAG_INTEROPERABILITY_IFD_POINTER")
00210 return EXIF_TAG_INTEROPERABILITY_IFD_POINTER;
00211 if (tag == "EXIF_TAG_FLASH_ENERGY")
00212 return EXIF_TAG_FLASH_ENERGY;
00213 if (tag == "EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE")
00214 return EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE;
00215 if (tag == "EXIF_TAG_FOCAL_PLANE_X_RESOLUTION")
00216 return EXIF_TAG_FOCAL_PLANE_X_RESOLUTION;
00217 if (tag == "EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION")
00218 return EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION;
00219 if (tag == "EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT")
00220 return EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT;
00221 if (tag == "EXIF_TAG_SUBJECT_LOCATION")
00222 return EXIF_TAG_SUBJECT_LOCATION;
00223 if (tag == "EXIF_TAG_EXPOSURE_INDEX")
00224 return EXIF_TAG_EXPOSURE_INDEX;
00225 if (tag == "EXIF_TAG_SENSING_METHOD")
00226 return EXIF_TAG_SENSING_METHOD;
00227 if (tag == "EXIF_TAG_FILE_SOURCE")
00228 return EXIF_TAG_FILE_SOURCE;
00229 if (tag == "EXIF_TAG_SCENE_TYPE")
00230 return EXIF_TAG_SCENE_TYPE;
00231 if (tag == "EXIF_TAG_NEW_CFA_PATTERN")
00232 return EXIF_TAG_NEW_CFA_PATTERN;
00233 if (tag == "EXIF_TAG_CUSTOM_RENDERED")
00234 return EXIF_TAG_CUSTOM_RENDERED;
00235 if (tag == "EXIF_TAG_EXPOSURE_MODE")
00236 return EXIF_TAG_CUSTOM_RENDERED;
00237 if (tag == "EXIF_TAG_WHITE_BALANCE")
00238 return EXIF_TAG_CUSTOM_RENDERED;
00239 if (tag == "EXIF_TAG_DIGITAL_ZOOM_RATIO")
00240 return EXIF_TAG_CUSTOM_RENDERED;
00241 if (tag == "EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM")
00242 return EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM;
00243 if (tag == "EXIF_TAG_SCENE_CAPTURE_TYPE")
00244 return EXIF_TAG_SCENE_CAPTURE_TYPE;
00245 if (tag == "EXIF_TAG_GAIN_CONTROL")
00246 return EXIF_TAG_GAIN_CONTROL;
00247 if (tag == "EXIF_TAG_CONTRAST")
00248 return EXIF_TAG_CONTRAST;
00249 if (tag == "EXIF_TAG_SATURATION")
00250 return EXIF_TAG_SATURATION;
00251 if (tag == "EXIF_TAG_SHARPNESS")
00252 return EXIF_TAG_SHARPNESS;
00253 if (tag == "EXIF_TAG_DEVICE_SETTING_DESCRIPTION")
00254 return EXIF_TAG_DEVICE_SETTING_DESCRIPTION;
00255 if (tag == "EXIF_TAG_SUBJECT_DISTANCE_RANGE")
00256 return EXIF_TAG_DEVICE_SETTING_DESCRIPTION;
00257 if (tag == "EXIF_TAG_IMAGE_UNIQUE_ID")
00258 return EXIF_TAG_IMAGE_UNIQUE_ID;
00259
00260 log_warning("Ignoring unknown libexif tag: %s\n", tag.c_str());
00261 return -1;
00262 }
00263
00264
00265
00266 #ifdef EXIF_EGV_1
00267 #define exif_egv(arg) exif_entry_get_value(arg)
00268 #endif
00269
00270 #ifdef EXIF_EGV_3
00271 #define BUFLEN 4096
00272 char exif_entry_buffer[BUFLEN];
00273 #define exif_egv(arg) exif_entry_get_value(arg, exif_entry_buffer, BUFLEN)
00274 #endif
00275
00276 void LibExifHandler::process_ifd (ExifContent *content, Ref<CdsItem> item, Ref<StringConverter> sc, Ref<Array<StringBase> > auxtags)
00277 {
00278 ExifEntry *e;
00279 unsigned int i;
00280 String value;
00281 String tmp;
00282
00283
00284 for (i = 0; i < content->count; i++) {
00285 e = content->entries[i];
00286
00287
00288
00289 switch (e->tag)
00290 {
00291 case EXIF_TAG_DATE_TIME_ORIGINAL:
00292 value = (char *)exif_egv(e);
00293 value = trim_string(value);
00294 if (string_ok(value))
00295 {
00296 value = sc->convert(value);
00297
00299
00300 if (value.length() >= 11)
00301 {
00302 value = value.substring(0, 4) + "-" +
00303 value.substring(5, 2) + "-" +
00304 value.substring(8, 2);
00305 item->setMetadata(MetadataHandler::getMetaFieldName(M_DATE), value);
00306 }
00307 }
00308 break;
00309
00310 case EXIF_TAG_USER_COMMENT:
00311 value = (char *)exif_egv(e);
00312 value = trim_string(value);
00313 if (string_ok(value))
00314 {
00315 value = sc->convert(value);
00316 item->setMetadata(MetadataHandler::getMetaFieldName(M_DESCRIPTION), value);
00317 }
00318 break;
00319
00320 case EXIF_TAG_PIXEL_X_DIMENSION:
00321 value = (char *)exif_egv(e);
00322 value = trim_string(value);
00323 if (string_ok(value))
00324 {
00325 value = sc->convert(value);
00326 imageX = value;
00327 }
00328 break;
00329
00330 case EXIF_TAG_PIXEL_Y_DIMENSION:
00331 value = (char *)exif_egv(e);
00332 value = trim_string(value);
00333 if (string_ok(value))
00334 {
00335 value = sc->convert(value);
00336 imageY = value;
00337 }
00338 break;
00339 default:
00340 break;
00341 }
00342
00343
00344 if (auxtags != nil)
00345 {
00346 for (int j = 0; j < auxtags->size(); j++)
00347 {
00348
00349 tmp = auxtags->get(j);
00350 if (string_ok(tmp))
00351 {
00352 if (e->tag == getTagFromString(tmp))
00353 {
00354 value = (char *)exif_egv(e);
00355 value = trim_string(value);
00356 if (string_ok(value))
00357 {
00358 value = sc->convert(value);
00359 item->setAuxData(tmp, value);
00360
00361 }
00362 }
00363 }
00364 }
00365 }
00366 }
00367 }
00368
00369
00370 void LibExifHandler::fillMetadata(Ref<CdsItem> item)
00371 {
00372 ExifData *ed;
00373 Ref<Array<StringBase> > aux;
00374
00375 Ref<StringConverter> sc = StringConverter::m2i();
00376
00377 ed = exif_data_new_from_file(item->getLocation().c_str());
00378
00379 if (!ed)
00380 {
00381 log_debug("Exif data not found, attempting to set resolution internally...\n");
00382 set_jpeg_resolution_resource(item, 0);
00383 return;
00384 }
00385
00386 Ref<ConfigManager> cm = ConfigManager::getInstance();
00387 aux = cm->getStringArrayOption(CFG_IMPORT_LIBOPTS_EXIF_AUXDATA_TAGS_LIST);
00388 for (int i = 0; i < EXIF_IFD_COUNT; i++)
00389 {
00390 if (ed->ifd[i])
00391 process_ifd (ed->ifd[i], item, sc, aux);
00392 }
00393
00394
00395 if (string_ok(imageX) && string_ok(imageY))
00396 {
00397 item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(R_RESOLUTION),
00398 imageX + "x" + imageY);
00399 }
00400 else
00401 {
00402 set_jpeg_resolution_resource(item, 0);
00403 }
00404
00405 if (ed->size)
00406 {
00407 try
00408 {
00409 Ref<IOHandler> io_h(new MemIOHandler(ed->data, ed->size));
00410 io_h->open(UPNP_READ);
00411 String th_resolution = get_jpeg_resolution(io_h);
00412 log_debug("RESOLUTION: %s\n", th_resolution.c_str());
00413
00414 Ref<CdsResource> resource(new CdsResource(CH_LIBEXIF));
00415 resource->addAttribute(MetadataHandler::getResAttrName(R_PROTOCOLINFO), renderProtocolInfo(item->getMimeType()));
00416 resource->addAttribute(MetadataHandler::getResAttrName(R_RESOLUTION), th_resolution);
00417 resource->addParameter(_(RESOURCE_CONTENT_TYPE), _(EXIF_THUMBNAIL));
00418 item->addResource(resource);
00419 }
00420 catch (Exception e)
00421 {
00422 e.printStackTrace();
00423 }
00424
00425 }
00426 exif_data_unref(ed);
00427 }
00428
00429 Ref<IOHandler> LibExifHandler::serveContent(Ref<CdsItem> item, int resNum, off_t *data_size)
00430 {
00431 ExifData *ed;
00432 Ref<CdsResource> res = item->getResource(resNum);
00433
00434 String ctype = res->getParameters()->get(_(RESOURCE_CONTENT_TYPE));
00435
00436 if (ctype != EXIF_THUMBNAIL)
00437 throw _Exception(_("LibExifHandler: got unknown content type: ") + ctype);
00438 ed = exif_data_new_from_file(item->getLocation().c_str());
00439 if (!ed)
00440 throw _Exception(_("LibExifHandler: resource has no exif information"));
00441
00442 if (!(ed->size))
00443 throw _Exception(_("LibExifHandler: resource has no exif thumbnail"));
00444
00445 Ref<IOHandler> h(new MemIOHandler(ed->data, ed->size));
00446 *data_size = ed->size;
00447
00448 exif_data_unref(ed);
00449
00450 return h;
00451 }
00452
00453 #endif // HAVE_LIBEXIF