2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "PictureInfoTag.h"
22 #include "XBDateTime.h"
24 #include "utils/Variant.h"
25 #include "utils/CharsetConverter.h"
26 #include "utils/StringUtils.h"
30 void CPictureInfoTag::Reset()
32 memset(&m_exifInfo, 0, sizeof(m_exifInfo));
33 memset(&m_iptcInfo, 0, sizeof(m_iptcInfo));
35 m_isInfoSetExternally = false;
36 m_dateTimeTaken.Reset();
39 const CPictureInfoTag& CPictureInfoTag::operator=(const CPictureInfoTag& right)
41 if (this == &right) return * this;
42 memcpy(&m_exifInfo, &right.m_exifInfo, sizeof(m_exifInfo));
43 memcpy(&m_iptcInfo, &right.m_iptcInfo, sizeof(m_iptcInfo));
44 m_isLoaded = right.m_isLoaded;
45 m_isInfoSetExternally = right.m_isInfoSetExternally;
46 m_dateTimeTaken = right.m_dateTimeTaken;
50 bool CPictureInfoTag::Load(const CStdString &path)
55 if (path.IsEmpty() || !exifDll.Load())
58 if (exifDll.process_jpeg(path.c_str(), &m_exifInfo, &m_iptcInfo))
66 void CPictureInfoTag::Archive(CArchive& ar)
71 ar << m_isInfoSetExternally;
72 ar << m_exifInfo.ApertureFNumber;
73 ar << CStdString(m_exifInfo.CameraMake);
74 ar << CStdString(m_exifInfo.CameraModel);
75 ar << m_exifInfo.CCDWidth;
76 ar << GetInfo(SLIDE_EXIF_COMMENT); // Store and restore the comment charset converted
77 ar << CStdString(m_exifInfo.Description);
78 ar << CStdString(m_exifInfo.DateTime);
79 for (int i = 0; i < 10; i++)
80 ar << m_exifInfo.DateTimeOffsets[i];
81 ar << m_exifInfo.DigitalZoomRatio;
82 ar << m_exifInfo.Distance;
83 ar << m_exifInfo.ExposureBias;
84 ar << m_exifInfo.ExposureMode;
85 ar << m_exifInfo.ExposureProgram;
86 ar << m_exifInfo.ExposureTime;
87 ar << m_exifInfo.FlashUsed;
88 ar << m_exifInfo.FocalLength;
89 ar << m_exifInfo.FocalLength35mmEquiv;
90 ar << m_exifInfo.GpsInfoPresent;
91 ar << CStdString(m_exifInfo.GpsAlt);
92 ar << CStdString(m_exifInfo.GpsLat);
93 ar << CStdString(m_exifInfo.GpsLong);
94 ar << m_exifInfo.Height;
95 ar << m_exifInfo.IsColor;
96 ar << m_exifInfo.ISOequivalent;
97 ar << m_exifInfo.LargestExifOffset;
98 ar << m_exifInfo.LightSource;
99 ar << m_exifInfo.MeteringMode;
100 ar << m_exifInfo.numDateTimeTags;
101 ar << m_exifInfo.Orientation;
102 ar << m_exifInfo.Process;
103 ar << m_exifInfo.ThumbnailAtEnd;
104 ar << m_exifInfo.ThumbnailOffset;
105 ar << m_exifInfo.ThumbnailSize;
106 ar << m_exifInfo.ThumbnailSizeOffset;
107 ar << m_exifInfo.Whitebalance;
108 ar << m_exifInfo.Width;
109 ar << m_dateTimeTaken;
111 ar << CStdString(m_iptcInfo.Author);
112 ar << CStdString(m_iptcInfo.Byline);
113 ar << CStdString(m_iptcInfo.BylineTitle);
114 ar << CStdString(m_iptcInfo.Caption);
115 ar << CStdString(m_iptcInfo.Category);
116 ar << CStdString(m_iptcInfo.City);
117 ar << CStdString(m_iptcInfo.Urgency);
118 ar << CStdString(m_iptcInfo.CopyrightNotice);
119 ar << CStdString(m_iptcInfo.Country);
120 ar << CStdString(m_iptcInfo.CountryCode);
121 ar << CStdString(m_iptcInfo.Credit);
122 ar << CStdString(m_iptcInfo.Date);
123 ar << CStdString(m_iptcInfo.Headline);
124 ar << CStdString(m_iptcInfo.Keywords);
125 ar << CStdString(m_iptcInfo.ObjectName);
126 ar << CStdString(m_iptcInfo.ReferenceService);
127 ar << CStdString(m_iptcInfo.Source);
128 ar << CStdString(m_iptcInfo.SpecialInstructions);
129 ar << CStdString(m_iptcInfo.State);
130 ar << CStdString(m_iptcInfo.SupplementalCategories);
131 ar << CStdString(m_iptcInfo.TransmissionReference);
132 ar << CStdString(m_iptcInfo.TimeCreated);
133 ar << CStdString(m_iptcInfo.SubLocation);
134 ar << CStdString(m_iptcInfo.ImageType);
139 ar >> m_isInfoSetExternally;
140 ar >> m_exifInfo.ApertureFNumber;
141 GetStringFromArchive(ar, m_exifInfo.CameraMake, sizeof(m_exifInfo.CameraMake));
142 GetStringFromArchive(ar, m_exifInfo.CameraModel, sizeof(m_exifInfo.CameraModel));
143 ar >> m_exifInfo.CCDWidth;
144 GetStringFromArchive(ar, m_exifInfo.Comments, sizeof(m_exifInfo.Comments));
145 m_exifInfo.CommentsCharset = EXIF_COMMENT_CHARSET_CONVERTED; // Store and restore the comment charset converted
146 GetStringFromArchive(ar, m_exifInfo.Description, sizeof(m_exifInfo.Description));
147 GetStringFromArchive(ar, m_exifInfo.DateTime, sizeof(m_exifInfo.DateTime));
148 for (int i = 0; i < 10; i++)
149 ar >> m_exifInfo.DateTimeOffsets[i];
150 ar >> m_exifInfo.DigitalZoomRatio;
151 ar >> m_exifInfo.Distance;
152 ar >> m_exifInfo.ExposureBias;
153 ar >> m_exifInfo.ExposureMode;
154 ar >> m_exifInfo.ExposureProgram;
155 ar >> m_exifInfo.ExposureTime;
156 ar >> m_exifInfo.FlashUsed;
157 ar >> m_exifInfo.FocalLength;
158 ar >> m_exifInfo.FocalLength35mmEquiv;
159 ar >> m_exifInfo.GpsInfoPresent;
160 GetStringFromArchive(ar, m_exifInfo.GpsAlt, sizeof(m_exifInfo.GpsAlt));
161 GetStringFromArchive(ar, m_exifInfo.GpsLat, sizeof(m_exifInfo.GpsLat));
162 GetStringFromArchive(ar, m_exifInfo.GpsLong, sizeof(m_exifInfo.GpsLong));
163 ar >> m_exifInfo.Height;
164 ar >> m_exifInfo.IsColor;
165 ar >> m_exifInfo.ISOequivalent;
166 ar >> m_exifInfo.LargestExifOffset;
167 ar >> m_exifInfo.LightSource;
168 ar >> m_exifInfo.MeteringMode;
169 ar >> m_exifInfo.numDateTimeTags;
170 ar >> m_exifInfo.Orientation;
171 ar >> m_exifInfo.Process;
172 ar >> m_exifInfo.ThumbnailAtEnd;
173 ar >> m_exifInfo.ThumbnailOffset;
174 ar >> m_exifInfo.ThumbnailSize;
175 ar >> m_exifInfo.ThumbnailSizeOffset;
176 ar >> m_exifInfo.Whitebalance;
177 ar >> m_exifInfo.Width;
178 ar >> m_dateTimeTaken;
180 GetStringFromArchive(ar, m_iptcInfo.Author, sizeof(m_iptcInfo.Author));
181 GetStringFromArchive(ar, m_iptcInfo.Byline, sizeof(m_iptcInfo.Byline));
182 GetStringFromArchive(ar, m_iptcInfo.BylineTitle, sizeof(m_iptcInfo.BylineTitle));
183 GetStringFromArchive(ar, m_iptcInfo.Caption, sizeof(m_iptcInfo.Caption));
184 GetStringFromArchive(ar, m_iptcInfo.Category, sizeof(m_iptcInfo.Category));
185 GetStringFromArchive(ar, m_iptcInfo.City, sizeof(m_iptcInfo.City));
186 GetStringFromArchive(ar, m_iptcInfo.Urgency, sizeof(m_iptcInfo.Urgency));
187 GetStringFromArchive(ar, m_iptcInfo.CopyrightNotice, sizeof(m_iptcInfo.CopyrightNotice));
188 GetStringFromArchive(ar, m_iptcInfo.Country, sizeof(m_iptcInfo.Country));
189 GetStringFromArchive(ar, m_iptcInfo.CountryCode, sizeof(m_iptcInfo.CountryCode));
190 GetStringFromArchive(ar, m_iptcInfo.Credit, sizeof(m_iptcInfo.Credit));
191 GetStringFromArchive(ar, m_iptcInfo.Date, sizeof(m_iptcInfo.Date));
192 GetStringFromArchive(ar, m_iptcInfo.Headline, sizeof(m_iptcInfo.Headline));
193 GetStringFromArchive(ar, m_iptcInfo.Keywords, sizeof(m_iptcInfo.Keywords));
194 GetStringFromArchive(ar, m_iptcInfo.ObjectName, sizeof(m_iptcInfo.ObjectName));
195 GetStringFromArchive(ar, m_iptcInfo.ReferenceService, sizeof(m_iptcInfo.ReferenceService));
196 GetStringFromArchive(ar, m_iptcInfo.Source, sizeof(m_iptcInfo.Source));
197 GetStringFromArchive(ar, m_iptcInfo.SpecialInstructions, sizeof(m_iptcInfo.SpecialInstructions));
198 GetStringFromArchive(ar, m_iptcInfo.State, sizeof(m_iptcInfo.State));
199 GetStringFromArchive(ar, m_iptcInfo.SupplementalCategories, sizeof(m_iptcInfo.SupplementalCategories));
200 GetStringFromArchive(ar, m_iptcInfo.TransmissionReference, sizeof(m_iptcInfo.TransmissionReference));
201 GetStringFromArchive(ar, m_iptcInfo.TimeCreated, sizeof(m_iptcInfo.TimeCreated));
202 GetStringFromArchive(ar, m_iptcInfo.SubLocation, sizeof(m_iptcInfo.SubLocation));
203 GetStringFromArchive(ar, m_iptcInfo.ImageType, sizeof(m_iptcInfo.ImageType));
207 void CPictureInfoTag::Serialize(CVariant& value) const
209 value["aperturefnumber"] = m_exifInfo.ApertureFNumber;
210 value["cameramake"] = CStdString(m_exifInfo.CameraMake);
211 value["cameramodel"] = CStdString(m_exifInfo.CameraModel);
212 value["ccdwidth"] = m_exifInfo.CCDWidth;
213 value["comments"] = GetInfo(SLIDE_EXIF_COMMENT); // Charset conversion
214 value["description"] = CStdString(m_exifInfo.Description);
215 value["datetime"] = CStdString(m_exifInfo.DateTime);
216 for (int i = 0; i < 10; i++)
217 value["datetimeoffsets"][i] = m_exifInfo.DateTimeOffsets[i];
218 value["digitalzoomratio"] = m_exifInfo.DigitalZoomRatio;
219 value["distance"] = m_exifInfo.Distance;
220 value["exposurebias"] = m_exifInfo.ExposureBias;
221 value["exposuremode"] = m_exifInfo.ExposureMode;
222 value["exposureprogram"] = m_exifInfo.ExposureProgram;
223 value["exposuretime"] = m_exifInfo.ExposureTime;
224 value["flashused"] = m_exifInfo.FlashUsed;
225 value["focallength"] = m_exifInfo.FocalLength;
226 value["focallength35mmequiv"] = m_exifInfo.FocalLength35mmEquiv;
227 value["gpsinfopresent"] = m_exifInfo.GpsInfoPresent;
228 value["gpsinfo"]["alt"] = CStdString(m_exifInfo.GpsAlt);
229 value["gpsinfo"]["lat"] = CStdString(m_exifInfo.GpsLat);
230 value["gpsinfo"]["long"] = CStdString(m_exifInfo.GpsLong);
231 value["height"] = m_exifInfo.Height;
232 value["iscolor"] = m_exifInfo.IsColor;
233 value["isoequivalent"] = m_exifInfo.ISOequivalent;
234 value["largestexifoffset"] = m_exifInfo.LargestExifOffset;
235 value["lightsource"] = m_exifInfo.LightSource;
236 value["meteringmode"] = m_exifInfo.MeteringMode;
237 value["numdatetimetags"] = m_exifInfo.numDateTimeTags;
238 value["orientation"] = m_exifInfo.Orientation;
239 value["process"] = m_exifInfo.Process;
240 value["thumbnailatend"] = m_exifInfo.ThumbnailAtEnd;
241 value["thumbnailoffset"] = m_exifInfo.ThumbnailOffset;
242 value["thumbnailsize"] = m_exifInfo.ThumbnailSize;
243 value["thumbnailsizeoffset"] = m_exifInfo.ThumbnailSizeOffset;
244 value["whitebalance"] = m_exifInfo.Whitebalance;
245 value["width"] = m_exifInfo.Width;
247 value["author"] = CStdString(m_iptcInfo.Author);
248 value["byline"] = CStdString(m_iptcInfo.Byline);
249 value["bylinetitle"] = CStdString(m_iptcInfo.BylineTitle);
250 value["caption"] = CStdString(m_iptcInfo.Caption);
251 value["category"] = CStdString(m_iptcInfo.Category);
252 value["city"] = CStdString(m_iptcInfo.City);
253 value["urgency"] = CStdString(m_iptcInfo.Urgency);
254 value["copyrightnotice"] = CStdString(m_iptcInfo.CopyrightNotice);
255 value["country"] = CStdString(m_iptcInfo.Country);
256 value["countrycode"] = CStdString(m_iptcInfo.CountryCode);
257 value["credit"] = CStdString(m_iptcInfo.Credit);
258 value["date"] = CStdString(m_iptcInfo.Date);
259 value["headline"] = CStdString(m_iptcInfo.Headline);
260 value["keywords"] = CStdString(m_iptcInfo.Keywords);
261 value["objectname"] = CStdString(m_iptcInfo.ObjectName);
262 value["referenceservice"] = CStdString(m_iptcInfo.ReferenceService);
263 value["source"] = CStdString(m_iptcInfo.Source);
264 value["specialinstructions"] = CStdString(m_iptcInfo.SpecialInstructions);
265 value["state"] = CStdString(m_iptcInfo.State);
266 value["supplementalcategories"] = CStdString(m_iptcInfo.SupplementalCategories);
267 value["transmissionreference"] = CStdString(m_iptcInfo.TransmissionReference);
268 value["timecreated"] = CStdString(m_iptcInfo.TimeCreated);
269 value["sublocation"] = CStdString(m_iptcInfo.SubLocation);
270 value["imagetype"] = CStdString(m_iptcInfo.ImageType);
273 void CPictureInfoTag::ToSortable(SortItem& sortable, Field field) const
275 if (field == FieldDateTaken && m_dateTimeTaken.IsValid())
276 sortable[FieldDateTaken] = m_dateTimeTaken.GetAsDBDateTime();
279 void CPictureInfoTag::GetStringFromArchive(CArchive &ar, char *string, size_t length)
283 length = min((size_t)temp.GetLength(), length - 1);
285 memcpy(string, temp.c_str(), length);
289 const CStdString CPictureInfoTag::GetInfo(int info) const
291 if (!m_isLoaded && !m_isInfoSetExternally) // If no metadata has been loaded from the picture file or set with SetInfo(), just return
297 case SLIDE_RESOLUTION:
298 value = StringUtils::Format("%d x %d", m_exifInfo.Width, m_exifInfo.Height);
301 value = m_exifInfo.IsColor ? "Colour" : "Black and White";
304 switch (m_exifInfo.Process)
307 // don't show it if its the plain old boring 'baseline' process, but do
308 // show it if its something else, like 'progressive' (used on web sometimes)
311 case M_SOF1: value = "Extended sequential"; break;
312 case M_SOF2: value = "Progressive"; break;
313 case M_SOF3: value = "Lossless"; break;
314 case M_SOF5: value = "Differential sequential"; break;
315 case M_SOF6: value = "Differential progressive"; break;
316 case M_SOF7: value = "Differential lossless"; break;
317 case M_SOF9: value = "Extended sequential, arithmetic coding"; break;
318 case M_SOF10: value = "Progressive, arithmetic coding"; break;
319 case M_SOF11: value = "Lossless, arithmetic coding"; break;
320 case M_SOF13: value = "Differential sequential, arithmetic coding"; break;
321 case M_SOF14: value = "Differential progressive, arithmetic coding"; break;
322 case M_SOF15: value = "Differential lossless, arithmetic coding"; break;
323 default: value = "Unknown"; break;
327 case SLIDE_EXIF_COMMENT:
328 // The charset used for the UserComment is stored in CommentsCharset:
329 // Ascii, Unicode (UCS2), JIS (X208-1990), Unknown (application specific)
330 if (m_exifInfo.CommentsCharset == EXIF_COMMENT_CHARSET_UNICODE)
332 g_charsetConverter.ucs2ToUTF8(std::u16string((char16_t*)m_exifInfo.Comments), value);
336 // Ascii doesn't need to be converted (EXIF_COMMENT_CHARSET_ASCII)
337 // Archived data is already converted (EXIF_COMMENT_CHARSET_CONVERTED)
338 // Unknown data can't be converted as it could be any codec (EXIF_COMMENT_CHARSET_UNKNOWN)
339 // JIS data can't be converted as CharsetConverter and iconv lacks support (EXIF_COMMENT_CHARSET_JIS)
340 value = m_exifInfo.Comments;
343 case SLIDE_EXIF_LONG_DATE_TIME:
344 if (m_dateTimeTaken.IsValid())
345 value = m_dateTimeTaken.GetAsLocalizedDateTime(true);
347 case SLIDE_EXIF_DATE_TIME:
348 if (m_dateTimeTaken.IsValid())
349 value = m_dateTimeTaken.GetAsLocalizedDateTime();
351 case SLIDE_EXIF_LONG_DATE:
352 if (m_dateTimeTaken.IsValid())
353 value = m_dateTimeTaken.GetAsLocalizedDate(true);
355 case SLIDE_EXIF_DATE:
356 if (m_dateTimeTaken.IsValid())
357 value = m_dateTimeTaken.GetAsLocalizedDate();
359 case SLIDE_EXIF_DESCRIPTION:
360 value = m_exifInfo.Description;
362 case SLIDE_EXIF_CAMERA_MAKE:
363 value = m_exifInfo.CameraMake;
365 case SLIDE_EXIF_CAMERA_MODEL:
366 value = m_exifInfo.CameraModel;
368 // case SLIDE_EXIF_SOFTWARE:
369 // value = m_exifInfo.Software;
370 case SLIDE_EXIF_APERTURE:
371 if (m_exifInfo.ApertureFNumber)
372 value = StringUtils::Format("%3.1f", m_exifInfo.ApertureFNumber);
374 case SLIDE_EXIF_ORIENTATION:
375 switch (m_exifInfo.Orientation)
377 case 1: value = "Top Left"; break;
378 case 2: value = "Top Right"; break;
379 case 3: value = "Bottom Right"; break;
380 case 4: value = "Bottom Left"; break;
381 case 5: value = "Left Top"; break;
382 case 6: value = "Right Top"; break;
383 case 7: value = "Right Bottom"; break;
384 case 8: value = "Left Bottom"; break;
387 case SLIDE_EXIF_FOCAL_LENGTH:
388 if (m_exifInfo.FocalLength)
390 value = StringUtils::Format("%4.2fmm", m_exifInfo.FocalLength);
391 if (m_exifInfo.FocalLength35mmEquiv != 0)
392 value.AppendFormat(" (35mm Equivalent = %umm)", m_exifInfo.FocalLength35mmEquiv);
395 case SLIDE_EXIF_FOCUS_DIST:
396 if (m_exifInfo.Distance < 0)
398 else if (m_exifInfo.Distance > 0)
399 value = StringUtils::Format("%4.2fm", m_exifInfo.Distance);
401 case SLIDE_EXIF_EXPOSURE:
402 switch (m_exifInfo.ExposureProgram)
404 case 1: value = "Manual"; break;
405 case 2: value = "Program (Auto)"; break;
406 case 3: value = "Aperture priority (Semi-Auto)"; break;
407 case 4: value = "Shutter priority (semi-auto)"; break;
408 case 5: value = "Creative Program (based towards depth of field)"; break;
409 case 6: value = "Action program (based towards fast shutter speed)"; break;
410 case 7: value = "Portrait Mode"; break;
411 case 8: value = "Landscape Mode"; break;
414 case SLIDE_EXIF_EXPOSURE_TIME:
415 if (m_exifInfo.ExposureTime)
417 if (m_exifInfo.ExposureTime < 0.010f)
418 value = StringUtils::Format("%6.4fs", m_exifInfo.ExposureTime);
420 value = StringUtils::Format("%5.3fs", m_exifInfo.ExposureTime);
421 if (m_exifInfo.ExposureTime <= 0.5)
422 value.AppendFormat(" (1/%d)", (int)(0.5 + 1/m_exifInfo.ExposureTime));
425 case SLIDE_EXIF_EXPOSURE_BIAS:
426 if (m_exifInfo.ExposureBias != 0)
427 value = StringUtils::Format("%4.2f EV", m_exifInfo.ExposureBias);
429 case SLIDE_EXIF_EXPOSURE_MODE:
430 switch (m_exifInfo.ExposureMode)
432 case 0: value = "Automatic"; break;
433 case 1: value = "Manual"; break;
434 case 2: value = "Auto bracketing"; break;
437 case SLIDE_EXIF_FLASH_USED:
438 if (m_exifInfo.FlashUsed >= 0)
440 if (m_exifInfo.FlashUsed & 1)
443 switch (m_exifInfo.FlashUsed)
445 case 0x5: value = "Yes (Strobe light not detected)"; break;
446 case 0x7: value = "Yes (Strobe light detected)"; break;
447 case 0x9: value = "Yes (Manual)"; break;
448 case 0xd: value = "Yes (Manual, return light not detected)"; break;
449 case 0xf: value = "Yes (Manual, return light detected)"; break;
450 case 0x19: value = "Yes (Auto)"; break;
451 case 0x1d: value = "Yes (Auto, return light not detected)"; break;
452 case 0x1f: value = "Yes (Auto, return light detected)"; break;
453 case 0x41: value = "Yes (Red eye reduction mode)"; break;
454 case 0x45: value = "Yes (Red eye reduction mode return light not detected)"; break;
455 case 0x47: value = "Yes (Red eye reduction mode return light detected)"; break;
456 case 0x49: value = "Yes (Manual, red eye reduction mode)"; break;
457 case 0x4d: value = "Yes (Manual, red eye reduction mode, return light not detected)"; break;
458 case 0x4f: value = "Yes (Manual, red eye reduction mode, return light detected)"; break;
459 case 0x59: value = "Yes (Auto, red eye reduction mode)"; break;
460 case 0x5d: value = "Yes (Auto, red eye reduction mode, return light not detected)"; break;
461 case 0x5f: value = "Yes (Auto, red eye reduction mode, return light detected)"; break;
465 value = m_exifInfo.FlashUsed == 0x18 ? "No (Auto)" : "No";
468 case SLIDE_EXIF_WHITE_BALANCE:
469 return m_exifInfo.Whitebalance ? "Manual" : "Auto";
470 case SLIDE_EXIF_LIGHT_SOURCE:
471 switch (m_exifInfo.LightSource)
473 case 1: value = "Daylight"; break;
474 case 2: value = "Fluorescent"; break;
475 case 3: value = "Incandescent"; break;
476 case 4: value = "Flash"; break;
477 case 9: value = "Fine Weather"; break;
478 case 11: value = "Shade"; break;
479 default:; //Quercus: 17-1-2004 There are many more modes for this, check Exif2.2 specs
480 // If it just says 'unknown' or we don't know it, then
481 // don't bother showing it - it doesn't add any useful information.
484 case SLIDE_EXIF_METERING_MODE:
485 switch (m_exifInfo.MeteringMode)
487 case 2: value = "Center weight"; break;
488 case 3: value = "Spot"; break;
489 case 5: value = "Matrix"; break;
492 case SLIDE_EXIF_ISO_EQUIV:
493 if (m_exifInfo.ISOequivalent)
494 value = StringUtils::Format("%2d", m_exifInfo.ISOequivalent);
496 case SLIDE_EXIF_DIGITAL_ZOOM:
497 if (m_exifInfo.DigitalZoomRatio)
498 value = StringUtils::Format("%1.3fx", m_exifInfo.DigitalZoomRatio);
500 case SLIDE_EXIF_CCD_WIDTH:
501 if (m_exifInfo.CCDWidth)
502 value = StringUtils::Format("%4.2fmm", m_exifInfo.CCDWidth);
504 case SLIDE_EXIF_GPS_LATITUDE:
505 value = m_exifInfo.GpsLat;
507 case SLIDE_EXIF_GPS_LONGITUDE:
508 value = m_exifInfo.GpsLong;
510 case SLIDE_EXIF_GPS_ALTITUDE:
511 value = m_exifInfo.GpsAlt;
513 case SLIDE_IPTC_SUP_CATEGORIES: value = m_iptcInfo.SupplementalCategories; break;
514 case SLIDE_IPTC_KEYWORDS: value = m_iptcInfo.Keywords; break;
515 case SLIDE_IPTC_CAPTION: value = m_iptcInfo.Caption; break;
516 case SLIDE_IPTC_AUTHOR: value = m_iptcInfo.Author; break;
517 case SLIDE_IPTC_HEADLINE: value = m_iptcInfo.Headline; break;
518 case SLIDE_IPTC_SPEC_INSTR: value = m_iptcInfo.SpecialInstructions; break;
519 case SLIDE_IPTC_CATEGORY: value = m_iptcInfo.Category; break;
520 case SLIDE_IPTC_BYLINE: value = m_iptcInfo.Byline; break;
521 case SLIDE_IPTC_BYLINE_TITLE: value = m_iptcInfo.BylineTitle; break;
522 case SLIDE_IPTC_CREDIT: value = m_iptcInfo.Credit; break;
523 case SLIDE_IPTC_SOURCE: value = m_iptcInfo.Source; break;
524 case SLIDE_IPTC_COPYRIGHT_NOTICE: value = m_iptcInfo.CopyrightNotice; break;
525 case SLIDE_IPTC_OBJECT_NAME: value = m_iptcInfo.ObjectName; break;
526 case SLIDE_IPTC_CITY: value = m_iptcInfo.City; break;
527 case SLIDE_IPTC_STATE: value = m_iptcInfo.State; break;
528 case SLIDE_IPTC_COUNTRY: value = m_iptcInfo.Country; break;
529 case SLIDE_IPTC_TX_REFERENCE: value = m_iptcInfo.TransmissionReference; break;
530 case SLIDE_IPTC_DATE: value = m_iptcInfo.Date; break;
531 case SLIDE_IPTC_URGENCY: value = m_iptcInfo.Urgency; break;
532 case SLIDE_IPTC_COUNTRY_CODE: value = m_iptcInfo.CountryCode; break;
533 case SLIDE_IPTC_REF_SERVICE: value = m_iptcInfo.ReferenceService; break;
534 case SLIDE_IPTC_TIMECREATED: value = m_iptcInfo.TimeCreated; break;
535 case SLIDE_IPTC_SUBLOCATION: value = m_iptcInfo.SubLocation; break;
536 case SLIDE_IPTC_IMAGETYPE: value = m_iptcInfo.ImageType; break;
543 int CPictureInfoTag::TranslateString(const CStdString &info)
545 if (info.Equals("filename")) return SLIDE_FILE_NAME;
546 else if (info.Equals("path")) return SLIDE_FILE_PATH;
547 else if (info.Equals("filesize")) return SLIDE_FILE_SIZE;
548 else if (info.Equals("filedate")) return SLIDE_FILE_DATE;
549 else if (info.Equals("slideindex")) return SLIDE_INDEX;
550 else if (info.Equals("resolution")) return SLIDE_RESOLUTION;
551 else if (info.Equals("slidecomment")) return SLIDE_COMMENT;
552 else if (info.Equals("colour")) return SLIDE_COLOUR;
553 else if (info.Equals("process")) return SLIDE_PROCESS;
554 else if (info.Equals("exiftime")) return SLIDE_EXIF_DATE_TIME;
555 else if (info.Equals("exifdate")) return SLIDE_EXIF_DATE;
556 else if (info.Equals("longexiftime")) return SLIDE_EXIF_LONG_DATE_TIME;
557 else if (info.Equals("longexifdate")) return SLIDE_EXIF_LONG_DATE;
558 else if (info.Equals("exifdescription")) return SLIDE_EXIF_DESCRIPTION;
559 else if (info.Equals("cameramake")) return SLIDE_EXIF_CAMERA_MAKE;
560 else if (info.Equals("cameramodel")) return SLIDE_EXIF_CAMERA_MODEL;
561 else if (info.Equals("exifcomment")) return SLIDE_EXIF_COMMENT;
562 else if (info.Equals("exifsoftware")) return SLIDE_EXIF_SOFTWARE;
563 else if (info.Equals("aperture")) return SLIDE_EXIF_APERTURE;
564 else if (info.Equals("focallength")) return SLIDE_EXIF_FOCAL_LENGTH;
565 else if (info.Equals("focusdistance")) return SLIDE_EXIF_FOCUS_DIST;
566 else if (info.Equals("exposure")) return SLIDE_EXIF_EXPOSURE;
567 else if (info.Equals("exposuretime")) return SLIDE_EXIF_EXPOSURE_TIME;
568 else if (info.Equals("exposurebias")) return SLIDE_EXIF_EXPOSURE_BIAS;
569 else if (info.Equals("exposuremode")) return SLIDE_EXIF_EXPOSURE_MODE;
570 else if (info.Equals("flashused")) return SLIDE_EXIF_FLASH_USED;
571 else if (info.Equals("whitebalance")) return SLIDE_EXIF_WHITE_BALANCE;
572 else if (info.Equals("lightsource")) return SLIDE_EXIF_LIGHT_SOURCE;
573 else if (info.Equals("meteringmode")) return SLIDE_EXIF_METERING_MODE;
574 else if (info.Equals("isoequivalence")) return SLIDE_EXIF_ISO_EQUIV;
575 else if (info.Equals("digitalzoom")) return SLIDE_EXIF_DIGITAL_ZOOM;
576 else if (info.Equals("ccdwidth")) return SLIDE_EXIF_CCD_WIDTH;
577 else if (info.Equals("orientation")) return SLIDE_EXIF_ORIENTATION;
578 else if (info.Equals("supplementalcategories")) return SLIDE_IPTC_SUP_CATEGORIES;
579 else if (info.Equals("keywords")) return SLIDE_IPTC_KEYWORDS;
580 else if (info.Equals("caption")) return SLIDE_IPTC_CAPTION;
581 else if (info.Equals("author")) return SLIDE_IPTC_AUTHOR;
582 else if (info.Equals("headline")) return SLIDE_IPTC_HEADLINE;
583 else if (info.Equals("specialinstructions")) return SLIDE_IPTC_SPEC_INSTR;
584 else if (info.Equals("category")) return SLIDE_IPTC_CATEGORY;
585 else if (info.Equals("byline")) return SLIDE_IPTC_BYLINE;
586 else if (info.Equals("bylinetitle")) return SLIDE_IPTC_BYLINE_TITLE;
587 else if (info.Equals("credit")) return SLIDE_IPTC_CREDIT;
588 else if (info.Equals("source")) return SLIDE_IPTC_SOURCE;
589 else if (info.Equals("copyrightnotice")) return SLIDE_IPTC_COPYRIGHT_NOTICE;
590 else if (info.Equals("objectname")) return SLIDE_IPTC_OBJECT_NAME;
591 else if (info.Equals("city")) return SLIDE_IPTC_CITY;
592 else if (info.Equals("state")) return SLIDE_IPTC_STATE;
593 else if (info.Equals("country")) return SLIDE_IPTC_COUNTRY;
594 else if (info.Equals("transmissionreference")) return SLIDE_IPTC_TX_REFERENCE;
595 else if (info.Equals("iptcdate")) return SLIDE_IPTC_DATE;
596 else if (info.Equals("urgency")) return SLIDE_IPTC_URGENCY;
597 else if (info.Equals("countrycode")) return SLIDE_IPTC_COUNTRY_CODE;
598 else if (info.Equals("referenceservice")) return SLIDE_IPTC_REF_SERVICE;
599 else if (info.Equals("latitude")) return SLIDE_EXIF_GPS_LATITUDE;
600 else if (info.Equals("longitude")) return SLIDE_EXIF_GPS_LONGITUDE;
601 else if (info.Equals("altitude")) return SLIDE_EXIF_GPS_ALTITUDE;
602 else if (info.Equals("timecreated")) return SLIDE_IPTC_TIMECREATED;
603 else if (info.Equals("sublocation")) return SLIDE_IPTC_SUBLOCATION;
604 else if (info.Equals("imagetype")) return SLIDE_IPTC_IMAGETYPE;
608 void CPictureInfoTag::SetInfo(int info, const CStdString& value)
612 case SLIDE_RESOLUTION:
614 vector<std::string> dimension;
615 StringUtils::Tokenize(value, dimension, ",");
616 if (dimension.size() == 2)
618 m_exifInfo.Width = atoi(dimension[0].c_str());
619 m_exifInfo.Height = atoi(dimension[1].c_str());
620 m_isInfoSetExternally = true; // Set the internal state to show metadata has been set by call to SetInfo
624 case SLIDE_EXIF_DATE_TIME:
626 strcpy(m_exifInfo.DateTime, value.c_str());
627 m_isInfoSetExternally = true; // Set the internal state to show metadata has been set by call to SetInfo
636 const CDateTime& CPictureInfoTag::GetDateTimeTaken() const
638 return m_dateTimeTaken;
641 void CPictureInfoTag::ConvertDateTime()
643 if (strlen(m_exifInfo.DateTime) >= 19 && m_exifInfo.DateTime[0] != ' ')
645 CStdString dateTime = m_exifInfo.DateTime;
646 int year = atoi(dateTime.Mid(0, 4).c_str());
647 int month = atoi(dateTime.Mid(5, 2).c_str());
648 int day = atoi(dateTime.Mid(8, 2).c_str());
649 int hour = atoi(dateTime.Mid(11,2).c_str());
650 int min = atoi(dateTime.Mid(14,2).c_str());
651 int sec = atoi(dateTime.Mid(17,2).c_str());
652 m_dateTimeTaken.SetDateTime(year, month, day, hour, min, sec);