|
From: <kin...@us...> - 2003-12-19 03:52:33
|
Update of /cvsroot/teem/teem/src/nrrd
In directory sc8-pr-cvs1:/tmp/cvs-serv18521
Modified Files:
encoding.c encodingAscii.c encodingBzip2.c encodingGzip.c
encodingHex.c encodingRaw.c formatPNG.c formatText.c
methodsNrrd.c nrrd.h privateNrrd.h read.c
Log Message:
This is a functionality change relating to use of pre-allocated data
in nrrdRead(). There is no public API change.
Prior to this change, a nrrd that was already already valid and allocated
with some amount of memory would be stripped of that memory (the memory
was freed) by nrrdRead(). The various encodings would allocate new memory
via _nrrdCalloc. This meant that even when the caller to nrrdRead knew
in advance that the given nrrd could hold the data that would be read from
the given file, the memory was freed and re-allocated. This presented a
problem for ITK's use of nrrd in NrrdIO.
Now, near the beginning of nrrdRead(), any existing memory (via nrrd->data
being non-NULL) and its allocated size (via nrrd->type and nrrd->axis[i].size)
are remembered in the NrrdIoState struct (void *oldData, size_t oldDataSize),
which is then referred to via _nrrdCalloc, or directly by the format's reader.
The result is that existing memory is used whenever the allocated size
matches the size described by the new nrrd's header. This change has been
made in all existing formats, which involved more modifications for
formatText.c and formatPNG.c, since these do not use (nor should they)
functions in the existing encodingXXX.c files.
Near the end of nrrdRead(), the old data is freed if it turns out that it
wasn't re-used.
Index: encoding.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/encoding.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** encoding.c 29 Nov 2003 08:16:07 -0000 1.2
--- encoding.c 19 Dec 2003 03:52:29 -0000 1.3
***************
*** 27,33 ****
**
** what a NrrdEncoding has to do:
! ** -- allocate nrrd->data for the amount of space required (very likely
! ** via _nrrdCalloc). That this has to be done here is because of the
! ** restrictions imposed by DirectIO (used by nrrdEncodingRaw).
** -- do nothing on read/write if nio->skipData
** -- read data from nio->dataFile into nrrd->data, or vice versa.
--- 27,34 ----
**
** what a NrrdEncoding has to do:
! ** -- allocate nrrd->data for the amount of space required, or use existing
! ** memory described by nio->oldData and nio->oldDataSize. This is most
! ** easily done via _nrrdCalloc(). Allocation has to be done here because
! ** of the restrictions imposed by DirectIO (used by nrrdEncodingRaw).
** -- do nothing on read/write if nio->skipData
** -- read data from nio->dataFile into nrrd->data, or vice versa.
Index: encodingAscii.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/encodingAscii.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** encodingAscii.c 29 Nov 2003 08:16:07 -0000 1.3
--- encodingAscii.c 19 Dec 2003 03:52:29 -0000 1.4
***************
*** 44,48 ****
}
num = nrrdElementNumber(nrrd);
! if (_nrrdCalloc(nrrd)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
--- 44,48 ----
}
num = nrrdElementNumber(nrrd);
! if (_nrrdCalloc(nrrd, nio)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
Index: encodingBzip2.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/encodingBzip2.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** encodingBzip2.c 29 Nov 2003 08:16:07 -0000 1.3
--- encodingBzip2.c 19 Dec 2003 03:52:29 -0000 1.4
***************
*** 57,61 ****
/* Allocate memory for the incoming data. */
! if (_nrrdCalloc(nrrd)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
--- 57,61 ----
/* Allocate memory for the incoming data. */
! if (_nrrdCalloc(nrrd, nio)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
Index: encodingGzip.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/encodingGzip.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** encodingGzip.c 29 Nov 2003 08:16:07 -0000 1.3
--- encodingGzip.c 19 Dec 2003 03:52:29 -0000 1.4
***************
*** 54,58 ****
/* Allocate memory for the incoming data. */
! if (_nrrdCalloc(nrrd)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
--- 54,58 ----
/* Allocate memory for the incoming data. */
! if (_nrrdCalloc(nrrd, nio)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
Index: encodingHex.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/encodingHex.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** encodingHex.c 29 Nov 2003 08:16:07 -0000 1.4
--- encodingHex.c 19 Dec 2003 03:52:29 -0000 1.5
***************
*** 67,71 ****
return 0;
}
! if (_nrrdCalloc(nrrd)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
--- 67,71 ----
return 0;
}
! if (_nrrdCalloc(nrrd, nio)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
Index: encodingRaw.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/encodingRaw.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** encodingRaw.c 29 Nov 2003 08:16:07 -0000 1.4
--- encodingRaw.c 19 Dec 2003 03:52:29 -0000 1.5
***************
*** 51,55 ****
dio = airNoDio_format;
}
! if (airNoDio_okay == dio) {
if (nio->format->usesDIO) {
if (3 <= nrrdStateVerboseIO) {
--- 51,59 ----
dio = airNoDio_format;
}
! /* Notice that DIO will NOT be used if we are given pre-allocated memory
! that fits the new nrrd. The memory could be used if we were to check
! its alignment here, but there currently is a laziness problem */
! if (airNoDio_okay == dio
! && !(nio->oldData && bsize == nio->oldDataSize) ) {
if (nio->format->usesDIO) {
if (3 <= nrrdStateVerboseIO) {
***************
*** 68,72 ****
}
} else {
! if (_nrrdCalloc(nrrd)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
--- 72,82 ----
}
} else {
! if (airNoDio_okay == dio && nio->oldData && bsize == nio->oldDataSize) {
! if (nrrdStateVerboseIO) {
! fprintf(stderr,
! "%s: sorry, too lazy to use existing memory for DIO\n", me);
! }
! }
! if (_nrrdCalloc(nrrd, nio)) {
sprintf(err, "%s: couldn't allocate sufficient memory for all data", me);
biffAdd(NRRD, err); return 1;
Index: formatPNG.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/formatPNG.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** formatPNG.c 29 Nov 2003 08:16:07 -0000 1.3
--- formatPNG.c 19 Dec 2003 03:52:29 -0000 1.4
***************
*** 165,169 ****
png_uint_32 width, height, rowsize;
png_text* txt;
! int depth, type, i, channels, numtxt;
int ntype, ndim, nsize[3];
#endif /* TEEM_PNG */
--- 165,169 ----
png_uint_32 width, height, rowsize;
png_text* txt;
! int depth, type, i, channels, numtxt, ret;
int ntype, ndim, nsize[3];
#endif /* TEEM_PNG */
***************
*** 246,262 ****
ntype = depth > 8 ? nrrdTypeUShort : nrrdTypeUChar;
switch (type) {
! case PNG_COLOR_TYPE_GRAY:
ndim = 2; nsize[0] = width; nsize[1] = height;
break;
! case PNG_COLOR_TYPE_GRAY_ALPHA:
ndim = 3; nsize[0] = 2; nsize[1] = width; nsize[2] = height;
break;
! case PNG_COLOR_TYPE_RGB:
ndim = 3; nsize[0] = 3; nsize[1] = width; nsize[2] = height;
break;
! case PNG_COLOR_TYPE_RGB_ALPHA:
ndim = 3; nsize[0] = 4; nsize[1] = width; nsize[2] = height;
break;
! case PNG_COLOR_TYPE_PALETTE:
/* TODO: merge this with the outer switch, needs to be tested */
channels = png_get_channels(png, info);
--- 246,263 ----
ntype = depth > 8 ? nrrdTypeUShort : nrrdTypeUChar;
switch (type) {
! case PNG_COLOR_TYPE_GRAY:
ndim = 2; nsize[0] = width; nsize[1] = height;
+ nsize[2] = 1; /* to simplify code below */
break;
! case PNG_COLOR_TYPE_GRAY_ALPHA:
ndim = 3; nsize[0] = 2; nsize[1] = width; nsize[2] = height;
break;
! case PNG_COLOR_TYPE_RGB:
ndim = 3; nsize[0] = 3; nsize[1] = width; nsize[2] = height;
break;
! case PNG_COLOR_TYPE_RGB_ALPHA:
ndim = 3; nsize[0] = 4; nsize[1] = width; nsize[2] = height;
break;
! case PNG_COLOR_TYPE_PALETTE:
/* TODO: merge this with the outer switch, needs to be tested */
channels = png_get_channels(png, info);
***************
*** 267,271 ****
}
break;
! default:
png_destroy_read_struct(&png, &info, NULL);
sprintf(err, "%s: unknown png type: %d", me, type);
--- 268,272 ----
}
break;
! default:
png_destroy_read_struct(&png, &info, NULL);
sprintf(err, "%s: unknown png type: %d", me, type);
***************
*** 273,277 ****
break;
}
! if (nrrdMaybeAlloc_nva(nrrd, ntype, ndim, nsize)) {
png_destroy_read_struct(&png, &info, NULL);
sprintf(err, "%s: failed to allocate nrrd", me);
--- 274,285 ----
break;
}
! if (nio->oldData
! && (nio->oldDataSize
! == nrrdTypeSize[ntype]*nsize[0]*nsize[1]*nsize[2])) {
! ret = nrrdWrap_nva(nrrd, nio->oldData, ntype, ndim, nsize);
! } else {
! ret = nrrdMaybeAlloc_nva(nrrd, ntype, ndim, nsize);
! }
! if (ret) {
png_destroy_read_struct(&png, &info, NULL);
sprintf(err, "%s: failed to allocate nrrd", me);
Index: formatText.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/formatText.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** formatText.c 29 Nov 2003 08:16:07 -0000 1.3
--- formatText.c 19 Dec 2003 03:52:29 -0000 1.4
***************
*** 67,71 ****
char me[]="_nrrdFormatText_read", err[AIR_STRLEN_MED], *errS;
const char *fs;
! int line, len, ret, sx, sy, settwo = 0, gotOnePerAxis = AIR_FALSE;
/* fl: first line, al: all lines */
airArray *flArr, *alArr;
--- 67,72 ----
char me[]="_nrrdFormatText_read", err[AIR_STRLEN_MED], *errS;
const char *fs;
! int line, len, ret, sx, sy, settwo = 0, gotOnePerAxis = AIR_FALSE,
! size[NRRD_DIM_MAX];
/* fl: first line, al: all lines */
airArray *flArr, *alArr;
***************
*** 195,198 ****
--- 196,200 ----
biffAdd(NRRD, err); UNSETTWO; return 1;
}
+ /* else sx == 1 when nrrd->dim == 1 */
/* now see how many more lines there are */
***************
*** 225,246 ****
me, nrrd->dim, sx, sy);
*/
!
! switch (nrrd->dim) {
! case 2:
! if (nrrdMaybeAlloc(nrrd, nrrdTypeFloat, 2, sx, sy)) {
! sprintf(err, "%s: couldn't allocate plain text data", me);
! biffAdd(NRRD, err); UNSETTWO; return 1;
! }
! break;
! case 1:
! if (nrrdMaybeAlloc(nrrd, nrrdTypeFloat, 1, sy)) {
! sprintf(err, "%s: couldn't allocate plain text data", me);
! biffAdd(NRRD, err); UNSETTWO; return 1;
! }
! break;
! default:
fprintf(stderr, "%s: PANIC about to save, but dim = %d\n", me, nrrd->dim);
exit(1);
! break;
}
memcpy(nrrd->data, al, sx*sy*sizeof(float));
--- 227,251 ----
me, nrrd->dim, sx, sy);
*/
!
! if (!( 1 == nrrd->dim || 2 == nrrd->dim )) {
fprintf(stderr, "%s: PANIC about to save, but dim = %d\n", me, nrrd->dim);
exit(1);
! }
! if (1 == nrrd->dim) {
! size[0] = sy;
! } else {
! size[0] = sx;
! size[1] = sy;
! }
!
! if (nio->oldData
! && nio->oldDataSize == sx*sy*nrrdTypeSize[nrrdTypeFloat]) {
! ret = nrrdWrap_nva(nrrd, nio->oldData, nrrdTypeFloat, nrrd->dim, size);
! } else {
! ret = nrrdMaybeAlloc_nva(nrrd, nrrdTypeFloat, nrrd->dim, size);
! }
! if (ret) {
! sprintf(err, "%s: couldn't create nrrd for plain text data", me);
! biffAdd(NRRD, err); UNSETTWO; return 1;
}
memcpy(nrrd->data, al, sx*sy*sizeof(float));
Index: methodsNrrd.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/methodsNrrd.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** methodsNrrd.c 1 Dec 2003 09:21:20 -0000 1.36
--- methodsNrrd.c 19 Dec 2003 03:52:29 -0000 1.37
***************
*** 50,53 ****
--- 50,55 ----
nio->skipData = AIR_FALSE;
nio->keepNrrdDataFileOpen = AIR_FALSE;
+ nio->oldData = NULL;
+ nio->oldDataSize = 0;
memset(nio->seen, 0, (NRRD_FIELD_MAX+1)*sizeof(int));
}
***************
*** 81,84 ****
--- 83,87 ----
AIR_FREE(nio->line);
AIR_FREE(nio);
+ /* the NrrdIoState never owned nio->oldData; we don't free it */
return NULL;
}
Index: nrrd.h
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/nrrd.h,v
retrieving revision 1.126
retrieving revision 1.127
diff -C2 -d -r1.126 -r1.127
*** nrrd.h 1 Dec 2003 09:21:21 -0000 1.126
--- nrrd.h 19 Dec 2003 03:52:29 -0000 1.127
***************
*** 276,279 ****
--- 276,282 ----
roughly equivalent to better but slower
(1-9, -1 for default[9]). */
+ void *oldData; /* ON READ: data pointer that may have already been
+ allocated for the right size to hold the data */
+ size_t oldDataSize; /* ON READ: size of data pointed to by oldData */
/* format and encoding. These are initialized to nrrdFormatUnknown
and nrrdEncodingUnknown, respectively. USE THESE VALUES for
***************
*** 315,319 ****
** around zero, but does not assume anything about even- or oddness
**
! ** It is a strong but very simplifying assumption that the paramater
** array ("parm") is always type double. There is essentially no
** value in allowing flexibility between float and double, and much
--- 318,322 ----
** around zero, but does not assume anything about even- or oddness
**
! ** It is a strong but very simplifying assumption that the parameter
** array ("parm") is always type double. There is essentially no
** value in allowing flexibility between float and double, and much
Index: privateNrrd.h
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/privateNrrd.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** privateNrrd.h 29 Nov 2003 08:16:07 -0000 1.28
--- privateNrrd.h 19 Dec 2003 03:52:29 -0000 1.29
***************
*** 87,92 ****
/* read.c */
! extern int _nrrdOneLine (int *lenP, NrrdIoState *io, FILE *file);
! extern int _nrrdCalloc (Nrrd *nrrd);
/* arrays.c */
--- 87,92 ----
/* read.c */
! extern int _nrrdOneLine (int *lenP, NrrdIoState *nio, FILE *file);
! extern int _nrrdCalloc (Nrrd *nrrd, NrrdIoState *nio);
/* arrays.c */
***************
*** 136,142 ****
/* parseNrrd.c */
! extern int (*_nrrdReadNrrdParseInfo[NRRD_FIELD_MAX+1])(Nrrd *, NrrdIoState *,
int useBiff);
! extern int _nrrdReadNrrdParseField(Nrrd *nrrd, NrrdIoState *io, int useBiff);
/* methods.c */
--- 136,143 ----
/* parseNrrd.c */
! extern int (*_nrrdReadNrrdParseInfo[NRRD_FIELD_MAX+1])(Nrrd *nrrd,
! NrrdIoState *nio,
int useBiff);
! extern int _nrrdReadNrrdParseField(Nrrd *nrrd, NrrdIoState *nio, int useBiff);
/* methods.c */
Index: read.c
===================================================================
RCS file: /cvsroot/teem/teem/src/nrrd/read.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -C2 -d -r1.84 -r1.85
*** read.c 30 Nov 2003 22:48:29 -0000 1.84
--- read.c 19 Dec 2003 03:52:29 -0000 1.85
***************
*** 121,138 ****
** _nrrdCalloc()
**
! ** allocates the data for the array. Only to be called by data readers,
** since it assume the validity of size information, as enforced by
** _nrrdHeaderCheck().
*/
int
! _nrrdCalloc (Nrrd *nrrd) {
char me[]="_nrrdCalloc", err[AIR_STRLEN_MED];
! AIR_FREE(nrrd->data);
! nrrd->data = calloc(nrrdElementNumber(nrrd), nrrdElementSize(nrrd));
! if (!nrrd->data) {
! sprintf(err, "%s: couldn't calloc(" _AIR_SIZE_T_FMT
! ", %d)", me, nrrdElementNumber(nrrd), nrrdElementSize(nrrd));
! biffAdd(NRRD, err); return 1;
}
return 0;
--- 121,147 ----
** _nrrdCalloc()
**
! ** allocates the data for the array, but only if necessary (as informed by
! ** nio->oldData and nio->oldDataSate). Only to be called by data readers,
** since it assume the validity of size information, as enforced by
** _nrrdHeaderCheck().
*/
int
! _nrrdCalloc (Nrrd *nrrd, NrrdIoState *nio) {
char me[]="_nrrdCalloc", err[AIR_STRLEN_MED];
+ size_t needDataSize;
! needDataSize = nrrdElementNumber(nrrd)*nrrdElementSize(nrrd);
! if (nio->oldData && needDataSize == nio->oldDataSize) {
! nrrd->data = nio->oldData;
! /* make the data look like it came from calloc() */
! memset(nrrd->data, 0, needDataSize);
! } else {
! AIR_FREE(nrrd->data);
! nrrd->data = calloc(nrrdElementNumber(nrrd), nrrdElementSize(nrrd));
! if (!nrrd->data) {
! sprintf(err, "%s: couldn't calloc(" _AIR_SIZE_T_FMT
! ", %d)", me, nrrdElementNumber(nrrd), nrrdElementSize(nrrd));
! biffAdd(NRRD, err); return 1;
! }
}
return 0;
***************
*** 226,230 ****
char me[]="nrrdRead", err[AIR_STRLEN_MED];
int len, fi;
! airArray *mop;
/* sanity check, for good measure */
--- 235,239 ----
char me[]="nrrdRead", err[AIR_STRLEN_MED];
int len, fi;
! airArray *mop;
/* sanity check, for good measure */
***************
*** 247,252 ****
airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways);
}
! /* clear out anything in the given nrrd */
nrrdInit(nrrd);
--- 256,273 ----
airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways);
}
+
+ /* remember old data pointer and allocated size. Whether or not to
+ free() this memory will be decided later */
+ nio->oldData = nrrd->data;
+ nio->oldDataSize = (nio->oldData
+ ? nrrdElementNumber(nrrd)*nrrdElementSize(nrrd)
+ : 0);
+ /*
+ fprintf(stderr, "!%s: nio->oldData = %p, oldDataSize = %d\n", me,
+ nio->oldData, (int)(nio->oldDataSize));
+ */
+ nrrd->data = NULL;
! /* initialize given nrrd (but we have thwarted freeing existing memory) */
nrrdInit(nrrd);
***************
*** 287,290 ****
--- 308,317 ----
biffAdd(NRRD, err); return 1;
}
+ }
+
+ /* free prior memory if we didn't end up using it */
+ if (nio->oldData != nrrd->data) {
+ AIR_FREE(nio->oldData);
+ nio->oldDataSize = 0;
}
|