dcp.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #include "dcp.h"
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. unsigned int
  8. get_int32(const unsigned char *buffer, size_t offset)
  9. {
  10. return (buffer[offset + 3] << 24) | (buffer[offset + 2] << 16) |
  11. (buffer[offset + 1] << 8) | (buffer[offset]);
  12. }
  13. unsigned int
  14. get_int16(const unsigned char *buffer, size_t offset)
  15. {
  16. return (buffer[offset + 1] << 8) | (buffer[offset]);
  17. }
  18. float
  19. get_float(unsigned char *buffer, size_t offset)
  20. {
  21. float f;
  22. unsigned char b[] = { buffer[offset + 0],
  23. buffer[offset + 1],
  24. buffer[offset + 2],
  25. buffer[offset + 3] };
  26. memcpy(&f, &b, sizeof(f));
  27. return f;
  28. }
  29. float
  30. get_srational(unsigned char *buffer, size_t offset)
  31. {
  32. int a = (int)get_int32(buffer, offset);
  33. int b = (int)get_int32(buffer, offset + 4);
  34. return (float)a / (float)b;
  35. }
  36. struct MPCameraCalibration
  37. parse_calibration_file(const char *path)
  38. {
  39. FILE *fp;
  40. size_t size;
  41. unsigned char *buffer;
  42. struct MPCameraCalibration result = { 0 };
  43. fp = fopen(path, "rb");
  44. if (fp == NULL) {
  45. return result;
  46. }
  47. fseek(fp, 0, SEEK_END);
  48. size = ftell(fp);
  49. fseek(fp, 0, SEEK_SET);
  50. buffer = malloc(sizeof(char) * size);
  51. size_t ret = fread(buffer, 1, size, fp);
  52. if (ret != size) {
  53. return result;
  54. }
  55. fclose(fp);
  56. if (buffer[0] != 'I' || buffer[1] != 'I') {
  57. fprintf(stderr, "Magic for DCP file incorrect\n");
  58. return result;
  59. }
  60. if (buffer[2] != 0x52 || buffer[3] != 0x43) {
  61. fprintf(stderr, "Invalid DCP version\n");
  62. return result;
  63. }
  64. unsigned int ifd0 = get_int32(buffer, 4);
  65. unsigned int tag_count = get_int16(buffer, ifd0);
  66. for (int i = 0; i < tag_count; i++) {
  67. int tag_offset = ifd0 + 2 + (i * 12);
  68. unsigned int tag = get_int16(buffer, tag_offset + 0);
  69. unsigned int type = get_int16(buffer, tag_offset + 2);
  70. unsigned int count = get_int32(buffer, tag_offset + 4);
  71. unsigned int offset = get_int32(buffer, tag_offset + 8);
  72. switch (tag) {
  73. case DCPTAG_COLOR_MATRIX_1:
  74. for (int j = 0; j < 9; j++) {
  75. float point =
  76. get_srational(buffer, offset + (j * 8));
  77. result.color_matrix_1[j] = point;
  78. }
  79. break;
  80. case DCPTAG_COLOR_MATRIX_2:
  81. for (int j = 0; j < 9; j++) {
  82. float point =
  83. get_srational(buffer, offset + (j * 8));
  84. result.color_matrix_2[j] = point;
  85. }
  86. break;
  87. case DCPTAG_FORWARD_MATRIX_1:
  88. for (int j = 0; j < 9; j++) {
  89. float point =
  90. get_srational(buffer, offset + (j * 8));
  91. result.forward_matrix_1[j] = point;
  92. }
  93. break;
  94. case DCPTAG_FORWARD_MATRIX_2:
  95. for (int j = 0; j < 9; j++) {
  96. float point =
  97. get_srational(buffer, offset + (j * 8));
  98. result.forward_matrix_2[j] = point;
  99. }
  100. break;
  101. case DCPTAG_CALIBRATION_ILLUMINANT_1:
  102. result.illuminant_1 = offset;
  103. break;
  104. case DCPTAG_CALIBRATION_ILLUMINANT_2:
  105. result.illuminant_2 = offset;
  106. break;
  107. case DCPTAG_PROFILE_TONE_CURVE:
  108. result.tone_curve = malloc(count * sizeof(float));
  109. result.tone_curve_length = count;
  110. for (int j = 0; j < count; j++) {
  111. result.tone_curve[j] =
  112. get_float(buffer, offset + (j * 4));
  113. }
  114. break;
  115. case DCPTAG_PROFILE_HUE_SAT_MAP_DIMS:
  116. result.hue_sat_map_dims[0] = get_int32(buffer, offset);
  117. result.hue_sat_map_dims[1] = get_int32(buffer, offset + 4);
  118. result.hue_sat_map_dims[2] = get_int32(buffer, offset + 8);
  119. break;
  120. case DCPTAG_PROFILE_HUE_SAT_MAP_DATA_1:
  121. result.hue_sat_map_data_1 = malloc(count * sizeof(float));
  122. for (int j = 0; j < count; j++) {
  123. result.hue_sat_map_data_1[j] =
  124. get_float(buffer, offset + (j * 4));
  125. }
  126. break;
  127. case DCPTAG_PROFILE_HUE_SAT_MAP_DATA_2:
  128. result.hue_sat_map_data_2 = malloc(count * sizeof(float));
  129. for (int j = 0; j < count; j++) {
  130. result.hue_sat_map_data_2[j] =
  131. get_float(buffer, offset + (j * 4));
  132. }
  133. break;
  134. }
  135. }
  136. return result;
  137. }
  138. bool
  139. find_calibration_by_model(char *conffile, char *model, const char *sensor)
  140. {
  141. // Check config/%model,%sensor.dcp in the current working directory
  142. sprintf(conffile, "config/%s,%s.dcp", model, sensor);
  143. if (access(conffile, F_OK) != -1) {
  144. printf("Found calibration file at %s\n", conffile);
  145. return true;
  146. }
  147. // Check user overridden /etc/megapixels/config/%model,%sensor.dcp
  148. sprintf(conffile,
  149. "%s/megapixels/config/%s,%s.dcp",
  150. "/etc",
  151. model,
  152. sensor);
  153. if (access(conffile, F_OK) != -1) {
  154. printf("Found calibration file at %s\n", conffile);
  155. return true;
  156. }
  157. // Check packaged /usr/share/megapixels/config/%model,%sensor.ini
  158. sprintf(conffile, "%s/megapixels/config/%s,%s.dcp", "/usr/share", model, sensor);
  159. if (access(conffile, F_OK) != -1) {
  160. printf("Found calibration file at %s\n", conffile);
  161. return true;
  162. }
  163. printf("No calibration found for %s,%s\n", model, sensor);
  164. return false;
  165. }
  166. bool
  167. find_calibration(char *conffile, const char *sensor)
  168. {
  169. char model[512];
  170. FILE *fp;
  171. if (access("/proc/device-tree/compatible", F_OK) == -1) {
  172. return false;
  173. }
  174. fp = fopen("/proc/device-tree/compatible", "r");
  175. char *modelptr = model;
  176. while (1) {
  177. int c = fgetc(fp);
  178. if (c == EOF) {
  179. *(modelptr) = '\0';
  180. return find_calibration_by_model(conffile, model, sensor);
  181. }
  182. *(modelptr++) = (char)c;
  183. if (c == 0) {
  184. bool res =
  185. find_calibration_by_model(conffile, model, sensor);
  186. if (res) {
  187. return true;
  188. }
  189. modelptr = model;
  190. }
  191. }
  192. }