MISR Toolkit  1.5.1
MtkResampleCubicConvolution.c
Go to the documentation of this file.
1 /*===========================================================================
2 = =
3 = MtkResampleCubicConvolution =
4 = =
5 =============================================================================
6 
7  Jet Propulsion Laboratory
8  MISR
9  MISR Toolkit
10 
11  Copyright 2008, California Institute of Technology.
12  ALL RIGHTS RESERVED.
13  U.S. Government Sponsorship acknowledged.
14 
15 ============================================================================*/
16 
17 #include "MisrReProject.h"
18 #include "MisrUtil.h"
19 #include <stdlib.h>
20 #include <math.h>
21 
22 float kernel(float d, float a) {
23  if (d >= 0.0 && d <= 1.0) {
24  return ((a+2.0) * d * d * d - (a+3.0) * d * d + 1.0);
25  }
26  if (d > 1.0 && d <= 2.0) {
27  return (a * d * d * d - 5.0 * a * d * d + 8.0 * a * d - 4.0 * a);
28  }
29  return 0.0;
30 }
31 
52  const MTKt_DataBuffer *Source,
53  const MTKt_DataBuffer *Source_mask,
54  const MTKt_DataBuffer *Line,
55  const MTKt_DataBuffer *Sample,
56  float A,
57  MTKt_DataBuffer *Resampled,
58  MTKt_DataBuffer *Resampled_mask
59 )
60 {
61  MTKt_status status_code; /* Return status of this function */
62  MTKt_status status; /* Return status of called routines. */
63  MTKt_DataBuffer resampled_tmp = MTKT_DATABUFFER_INIT;
64  /* Resampled data */
65  MTKt_DataBuffer resampled_mask_tmp = MTKT_DATABUFFER_INIT;
66  /* Valid mask for resampled data */
67  int iline;
68  int isample;
69 
70  /* ------------------------------------------------------------------ */
71  /* Argument check: Source == NULL */
72  /* Source->nline < 1 */
73  /* Source->nsample < 1 */
74  /* Source->datatype == MTKe_float */
75  /* ------------------------------------------------------------------ */
76 
77  if (Source == NULL) {
78  MTK_ERR_CODE_MSG_JUMP(MTK_NULLPTR,"Source == NULL");
79  }
80  if (Source->nline < 1) {
81  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Source->nline < 1");
82  }
83  if (Source->nsample < 1) {
84  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Source->nsample < 1");
85  }
86  if (Source->datatype != MTKe_float) {
87  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Source->datatype != MTKe_float");
88  }
89 
90  /* ------------------------------------------------------------------ */
91  /* Argument check: Source_mask == NULL */
92  /* Source_mask->nline != Source->nline */
93  /* Source_mask->nsample != Source->nsample */
94  /* Source_mask->datatype = MTKe_uint8 */
95  /* ------------------------------------------------------------------ */
96 
97  if (Source_mask == NULL) {
98  MTK_ERR_CODE_MSG_JUMP(MTK_NULLPTR,"Source_mask == NULL");
99  }
100  if (Source_mask->nline != Source->nline) {
101  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Source_mask->nline != Source->nline");
102  }
103  if (Source_mask->nsample != Source->nsample) {
104  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Source_mask->nsample != Source->nsample");
105  }
106  if (Source_mask->datatype != MTKe_uint8) {
107  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Source_mask->datatype != MTKe_uint8");
108  }
109 
110  /* ------------------------------------------------------------------ */
111  /* Argument check: Line == NULL */
112  /* Line->nline < 1 */
113  /* Line->nsample < 1 */
114  /* Line->datatype != MTKe_float */
115  /* ------------------------------------------------------------------ */
116 
117  if (Line == NULL) {
118  MTK_ERR_CODE_MSG_JUMP(MTK_NULLPTR,"Line == NULL");
119  }
120  if (Line->nline < 1) {
121  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Line->nline < 1");
122  }
123  if (Line->nsample < 1) {
124  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Line->nsample < 1");
125  }
126  if (Line->datatype != MTKe_float) {
127  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Line->datatype != MTKe_float");
128  }
129 
130  /* ------------------------------------------------------------------ */
131  /* Argument check: Sample == NULL */
132  /* Sample->nline != Line->nline */
133  /* Sample->nsample != Line->nsample */
134  /* Sample->datatype != MTKe_float */
135  /* ------------------------------------------------------------------ */
136 
137  if (Sample == NULL) {
138  MTK_ERR_CODE_MSG_JUMP(MTK_NULLPTR,"Sample == NULL");
139  }
140  if (Sample->nline != Line->nline) {
141  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Sample->nline != Line->nline");
142  }
143  if (Sample->nsample != Line->nsample) {
144  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Sample->nsample != Line->nsample");
145  }
146  if (Sample->datatype != MTKe_float) {
147  MTK_ERR_CODE_MSG_JUMP(MTK_OUTBOUNDS,"Sample->datatype != MTKe_float");
148  }
149 
150  /* ------------------------------------------------------------------ */
151  /* Argument check: A > 0.0 */
152  /* A < -1.0 */
153  /* ------------------------------------------------------------------ */
154 
155  if (A > 0.0) {
157  }
158  if (A < -1.0) {
160  }
161 
162  /* ------------------------------------------------------------------ */
163  /* Argument check: Resampled == NULL */
164  /* ------------------------------------------------------------------ */
165 
166  if (Resampled == NULL) {
167  MTK_ERR_CODE_MSG_JUMP(MTK_NULLPTR,"Resampled == NULL");
168  }
169 
170  /* ------------------------------------------------------------------ */
171  /* Argument check: Resampled_mask == NULL */
172  /* ------------------------------------------------------------------ */
173 
174  if (Resampled_mask == NULL) {
175  MTK_ERR_CODE_MSG_JUMP(MTK_NULLPTR,"Resampled_mask == NULL");
176  }
177 
178  /* ------------------------------------------------------------------ */
179  /* Allocate memory for resampled data. */
180  /* ------------------------------------------------------------------ */
181 
182  status = MtkDataBufferAllocate(Line->nline, Line->nsample,
183  MTKe_float, &resampled_tmp);
184  MTK_ERR_COND_JUMP(status);
185 
186  status = MtkDataBufferAllocate(Line->nline, Line->nsample,
187  MTKe_uint8, &resampled_mask_tmp);
188  MTK_ERR_COND_JUMP(status);
189 
190  /* ------------------------------------------------------------------ */
191  /* For each location to resample... */
192  /* ------------------------------------------------------------------ */
193 
194  for (iline = 0; iline < Line->nline ; iline++) {
195  for (isample = 0; isample < Line->nsample; isample++) {
196  float pline = Line->data.f[iline][isample];
197  /* Location to resample. */
198  float psample = Sample->data.f[iline][isample];
199  /* Location to resample. */
200  int pline_int = (int)floor(pline + 0.5);
201  /* Integer pixel location containing location
202  to resample. */
203  int psample_int = (int)floor(psample + 0.5);
204  /* Integer pixel location containing location
205  to resample. */
206  float missing_default; /* Default value to use for missing data. */
207  int start_line; /* Convolution window start. */
208  int start_sample; /* Convolution window start. */
209  int end_line; /* Convolution window end. */
210  int end_sample; /* Convolution window end. */
211  int wline; /* Iterator for convolution window. */
212  int wsample; /* Iterator for convolution window. */
213  float resampled_value = 0.0;
214  /* Resampled value. */
215 
216  /* ------------------------------------------------------------------ */
217  /* If the source pixel containing this point is not valid, then skip */
218  /* this point. */
219  /* ------------------------------------------------------------------ */
220 
221  if (pline_int < 0 || pline_int >= Source->nline ||
222  psample_int < 0 || psample_int >= Source->nsample) {
223  continue;
224  }
225 
226  if (!Source_mask->data.u8[pline_int][psample_int]) {
227  continue;
228  }
229 
230  /* ------------------------------------------------------------------ */
231  /* Use the source pixel containing this point at the default value */
232  /* for missing data in the convolution window. */
233  /* ------------------------------------------------------------------ */
234 
235  missing_default = Source->data.f[pline_int][psample_int];
236 
237  /* ------------------------------------------------------------------ */
238  /* Determine the convolution window for resampling this point. */
239  /* ------------------------------------------------------------------ */
240 
241  start_line = (int)floor(pline-1);
242  start_sample = (int)floor(psample-1);
243  end_line = start_line + 4;
244  end_sample = start_sample + 4;
245 
246  /* ------------------------------------------------------------------ */
247  /* For each point in the convolution window... */
248  /* ------------------------------------------------------------------ */
249 
250  for (wline = start_line ; wline < end_line; wline++) {
251  for (wsample = start_sample ; wsample < end_sample; wsample++) {
252  float wvalue; /* Source value at this point
253  in the convolution window. */
254  int valid = 1; /* Flag indicating if data is valid
255  at this point in the convolution
256  window. */
257  float dline; /* Distance from this point to interpolation
258  point. */
259  float dsample; /* Distance from this point to interpolation
260  point. */
261 
262  /* ------------------------------------------------------------------ */
263  /* Get the source data value for this point. If the point is not */
264  /* valid use the default for missing data (above). */
265  /* ------------------------------------------------------------------ */
266 
267  if (wline < 0 || wline >= Source->nline ||
268  wsample < 0 || wsample >= Source->nsample) {
269  valid = 0;
270  } else {
271  if (!Source_mask->data.u8[wline][wsample]) {
272  valid = 0;
273  }
274  }
275 
276  if (valid) {
277  wvalue = Source->data.f[wline][wsample];
278  } else {
279  wvalue = missing_default;
280  }
281 
282  /* ------------------------------------------------------------------ */
283  /* Calculate distance from this point to the interpolation point. */
284  /* ------------------------------------------------------------------ */
285 
286  dline = fabs((float)wline - pline);
287  dsample = fabs((float)wsample - psample);
288 
289  /* ------------------------------------------------------------------ */
290  /* Calculate contribution to resampled value for this point. */
291  /* ------------------------------------------------------------------ */
292 
293  resampled_value += wvalue * kernel(dline,A) * kernel(dsample,A);
294 
295  /* ------------------------------------------------------------------ */
296  /* End loop for each point in convolution window. */
297  /* ------------------------------------------------------------------ */
298 
299  }
300  }
301 
302  /* ------------------------------------------------------------------ */
303  /* Set resampled value at this point. */
304  /* ------------------------------------------------------------------ */
305 
306  resampled_tmp.data.f[iline][isample] = resampled_value;
307  resampled_mask_tmp.data.u8[iline][isample] = 1;
308 
309  /* ------------------------------------------------------------------ */
310  /* End loop for each location to resample. */
311  /* ------------------------------------------------------------------ */
312 
313  }
314  }
315 
316  *Resampled = resampled_tmp;
317  *Resampled_mask = resampled_mask_tmp;
318  return MTK_SUCCESS;
319 
320 ERROR_HANDLE:
321  MtkDataBufferFree(&resampled_tmp);
322  MtkDataBufferFree(&resampled_mask_tmp);
323  return status_code;
324 }
325 
326 
MTKt_status MtkDataBufferAllocate(int nline, int nsample, MTKt_DataType datatype, MTKt_DataBuffer *databuf)
Allocate Data Buffer.
MTKt_DataBufferType data
Definition: MisrUtil.h:104
2-dimensional Data Buffer
Definition: MisrUtil.h:98
MTKt_float ** f
Definition: MisrUtil.h:93
float kernel(float d, float a)
#define MTKT_DATABUFFER_INIT
Definition: MisrUtil.h:109
MTKt_status MtkDataBufferFree(MTKt_DataBuffer *databuf)
Free data buffer.
MTKt_DataType datatype
Definition: MisrUtil.h:102
MTKt_uint8 ** u8
Definition: MisrUtil.h:86
MTKt_status MtkResampleCubicConvolution(const MTKt_DataBuffer *Source, const MTKt_DataBuffer *Source_mask, const MTKt_DataBuffer *Line, const MTKt_DataBuffer *Sample, float A, MTKt_DataBuffer *Resampled, MTKt_DataBuffer *Resampled_mask)
Resample source data at the given coordinates using interpolation by cubic convolution.
#define MTK_ERR_CODE_MSG_JUMP(code, msg)
Definition: MisrError.h:181
#define MTK_ERR_COND_JUMP(code)
Definition: MisrError.h:188
MTKt_status
Definition: MisrError.h:11

MISR Toolkit - Copyright © 2005 - 2020 Jet Propulsion Laboratory
Generated on Fri Jun 19 2020 22:49:51