You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

320 lines
7.5 KiB

  1. /*
  2. * Aptdec
  3. * Copyright (c) 2004 by Thierry Leconte (F4DWV)
  4. *
  5. * $Id$
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Library General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <sndfile.h>
  25. #include <math.h>
  26. #include "offsets.h"
  27. #include "messages.h"
  28. #define REGORDER 3
  29. typedef struct {
  30. double cf[REGORDER + 1];
  31. } rgparam;
  32. static void rgcomp(double x[16], rgparam * rgpr) {
  33. //const double y[9] = { 0.106, 0.215, 0.324, 0.433, 0.542, 0.652, 0.78, 0.87, 0.0 };
  34. const double y[9] = { 31.07, 63.02, 94.96, 126.9, 158.86, 191.1, 228.62, 255.0, 0.0 };
  35. extern void polyreg(const int m, const int n, const double x[], const double y[], double c[]);
  36. polyreg(REGORDER, 9, x, y, rgpr -> cf);
  37. }
  38. static double rgcal(float x, rgparam * rgpr) {
  39. double y, p;
  40. int i;
  41. for (i = 0, y = 0.0, p = 1.0; i < REGORDER + 1; i++) {
  42. y += rgpr->cf[i] * p;
  43. p = p * x;
  44. }
  45. return(y);
  46. }
  47. static double tele[16];
  48. static double Cs;
  49. static int nbtele;
  50. // Contrast enchance
  51. void equalise(float **prow, int nrow, int offset, int telestart, rgparam regr[30]){
  52. for (int n = 0; n < nrow; n++) {
  53. float *pixelv;
  54. int i;
  55. pixelv = prow[n];
  56. for (i = 0; i < CH_WIDTH; i++) {
  57. float pv;
  58. int k, kof;
  59. pv = pixelv[i + offset];
  60. k = (n - telestart) / 128;
  61. if (k >= nbtele)
  62. k = nbtele - 1;
  63. kof = (n - telestart) % 128;
  64. if (kof < 64) {
  65. if (k < 1) {
  66. pv = rgcal(pv, &(regr[k]));
  67. } else {
  68. pv = rgcal(pv, &(regr[k])) * (64 + kof) / 128.0 + rgcal(pv, &(regr[k - 1])) * (64 - kof) / 128.0;
  69. }
  70. } else {
  71. if ((k + 1) >= nbtele) {
  72. pv = rgcal(pv, &(regr[k]));
  73. } else {
  74. pv = rgcal(pv, &(regr[k])) * (192 - kof) / 128.0 + rgcal(pv, &(regr[k + 1])) * (kof - 64) / 128.0;
  75. }
  76. }
  77. pv = CLIP(pv, 0, 255);
  78. pixelv[i + offset] = pv;
  79. }
  80. }
  81. }
  82. // Get telemetry data for thermal calibration
  83. int calibrate(float **prow, int nrow, int offset, int contrastBoost) {
  84. double teleline[3000];
  85. double wedge[16];
  86. rgparam regr[30];
  87. int n;
  88. int k;
  89. int mtelestart, telestart;
  90. int channel = -1;
  91. float max;
  92. // Extract telemetry data, for a single pixel row
  93. for (n = 0; n < nrow; n++) {
  94. int i;
  95. teleline[n] = 0.0;
  96. // Average the 40 center pixels from the telemetry block
  97. for (i = 3; i < 43; i++) {
  98. teleline[n] += prow[n][i + offset + CH_WIDTH];
  99. }
  100. // Compute the average
  101. teleline[n] /= 40.0;
  102. }
  103. // A good minimum amount of pixels to find the telemetry start
  104. if (nrow < 192) {
  105. fprintf(stderr, ERR_TELE_ROW);
  106. return(0);
  107. }
  108. // Find the biggest contrast in the telemetry
  109. max = 0.0;
  110. mtelestart = 0;
  111. // Only check the center of the image, where the signal is most likely strongest
  112. for (n = nrow / 3 - 64; n < 2 * nrow / 3 - 64; n++) {
  113. float df;
  114. // Calculate the contrast, in other words
  115. // (sum 4px below) / (sum 4px above)
  116. df = (teleline[n - 4] + teleline[n - 3] + teleline[n - 2] +
  117. teleline[n - 1]) / (teleline[n] + teleline[n + 1] +
  118. teleline[n + 2] + teleline[n + 3]);
  119. // Find the biggest contrast
  120. if (df > max) {
  121. mtelestart = n;
  122. max = df;
  123. }
  124. }
  125. // Calculate relative offset
  126. telestart = (mtelestart - 64) % 128;
  127. // If we cannot find the start of the telemetry or if there is not enough of it
  128. if (mtelestart < 0 || nrow < telestart + 128) {
  129. fprintf(stderr, ERR_TELE_ROW);
  130. return(0);
  131. }
  132. /* Compute wedges and regression
  133. *
  134. * This loop loops every 128 pixels after the relative telemetry start.
  135. * Gets the values of where the wedges should be and then feeds into a
  136. * regression algorithm which calculates the amount of noise on the
  137. * telemetry.
  138. *
  139. * It then finds the part of the telemetry data with the least noise and
  140. * turns it into digital values.
  141. */
  142. for (n = telestart, k = 0; n < nrow - 128; n += 128, k++) {
  143. int j;
  144. // Loop through the 16 wedges
  145. for (j = 0; j < 16; j++) {
  146. int i;
  147. wedge[j] = 0.0;
  148. // Center 6 pixels
  149. for (i = 1; i < 7; i++){
  150. wedge[j] += teleline[(j * 8) + n + i];
  151. }
  152. // Average
  153. wedge[j] /= 6;
  154. }
  155. rgcomp(wedge, &(regr[k]));
  156. if (k == nrow / 256) {
  157. int i, l;
  158. // Telemetry calibration
  159. for (j = 0; j < 16; j++) {
  160. tele[j] = rgcal(wedge[j], &(regr[k]));
  161. }
  162. // Channel ID
  163. for (j = 0, max = 10000.0, channel = -1; j < 6; j++) {
  164. float df;
  165. df = wedge[15] - wedge[j];
  166. df = df * df;
  167. if (df < max) {
  168. channel = j;
  169. max = df;
  170. }
  171. }
  172. /* Cs computation */
  173. for (Cs = 0.0, i = 0, j = n; j < n + 128; j++) {
  174. double csline;
  175. for (csline = 0.0, l = 3; l < 43; l++)
  176. csline += prow[n][l + offset -SPC_WIDTH];
  177. csline /= 40.0;
  178. if (csline > 50.0) {
  179. Cs += csline;
  180. i++;
  181. }
  182. }
  183. Cs /= i;
  184. Cs = rgcal(Cs, &(regr[k]));
  185. }
  186. }
  187. nbtele = k;
  188. // Image contrast
  189. if(contrastBoost) equalise(prow, nrow, offset, telestart, regr);
  190. return(channel + 1);
  191. }
  192. // --- Temperature Calibration --- //
  193. extern int satnum;
  194. #include "satcal.h"
  195. typedef struct {
  196. double Nbb;
  197. double Cs;
  198. double Cb;
  199. int ch;
  200. } tempparam;
  201. /* temperature compensation for IR channel */
  202. static void tempcomp(double t[16], int ch, tempparam * tpr) {
  203. double Tbb, T[4];
  204. double C;
  205. int n;
  206. tpr -> ch = ch - 4;
  207. /* compute equivalent T black body */
  208. for (n = 0; n < 4; n++) {
  209. float d0, d1, d2;
  210. C = t[9 + n] * 4.0;
  211. d0 = satcal[satnum].d[n][0];
  212. d1 = satcal[satnum].d[n][1];
  213. d2 = satcal[satnum].d[n][2];
  214. T[n] = d0;
  215. T[n] += d1 * C;
  216. C = C * C;
  217. T[n] += d2 * C;
  218. }
  219. Tbb = (T[0] + T[1] + T[2] + T[3]) / 4.0;
  220. Tbb = satcal[satnum].rad[tpr->ch].A + satcal[satnum].rad[tpr->ch].B * Tbb;
  221. /* compute radiance Black body */
  222. C = satcal[satnum].rad[tpr->ch].vc;
  223. tpr->Nbb = c1 * C * C * C / (expm1(c2 * C / Tbb));
  224. /* store Count Blackbody and space */
  225. tpr->Cs = Cs * 4.0;
  226. tpr->Cb = t[14] * 4.0;
  227. }
  228. static double tempcal(float Ce, tempparam * rgpr) {
  229. double Nl, Nc, Ns, Ne;
  230. double T, vc;
  231. Ns = satcal[satnum].cor[rgpr->ch].Ns;
  232. Nl = Ns + (rgpr->Nbb - Ns) * (rgpr->Cs - Ce * 4.0) / (rgpr->Cs - rgpr->Cb);
  233. Nc = satcal[satnum].cor[rgpr->ch].b[0] +
  234. satcal[satnum].cor[rgpr->ch].b[1] * Nl +
  235. satcal[satnum].cor[rgpr->ch].b[2] * Nl * Nl;
  236. Ne = Nl + Nc;
  237. vc = satcal[satnum].rad[rgpr->ch].vc;
  238. T = c2 * vc / log1p(c1 * vc * vc * vc / Ne);
  239. T = (T - satcal[satnum].rad[rgpr->ch].A) / satcal[satnum].rad[rgpr->ch].B;
  240. /* rescale to range 0-255 for -60 +40 'C */
  241. T = (T - 273.15 + 60.0) / 100.0 * 256.0;
  242. return(T);
  243. }
  244. void Temperature(float **prow, int nrow, int channel, int offset) {
  245. tempparam temp;
  246. int n;
  247. printf("Temperature... ");
  248. fflush(stdout);
  249. tempcomp(tele, channel, &temp);
  250. for (n = 0; n < nrow; n++) {
  251. float *pixelv;
  252. int i;
  253. pixelv = prow[n];
  254. for (i = 0; i < CH_WIDTH; i++) {
  255. float pv;
  256. pv = tempcal(pixelv[i + offset], &temp);
  257. pv = CLIP(pv, 0, 255);
  258. pixelv[i + offset] = pv;
  259. }
  260. }
  261. printf("Done\n");
  262. }