/src/FreeImage/Source/Metadata/TagConversion.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 1094 lines · 942 code · 99 blank · 53 comment · 81 complexity · ad5c0255e89dfcf60732bf9f6cab64a3 MD5 · raw file

  1. // ==========================================================
  2. // Tag to string conversion functions
  3. //
  4. // Design and implementation by
  5. // - Hervé Drolon <drolon@infonie.fr>
  6. //
  7. // This file is part of FreeImage 3
  8. //
  9. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  10. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  11. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  12. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  13. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  14. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  15. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  16. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  17. // THIS DISCLAIMER.
  18. //
  19. // Use at your own risk!
  20. // ==========================================================
  21. #ifdef _MSC_VER
  22. #pragma warning (disable : 4786) // identifier was truncated to 'number' characters
  23. #endif
  24. #include "FreeImage.h"
  25. #include "Utilities.h"
  26. #include "FreeImageTag.h"
  27. #include "FIRational.h"
  28. #define MAX_TEXT_EXTENT 512
  29. /**
  30. Convert a tag to a C string
  31. */
  32. static const char*
  33. ConvertAnyTag(FITAG *tag) {
  34. char format[MAX_TEXT_EXTENT];
  35. static std::string buffer;
  36. DWORD i;
  37. if(!tag)
  38. return NULL;
  39. buffer.erase();
  40. // convert the tag value to a string buffer
  41. FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
  42. DWORD tag_count = FreeImage_GetTagCount(tag);
  43. switch(tag_type) {
  44. case FIDT_BYTE: // N x 8-bit unsigned integer
  45. {
  46. BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
  47. sprintf(format, "%ld", (LONG) pvalue[0]);
  48. buffer += format;
  49. for(i = 1; i < tag_count; i++) {
  50. sprintf(format, " %ld", (LONG) pvalue[i]);
  51. buffer += format;
  52. }
  53. break;
  54. }
  55. case FIDT_SHORT: // N x 16-bit unsigned integer
  56. {
  57. unsigned short *pvalue = (unsigned short *)FreeImage_GetTagValue(tag);
  58. sprintf(format, "%hu", pvalue[0]);
  59. buffer += format;
  60. for(i = 1; i < tag_count; i++) {
  61. sprintf(format, " %hu", pvalue[i]);
  62. buffer += format;
  63. }
  64. break;
  65. }
  66. case FIDT_LONG: // N x 32-bit unsigned integer
  67. {
  68. DWORD *pvalue = (DWORD *)FreeImage_GetTagValue(tag);
  69. sprintf(format, "%lu", pvalue[0]);
  70. buffer += format;
  71. for(i = 1; i < tag_count; i++) {
  72. sprintf(format, " %lu", pvalue[i]);
  73. buffer += format;
  74. }
  75. break;
  76. }
  77. case FIDT_RATIONAL: // N x 64-bit unsigned fraction
  78. {
  79. DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
  80. sprintf(format, "%ld/%ld", pvalue[0], pvalue[1]);
  81. buffer += format;
  82. for(i = 1; i < tag_count; i++) {
  83. sprintf(format, " %ld/%ld", pvalue[2*i], pvalue[2*i+1]);
  84. buffer += format;
  85. }
  86. break;
  87. }
  88. case FIDT_SBYTE: // N x 8-bit signed integer
  89. {
  90. char *pvalue = (char*)FreeImage_GetTagValue(tag);
  91. sprintf(format, "%ld", (LONG) pvalue[0]);
  92. buffer += format;
  93. for(i = 1; i < tag_count; i++) {
  94. sprintf(format, " %ld", (LONG) pvalue[i]);
  95. buffer += format;
  96. }
  97. break;
  98. }
  99. case FIDT_SSHORT: // N x 16-bit signed integer
  100. {
  101. short *pvalue = (short *)FreeImage_GetTagValue(tag);
  102. sprintf(format, "%hd", pvalue[0]);
  103. buffer += format;
  104. for(i = 1; i < tag_count; i++) {
  105. sprintf(format, " %hd", pvalue[i]);
  106. buffer += format;
  107. }
  108. break;
  109. }
  110. case FIDT_SLONG: // N x 32-bit signed integer
  111. {
  112. LONG *pvalue = (LONG *)FreeImage_GetTagValue(tag);
  113. sprintf(format, "%ld", pvalue[0]);
  114. buffer += format;
  115. for(i = 1; i < tag_count; i++) {
  116. sprintf(format, " %ld", pvalue[i]);
  117. buffer += format;
  118. }
  119. break;
  120. }
  121. case FIDT_SRATIONAL:// N x 64-bit signed fraction
  122. {
  123. LONG *pvalue = (LONG*)FreeImage_GetTagValue(tag);
  124. sprintf(format, "%ld/%ld", pvalue[0], pvalue[1]);
  125. buffer += format;
  126. for(i = 1; i < tag_count; i++) {
  127. sprintf(format, " %ld/%ld", pvalue[2*i], pvalue[2*i+1]);
  128. buffer += format;
  129. }
  130. break;
  131. }
  132. case FIDT_FLOAT: // N x 32-bit IEEE floating point
  133. {
  134. float *pvalue = (float *)FreeImage_GetTagValue(tag);
  135. sprintf(format, "%f", (double) pvalue[0]);
  136. buffer += format;
  137. for(i = 1; i < tag_count; i++) {
  138. sprintf(format, "%f", (double) pvalue[i]);
  139. buffer += format;
  140. }
  141. break;
  142. }
  143. case FIDT_DOUBLE: // N x 64-bit IEEE floating point
  144. {
  145. double *pvalue = (double *)FreeImage_GetTagValue(tag);
  146. sprintf(format, "%f", pvalue[0]);
  147. buffer += format;
  148. for(i = 1; i < tag_count; i++) {
  149. sprintf(format, "%f", pvalue[i]);
  150. buffer += format;
  151. }
  152. break;
  153. }
  154. case FIDT_IFD: // N x 32-bit unsigned integer (offset)
  155. {
  156. DWORD *pvalue = (DWORD *)FreeImage_GetTagValue(tag);
  157. sprintf(format, "%X", pvalue[0]);
  158. buffer += format;
  159. for(i = 1; i < tag_count; i++) {
  160. sprintf(format, " %X", pvalue[i]);
  161. buffer += format;
  162. }
  163. break;
  164. }
  165. case FIDT_PALETTE: // N x 32-bit RGBQUAD
  166. {
  167. RGBQUAD *pvalue = (RGBQUAD *)FreeImage_GetTagValue(tag);
  168. sprintf(format, "(%d,%d,%d,%d)", pvalue[0].rgbRed, pvalue[0].rgbGreen, pvalue[0].rgbBlue, pvalue[0].rgbReserved);
  169. buffer += format;
  170. for(i = 1; i < tag_count; i++) {
  171. sprintf(format, " (%d,%d,%d,%d)", pvalue[i].rgbRed, pvalue[i].rgbGreen, pvalue[i].rgbBlue, pvalue[i].rgbReserved);
  172. buffer += format;
  173. }
  174. break;
  175. }
  176. case FIDT_LONG8: // N x 64-bit unsigned integer
  177. {
  178. FIUINT64 *pvalue = (FIUINT64 *)FreeImage_GetTagValue(tag);
  179. sprintf(format, "%ld", pvalue[0]);
  180. buffer += format;
  181. for(i = 1; i < tag_count; i++) {
  182. sprintf(format, "%ld", pvalue[i]);
  183. buffer += format;
  184. }
  185. break;
  186. }
  187. case FIDT_IFD8: // N x 64-bit unsigned integer (offset)
  188. {
  189. FIUINT64 *pvalue = (FIUINT64 *)FreeImage_GetTagValue(tag);
  190. sprintf(format, "%X", pvalue[0]);
  191. buffer += format;
  192. for(i = 1; i < tag_count; i++) {
  193. sprintf(format, "%X", pvalue[i]);
  194. buffer += format;
  195. }
  196. break;
  197. }
  198. case FIDT_SLONG8: // N x 64-bit signed integer
  199. {
  200. FIINT64 *pvalue = (FIINT64 *)FreeImage_GetTagValue(tag);
  201. sprintf(format, "%ld", pvalue[0]);
  202. buffer += format;
  203. for(i = 1; i < tag_count; i++) {
  204. sprintf(format, "%ld", pvalue[i]);
  205. buffer += format;
  206. }
  207. break;
  208. }
  209. case FIDT_ASCII: // 8-bit bytes w/ last byte null
  210. case FIDT_UNDEFINED:// 8-bit untyped data
  211. default:
  212. {
  213. int max_size = MIN((int)FreeImage_GetTagLength(tag), (int)MAX_TEXT_EXTENT);
  214. if(max_size == MAX_TEXT_EXTENT)
  215. max_size--;
  216. memcpy(format, (char*)FreeImage_GetTagValue(tag), max_size);
  217. format[max_size] = '\0';
  218. buffer += format;
  219. break;
  220. }
  221. }
  222. return buffer.c_str();
  223. }
  224. /**
  225. Convert a Exif tag to a C string
  226. */
  227. static const char*
  228. ConvertExifTag(FITAG *tag) {
  229. char format[MAX_TEXT_EXTENT];
  230. static std::string buffer;
  231. if(!tag)
  232. return NULL;
  233. buffer.erase();
  234. // convert the tag value to a string buffer
  235. switch(FreeImage_GetTagID(tag)) {
  236. case TAG_ORIENTATION:
  237. {
  238. unsigned short orientation = *((unsigned short *)FreeImage_GetTagValue(tag));
  239. switch (orientation) {
  240. case 1:
  241. return "top, left side";
  242. case 2:
  243. return "top, right side";
  244. case 3:
  245. return "bottom, right side";
  246. case 4:
  247. return "bottom, left side";
  248. case 5:
  249. return "left side, top";
  250. case 6:
  251. return "right side, top";
  252. case 7:
  253. return "right side, bottom";
  254. case 8:
  255. return "left side, bottom";
  256. default:
  257. break;
  258. }
  259. }
  260. break;
  261. case TAG_REFERENCE_BLACK_WHITE:
  262. {
  263. DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
  264. if(FreeImage_GetTagLength(tag) == 48) {
  265. // reference black point value and reference white point value (ReferenceBlackWhite)
  266. int blackR = 0, whiteR = 0, blackG = 0, whiteG = 0, blackB = 0, whiteB = 0;
  267. if(pvalue[1])
  268. blackR = (int)(pvalue[0] / pvalue[1]);
  269. if(pvalue[3])
  270. whiteR = (int)(pvalue[2] / pvalue[3]);
  271. if(pvalue[5])
  272. blackG = (int)(pvalue[4] / pvalue[5]);
  273. if(pvalue[7])
  274. whiteG = (int)(pvalue[6] / pvalue[7]);
  275. if(pvalue[9])
  276. blackB = (int)(pvalue[8] / pvalue[9]);
  277. if(pvalue[11])
  278. whiteB = (int)(pvalue[10] / pvalue[11]);
  279. sprintf(format, "[%d,%d,%d] [%d,%d,%d]", blackR, blackG, blackB, whiteR, whiteG, whiteB);
  280. buffer += format;
  281. return buffer.c_str();
  282. }
  283. }
  284. break;
  285. case TAG_COLOR_SPACE:
  286. {
  287. unsigned short colorSpace = *((unsigned short *)FreeImage_GetTagValue(tag));
  288. if (colorSpace == 1) {
  289. return "sRGB";
  290. } else if (colorSpace == 65535) {
  291. return "Undefined";
  292. } else {
  293. return "Unknown";
  294. }
  295. }
  296. break;
  297. case TAG_COMPONENTS_CONFIGURATION:
  298. {
  299. const char *componentStrings[7] = {"", "Y", "Cb", "Cr", "R", "G", "B"};
  300. BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
  301. for(DWORD i = 0; i < MIN((DWORD)4, FreeImage_GetTagCount(tag)); i++) {
  302. int j = pvalue[i];
  303. if(j > 0 && j < 7)
  304. buffer += componentStrings[j];
  305. }
  306. return buffer.c_str();
  307. }
  308. break;
  309. case TAG_COMPRESSED_BITS_PER_PIXEL:
  310. {
  311. FIRational r(tag);
  312. buffer = r.toString();
  313. if(buffer == "1")
  314. buffer += " bit/pixel";
  315. else
  316. buffer += " bits/pixel";
  317. return buffer.c_str();
  318. }
  319. break;
  320. case TAG_X_RESOLUTION:
  321. case TAG_Y_RESOLUTION:
  322. case TAG_FOCAL_PLANE_X_RES:
  323. case TAG_FOCAL_PLANE_Y_RES:
  324. case TAG_BRIGHTNESS_VALUE:
  325. case TAG_EXPOSURE_BIAS_VALUE:
  326. {
  327. FIRational r(tag);
  328. buffer = r.toString();
  329. return buffer.c_str();
  330. }
  331. break;
  332. case TAG_RESOLUTION_UNIT:
  333. case TAG_FOCAL_PLANE_UNIT:
  334. {
  335. unsigned short resolutionUnit = *((unsigned short *)FreeImage_GetTagValue(tag));
  336. switch (resolutionUnit) {
  337. case 1:
  338. return "(No unit)";
  339. case 2:
  340. return "inches";
  341. case 3:
  342. return "cm";
  343. default:
  344. break;
  345. }
  346. }
  347. break;
  348. case TAG_YCBCR_POSITIONING:
  349. {
  350. unsigned short yCbCrPosition = *((unsigned short *)FreeImage_GetTagValue(tag));
  351. switch (yCbCrPosition) {
  352. case 1:
  353. return "Center of pixel array";
  354. case 2:
  355. return "Datum point";
  356. default:
  357. break;
  358. }
  359. }
  360. break;
  361. case TAG_EXPOSURE_TIME:
  362. {
  363. FIRational r(tag);
  364. buffer = r.toString();
  365. buffer += " sec";
  366. return buffer.c_str();
  367. }
  368. break;
  369. case TAG_SHUTTER_SPEED_VALUE:
  370. {
  371. FIRational r(tag);
  372. LONG apexValue = r.longValue();
  373. LONG apexPower = 1 << apexValue;
  374. sprintf(format, "1/%d sec", (int)apexPower);
  375. buffer += format;
  376. return buffer.c_str();
  377. }
  378. break;
  379. case TAG_APERTURE_VALUE:
  380. case TAG_MAX_APERTURE_VALUE:
  381. {
  382. FIRational r(tag);
  383. double apertureApex = r.doubleValue();
  384. double rootTwo = sqrt((double)2);
  385. double fStop = pow(rootTwo, apertureApex);
  386. sprintf(format, "F%.1f", fStop);
  387. buffer += format;
  388. return buffer.c_str();
  389. }
  390. break;
  391. case TAG_FNUMBER:
  392. {
  393. FIRational r(tag);
  394. double fnumber = r.doubleValue();
  395. sprintf(format, "F%.1f", fnumber);
  396. buffer += format;
  397. return buffer.c_str();
  398. }
  399. break;
  400. case TAG_FOCAL_LENGTH:
  401. {
  402. FIRational r(tag);
  403. double focalLength = r.doubleValue();
  404. sprintf(format, "%.1f mm", focalLength);
  405. buffer += format;
  406. return buffer.c_str();
  407. }
  408. break;
  409. case TAG_FOCAL_LENGTH_IN_35MM_FILM:
  410. {
  411. unsigned short focalLength = *((unsigned short *)FreeImage_GetTagValue(tag));
  412. sprintf(format, "%hu mm", focalLength);
  413. buffer += format;
  414. return buffer.c_str();
  415. }
  416. break;
  417. case TAG_FLASH:
  418. {
  419. unsigned short flash = *((unsigned short *)FreeImage_GetTagValue(tag));
  420. switch(flash) {
  421. case 0x0000:
  422. return "Flash did not fire";
  423. case 0x0001:
  424. return "Flash fired";
  425. case 0x0005:
  426. return "Strobe return light not detected";
  427. case 0x0007:
  428. return "Strobe return light detected";
  429. case 0x0009:
  430. return "Flash fired, compulsory flash mode";
  431. case 0x000D:
  432. return "Flash fired, compulsory flash mode, return light not detected";
  433. case 0x000F:
  434. return "Flash fired, compulsory flash mode, return light detected";
  435. case 0x0010:
  436. return "Flash did not fire, compulsory flash mode";
  437. case 0x0018:
  438. return "Flash did not fire, auto mode";
  439. case 0x0019:
  440. return "Flash fired, auto mode";
  441. case 0x001D:
  442. return "Flash fired, auto mode, return light not detected";
  443. case 0x001F:
  444. return "Flash fired, auto mode, return light detected";
  445. case 0x0020:
  446. return "No flash function";
  447. case 0x0041:
  448. return "Flash fired, red-eye reduction mode";
  449. case 0x0045:
  450. return "Flash fired, red-eye reduction mode, return light not detected";
  451. case 0x0047:
  452. return "Flash fired, red-eye reduction mode, return light detected";
  453. case 0x0049:
  454. return "Flash fired, compulsory flash mode, red-eye reduction mode";
  455. case 0x004D:
  456. return "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
  457. case 0x004F:
  458. return "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
  459. case 0x0059:
  460. return "Flash fired, auto mode, red-eye reduction mode";
  461. case 0x005D:
  462. return "Flash fired, auto mode, return light not detected, red-eye reduction mode";
  463. case 0x005F:
  464. return "Flash fired, auto mode, return light detected, red-eye reduction mode";
  465. default:
  466. sprintf(format, "Unknown (%d)", flash);
  467. buffer += format;
  468. return buffer.c_str();
  469. }
  470. }
  471. break;
  472. case TAG_SCENE_TYPE:
  473. {
  474. BYTE sceneType = *((BYTE*)FreeImage_GetTagValue(tag));
  475. if (sceneType == 1) {
  476. return "Directly photographed image";
  477. } else {
  478. sprintf(format, "Unknown (%d)", sceneType);
  479. buffer += format;
  480. return buffer.c_str();
  481. }
  482. }
  483. break;
  484. case TAG_SUBJECT_DISTANCE:
  485. {
  486. FIRational r(tag);
  487. if(r.getNumerator() == 0xFFFFFFFF) {
  488. return "Infinity";
  489. } else if(r.getNumerator() == 0) {
  490. return "Distance unknown";
  491. } else {
  492. double distance = r.doubleValue();
  493. sprintf(format, "%.3f meters", distance);
  494. buffer += format;
  495. return buffer.c_str();
  496. }
  497. }
  498. break;
  499. case TAG_METERING_MODE:
  500. {
  501. unsigned short meteringMode = *((unsigned short *)FreeImage_GetTagValue(tag));
  502. switch (meteringMode) {
  503. case 0:
  504. return "Unknown";
  505. case 1:
  506. return "Average";
  507. case 2:
  508. return "Center weighted average";
  509. case 3:
  510. return "Spot";
  511. case 4:
  512. return "Multi-spot";
  513. case 5:
  514. return "Multi-segment";
  515. case 6:
  516. return "Partial";
  517. case 255:
  518. return "(Other)";
  519. default:
  520. return "";
  521. }
  522. }
  523. break;
  524. case TAG_LIGHT_SOURCE:
  525. {
  526. unsigned short lightSource = *((unsigned short *)FreeImage_GetTagValue(tag));
  527. switch (lightSource) {
  528. case 0:
  529. return "Unknown";
  530. case 1:
  531. return "Daylight";
  532. case 2:
  533. return "Fluorescent";
  534. case 3:
  535. return "Tungsten (incandescent light)";
  536. case 4:
  537. return "Flash";
  538. case 9:
  539. return "Fine weather";
  540. case 10:
  541. return "Cloudy weather";
  542. case 11:
  543. return "Shade";
  544. case 12:
  545. return "Daylight fluorescent (D 5700 - 7100K)";
  546. case 13:
  547. return "Day white fluorescent (N 4600 - 5400K)";
  548. case 14:
  549. return "Cool white fluorescent (W 3900 - 4500K)";
  550. case 15:
  551. return "White fluorescent (WW 3200 - 3700K)";
  552. case 17:
  553. return "Standard light A";
  554. case 18:
  555. return "Standard light B";
  556. case 19:
  557. return "Standard light C";
  558. case 20:
  559. return "D55";
  560. case 21:
  561. return "D65";
  562. case 22:
  563. return "D75";
  564. case 23:
  565. return "D50";
  566. case 24:
  567. return "ISO studio tungsten";
  568. case 255:
  569. return "(Other)";
  570. default:
  571. return "";
  572. }
  573. }
  574. break;
  575. case TAG_SENSING_METHOD:
  576. {
  577. unsigned short sensingMethod = *((unsigned short *)FreeImage_GetTagValue(tag));
  578. switch (sensingMethod) {
  579. case 1:
  580. return "(Not defined)";
  581. case 2:
  582. return "One-chip color area sensor";
  583. case 3:
  584. return "Two-chip color area sensor";
  585. case 4:
  586. return "Three-chip color area sensor";
  587. case 5:
  588. return "Color sequential area sensor";
  589. case 7:
  590. return "Trilinear sensor";
  591. case 8:
  592. return "Color sequential linear sensor";
  593. default:
  594. return "";
  595. }
  596. }
  597. break;
  598. case TAG_FILE_SOURCE:
  599. {
  600. BYTE fileSource = *((BYTE*)FreeImage_GetTagValue(tag));
  601. if (fileSource == 3) {
  602. return "Digital Still Camera (DSC)";
  603. } else {
  604. sprintf(format, "Unknown (%d)", fileSource);
  605. buffer += format;
  606. return buffer.c_str();
  607. }
  608. }
  609. break;
  610. case TAG_EXPOSURE_PROGRAM:
  611. {
  612. unsigned short exposureProgram = *((unsigned short *)FreeImage_GetTagValue(tag));
  613. switch (exposureProgram) {
  614. case 1:
  615. return "Manual control";
  616. case 2:
  617. return "Program normal";
  618. case 3:
  619. return "Aperture priority";
  620. case 4:
  621. return "Shutter priority";
  622. case 5:
  623. return "Program creative (slow program)";
  624. case 6:
  625. return "Program action (high-speed program)";
  626. case 7:
  627. return "Portrait mode";
  628. case 8:
  629. return "Landscape mode";
  630. default:
  631. sprintf(format, "Unknown program (%d)", exposureProgram);
  632. buffer += format;
  633. return buffer.c_str();
  634. }
  635. }
  636. break;
  637. case TAG_CUSTOM_RENDERED:
  638. {
  639. unsigned short customRendered = *((unsigned short *)FreeImage_GetTagValue(tag));
  640. switch (customRendered) {
  641. case 0:
  642. return "Normal process";
  643. case 1:
  644. return "Custom process";
  645. default:
  646. sprintf(format, "Unknown rendering (%d)", customRendered);
  647. buffer += format;
  648. return buffer.c_str();
  649. }
  650. }
  651. break;
  652. case TAG_EXPOSURE_MODE:
  653. {
  654. unsigned short exposureMode = *((unsigned short *)FreeImage_GetTagValue(tag));
  655. switch (exposureMode) {
  656. case 0:
  657. return "Auto exposure";
  658. case 1:
  659. return "Manual exposure";
  660. case 2:
  661. return "Auto bracket";
  662. default:
  663. sprintf(format, "Unknown mode (%d)", exposureMode);
  664. buffer += format;
  665. return buffer.c_str();
  666. }
  667. }
  668. break;
  669. case TAG_WHITE_BALANCE:
  670. {
  671. unsigned short whiteBalance = *((unsigned short *)FreeImage_GetTagValue(tag));
  672. switch (whiteBalance) {
  673. case 0:
  674. return "Auto white balance";
  675. case 1:
  676. return "Manual white balance";
  677. default:
  678. sprintf(format, "Unknown (%d)", whiteBalance);
  679. buffer += format;
  680. return buffer.c_str();
  681. }
  682. }
  683. break;
  684. case TAG_SCENE_CAPTURE_TYPE:
  685. {
  686. unsigned short sceneType = *((unsigned short *)FreeImage_GetTagValue(tag));
  687. switch (sceneType) {
  688. case 0:
  689. return "Standard";
  690. case 1:
  691. return "Landscape";
  692. case 2:
  693. return "Portrait";
  694. case 3:
  695. return "Night scene";
  696. default:
  697. sprintf(format, "Unknown (%d)", sceneType);
  698. buffer += format;
  699. return buffer.c_str();
  700. }
  701. }
  702. break;
  703. case TAG_GAIN_CONTROL:
  704. {
  705. unsigned short gainControl = *((unsigned short *)FreeImage_GetTagValue(tag));
  706. switch (gainControl) {
  707. case 0:
  708. return "None";
  709. case 1:
  710. return "Low gain up";
  711. case 2:
  712. return "High gain up";
  713. case 3:
  714. return "Low gain down";
  715. case 4:
  716. return "High gain down";
  717. default:
  718. sprintf(format, "Unknown (%d)", gainControl);
  719. buffer += format;
  720. return buffer.c_str();
  721. }
  722. }
  723. break;
  724. case TAG_CONTRAST:
  725. {
  726. unsigned short contrast = *((unsigned short *)FreeImage_GetTagValue(tag));
  727. switch (contrast) {
  728. case 0:
  729. return "Normal";
  730. case 1:
  731. return "Soft";
  732. case 2:
  733. return "Hard";
  734. default:
  735. sprintf(format, "Unknown (%d)", contrast);
  736. buffer += format;
  737. return buffer.c_str();
  738. }
  739. }
  740. break;
  741. case TAG_SATURATION:
  742. {
  743. unsigned short saturation = *((unsigned short *)FreeImage_GetTagValue(tag));
  744. switch (saturation) {
  745. case 0:
  746. return "Normal";
  747. case 1:
  748. return "Low saturation";
  749. case 2:
  750. return "High saturation";
  751. default:
  752. sprintf(format, "Unknown (%d)", saturation);
  753. buffer += format;
  754. return buffer.c_str();
  755. }
  756. }
  757. break;
  758. case TAG_SHARPNESS:
  759. {
  760. unsigned short sharpness = *((unsigned short *)FreeImage_GetTagValue(tag));
  761. switch (sharpness) {
  762. case 0:
  763. return "Normal";
  764. case 1:
  765. return "Soft";
  766. case 2:
  767. return "Hard";
  768. default:
  769. sprintf(format, "Unknown (%d)", sharpness);
  770. buffer += format;
  771. return buffer.c_str();
  772. }
  773. }
  774. break;
  775. case TAG_SUBJECT_DISTANCE_RANGE:
  776. {
  777. unsigned short distanceRange = *((unsigned short *)FreeImage_GetTagValue(tag));
  778. switch (distanceRange) {
  779. case 0:
  780. return "unknown";
  781. case 1:
  782. return "Macro";
  783. case 2:
  784. return "Close view";
  785. case 3:
  786. return "Distant view";
  787. default:
  788. sprintf(format, "Unknown (%d)", distanceRange);
  789. buffer += format;
  790. return buffer.c_str();
  791. }
  792. }
  793. break;
  794. case TAG_ISO_SPEED_RATINGS:
  795. {
  796. unsigned short isoEquiv = *((unsigned short *)FreeImage_GetTagValue(tag));
  797. if (isoEquiv < 50) {
  798. isoEquiv *= 200;
  799. }
  800. sprintf(format, "%d", isoEquiv);
  801. buffer += format;
  802. return buffer.c_str();
  803. }
  804. break;
  805. case TAG_USER_COMMENT:
  806. {
  807. // first 8 bytes are used to define an ID code
  808. // we assume this is an ASCII string
  809. const BYTE *userComment = (BYTE*)FreeImage_GetTagValue(tag);
  810. for(DWORD i = 8; i < FreeImage_GetTagLength(tag); i++) {
  811. buffer += userComment[i];
  812. }
  813. buffer += '\0';
  814. return buffer.c_str();
  815. }
  816. break;
  817. case TAG_COMPRESSION:
  818. {
  819. WORD compression = *((WORD*)FreeImage_GetTagValue(tag));
  820. switch(compression) {
  821. case TAG_COMPRESSION_NONE:
  822. sprintf(format, "dump mode (%d)", compression);
  823. break;
  824. case TAG_COMPRESSION_CCITTRLE:
  825. sprintf(format, "CCITT modified Huffman RLE (%d)", compression);
  826. break;
  827. case TAG_COMPRESSION_CCITTFAX3:
  828. sprintf(format, "CCITT Group 3 fax encoding (%d)", compression);
  829. break;
  830. /*
  831. case TAG_COMPRESSION_CCITT_T4:
  832. sprintf(format, "CCITT T.4 (TIFF 6 name) (%d)", compression);
  833. break;
  834. */
  835. case TAG_COMPRESSION_CCITTFAX4:
  836. sprintf(format, "CCITT Group 4 fax encoding (%d)", compression);
  837. break;
  838. /*
  839. case TAG_COMPRESSION_CCITT_T6:
  840. sprintf(format, "CCITT T.6 (TIFF 6 name) (%d)", compression);
  841. break;
  842. */
  843. case TAG_COMPRESSION_LZW:
  844. sprintf(format, "LZW (%d)", compression);
  845. break;
  846. case TAG_COMPRESSION_OJPEG:
  847. sprintf(format, "!6.0 JPEG (%d)", compression);
  848. break;
  849. case TAG_COMPRESSION_JPEG:
  850. sprintf(format, "JPEG (%d)", compression);
  851. break;
  852. case TAG_COMPRESSION_NEXT:
  853. sprintf(format, "NeXT 2-bit RLE (%d)", compression);
  854. break;
  855. case TAG_COMPRESSION_CCITTRLEW:
  856. sprintf(format, "CCITTRLEW (%d)", compression);
  857. break;
  858. case TAG_COMPRESSION_PACKBITS:
  859. sprintf(format, "PackBits Macintosh RLE (%d)", compression);
  860. break;
  861. case TAG_COMPRESSION_THUNDERSCAN:
  862. sprintf(format, "ThunderScan RLE (%d)", compression);
  863. break;
  864. case TAG_COMPRESSION_PIXARFILM:
  865. sprintf(format, "Pixar companded 10bit LZW (%d)", compression);
  866. break;
  867. case TAG_COMPRESSION_PIXARLOG:
  868. sprintf(format, "Pixar companded 11bit ZIP (%d)", compression);
  869. break;
  870. case TAG_COMPRESSION_DEFLATE:
  871. sprintf(format, "Deflate compression (%d)", compression);
  872. break;
  873. case TAG_COMPRESSION_ADOBE_DEFLATE:
  874. sprintf(format, "Adobe Deflate compression (%d)", compression);
  875. break;
  876. case TAG_COMPRESSION_DCS:
  877. sprintf(format, "Kodak DCS encoding (%d)", compression);
  878. break;
  879. case TAG_COMPRESSION_JBIG:
  880. sprintf(format, "ISO JBIG (%d)", compression);
  881. break;
  882. case TAG_COMPRESSION_SGILOG:
  883. sprintf(format, "SGI Log Luminance RLE (%d)", compression);
  884. break;
  885. case TAG_COMPRESSION_SGILOG24:
  886. sprintf(format, "SGI Log 24-bit packed (%d)", compression);
  887. break;
  888. case TAG_COMPRESSION_JP2000:
  889. sprintf(format, "Leadtools JPEG2000 (%d)", compression);
  890. break;
  891. case TAG_COMPRESSION_LZMA:
  892. sprintf(format, "LZMA2 (%d)", compression);
  893. break;
  894. default:
  895. sprintf(format, "Unknown type (%d)", compression);
  896. break;
  897. }
  898. buffer += format;
  899. return buffer.c_str();
  900. }
  901. break;
  902. }
  903. return ConvertAnyTag(tag);
  904. }
  905. /**
  906. Convert a Exif GPS tag to a C string
  907. */
  908. static const char*
  909. ConvertExifGPSTag(FITAG *tag) {
  910. char format[MAX_TEXT_EXTENT];
  911. static std::string buffer;
  912. if(!tag)
  913. return NULL;
  914. buffer.erase();
  915. // convert the tag value to a string buffer
  916. switch(FreeImage_GetTagID(tag)) {
  917. case TAG_GPS_LATITUDE:
  918. case TAG_GPS_LONGITUDE:
  919. case TAG_GPS_TIME_STAMP:
  920. {
  921. DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
  922. if(FreeImage_GetTagLength(tag) == 24) {
  923. // dd:mm:ss or hh:mm:ss
  924. int dd = 0, mm = 0;
  925. double ss = 0;
  926. // convert to seconds
  927. if(pvalue[1])
  928. ss += ((double)pvalue[0] / (double)pvalue[1]) * 3600;
  929. if(pvalue[3])
  930. ss += ((double)pvalue[2] / (double)pvalue[3]) * 60;
  931. if(pvalue[5])
  932. ss += ((double)pvalue[4] / (double)pvalue[5]);
  933. // convert to dd:mm:ss.ss
  934. dd = (int)(ss / 3600);
  935. mm = (int)(ss / 60) - dd * 60;
  936. ss = ss - dd * 3600 - mm * 60;
  937. sprintf(format, "%d:%d:%.2f", dd, mm, ss);
  938. buffer += format;
  939. return buffer.c_str();
  940. }
  941. }
  942. break;
  943. case TAG_GPS_VERSION_ID:
  944. case TAG_GPS_LATITUDE_REF:
  945. case TAG_GPS_LONGITUDE_REF:
  946. case TAG_GPS_ALTITUDE_REF:
  947. case TAG_GPS_ALTITUDE:
  948. case TAG_GPS_SATELLITES:
  949. case TAG_GPS_STATUS:
  950. case TAG_GPS_MEASURE_MODE:
  951. case TAG_GPS_DOP:
  952. case TAG_GPS_SPEED_REF:
  953. case TAG_GPS_SPEED:
  954. case TAG_GPS_TRACK_REF:
  955. case TAG_GPS_TRACK:
  956. case TAG_GPS_IMG_DIRECTION_REF:
  957. case TAG_GPS_IMG_DIRECTION:
  958. case TAG_GPS_MAP_DATUM:
  959. case TAG_GPS_DEST_LATITUDE_REF:
  960. case TAG_GPS_DEST_LATITUDE:
  961. case TAG_GPS_DEST_LONGITUDE_REF:
  962. case TAG_GPS_DEST_LONGITUDE:
  963. case TAG_GPS_DEST_BEARING_REF:
  964. case TAG_GPS_DEST_BEARING:
  965. case TAG_GPS_DEST_DISTANCE_REF:
  966. case TAG_GPS_DEST_DISTANCE:
  967. case TAG_GPS_PROCESSING_METHOD:
  968. case TAG_GPS_AREA_INFORMATION:
  969. case TAG_GPS_DATE_STAMP:
  970. case TAG_GPS_DIFFERENTIAL:
  971. break;
  972. }
  973. return ConvertAnyTag(tag);
  974. }
  975. // ==========================================================
  976. // Tag to string conversion function
  977. //
  978. const char* DLL_CALLCONV
  979. FreeImage_TagToString(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make) {
  980. switch(model) {
  981. case FIMD_EXIF_MAIN:
  982. case FIMD_EXIF_EXIF:
  983. return ConvertExifTag(tag);
  984. case FIMD_EXIF_GPS:
  985. return ConvertExifGPSTag(tag);
  986. case FIMD_EXIF_MAKERNOTE:
  987. // We should use the Make string to select an appropriate conversion function
  988. // TO DO ...
  989. break;
  990. case FIMD_EXIF_INTEROP:
  991. default:
  992. break;
  993. }
  994. return ConvertAnyTag(tag);
  995. }