/src/FreeImage/Source/Metadata/FreeImageTag.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 318 lines · 229 code · 38 blank · 51 comment · 34 complexity · 45295f34b3074de6cf5419888168be5f MD5 · raw file

  1. // ==========================================================
  2. // Tag manipulation 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. // --------------------------------------------------------------------------
  28. // FITAG header definition
  29. // --------------------------------------------------------------------------
  30. FI_STRUCT (FITAGHEADER) {
  31. char *key; // tag field name
  32. char *description; // tag description
  33. WORD id; // tag ID
  34. WORD type; // tag data type (see FREE_IMAGE_MDTYPE)
  35. DWORD count; // number of components (in 'tag data types' units)
  36. DWORD length; // value length in bytes
  37. void *value; // tag value
  38. };
  39. // --------------------------------------------------------------------------
  40. // FITAG creation / destruction
  41. // --------------------------------------------------------------------------
  42. FITAG * DLL_CALLCONV
  43. FreeImage_CreateTag() {
  44. FITAG *tag = (FITAG *)malloc(sizeof(FITAG));
  45. if (tag != NULL) {
  46. unsigned tag_size = sizeof(FITAGHEADER);
  47. tag->data = (BYTE *)malloc(tag_size * sizeof(BYTE));
  48. if (tag->data != NULL) {
  49. memset(tag->data, 0, tag_size);
  50. return tag;
  51. }
  52. free(tag);
  53. }
  54. return NULL;
  55. }
  56. void DLL_CALLCONV
  57. FreeImage_DeleteTag(FITAG *tag) {
  58. if (NULL != tag) {
  59. if (NULL != tag->data) {
  60. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  61. // delete tag members
  62. free(tag_header->key);
  63. free(tag_header->description);
  64. free(tag_header->value);
  65. // delete the tag
  66. free(tag->data);
  67. }
  68. // and the wrapper
  69. free(tag);
  70. }
  71. }
  72. FITAG * DLL_CALLCONV
  73. FreeImage_CloneTag(FITAG *tag) {
  74. if(!tag) return NULL;
  75. // allocate a new tag
  76. FITAG *clone = FreeImage_CreateTag();
  77. if(!clone) return NULL;
  78. try {
  79. // copy the tag
  80. FITAGHEADER *src_tag = (FITAGHEADER *)tag->data;
  81. FITAGHEADER *dst_tag = (FITAGHEADER *)clone->data;
  82. // tag ID
  83. dst_tag->id = src_tag->id;
  84. // tag key
  85. if(src_tag->key) {
  86. dst_tag->key = (char*)malloc((strlen(src_tag->key) + 1) * sizeof(char));
  87. if(!dst_tag->key) {
  88. throw FI_MSG_ERROR_MEMORY;
  89. }
  90. strcpy(dst_tag->key, src_tag->key);
  91. }
  92. // tag description
  93. if(src_tag->description) {
  94. dst_tag->description = (char*)malloc((strlen(src_tag->description) + 1) * sizeof(char));
  95. if(!dst_tag->description) {
  96. throw FI_MSG_ERROR_MEMORY;
  97. }
  98. strcpy(dst_tag->description, src_tag->description);
  99. }
  100. // tag data type
  101. dst_tag->type = src_tag->type;
  102. // tag count
  103. dst_tag->count = src_tag->count;
  104. // tag length
  105. dst_tag->length = src_tag->length;
  106. // tag value
  107. dst_tag->value = (BYTE*)malloc(src_tag->length * sizeof(BYTE));
  108. if(!dst_tag->value) {
  109. throw FI_MSG_ERROR_MEMORY;
  110. }
  111. memcpy(dst_tag->value, src_tag->value, src_tag->length);
  112. return clone;
  113. } catch(const char *message) {
  114. FreeImage_DeleteTag(clone);
  115. FreeImage_OutputMessageProc(FIF_UNKNOWN, message);
  116. return NULL;
  117. }
  118. }
  119. // --------------------------------------------------------------------------
  120. // FITAG getters / setters
  121. // --------------------------------------------------------------------------
  122. const char * DLL_CALLCONV
  123. FreeImage_GetTagKey(FITAG *tag) {
  124. return tag ? ((FITAGHEADER *)tag->data)->key : 0;
  125. }
  126. const char * DLL_CALLCONV
  127. FreeImage_GetTagDescription(FITAG *tag) {
  128. return tag ? ((FITAGHEADER *)tag->data)->description : 0;
  129. }
  130. WORD DLL_CALLCONV
  131. FreeImage_GetTagID(FITAG *tag) {
  132. return tag ? ((FITAGHEADER *)tag->data)->id : 0;
  133. }
  134. FREE_IMAGE_MDTYPE DLL_CALLCONV
  135. FreeImage_GetTagType(FITAG *tag) {
  136. return tag ? (FREE_IMAGE_MDTYPE)(((FITAGHEADER *)tag->data)->type) : FIDT_NOTYPE;
  137. }
  138. DWORD DLL_CALLCONV
  139. FreeImage_GetTagCount(FITAG *tag) {
  140. return tag ? ((FITAGHEADER *)tag->data)->count : 0;
  141. }
  142. DWORD DLL_CALLCONV
  143. FreeImage_GetTagLength(FITAG *tag) {
  144. return tag ? ((FITAGHEADER *)tag->data)->length : 0;
  145. }
  146. const void *DLL_CALLCONV
  147. FreeImage_GetTagValue(FITAG *tag) {
  148. return tag ? ((FITAGHEADER *)tag->data)->value : 0;
  149. }
  150. BOOL DLL_CALLCONV
  151. FreeImage_SetTagKey(FITAG *tag, const char *key) {
  152. if(tag && key) {
  153. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  154. if(tag_header->key) free(tag_header->key);
  155. tag_header->key = (char*)malloc(strlen(key) + 1);
  156. strcpy(tag_header->key, key);
  157. return TRUE;
  158. }
  159. return FALSE;
  160. }
  161. BOOL DLL_CALLCONV
  162. FreeImage_SetTagDescription(FITAG *tag, const char *description) {
  163. if(tag && description) {
  164. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  165. if(tag_header->description) free(tag_header->description);
  166. tag_header->description = (char*)malloc(strlen(description) + 1);
  167. strcpy(tag_header->description, description);
  168. return TRUE;
  169. }
  170. return FALSE;
  171. }
  172. BOOL DLL_CALLCONV
  173. FreeImage_SetTagID(FITAG *tag, WORD id) {
  174. if(tag) {
  175. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  176. tag_header->id = id;
  177. return TRUE;
  178. }
  179. return FALSE;
  180. }
  181. BOOL DLL_CALLCONV
  182. FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type) {
  183. if(tag) {
  184. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  185. tag_header->type = (WORD)type;
  186. return TRUE;
  187. }
  188. return FALSE;
  189. }
  190. BOOL DLL_CALLCONV
  191. FreeImage_SetTagCount(FITAG *tag, DWORD count) {
  192. if(tag) {
  193. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  194. tag_header->count = count;
  195. return TRUE;
  196. }
  197. return FALSE;
  198. }
  199. BOOL DLL_CALLCONV
  200. FreeImage_SetTagLength(FITAG *tag, DWORD length) {
  201. if(tag) {
  202. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  203. tag_header->length = length;
  204. return TRUE;
  205. }
  206. return FALSE;
  207. }
  208. BOOL DLL_CALLCONV
  209. FreeImage_SetTagValue(FITAG *tag, const void *value) {
  210. if(tag && value) {
  211. FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
  212. // first, check the tag
  213. if(tag_header->count * FreeImage_TagDataWidth((FREE_IMAGE_MDTYPE)tag_header->type) != tag_header->length) {
  214. // invalid data count ?
  215. return FALSE;
  216. }
  217. if(tag_header->value) {
  218. free(tag_header->value);
  219. }
  220. switch(tag_header->type) {
  221. case FIDT_ASCII:
  222. {
  223. tag_header->value = (char*)malloc((tag_header->length + 1) * sizeof(char));
  224. if(!tag_header->value) {
  225. return FALSE;
  226. }
  227. char *src_data = (char*)value;
  228. char *dst_data = (char*)tag_header->value;
  229. for(DWORD i = 0; i < tag_header->length; i++) {
  230. dst_data[i] = src_data[i];
  231. }
  232. dst_data[tag_header->length] = '\0';
  233. }
  234. break;
  235. default:
  236. tag_header->value = malloc(tag_header->length * sizeof(BYTE));
  237. if(!tag_header->value) {
  238. return FALSE;
  239. }
  240. memcpy(tag_header->value, value, tag_header->length);
  241. break;
  242. }
  243. return TRUE;
  244. }
  245. return FALSE;
  246. }
  247. // --------------------------------------------------------------------------
  248. // FITAG internal helper functions
  249. // --------------------------------------------------------------------------
  250. /**
  251. Given a FREE_IMAGE_MDTYPE, calculate the size of this type in bytes unit
  252. @param type Input data type
  253. @return Returns the size of the data type, in bytes unit
  254. */
  255. unsigned
  256. FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type) {
  257. static const unsigned format_bytes[] = {
  258. 0, // FIDT_NOTYPE = 0, // placeholder
  259. 1, // FIDT_BYTE = 1, // 8-bit unsigned integer
  260. 1, // FIDT_ASCII = 2, // 8-bit bytes w/ last byte null
  261. 2, // FIDT_SHORT = 3, // 16-bit unsigned integer
  262. 4, // FIDT_LONG = 4, // 32-bit unsigned integer
  263. 8, // FIDT_RATIONAL = 5, // 64-bit unsigned fraction
  264. 1, // FIDT_SBYTE = 6, // 8-bit signed integer
  265. 1, // FIDT_UNDEFINED= 7, // 8-bit untyped data
  266. 2, // FIDT_SSHORT = 8, // 16-bit signed integer
  267. 4, // FIDT_SLONG = 9, // 32-bit signed integer
  268. 8, // FIDT_SRATIONAL= 10, // 64-bit signed fraction
  269. 4, // FIDT_FLOAT = 11, // 32-bit IEEE floating point
  270. 8, // FIDT_DOUBLE = 12, // 64-bit IEEE floating point
  271. 4, // FIDT_IFD = 13, // 32-bit unsigned integer (offset)
  272. 4, // FIDT_PALETTE = 14 // 32-bit RGBQUAD
  273. 0, // placeholder (15)
  274. 8, // FIDT_LONG8 = 16, // 64-bit unsigned integer
  275. 8, // FIDT_SLONG8 = 17, // 64-bit signed integer
  276. 8 // FIDT_IFD8 = 18 // 64-bit unsigned integer (offset)
  277. };
  278. return (type < (sizeof(format_bytes)/sizeof(format_bytes[0]))) ?
  279. format_bytes[type] : 0;
  280. }