TPCCLIB
Loading...
Searching...
No Matches
nifti.c File Reference

Procedures for reading and writing NIfTI-1 PET images. More...

#include "libtpcimgio.h"

Go to the source code of this file.

Functions

void niftiRemoveFNameExtension (char *fname)
int niftiCreateFNames (const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
int niftiRemove (const char *dbname, int fileformat, int verbose)
int niftiExists (const char *filename, char *hdrfile, char *imgfile, char *siffile, NIFTI_DSR *header, int verbose, char *status)
int niftiReadHeader (char *filename, NIFTI_DSR *dsr, int verbose, char *status)
int niftiPrintHeader (NIFTI_DSR *dsr, FILE *fp)
int niftiReadImagedata (FILE *fp, NIFTI_DSR *dsr, int frame, float *data, int verbose, char *status)
int niftiWriteHeader (char *filename, NIFTI_DSR *dsr, int verbose, char *status)

Detailed Description

Procedures for reading and writing NIfTI-1 PET images.

Author
Vesa Oikonen

Function are not intended to support all NIfTI files or file properties, but only those that have been found necessary in Turku PET Centre. For full NIfTI support, use other libraries e.g. niftilib https://niftilib.sourceforge.net/

NIfTI-1 and NIfTI-2 documentation and source codes in https://nifti.nimh.nih.gov/

Procedures in this file are not dependent on IMG struct.

Definition in file nifti.c.

Function Documentation

◆ niftiCreateFNames()

int niftiCreateFNames ( const char * filename,
char * hdrfile,
char * imgfile,
char * siffile,
int fileformat )

Construct the file names for NIfTI image.

Returns
Returns 0 if successful, otherwise <>0.
See also
niftiExists
Parameters
filenameFilename, either header file, image file, or base name without extensions, but possibly with path name. This string is never modified.
hdrfileHeader filename will be written in this char pointer (space needs to allocated by caller); If header and image are combined, then this will be the name of combined file; enter NULL if not needed.
imgfileImage filename will be written in this char pointer (space needs to allocated by caller); If header and image are combined, then this will be the name of combined file; enter NULL if not needed.
siffileSIF filename will be written in this char pointer (space needs to allocated by caller); enter NULL if not needed.
fileformatNIfTI file format, either IMG_NIFTI_1D (31) or IMG_NIFTI_1S (32).

Definition at line 44 of file nifti.c.

63 {
64 int n;
65 char basename[FILENAME_MAX];
66
67 if(hdrfile!=NULL) strcpy(hdrfile, "");
68 if(imgfile!=NULL) strcpy(imgfile, "");
69 if(siffile!=NULL) strcpy(siffile, "");
70 n=strlen(filename); if(n<1 || n>=FILENAME_MAX) {return(1);}
71 strlcpy(basename, filename, FILENAME_MAX);
73
74 /* Create database filenames */
75 if(fileformat==IMG_NIFTI_1D) {
76 if(hdrfile!=NULL) snprintf(hdrfile, FILENAME_MAX, "%s.hdr", basename);
77 if(imgfile!=NULL) snprintf(imgfile, FILENAME_MAX, "%s.img", basename);
78 } else if(fileformat==IMG_NIFTI_1S) {
79 if(hdrfile!=NULL) snprintf(hdrfile, FILENAME_MAX, "%s.nii", basename);
80 if(imgfile!=NULL) snprintf(imgfile, FILENAME_MAX, "%s.nii", basename);
81 } else
82 return(2);
83 if(siffile!=NULL) snprintf(siffile, FILENAME_MAX, "%s.sif", basename);
84 return(0);
85}
#define IMG_NIFTI_1S
#define IMG_NIFTI_1D
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
void niftiRemoveFNameExtension(char *fname)
Definition nifti.c:23

Referenced by imgWriteNifti(), imgWriteNiftiFrame(), and niftiRemove().

◆ niftiExists()

int niftiExists ( const char * filename,
char * hdrfile,
char * imgfile,
char * siffile,
NIFTI_DSR * header,
int verbose,
char * status )

Verify if specified filename is a NIfTI file.

Returns
Returns 0 if it is not, 1 if header and image data are found (either as one combined file or as separate files, and 2, if SIF is found too.
See also
niftiRemove
Parameters
filenameFilename, either header file, image file, or base name without extensions. This string is never modified.
hdrfileIf filename refers to a Nifti file, then header filename will be written in this char pointer (space needs to allocated by caller); If header and image are combined, then this will be the name of combined file; enter NULL if not needed.
imgfileIf filename refers to a Nifti file, then image filename will be written in this char pointer (space needs to allocated by caller); If header and image are combined, then this will be the name of combined file; enter NULL if not needed.
siffileIf filename refers to a Nifti file, and if SIF exists, then SIF filename will be written in this char pointer (space needs to allocated by caller); NULL if not needed.
headerPointer to Nifti header, which is filled in this function; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 160 of file nifti.c.

185 {
186 char basefile[FILENAME_MAX], temp[FILENAME_MAX], localhdrfile[FILENAME_MAX];
187 NIFTI_DSR *dsr, local_dsr;
188 int ret, combined=0;
189
190 if(filename==NULL || strlen(filename)==0) return(0);
191 if(verbose>0) {printf("\nniftiExists(%s, ...)\n", filename); fflush(stdout);}
192 if(status!=NULL) strcpy(status, "OK");
193 if(header==NULL) dsr=&local_dsr; else dsr=header;
194
195 localhdrfile[0]=(char)0;
196
197 /* Construct the base file name wo extensions */
198 strlcpy(basefile, filename, FILENAME_MAX);
200 if(verbose>1) printf("\n basefile := %s\n", basefile);
201
202 /* Combined header and image file exists? */
203 strcpy(temp, basefile); strcat(temp, ".nii");
204 if(access(temp, 0) == -1) {
205 if(verbose>0) printf(" %s not found or accessible.\n", temp);
206 } else {
207 /* Preserve header and image filenames */
208 strcpy(localhdrfile, temp);
209 if(hdrfile!=NULL) strcpy(hdrfile, temp);
210 if(imgfile!=NULL) strcpy(imgfile, temp);
211 combined=1;
212 if(verbose>1) printf(" %s is accessible.\n", temp);
213 }
214
215 /* If not, then check if header file exists */
216 if(combined==0) {
217 strcpy(temp, basefile); strcat(temp, ".hdr");
218 if(access(temp, 0) == -1) {
219 strcpy(temp, basefile); strcat(temp, ".img.hdr");
220 if(access(temp, 0) == -1) {
221 if(verbose>0) printf(" hdr file not found or accessible.\n");
222 if(status!=NULL) strcpy(status, "file not accessible");
223 return(0);
224 }
225 }
226 /* Preserve header filename */
227 strcpy(localhdrfile, temp);
228 if(hdrfile!=NULL) strcpy(hdrfile, temp);
229 if(verbose>1) printf(" %s is accessible.\n", temp);
230 }
231
232 /* If not combined, then does image file exists? */
233 if(combined==0) {
234 strcpy(temp, basefile); strcat(temp, ".img");
235 if(access(temp, 0) == -1) {
236 if(verbose>0) printf(" %s not found or accessible.\n", temp);
237 if(status!=NULL) strcpy(status, "file not accessible");
238 return(0);
239 }
240 /* Preserve image filename */
241 if(imgfile!=NULL) strcpy(imgfile, temp);
242 if(verbose>1) printf(" %s is accessible.\n", temp);
243 }
244
245 /* Is this Nifti file? */
246 if((ret=niftiReadHeader(localhdrfile, dsr, verbose, temp))!=0) {
247 if(status!=NULL) strcpy(status, "file is not Nifti");
248 if(verbose>0) {
249 printf(" %s was not identified as Nifti header file (%d).\n", localhdrfile, ret);
250 printf(" %s\n", temp);
251 }
252 return(0);
253 }
254 if(verbose>1) printf(" %s is identified as Nifti.\n", localhdrfile);
255 if(verbose>10) niftiPrintHeader(dsr, stdout);
256
257 /* SIF exists? */
258 strcpy(temp, basefile); strcat(temp, ".sif");
259 if(verbose>3) printf(" checking if %s exists\n", temp);
260 if(access(temp, 0) == -1) {
261 strcpy(temp, basefile); strcat(temp, ".img.sif");
262 if(verbose>3) printf(" checking if %s exists\n", temp);
263 if(access(temp, 0) == -1) {
264 strcpy(temp, basefile); strcat(temp, ".nii.sif");
265 if(verbose>3) printf(" checking if %s exists\n", temp);
266 if(access(temp, 0) == -1) {
267 if(verbose>0) printf("\n SIF not found or accessible.\n");
268 if(siffile!=NULL) strcpy(siffile, "");
269 if(status!=NULL) {
270 if(combined) strcpy(status, "combined Nifti file is accessible");
271 else strcpy(status, "Nifti files are accessible");
272 }
273 return(1); // but otherwise ok
274 }
275 }
276 }
277 /* Preserve SIF filename */
278 if(siffile!=NULL) strcpy(siffile, temp);
279 if(verbose>1) printf(" %s is accessible.\n", temp);
280 if(status!=NULL) {
281 if(combined) strcpy(status, "combined Nifti file and SIF are accessible");
282 else strcpy(status, "Nifti files and SIF are accessible");
283 }
284 return(2);
285}
int niftiReadHeader(char *filename, NIFTI_DSR *dsr, int verbose, char *status)
Definition nifti.c:293
int niftiPrintHeader(NIFTI_DSR *dsr, FILE *fp)
Definition nifti.c:501

Referenced by imgFormatDetermine(), imgRead(), imgReadNiftiFrame(), imgReadNiftiHeader(), and imgWriteNiftiFrame().

◆ niftiPrintHeader()

int niftiPrintHeader ( NIFTI_DSR * dsr,
FILE * fp )

Print the contents of Nifti header to specified file pointer.

Returns
Returns 0 if ok, 1 if invalid input.
Parameters
dsrPointer to combined Nifti header.
fpFile pointer where header information is printed.

Definition at line 501 of file nifti.c.

506 {
507 int i;
508 char *cptr, tmp[256];
509
510 /* Check input */
511 if(fp==NULL || dsr==NULL) return(1);
512
513 fprintf(fp, "Nifti header:\n");
514
515 /* Byte order */
516 if(dsr->byte_order==0) strcpy(tmp, "big"); else strcpy(tmp, "little");
517 fprintf(fp, "byte_order := %s endian\n", tmp);
518 /* sizeof_hdr */
519 fprintf(fp, "sizeof_hdr := %d\n", dsr->h.sizeof_hdr);
520 /* data_type */
521 strncpy(tmp, dsr->h.data_type, 10); tmp[10]=(char)0;
522 cptr=tmp; while(*cptr) {if(!isprint(cptr[0])) cptr[0]=' '; cptr++;}
523 fprintf(fp, "data_type := %s\n", tmp);
524 /* db_name */
525 strncpy(tmp, dsr->h.db_name, 18); tmp[18]=(char)0;
526 cptr=tmp; while(*cptr) {if(!isprint(*cptr)) *cptr=' '; cptr++;}
527 fprintf(fp, "db_name := %s\n", tmp);
528 /* extents */
529 fprintf(fp, "extents := %d\n", dsr->h.extents);
530 /* session_error */
531 fprintf(fp, "session_error := %d\n", dsr->h.session_error);
532 /* regular */
533 fprintf(fp, "regular := %d\n", dsr->h.regular);
534 /* dim_info */
535 fprintf(fp, "dim_info := %d\n", dsr->h.dim_info);
536
537 /* Data array dimensions */
538 i=0; fprintf(fp, "dim := {%d", dsr->h.dim[i]);
539 for(i=1; i<8; i++) fprintf(fp, ", %d", dsr->h.dim[i]);
540 fprintf(fp, "}\n");
541
542 /* Intent parameters */
543 fprintf(fp, "intent_p1 := %g\n", dsr->h.intent_p1);
544 fprintf(fp, "intent_p2 := %g\n", dsr->h.intent_p2);
545 fprintf(fp, "intent_p3 := %g\n", dsr->h.intent_p3);
546 fprintf(fp, "intent_code := %d\n", dsr->h.intent_code);
547
548 /* */
549 fprintf(fp, "datatype := %d\n", dsr->h.datatype);
550 fprintf(fp, "bitpix := %d\n", dsr->h.bitpix);
551 fprintf(fp, "slice_start := %d\n", dsr->h.slice_start);
552 i=0; fprintf(fp, "pixdim := {%g", dsr->h.pixdim[i]);
553 for(i=1; i<8; i++) fprintf(fp, ", %g", dsr->h.pixdim[i]);
554 fprintf(fp, "}\n");
555 fprintf(fp, "vox_offset := %g\n", dsr->h.vox_offset);
556 fprintf(fp, "scl_slope := %g\n", dsr->h.scl_slope);
557 fprintf(fp, "scl_inter := %g\n", dsr->h.scl_inter);
558 fprintf(fp, "slice_end := %d\n", dsr->h.slice_end);
559 fprintf(fp, "slice_code := %d\n", dsr->h.slice_code);
560 fprintf(fp, "xyzt_units := %d\n", dsr->h.xyzt_units);
561 fprintf(fp, "cal_max := %g\n", dsr->h.cal_max);
562 fprintf(fp, "cal_min := %g\n", dsr->h.cal_min);
563 fprintf(fp, "slice_duration := %g\n", dsr->h.slice_duration);
564 fprintf(fp, "toffset := %g\n", dsr->h.toffset);
565 fprintf(fp, "glmax := %d\n", dsr->h.glmax);
566 fprintf(fp, "glmin := %d\n", dsr->h.glmin);
567
568 /* Study description */
569 strncpy(tmp, dsr->h.descrip, 80); tmp[80]=(char)0;
570 cptr=tmp; while(*cptr) {if(!isprint(*cptr)) *cptr=' '; cptr++;}
571 fprintf(fp, "descrip := %s\n", tmp);
572 strncpy(tmp, dsr->h.aux_file, 24); tmp[24]=(char)0;
573 cptr=tmp; while(*cptr) {if(!isprint(*cptr)) *cptr=' '; cptr++;}
574 fprintf(fp, "aux_file := %s\n", tmp);
575
576 /* Transformation parameters */
577 fprintf(fp, "qform_code := %d\n", dsr->h.qform_code);
578 fprintf(fp, "sform_code := %d\n", dsr->h.sform_code);
579 fprintf(fp, "quatern_b := %g\n", dsr->h.quatern_b);
580 fprintf(fp, "quatern_c := %g\n", dsr->h.quatern_c);
581 fprintf(fp, "quatern_d := %g\n", dsr->h.quatern_d);
582 fprintf(fp, "qoffset_x := %g\n", dsr->h.qoffset_x);
583 fprintf(fp, "qoffset_y := %g\n", dsr->h.qoffset_y);
584 fprintf(fp, "qoffset_z := %g\n", dsr->h.qoffset_z);
585 i=0; fprintf(fp, "srow_x := {%g", dsr->h.srow_x[i]);
586 for(i=1; i<4; i++) fprintf(fp, ", %g", dsr->h.srow_x[i]);
587 fprintf(fp, "}\n");
588 i=0; fprintf(fp, "srow_y := {%g", dsr->h.srow_y[i]);
589 for(i=1; i<4; i++) fprintf(fp, ", %g", dsr->h.srow_y[i]);
590 fprintf(fp, "}\n");
591 i=0; fprintf(fp, "srow_z := {%g", dsr->h.srow_z[i]);
592 for(i=1; i<4; i++) fprintf(fp, ", %g", dsr->h.srow_z[i]);
593 fprintf(fp, "}\n");
594
595 strncpy(tmp, dsr->h.intent_name, 16); tmp[16]=(char)0;
596 cptr=tmp; while(*cptr) {if(!isprint(*cptr)) *cptr=' '; cptr++;}
597 fprintf(fp, "intent_name := %s\n", tmp);
598
599 /* Nifti magic number */
600 fprintf(fp, "magic := %s\n", dsr->h.magic);
601
602 /* Nifti header extender */
603 i=0; fprintf(fp, "extension := {%d", dsr->e.extension[i]);
604 for(i=1; i<4; i++) fprintf(fp, ", %d", dsr->e.extension[i]);
605 fprintf(fp, "}\n");
606
607 fflush(fp);
608 return(0);
609}
short int qform_code
short int slice_start
short int slice_end
short int datatype
char aux_file[24]
char intent_name[16]
short int bitpix
char data_type[10]
short int sform_code
short int dim[8]
short int intent_code
short int session_error
NIFTI_1_HEADER h
NIFTI_EXTENDER e

Referenced by niftiExists().

◆ niftiReadHeader()

int niftiReadHeader ( char * filename,
NIFTI_DSR * dsr,
int verbose,
char * status )

Read Nifti header contents. Currently, does not read Nifti-1 header extension.

Returns
Returns 0, if successful, otherwise >0.
See also
niftiReadImagedata, niftiWriteHeader, niftiExists
Parameters
filenameName of file to read (including path and extension)
dsrPointer to previously allocated header structure
verboseVerbose level; if zero, then nothing is printed to stderr or stdout
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed

Definition at line 293 of file nifti.c.

303 {
304 FILE *fp;
305 int little; // 1 if current platform is little endian (x86), else 0
306 int same_order, extender=0;
307 unsigned char buf[NIFTI_HEADER_SIZE];
308 short int s;
309
310 /* Check arguments */
311 if(filename==NULL || strlen(filename)==0 || dsr==NULL) return(1);
312 if(verbose>0) {
313 printf("\nniftiReadHeader(%s, ...)\n", filename); fflush(stdout);}
314 if(status!=NULL) strcpy(status, "OK");
315 little=little_endian(); if(verbose>3) printf(" little := %d\n", little);
316
317 /* Open file */
318 fp=fopen(filename, "rb"); if(fp==NULL) {
319 if(status!=NULL) strcpy(status, "cannot open file");
320 if(verbose>0) fprintf(stderr, "Error: cannot open file %s\n", filename);
321 return(2);
322 }
323
324 /* Read Nifti header */
325 if(fread(buf, NIFTI_HEADER_SIZE, 1, fp)<1) {
326 if(status!=NULL) strcpy(status, "complete Nifti header not found");
327 if(verbose>0)
328 fprintf(stderr, "Error: invalid Nifti header file %s\n", filename);
329 return(3);
330 }
331 /* Read nifti1 extender */
332 for(int n=0; n<4; n++) dsr->e.extension[n]=(char)0;
333 if(fread(dsr->e.extension, 4, 1, fp)<1) {
334 if(status!=NULL) strcpy(status, "complete Nifti header not found");
335 if(verbose>1)
336 fprintf(stdout, "Nifti header extender not found in %s\n", filename);
337 extender=0;
338 } else {
339 extender=1;
340 }
341 /* Close file */
342 fclose(fp);
343
344 /* Read Nifti Magic number */
345 memcpy(dsr->h.magic, buf+344, 4);
346 if(strcasecmp(dsr->h.magic, "ni1")==0) {
347 if(verbose>1) {printf(" separate hdr and img files.\n"); fflush(stdout);}
348 } else if(strcasecmp(dsr->h.magic, "n+1")==0) {
349 if(verbose>1) printf(" combined hdr and img data.\n");
350 } else {
351 if(status!=NULL) strcpy(status, "Nifti magic number not found");
352 if(verbose>0) {
353 fprintf(stderr, "Error: not a Nifti header file %s\n", filename);
354 fflush(stderr);
355 }
356 if(verbose>2) {
357 printf("magic := {%d, %d, %d, %d}\n", dsr->h.magic[0], dsr->h.magic[1],
358 dsr->h.magic[2], dsr->h.magic[3]);
359 }
360 return(4);
361 }
362 if(verbose>1) printf(" Nifti Magic number := %s\n", dsr->h.magic);
363 /* Check that 4-byte header extender was found, if magic number is n+1 */
364 if(strcasecmp(dsr->h.magic, "n+1")==0 && extender==0) {
365 if(status!=NULL) strcpy(status, "Nifti header extender not found");
366 if(verbose>0) {
367 fprintf(stderr, "Error: not valid Nifti n+1 header file %s\n", filename);
368 fflush(stderr);
369 }
370 return(5);
371 }
372
373 /* Determine from dim[0] if file is big or little endian */
374 memcpy(&s, buf+40, 2); if(verbose>10) printf(" s := %d\n", s);
375 if(s>0 && s<8) { // same order in file and current machine
376 dsr->byte_order=little;
377 same_order=1;
378 } else {
379 swabip(&s, 2); if(verbose>10) printf(" s := %d\n", s);
380 if(s>0 && s<8) { // opposite order in file and in current machine
381 if(little==1) dsr->byte_order=0; else dsr->byte_order=1;
382 same_order=0;
383 } else {
384 if(status!=NULL) strcpy(status, "invalid Nifti byte order");
385 if(verbose>0)
386 fprintf(stderr, "Error: not a valid Nifti header file %s\n", filename);
387 return(6);
388 }
389 }
390 if(verbose>1) printf(" Nifti byte order := %d\n", dsr->byte_order);
391
392 /* Size of header */
393 {
394 int n=0;
395 memcpy(&n, buf+0, 4); if(!same_order) swawbip(&n, 4);
396 if(n!=348) {
397 if(status!=NULL) strcpy(status, "invalid Nifti sizeof_hdr");
398 if(verbose>0)
399 fprintf(stderr, "Error: not a valid Nifti header file %s\n", filename);
400 return(7);
401 }
402 dsr->h.sizeof_hdr=n;
403 }
404
405 /* */
406 memcpy(&dsr->h.data_type, buf+4, 10);
407 memcpy(&dsr->h.db_name, buf+14, 18);
408 if(!same_order) swawbip(buf+32, 4);
409 memcpy(&dsr->h.extents, buf+32, 4);
410 if(!same_order) swabip(buf+36, 2);
411 memcpy(&dsr->h.session_error, buf+36, 2);
412 memcpy(&dsr->h.regular, buf+38, 1);
413 memcpy(&dsr->h.dim_info, buf+39, 1);
414
415 /* dim */
416 if(!same_order) swabip(buf+40, 16);
417 memcpy(dsr->h.dim, buf+40, 16);
418 /* intent parameters */
419 if(!same_order) swawbip(buf+56, 4);
420 memcpy(&dsr->h.intent_p1, buf+56, 4);
421 if(!same_order) swawbip(buf+60, 4);
422 memcpy(&dsr->h.intent_p2, buf+60, 4);
423 if(!same_order) swawbip(buf+64, 4);
424 memcpy(&dsr->h.intent_p3, buf+64, 4);
425 if(!same_order) swabip(buf+68, 2);
426 memcpy(&dsr->h.intent_code, buf+68, 2);
427
428 /* */
429 if(!same_order) swabip(buf+70, 2);
430 memcpy(&dsr->h.datatype, buf+70, 2);
431 if(!same_order) swabip(buf+72, 2);
432 memcpy(&dsr->h.bitpix, buf+72, 2);
433 if(!same_order) swabip(buf+74, 2);
434 memcpy(&dsr->h.slice_start, buf+74, 2);
435 if(!same_order) swawbip(buf+76, 32);
436 memcpy(dsr->h.pixdim, buf+76, 32);
437 if(!same_order) swawbip(buf+108, 4);
438 memcpy(&dsr->h.vox_offset, buf+108, 4);
439 if(!same_order) swawbip(buf+112, 4);
440 memcpy(&dsr->h.scl_slope, buf+112, 4);
441 if(!same_order) swawbip(buf+116, 4);
442 memcpy(&dsr->h.scl_inter, buf+116, 4);
443 if(!same_order) swabip(buf+120, 2);
444 memcpy(&dsr->h.slice_end, buf+120, 2);
445 memcpy(&dsr->h.slice_code, buf+122, 1);
446 memcpy(&dsr->h.xyzt_units, buf+123, 1);
447 if(!same_order) swawbip(buf+124, 4);
448 memcpy(&dsr->h.cal_max, buf+124, 4);
449 if(!same_order) swawbip(buf+128, 4);
450 memcpy(&dsr->h.cal_min, buf+128, 4);
451 if(!same_order) swawbip(buf+132, 4);
452 memcpy(&dsr->h.slice_duration,buf+132,4);
453 if(!same_order) swawbip(buf+136, 4);
454 memcpy(&dsr->h.toffset, buf+136, 4);
455 if(!same_order) swawbip(buf+140, 4);
456 memcpy(&dsr->h.glmax, buf+140, 4);
457 if(!same_order) swawbip(buf+144, 4);
458 memcpy(&dsr->h.glmin, buf+144, 4);
459
460 /* study description */
461 memcpy(&dsr->h.descrip, buf+148, 80);
462 /* Auxiliary filename */
463 memcpy(&dsr->h.aux_file, buf+228, 24);
464
465 /* Transformation parameters */
466 if(!same_order) swabip(buf+252, 2);
467 memcpy(&dsr->h.qform_code, buf+252, 2);
468 if(!same_order) swabip(buf+254, 2);
469 memcpy(&dsr->h.sform_code, buf+254, 2);
470 if(!same_order) swawbip(buf+256, 4);
471 memcpy(&dsr->h.quatern_b, buf+256, 4);
472 if(!same_order) swawbip(buf+260, 4);
473 memcpy(&dsr->h.quatern_c, buf+260, 4);
474 if(!same_order) swawbip(buf+264, 4);
475 memcpy(&dsr->h.quatern_d, buf+264, 4);
476 if(!same_order) swawbip(buf+268, 4);
477 memcpy(&dsr->h.qoffset_x, buf+268, 4);
478 if(!same_order) swawbip(buf+272, 4);
479 memcpy(&dsr->h.qoffset_y, buf+272, 4);
480 if(!same_order) swawbip(buf+276, 4);
481 memcpy(&dsr->h.qoffset_z, buf+276, 4);
482 if(!same_order) swawbip(buf+280, 16);
483 memcpy(dsr->h.srow_x, buf+280, 16);
484 if(!same_order) swawbip(buf+296, 16);
485 memcpy(dsr->h.srow_y, buf+296, 16);
486 if(!same_order) swawbip(buf+312, 16);
487 memcpy(dsr->h.srow_z, buf+312, 16);
488
489 memcpy(&dsr->h.intent_name, buf+328, 16);
490
491 if(status!=NULL) strcpy(status, "complete Nifti header was read");
492 if(verbose>0) fflush(stdout);
493 return(0);
494}
#define NIFTI_HEADER_SIZE
void swabip(void *buf, long long int size)
Definition swap.c:72
void swawbip(void *buf, long long int size)
Definition swap.c:93
int little_endian()
Definition swap.c:14

Referenced by niftiExists().

◆ niftiReadImagedata()

int niftiReadImagedata ( FILE * fp,
NIFTI_DSR * dsr,
int frame,
float * data,
int verbose,
char * status )

Read Nifti image data, convert byte order if necessary, and scale values to floats. Reads only one frame at a time!

Returns
Returns 0 if successful, >1 in case of an error, and specifically -1 in case that contents after the last image frame was requested.
See also
niftiReadHeader
Parameters
fpFile pointer to start of image data file, opened previously in binary mode.
dsrPointer to previously filled Nifti header structure
frameFrame number to read [1..number of frames].
dataPointer to image float data allocated previously for dimz*dimy*dimx floats.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 619 of file nifti.c.

633 {
634 int dimNr, dimx, dimy, dimz=1, dimt=1;
635 int little;
636 char *mdata, *mptr;
637 float *fptr, ss, si;
638 short int *sptr;
639 int *iptr;
640 double d;
641
642
643 if(verbose>0) {
644 printf("niftiReadImagedata(fp, h, %d, data, %d)\n", frame, verbose);
645 fflush(stdout);
646 }
647 /* Check the arguments */
648 if(status!=NULL) sprintf(status, "invalid function input");
649 if(frame<=0 || fp==NULL || dsr==NULL || data==NULL) return(1);
650
651 /* Get the image data start location from header, in case of single file
652 format */
653 long long start_pos;
654 {
655 long long int s=0;
656 if(strcasecmp(dsr->h.magic, "n+1")==0) s=(int)dsr->h.vox_offset;
657 if(s<0) start_pos=-s; else start_pos=s;
658 }
659 if(verbose>2) printf(" image_start_pos := %llu\n", start_pos);
660 /* edit it later to move to the correct frame */
661
662 /* Get the image dimensions from header */
663 if(status!=NULL) sprintf(status, "invalid image dimensions");
664 dimNr=dsr->h.dim[0]; if(dimNr<2 || dimNr>4) return(2);
665 dimx=dsr->h.dim[1];
666 dimy=dsr->h.dim[2];
667 if(dimNr>2) dimz=dsr->h.dim[3];
668 if(dimNr>3) dimt=dsr->h.dim[4];
669 if(frame>dimt) return(-1);
670 long long pxlNr=dimx*dimy*dimz; if(pxlNr<1) return(4);
671
672 // data_type is unused in Nifti
673 /* Check that datatype is supported */
674 if(verbose>1) printf(" verifying datatype %d\n", dsr->h.datatype);
675 {
676 int n=0;
677 if(dsr->h.datatype & NIFTI_DT_RGB) n+=NIFTI_DT_RGB;
680 if(dsr->h.datatype==NIFTI_DT_UNKNOWN) n+=512;
681 if(n!=0) {
682 if(verbose>0) printf("datatype error %d\n", n);
683 if(status!=NULL) sprintf(status, "unsupported pixel datatype %d", dsr->h.datatype);
684 return(6);
685 }
686 }
687
688 /* Allocate memory for the binary data */
689 if(verbose>1) printf(" allocating memory for binary data\n");
690 if(status!=NULL) sprintf(status, "invalid pixel data format");
691 if(dsr->h.bitpix==0) { // Carimas Nifti Writer does not set bitpix
692 if(dsr->h.datatype==NIFTI_DT_UNSIGNED_SHORT) dsr->h.bitpix=16;
693 }
694 if(dsr->h.bitpix<8) return(5); // We don't support bit data
695 long long rawSize=pxlNr*(dsr->h.bitpix/8); if(rawSize<1) return(6);
696 if(verbose>1) printf(" pxlNr=%lld rawSize=%lld\n", pxlNr, rawSize);
697 if(status!=NULL) sprintf(status, "out of memory");
698 mdata=(char*)malloc(rawSize); if(mdata==NULL) return(11);
699
700 /* Seek the start of current frame data */
701 if(verbose>1) printf(" seeking file position\n");
702 start_pos+=(frame-1)*rawSize;
703 if(verbose>2) printf("start_pos=%lld\n", start_pos);
704 fseeko(fp, start_pos, SEEK_SET);
705 if(ftello(fp)!=start_pos) {
706 if(status!=NULL) sprintf(status, "could not move to start_pos %lld", start_pos);
707 free(mdata); return(7);
708 }
709
710 /* Read the data */
711 if(verbose>1) printf(" reading binary data\n");
712 mptr=mdata;
713 {
714 size_t n=fread(mptr, rawSize, 1, fp);
715 if(n<1) {
716 if(status!=NULL)
717 sprintf(status, "could read only %zu bytes when request was %lld", n, rawSize);
718 free(mdata); return(8);
719 }
720 }
721
722 /* Convert byte order if necessary */
723 little=little_endian(); mptr=mdata;
724 if(little!=dsr->byte_order) {
725 if(verbose>0) printf("byte conversion\n");
726 switch(dsr->h.bitpix) {
727 case 8: /* no conversion needed */ break;
728 case 16: swabip(mptr, rawSize); break;
729 case 32: swawbip(mptr, rawSize); break;
730 case 64: swawbip(mptr, rawSize); break;
731 default:
732 if(verbose>5) printf("unsupported nifti bitpix := %d\n", dsr->h.bitpix);
733 sprintf(status, "unsupported nifti bitpix := %d", dsr->h.bitpix);
734 free(mdata); return(5);
735 }
736 }
737
738 /* Get scaling factors */
739 ss=dsr->h.scl_slope; if(ss==0) ss=1.0;
740 si=dsr->h.scl_inter;
741
742 /* Copy data to float pixel values */
743 if(verbose>1) printf(" conversion to floating point voxel values\n");
744 mptr=mdata;
745 switch(dsr->h.datatype) {
747 if(dsr->h.bitpix!=8) {
748 if(status!=NULL)
749 sprintf(status, "invalid combination of datatype and bitpix (%d, %d)",
750 dsr->h.datatype, dsr->h.bitpix);
751 free(mdata); return(5);
752 }
753 fptr=data;
754 for(long long i=0; i<pxlNr; i++, mptr++, fptr++)
755 *fptr=si+ss*(float)(*mptr);
756 break;
758 if(dsr->h.bitpix!=16) {
759 if(status!=NULL)
760 sprintf(status, "invalid combination of datatype and bitpix (%d, %d)",
761 dsr->h.datatype, dsr->h.bitpix);
762 free(mdata); return(5);
763 }
764 fptr=data;
765 for(long long i=0; i<pxlNr; i++, mptr+=2, fptr++) {
766 unsigned short int *uptr=(unsigned short int*)mptr; *fptr=si+ss*(float)(*uptr);
767 }
768 break;
770 if(dsr->h.bitpix!=16) {
771 if(status!=NULL)
772 sprintf(status, "invalid combination of datatype and bitpix (%d, %d)",
773 dsr->h.datatype, dsr->h.bitpix);
774 free(mdata); return(5);
775 }
776 fptr=data;
777 for(long long i=0; i<pxlNr; i++, mptr+=2, fptr++) {
778 sptr=(short int*)mptr; *fptr=si+ss*(float)(*sptr);
779 }
780 break;
782 if(dsr->h.bitpix!=16 && dsr->h.bitpix!=32) {
783 if(status!=NULL)
784 sprintf(status, "invalid combination of datatype and bitpix (%d, %d)",
785 dsr->h.datatype, dsr->h.bitpix);
786 free(mdata); return(5);
787 }
788 fptr=data;
789 if(dsr->h.bitpix==16) {
790 for(long long i=0; i<pxlNr; i++, mptr+=2, fptr++) {
791 iptr=(int*)mptr; *fptr=si+ss*(float)(*iptr);
792 }
793 } else if(dsr->h.bitpix==32) {
794 for(long long i=0; i<pxlNr; i++, mptr+=4, fptr++) {
795 iptr=(int*)mptr; *fptr=si+ss*(float)(*iptr);
796 }
797 }
798 break;
799 case NIFTI_DT_FLOAT: // 16
800 if(dsr->h.bitpix==32) {
801 fptr=data; memcpy(fptr, mptr, pxlNr*4);
802 fptr=data; for(long long i=0; i<pxlNr; i++, fptr++) *fptr*=ss;
803 fptr=data; for(long long i=0; i<pxlNr; i++, fptr++) *fptr+=si;
804 } else {
805 if(status!=NULL)
806 sprintf(status, "invalid combination of datatype and bitpix (%d, %d)",
807 dsr->h.datatype, dsr->h.bitpix);
808 free(mdata); return(5);
809 }
810 break;
811 case NIFTI_DT_DOUBLE:
812 if(dsr->h.bitpix!=64) {
813 if(status!=NULL)
814 sprintf(status, "invalid combination of datatype and bitpix (%d, %d)",
815 dsr->h.datatype, dsr->h.bitpix);
816 free(mdata); return(5);
817 }
818 fptr=data;
819 for(long long i=0; i<pxlNr; i++, mptr+=8, fptr++) {
820 memcpy(&d, mptr, 8); *fptr=si+ss*d;
821 }
822 break;
823 default:
824 if(status!=NULL)
825 sprintf(status, "unsupported pixel datatype %d", dsr->h.datatype);
826 free(mdata); return(5);
827 }
828
829 if(verbose>1) {printf(" data read successfully.\n"); fflush(stdout);}
830 free(mdata);
831 if(status!=NULL) sprintf(status, "ok");
832 return 0;
833}
#define NIFTI_DT_RGB
#define NIFTI_DT_BINARY
#define NIFTI_DT_FLOAT
#define NIFTI_DT_UNSIGNED_SHORT
#define NIFTI_DT_SIGNED_SHORT
#define NIFTI_DT_SIGNED_INT
#define NIFTI_DT_UNSIGNED_CHAR
#define NIFTI_DT_COMPLEX
#define NIFTI_DT_UNKNOWN
#define NIFTI_DT_DOUBLE

Referenced by imgReadNiftiFrame().

◆ niftiRemove()

int niftiRemove ( const char * dbname,
int fileformat,
int verbose )

Remove header and voxel data files or the single .nii file belonging to specified NIfTI database.

SIF is not deleted in any case. Validity of NIfTI is not verified, therefore this can be used to delete any files with similar name as NIfTI would have.

Returns
Returns 0 when call was successful, otherwise <>0. Call is considered successful, if files do not exist initially.
See also
niftiExists, niftiRemoveFNameExtension
Parameters
dbnameNIfTI database name with path, possibly with filename extension
fileformatNIfTI file format, either IMG_NIFTI_1D (31) or IMG_NIFTI_1S (32), or IMG_UNKNOWN (0) in case both are to be deleted.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 100 of file nifti.c.

108 {
109 if(verbose>0) {
110 printf("niftiRemove(%s, %d, ...)\n", dbname, fileformat);
111 fflush(stdout);
112 }
113
114 char imgfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX];
115 int errNr=0;
116 int ret=niftiCreateFNames(dbname, hdrfile, imgfile, siffile, fileformat);
117 if(ret==0 && fileformat==IMG_NIFTI_1D) { // dual format
118 if(access(hdrfile, 0)!=-1) {
119 if(verbose>1) {printf(" removing %s\n", hdrfile); fflush(stdout);}
120 if(remove(hdrfile)!=0) errNr++;
121 }
122 if(access(imgfile, 0)!=-1) {
123 if(verbose>1) {printf(" removing %s\n", imgfile); fflush(stdout);}
124 if(remove(imgfile)!=0) errNr++;
125 }
126 } else if(ret==0 && fileformat==IMG_NIFTI_1S) { // single format
127 if(access(imgfile, 0)!=-1) {
128 if(verbose>1) {printf(" removing %s\n", imgfile); fflush(stdout);}
129 if(remove(imgfile)!=0) errNr++;
130 }
131 } else { // dual and single formats
132 ret=niftiCreateFNames(dbname, hdrfile, imgfile, siffile, IMG_NIFTI_1D);
133 if(ret!=0) return 1;
134 if(access(hdrfile, 0)!=-1) {
135 if(verbose>1) {printf(" removing %s\n", hdrfile); fflush(stdout);}
136 if(remove(hdrfile)!=0) errNr++;
137 }
138 if(access(imgfile, 0)!=-1) {
139 if(verbose>1) {printf(" removing %s\n", imgfile); fflush(stdout);}
140 if(remove(imgfile)!=0) errNr++;
141 }
142
143 ret=niftiCreateFNames(dbname, hdrfile, imgfile, siffile, IMG_NIFTI_1S);
144 if(ret!=0) return 1;
145 if(access(imgfile, 0)!=-1) {
146 if(verbose>1) {printf(" removing %s\n", imgfile); fflush(stdout);}
147 if(remove(imgfile)!=0) errNr++;
148 }
149 }
150 return errNr;
151}
int niftiCreateFNames(const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
Definition nifti.c:44

Referenced by imgWriteNifti().

◆ niftiRemoveFNameExtension()

void niftiRemoveFNameExtension ( char * fname)

Remove any extensions from Nifti file name, leaving only base file name.

See also
niftiCreateFNames, niftiExists, niftiRemove
Parameters
fnameFull name of file.

Definition at line 23 of file nifti.c.

26 {
27 char *cptr;
28 cptr=strrchr(fname, '.'); if(cptr==NULL) return;
29 if(strcasecmp(cptr, ".")==0 || strcasecmp(cptr, ".img")==0 ||
30 strcasecmp(cptr, ".hdr")==0 || strcasecmp(cptr, ".sif")==0 ||
31 strcasecmp(cptr, ".nii")==0)
32 *cptr=(char)0;
33 /* Remove also double extensions, e.g. from data.img.hdr */
34 cptr=strrchr(fname, '.'); if(cptr==NULL) return;
35 if(strcasecmp(cptr, ".img")==0 || strcasecmp(cptr, ".nii")==0) *cptr=(char)0;
36}

Referenced by imgReadNiftiFrame(), imgReadNiftiHeader(), niftiCreateFNames(), and niftiExists().

◆ niftiWriteHeader()

int niftiWriteHeader ( char * filename,
NIFTI_DSR * dsr,
int verbose,
char * status )

Write NIfTI-1 header contents.

Currently, does not write header extension. Header field 'byte_order' is used to determine the required byte order.

Returns
Returns 0, if successful, otherwise >0.
See also
niftiReadHeader, imgWriteNifti
Parameters
filenameName of file to write (including path and extension).
dsrPointer to previously allocated header structure.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.

Definition at line 844 of file nifti.c.

854 {
855 FILE *fp;
856 int little; // 1 if current platform is little endian (x86), else 0
857 int same_order;
858 unsigned char buf1[NIFTI_HEADER_SIZE];
859 unsigned char buf2[NIFTI_HEADER_EXTENDER_SIZE];
860 unsigned char *bptr;
861
862
863 if(verbose>0) {
864 printf("\nniftiWriteHeader(%s, ...)\n", filename); fflush(stdout);
865 }
866
867 /* Check arguments */
868 if(status!=NULL) strcpy(status, "invalid function input");
869 if(filename==NULL || strlen(filename)==0 || dsr==NULL) return(1);
870 /* Check magic number */
871 if(strcmp(dsr->h.magic, "ni1")!=0 && strcmp(dsr->h.magic, "n+1")!=0)
872 return(1);
873
874 /* Check if byte swapping is needed */
875 little=little_endian(); if(verbose>3) printf(" little := %d\n", little);
876 if(little==dsr->byte_order) same_order=1; else same_order=0;
877
878 /* Make sure that buffers are all zeroes to begin with */
879 memset(buf1, 0, sizeof(NIFTI_HEADER_SIZE));
880 memset(buf2, 0, sizeof(NIFTI_HEADER_EXTENDER_SIZE));
881
882 /* Copy header contents into buffer */
883 if(verbose>2) printf(" setting write buffer\n");
884 bptr=buf1+0;
885 memcpy(bptr, &dsr->h.sizeof_hdr, 4); if(!same_order) swawbip(bptr, 4);
886 bptr=buf1+4;
887 memcpy(bptr, &dsr->h.data_type, 10);
888 bptr=buf1+14;
889 memcpy(bptr, &dsr->h.db_name, 18);
890 bptr=buf1+32;
891 memcpy(bptr, &dsr->h.extents, 4); if(!same_order) swawbip(bptr, 4);
892 bptr=buf1+36;
893 memcpy(bptr, &dsr->h.session_error, 2); if(!same_order) swabip(bptr, 2);
894 bptr=buf1+38;
895 memcpy(bptr, &dsr->h.regular, 1);
896 bptr=buf1+39;
897 memcpy(bptr, &dsr->h.dim_info, 1);
898
899 bptr=buf1+40;
900 memcpy(bptr, dsr->h.dim, 16); if(!same_order) swabip(bptr, 16);
901 bptr=buf1+56;
902 memcpy(bptr, &dsr->h.intent_p1, 4); if(!same_order) swawbip(bptr, 4);
903 bptr=buf1+60;
904 memcpy(bptr, &dsr->h.intent_p2, 4); if(!same_order) swawbip(bptr, 4);
905 bptr=buf1+64;
906 memcpy(bptr, &dsr->h.intent_p3, 4); if(!same_order) swawbip(bptr, 4);
907 bptr=buf1+68;
908 memcpy(bptr, &dsr->h.intent_code, 2); if(!same_order) swabip(bptr, 2);
909 bptr=buf1+70;
910 memcpy(bptr, &dsr->h.datatype, 2); if(!same_order) swabip(bptr, 2);
911 bptr=buf1+72;
912 memcpy(bptr, &dsr->h.bitpix, 2); if(!same_order) swabip(bptr, 2);
913 bptr=buf1+74;
914 memcpy(bptr, &dsr->h.slice_start, 2); if(!same_order) swabip(bptr, 2);
915 bptr=buf1+76;
916 memcpy(bptr, dsr->h.pixdim, 32); if(!same_order) swawbip(bptr, 32);
917 bptr=buf1+108;
918 memcpy(bptr, &dsr->h.vox_offset, 4); if(!same_order) swawbip(bptr, 4);
919 bptr=buf1+112;
920 memcpy(bptr, &dsr->h.scl_slope, 4); if(!same_order) swawbip(bptr, 4);
921 bptr=buf1+116;
922 memcpy(bptr, &dsr->h.scl_inter, 4); if(!same_order) swawbip(bptr, 4);
923 bptr=buf1+120;
924 memcpy(bptr, &dsr->h.slice_end, 2); if(!same_order) swabip(bptr, 2);
925 bptr=buf1+122;
926 memcpy(bptr, &dsr->h.slice_code, 1);
927 bptr=buf1+123;
928 memcpy(bptr, &dsr->h.xyzt_units, 1);
929 bptr=buf1+124;
930 memcpy(bptr, &dsr->h.cal_max, 4); if(!same_order) swawbip(bptr, 4);
931 bptr=buf1+128;
932 memcpy(bptr, &dsr->h.cal_min, 4); if(!same_order) swawbip(bptr, 4);
933 bptr=buf1+132;
934 memcpy(bptr, &dsr->h.slice_duration, 4); if(!same_order) swawbip(bptr, 4);
935 bptr=buf1+136;
936 memcpy(bptr, &dsr->h.toffset, 4); if(!same_order) swawbip(bptr, 4);
937 bptr=buf1+140;
938 memcpy(bptr, &dsr->h.glmax, 4); if(!same_order) swawbip(bptr, 4);
939 bptr=buf1+144;
940 memcpy(bptr, &dsr->h.glmin, 4); if(!same_order) swawbip(bptr, 4);
941
942 bptr=buf1+148;
943 memcpy(bptr, dsr->h.descrip, 80);
944 bptr=buf1+228;
945 memcpy(bptr, dsr->h.aux_file, 24);
946 bptr=buf1+252;
947 memcpy(bptr, &dsr->h.qform_code, 2); if(!same_order) swabip(bptr, 2);
948 bptr=buf1+254;
949 memcpy(bptr, &dsr->h.sform_code, 2); if(!same_order) swabip(bptr, 2);
950 bptr=buf1+256;
951 memcpy(bptr, &dsr->h.quatern_b, 4); if(!same_order) swawbip(bptr, 4);
952 bptr=buf1+260;
953 memcpy(bptr, &dsr->h.quatern_c, 4); if(!same_order) swawbip(bptr, 4);
954 bptr=buf1+264;
955 memcpy(bptr, &dsr->h.quatern_d, 4); if(!same_order) swawbip(bptr, 4);
956 bptr=buf1+268;
957 memcpy(bptr, &dsr->h.qoffset_x, 4); if(!same_order) swawbip(bptr, 4);
958 bptr=buf1+272;
959 memcpy(bptr, &dsr->h.qoffset_y, 4); if(!same_order) swawbip(bptr, 4);
960 bptr=buf1+276;
961 memcpy(bptr, &dsr->h.qoffset_z, 4); if(!same_order) swawbip(bptr, 4);
962 bptr=buf1+280;
963 memcpy(bptr, dsr->h.srow_x, 16); if(!same_order) swawbip(bptr, 16);
964 bptr=buf1+296;
965 memcpy(bptr, dsr->h.srow_y, 16); if(!same_order) swawbip(bptr, 16);
966 bptr=buf1+312;
967 memcpy(bptr, dsr->h.srow_z, 16); if(!same_order) swawbip(bptr, 16);
968 bptr=buf1+328;
969 memcpy(bptr, dsr->h.intent_name, 16);
970 bptr=buf1+344;
971 memcpy(bptr, dsr->h.magic, 4);
972
973 /* Open header file for write; do not delete old contents, since this
974 function may be called to update single format NIfTI */
975 if(strcmp(dsr->h.magic, "ni1")==0) { // dual file format
976 if(verbose>2) printf(" creating NIfTI header %s\n", filename);
977 fp=fopen(filename, "wb");
978 } else if(access(filename, 0)==-1) { // single file format, not exists
979 if(verbose>2) printf(" creating NIfTI header %s\n", filename);
980 fp=fopen(filename, "wb");
981 } else { // single file format, exists already
982 if(verbose>2) printf(" opening NIfTI header %s\n", filename);
983 fp=fopen(filename, "r+b");
984 }
985 if(fp==NULL) {
986 if(status!=NULL) strcpy(status, "cannot open Nifti header for write");
987 return(2);
988 }
989
990 /* Write header */
991 if(verbose>2) printf(" writing NIfTI header\n");
992 if(fwrite(buf1, 1, NIFTI_HEADER_SIZE, fp) != NIFTI_HEADER_SIZE) {
993 if(status!=NULL) strcpy(status, "cannot write Nifti header");
994 fclose(fp); return(3);
995 }
996
997 /* Write extender, if necessary (leave the contents 0 0 0 0 for now) */
998 if(verbose>2) printf(" writing NIfTI extender\n");
999 if(fwrite(buf2, 1, NIFTI_HEADER_EXTENDER_SIZE, fp)!= NIFTI_HEADER_EXTENDER_SIZE) {
1000 if(status!=NULL) strcpy(status, "cannot write Nifti header extender");
1001 fclose(fp); return(3);
1002 }
1003
1004 fclose(fp);
1005
1006 if(verbose>2) {printf(" complete Nifti header was written\n"); fflush(stdout);}
1007 if(status!=NULL) strcpy(status, "complete Nifti header was written");
1008 return(0);
1009}
#define NIFTI_HEADER_EXTENDER_SIZE

Referenced by imgWriteNiftiFrame().