File: | src/unrrdu/jhisto.c |
Location: | line 156, column 7 |
Description: | Potential leak of memory pointed to by 'npass' |
1 | /* | |||
2 | Teem: Tools to process and visualize scientific data and images . | |||
3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||
4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||
5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||
6 | ||||
7 | This library is free software; you can redistribute it and/or | |||
8 | modify it under the terms of the GNU Lesser General Public License | |||
9 | (LGPL) as published by the Free Software Foundation; either | |||
10 | version 2.1 of the License, or (at your option) any later version. | |||
11 | The terms of redistributing and/or modifying this software also | |||
12 | include exceptions to the LGPL that facilitate static linking. | |||
13 | ||||
14 | This library is distributed in the hope that it will be useful, | |||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | Lesser General Public License for more details. | |||
18 | ||||
19 | You should have received a copy of the GNU Lesser General Public License | |||
20 | along with this library; if not, write to Free Software Foundation, Inc., | |||
21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
22 | */ | |||
23 | ||||
24 | #include "unrrdu.h" | |||
25 | #include "privateUnrrdu.h" | |||
26 | ||||
27 | #define INFO"Create joint histogram of two or more nrrds" "Create joint histogram of two or more nrrds" | |||
28 | static const char *_unrrdu_jhistoInfoL = | |||
29 | (INFO"Create joint histogram of two or more nrrds" | |||
30 | ". Each axis of the output corresponds to one of the " | |||
31 | "input nrrds, and each bin in the output records the " | |||
32 | "number of corresponding positions in the inputs with " | |||
33 | "a combination of values represented by the coordinates " | |||
34 | "of the bin.\n " | |||
35 | "* Uses nrrdHistoJoint"); | |||
36 | ||||
37 | int | |||
38 | unrrdu_jhistoMain(int argc, const char **argv, const char *me, | |||
39 | hestParm *hparm) { | |||
40 | hestOpt *opt = NULL((void*)0); | |||
41 | char *out, *err; | |||
42 | Nrrd **nin, **npass; | |||
43 | Nrrd *nout, *nwght; | |||
44 | size_t *bin; | |||
45 | int type, clamp[NRRD_DIM_MAX16], pret; | |||
46 | unsigned int minLen, maxLen, ninLen, binLen, ai, diceax; | |||
47 | airArray *mop; | |||
48 | double *min, *max; | |||
49 | NrrdRange **range; | |||
50 | ||||
51 | hestOptAdd(&opt, "b,bin", "bins0 bins1", airTypeSize_t, 2, -1, &bin, NULL((void*)0), | |||
52 | "bins<i> is the number of bins to use along axis i (of joint " | |||
53 | "histogram), which represents the values of nin<i> ", | |||
54 | &binLen); | |||
55 | hestOptAdd(&opt, "w,weight", "nweight", airTypeOther, 1, 1, &nwght, "", | |||
56 | "how to weigh contributions to joint histogram. By default " | |||
57 | "(not using this option), the increment is one bin count per " | |||
58 | "sample, but by giving a nrrd, the value in the nrrd at the " | |||
59 | "corresponding location will be the bin count increment ", | |||
60 | NULL((void*)0), NULL((void*)0), nrrdHestNrrd); | |||
61 | hestOptAdd(&opt, "min,minimum", "min0 min1", airTypeDouble, 2, -1, | |||
62 | &min, "nan nan", | |||
63 | "min<i> is the low range of values to be quantized along " | |||
64 | "axis i; use \"nan\" to represent lowest value present ", | |||
65 | &minLen); | |||
66 | hestOptAdd(&opt, "max,maximum", "max0 max1", airTypeDouble, 2, -1, | |||
67 | &max, "nan nan", | |||
68 | "max<i> is the high range of values to be quantized along " | |||
69 | "axis i; use \"nan\" to represent highest value present ", | |||
70 | &maxLen); | |||
71 | OPT_ADD_TYPE(type, "type to use for output (the type used to store hit "hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType) | |||
72 | "counts in the joint histogram). Clamping is done on hit "hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType) | |||
73 | "counts so that they never overflow a fixed-point type",hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType) | |||
74 | "uint")hestOptAdd(&opt, "t,type", "type", airTypeEnum, 1, 1, & (type), "uint", "type to use for output (the type used to store hit " "counts in the joint histogram). Clamping is done on hit " "counts so that they never overflow a fixed-point type" , ((void*)0), nrrdType); | |||
75 | hestOptAdd(&opt, "i,input", "nin0 [nin1]", airTypeOther, 1, -1, &nin, "-", | |||
76 | "list of nrrds (one for each axis of joint histogram), " | |||
77 | "or, single nrrd that will be sliced along specified axis.", | |||
78 | &ninLen, NULL((void*)0), nrrdHestNrrd); | |||
79 | hestOptAdd(&opt, "a,axis", "axis", airTypeUInt, 1, 1, &diceax, "0", | |||
80 | "axis to slice along when working with single nrrd. "); | |||
81 | OPT_ADD_NOUT(out, "output nrrd")hestOptAdd(&opt, "o,output", "nout", airTypeString, 1, 1, &(out), "-", "output nrrd"); | |||
82 | ||||
83 | mop = airMopNew(); | |||
84 | airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); | |||
85 | ||||
86 | USAGE(_unrrdu_jhistoInfoL)if (!argc) { hestInfo(__stdoutp, me, (_unrrdu_jhistoInfoL), hparm ); hestUsage(__stdoutp, opt, me, hparm); hestGlossary(__stdoutp , opt, hparm); airMopError(mop); return 0; }; | |||
87 | PARSE()if ((pret=hestParse(opt, argc, argv, &err, hparm))) { if ( 1 == pret || 2 == pret) { if (!(getenv("UNRRDU_QUIET_QUIT") && airEndsWith(err, "[nrrd] _nrrdRead: immediately hit EOF" "\n" ))) { fprintf(__stderrp, "%s: %s\n", me, err); free(err); hestUsage (__stderrp, opt, me, hparm); hestGlossary(__stderrp, opt, hparm ); } airMopError(mop); return 1; } else { exit(1); } }; | |||
88 | airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); | |||
89 | ||||
90 | if (ninLen == 1) { | |||
| ||||
91 | /* Slice a nrrd on the fly */ | |||
92 | size_t asize; | |||
93 | if (!( diceax <= nin[0]->dim-1 )) { | |||
94 | fprintf(stderr__stderrp, "%s: slice axis %u not valid for single %u-D nrrd", | |||
95 | me, diceax, nin[0]->dim); | |||
96 | airMopError(mop); | |||
97 | return 1; | |||
98 | } | |||
99 | asize = nin[0]->axis[diceax].size; | |||
100 | if (asize != binLen) { | |||
101 | fprintf(stderr__stderrp, | |||
102 | "%s: size (%u) of slice axis %u != # bins given (%u)\n", me, | |||
103 | AIR_CAST(unsigned int, asize)((unsigned int)(asize)), diceax, | |||
104 | AIR_CAST(unsigned int, binLen)((unsigned int)(binLen))); | |||
105 | airMopError(mop); | |||
106 | return 1; | |||
107 | } | |||
108 | /* create buffer for slices */ | |||
109 | if (!( npass = AIR_CALLOC(binLen, Nrrd*)(Nrrd**)(calloc((binLen), sizeof(Nrrd*))) )) { | |||
110 | fprintf(stderr__stderrp, "%s: couldn't allocate nrrd array (size %u)\n", | |||
111 | me, binLen); | |||
112 | airMopError(mop); return 1; | |||
113 | } | |||
114 | airMopMem(mop, &npass, airMopAlways); | |||
115 | /* slice this nrrd, allocate new nrrds, and store the slices in nin */ | |||
116 | for (ai=0; ai<binLen; ai++) { | |||
117 | /* Allocate each slice nrrd */ | |||
118 | if (!( npass[ai] = nrrdNew() )) { | |||
119 | fprintf(stderr__stderrp, "%s: couldn't allocate npass[%u]\n", me, ai); | |||
120 | airMopError(mop); return 1; | |||
121 | } | |||
122 | airMopAdd(mop, npass[ai], (airMopper)nrrdNuke, airMopAlways); | |||
123 | if (nrrdSlice(npass[ai], nin[0], diceax, ai)) { | |||
124 | airMopAdd(mop, err = biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways); | |||
125 | fprintf(stderr__stderrp, "%s: error slicing:\n%s", me, err); | |||
126 | airMopError(mop); return 1; | |||
127 | } | |||
128 | } | |||
129 | } else { | |||
130 | /* we were given multiple nrrds */ | |||
131 | if (ninLen != binLen) { | |||
132 | fprintf(stderr__stderrp, | |||
133 | "%s: # input nrrds (%u) != # bin specifications (%u)\n", me, | |||
134 | AIR_CAST(unsigned int, ninLen)((unsigned int)(ninLen)), AIR_CAST(unsigned int, binLen)((unsigned int)(binLen))); | |||
135 | airMopError(mop); | |||
136 | return 1; | |||
137 | } | |||
138 | /* create buffer for slices (HEY copy and paste) */ | |||
139 | if (!( npass = AIR_CALLOC(binLen, Nrrd*)(Nrrd**)(calloc((binLen), sizeof(Nrrd*))) )) { | |||
140 | fprintf(stderr__stderrp, "%s: couldn't allocate nrrd array (size %u)\n", | |||
141 | me, binLen); | |||
142 | airMopError(mop); return 1; | |||
143 | } | |||
144 | for (ai=0; ai<binLen; ai++) { | |||
145 | npass[ai] = nin[ai]; | |||
146 | } | |||
147 | } | |||
148 | range = AIR_CALLOC(binLen, NrrdRange*)(NrrdRange**)(calloc((binLen), sizeof(NrrdRange*))); | |||
149 | airMopAdd(mop, range, airFree, airMopAlways); | |||
150 | for (ai=0; ai<binLen; ai++) { | |||
151 | range[ai] = nrrdRangeNew(AIR_NAN(airFloatQNaN.f), AIR_NAN(airFloatQNaN.f)); | |||
152 | airMopAdd(mop, range[ai], (airMopper)nrrdRangeNix, airMopAlways); | |||
153 | } | |||
154 | if (2 != minLen || (AIR_EXISTS(min[0])(((int)(!((min[0]) - (min[0]))))) || AIR_EXISTS(min[1])(((int)(!((min[1]) - (min[1]))))))) { | |||
155 | if (minLen != binLen) { | |||
156 | fprintf(stderr__stderrp, "%s: # mins (%d) != # input nrrds (%d)\n", me, | |||
| ||||
157 | minLen, binLen); | |||
158 | airMopError(mop); return 1; | |||
159 | } | |||
160 | for (ai=0; ai<binLen; ai++) { | |||
161 | range[ai]->min = min[ai]; | |||
162 | } | |||
163 | } | |||
164 | if (2 != maxLen || (AIR_EXISTS(max[0])(((int)(!((max[0]) - (max[0]))))) || AIR_EXISTS(max[1])(((int)(!((max[1]) - (max[1]))))))) { | |||
165 | if (maxLen != binLen) { | |||
166 | fprintf(stderr__stderrp, "%s: # maxs (%d) != # input nrrds (%d)\n", me, | |||
167 | maxLen, binLen); | |||
168 | airMopError(mop); return 1; | |||
169 | } | |||
170 | for (ai=0; ai<binLen; ai++) { | |||
171 | range[ai]->max = max[ai]; | |||
172 | } | |||
173 | } | |||
174 | for (ai=0; ai<binLen; ai++) { | |||
175 | clamp[ai] = 0; | |||
176 | } | |||
177 | ||||
178 | nout = nrrdNew(); | |||
179 | airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); | |||
180 | ||||
181 | if (nrrdHistoJoint(nout, (const Nrrd*const*)npass, | |||
182 | (const NrrdRange*const*)range, | |||
183 | binLen, nwght, bin, type, clamp)) { | |||
184 | airMopAdd(mop, err = biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways); | |||
185 | fprintf(stderr__stderrp, "%s: error doing joint histogram:\n%s", me, err); | |||
186 | airMopError(mop); | |||
187 | return 1; | |||
188 | } | |||
189 | ||||
190 | SAVE(out, nout, NULL)if (nrrdSave((out), (nout), (((void*)0)))) { airMopAdd(mop, err = biffGetDone(nrrdBiffKey), airFree, airMopAlways); fprintf( __stderrp, "%s: error saving nrrd to \"%s\":\n%s\n", me, (out ), err); airMopError(mop); return 1; }; | |||
191 | ||||
192 | airMopOkay(mop); | |||
193 | return 0; | |||
194 | } | |||
195 | ||||
196 | UNRRDU_CMD(jhisto, INFO)unrrduCmd unrrdu_jhistoCmd = { "jhisto", "Create joint histogram of two or more nrrds" , unrrdu_jhistoMain, 0 }; |