cyfile.c
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:17k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. /* module: grid.c grid format database file tools */
  2. /* This module is used to hide the format of the Cyberware type image file
  3.  * for historical reasons this file is in a compressed binary format and
  4.  * may have a header which is inaccessable (easily) by some architectures,
  5.  * especially iAPX xxx86 processors.  Also, the files from the digitizers
  6.  * come in the old non-portable binary header style and in a newer portable
  7.  * ASCII header style.  Use of this module will isolate you from all this
  8.  * ugliness.
  9.  *
  10.  * Use these functions as follows:
  11.  *
  12.  * #include "cyfile.h"
  13.  * GSPEC *cyread(int fd);
  14.  * int cywrite(GSPEC *gs, int fd);
  15.  * int cyfree(GSPEC *gs);
  16.  * long getr(GSPEC *gs, int latitude, int longitude);
  17.  * void putr(GSPEC *gs, int latitude, int longitude, long radius);
  18.  * int cyfree(GSPEC *gs);
  19.  *
  20.  * Cyread() allocates a new set of buffers each time it is called. If
  21.  * this is not what you intend, be sure to call cyfree(gs) first.
  22.  * Opening and closing the file descriptors is up to the caller.
  23.  * GETR() and PUTR() are inline macros for getr() and putr(), they
  24.  * usually execute about twice as fast as the function versions.
  25.  *
  26.  * Use the header variables as follows:
  27.  *
  28.  * char gs->name Image name string (40 characters max).
  29.  * long gs->ltincr Increment between latitudes, y, microns.
  30.  * long gs->lgincr Increment between longitudes, ur or um.
  31.  * short gs->ltmin Data window, min latitude, inclusive.
  32.  * short gs->ltmax Data window, max latitude, inclusive.
  33.  * short gs->lgmin Data window, min longitude, inclusive.
  34.  * short gs->lgmax Data window, max longitude, inclusive.
  35.  * short gs->nlt Total number of latitudes.
  36.  * short gs->nlg Total number of longitudes.
  37.  * long gs->flags Bit flags, as below.
  38.  *
  39.  * FLAG_OLDHEADER Force writing of old style header.
  40.  * FLAG_CARTESIAN Indicates cartesian data, lgincr is
  41.  * in microns (x), radius becomes z. Think
  42.  * of getr() as  z = getr(gs, yi, xi).
  43.  * FLAG_BILATERAL Cartesian and bilateral, ie: nus hands.
  44.  *
  45.  * Use other header variable at own risk.
  46.  */
  47. /* For linux... */
  48. #include <stdio.h>
  49. #include <math.h>
  50. #include <string.h>
  51. #ifdef WIN32
  52. #else
  53. #include <sys/fcntl.h>
  54. #include <unistd.h>
  55. #endif
  56. #include <sys/types.h>
  57. #include <sys/stat.h>
  58. #include <stdlib.h>
  59. #ifdef HIGHC
  60. # include <fcntl.h>
  61. # include <types.h>
  62. # include <stat.h>
  63. # include <io.h>
  64. # include <stdlib.h>
  65. #endif
  66. #include "strings.h"
  67. #include "malloc.h"
  68. #include "cyfile.h"
  69. /* external declarations */
  70. extern int errno;
  71. extern char *ctime();
  72. /* SGI uses off_t now */
  73. extern off_t lseek();
  74. extern void perror();
  75. GSPEC *gsallo();
  76. long getheader();
  77. /*************************** Public Functions ********************************/
  78. /* Cyread optionally allocates buffer space for an image and its header; and
  79.  * optionally reads an image file into these buffers.  If buffers are not
  80.  * yet allocated then call with gs set to NULL.  The return value will be
  81.  * a pointer to the header structure, gs.  If a file is to be read then
  82.  * open a file and pass the descriptor in fd.  If fd is -1 then no files are
  83.  * read and the buffers, if any, have undefined contents.
  84.  */
  85. GSPEC *cyread(gs, fd) /* read data file from fd */
  86. GSPEC *gs;
  87. int fd;
  88. {
  89. /* if gs is NULL allocate gs structure, if fd is not -1 read file */
  90. if (gs == NULL) {
  91. if ((gs = gsallo()) == NULL) { /* allocate header memory */
  92. return(NULL);
  93. }
  94. } else {
  95. if (gs->base != NULL) {
  96. free((char *)gs->base);
  97. gs->base = NULL;
  98. }
  99. }
  100. if (fd != -1) {
  101. if (gsget(gs, fd) == -1) { /* read header */
  102. return(NULL);
  103. }
  104. if (gs->base == NULL) { /* not yet allocated ? */
  105. if (gdallo(gs) == -1) { /* allocate data memory */
  106. return(NULL);
  107. }
  108. }
  109. if (gdget(gs, fd) == -1) { /* read data */
  110. return(NULL);
  111. }
  112. }
  113. return(gs);
  114. }
  115. /* Cywrite writes the header and image data defined by the header to the
  116.  * file with open descriptor fd.  The header and buffer contents are
  117.  * not altered in any way.  Use cyfree to release the buffers if necessary.
  118.  */
  119. int cywrite(gs, fd) /* write data file to fd */
  120. GSPEC *gs;
  121. int fd;
  122. {
  123. if (gsput(gs, fd) == -1) { /* write header */
  124. return(-1);
  125. }
  126. if (gdput(gs, fd) == -1) {
  127. return(-1);
  128. }
  129. return(0);
  130. }
  131. /* Cyfree will release any memory resources associated with the header gs
  132.  * and its image buffer.
  133.  */
  134. void cyfree(gs) /* free private resources */
  135. GSPEC *gs;
  136. {
  137. if (gs != NULL) {
  138. if (gs->base != NULL) {
  139. free((char *)gs->base);
  140. }
  141. free((char *)gs);
  142. }
  143. }
  144. /* Getr and putr are to be used to access the image data.  Please note
  145.  * the histroically backwards order of the arguments lt and lg.
  146.  * Getr may return the value VOID, which is a very large negative number.
  147.  * The return value should always be tested for VOID unless you can be
  148.  * sure that all have been filled.  Putr will accept VOID as the radius
  149.  * argument to store a void value.
  150.  */
  151. long getr(gs, lt, lg) /* a function version of GETR() used globally */
  152. register GSPEC *gs;
  153. register int lt, lg;
  154. {
  155. #ifdef HIGHC
  156. long offset;
  157. unsigned short range_packed;
  158. long range_um;
  159. offset = lg * gs->nlt + lt;
  160. range_packed = *(unsigned short *)(gs->base + offset);
  161. range_packed = range_packed << 8 | range_packed >> 8;
  162. range_um = (long)(short)range_packed << gs->rshift;
  163. return range_um;
  164. #else
  165. return(GETR(gs, lt, lg));
  166. #endif
  167. }
  168. void putr(gs, lt, lg, r) /* a function version of PUTR() used globally */
  169. register GSPEC *gs;
  170. register int lt, lg, r;
  171. {
  172. #ifdef HIGHC
  173. long offset;
  174. unsigned short range_packed;
  175. offset = lg * gs->nlt + lt;
  176. range_packed = (unsigned short)(r >> gs->rshift);
  177. range_packed = range_packed << 8 | range_packed >> 8;
  178. *(gs->base + offset) = (short)range_packed;
  179. #else
  180. PUTR(gs, lt, lg, r);
  181. #endif
  182. }
  183. /*************************** Private Functions *******************************/
  184. /* The loops around read()s facilitate the use of pipes, which may not always
  185.  * read an entire header or data array at one time.  HP Integral i/o is
  186.  * a little slow, so a line of dots is written across stderr to keep the user
  187.  * awake.
  188.  */
  189. int gsget(gs, fd) /* read GSPEC structure from file fd */
  190. GSPEC *gs;
  191. int fd;
  192. {
  193. unsigned count = sizeof(GSPEC); /* number of bytes in header */
  194. char *addr = (char *)gs; /* start of header */
  195. int n;
  196. short *base_save = gs->base; /* save address of start of data */
  197. if (lseek(fd, (long)0, 0) == -1L) { /* seek to beginning of file */
  198. perror(STR026);
  199. return(-1);
  200. }
  201. /* assume the header is of the older binary type */
  202. while (count > 0) {
  203. if ((n = read(fd, addr, count)) == -1) { /* n has number bytes read */
  204. perror(STR027);
  205. gs->base = base_save;
  206. return(-1);
  207. }
  208. count -= n; /* decrement count by number bytes read */
  209. addr += n;  /* update ptr to header structure */
  210. }
  211. /* determine header type */
  212. if (gs->offset != 122 && gs->offset != 114 && gs->offset != 128) {
  213. gs->flags |= FLAG_OLDHEADER;
  214. if (*((char *)gs + 4) == 'r') {
  215. /* reread header as portable type */
  216. if ((gs->offset = getheader(fd)) == -1) {
  217. puts(STR107); /* some format problem */
  218. gs->base = base_save;
  219. return(-1);
  220. }
  221. if (makegsheader(gs) == -1) {
  222. puts(STR107); /* some format problem */
  223. gs->base = base_save;
  224. return(-1);
  225. }
  226. } else {
  227. puts(STR106); /* undefined header type */
  228. gs->base = base_save;
  229. return(-1);
  230. }
  231. }
  232. gs->base = base_save;
  233. gs->saved = 0;
  234. gs->valid = 0;
  235. return(0);
  236. }
  237. int gsput(gs, fd) /* write GSPEC structure to file fd */
  238. GSPEC *gs;
  239. int fd;
  240. {
  241. unsigned count = sizeof(GSPEC);
  242. #ifdef HIGHC
  243. if (lseek(fd, (long)0, 0) == -1) {
  244. perror(STR026);
  245. return(-1);
  246. }
  247. #else
  248. #ifdef WIN32
  249. perror ("Sorry, not implemented in Win32 because of lack of ftruncaten");
  250. return (-1);
  251. #else
  252. if (ftruncate(fd, (long)0) == -1 || lseek(fd, (long)0, 0) == -1) {
  253. perror(STR026);
  254. return(-1);
  255. }
  256. #endif
  257. #endif
  258. if (gs->flags & FLAG_OLDHEADER) {
  259. gs->offset = count;
  260. if (write(fd, (char *)gs, count) != count) {
  261. perror(STR028);
  262. return(-1);
  263. }
  264. } else {
  265. if (writegsheader(gs, fd) == -1) {
  266. return(-1);
  267. }
  268. }
  269. return(0);
  270. }
  271. int gdget(gs, fd) /* read data from grid file fd */
  272. GSPEC *gs;
  273. int fd;
  274. {
  275. unsigned long count = (long)sizeof(short) * (long)gs->nlt * (long)gs->nlg;
  276. unsigned int n;
  277. unsigned int readsize;
  278. char *addr;
  279. unsigned size = count;
  280. /* if unallocated, allocate image memory */
  281. if (gs->base == NULL) {
  282. if (gdallo(gs) == -1) {
  283. return(-1);
  284. }
  285. }
  286. if (lseek(fd, gs->offset, 0) == -1L) {
  287. perror(STR026);
  288. return(-1);
  289. }
  290. addr = (char *)gs->base;
  291. while (count > 0) {
  292. readsize = (unsigned int) MIN(size, count);
  293. if ((n = read(fd, addr, readsize)) == -1L) {
  294. perror(STR027);
  295. return(-1);
  296. }
  297. count -= (unsigned long)n;
  298. addr += n;
  299. }
  300. return(0);
  301. }
  302. int gdput(gs, fd) /* write data to grid file */
  303. GSPEC *gs;
  304. int fd;
  305. {
  306. unsigned long count;
  307. unsigned int n;
  308. unsigned int writesize;
  309. char *addr = (char *)gs->base;
  310. unsigned size = 64*1024; /* a large block size */
  311. count = (long)sizeof(short) * (long)gs->nlt * (long)gs->nlg;
  312. if (gs->flags & FLAG_OLDHEADER) {
  313. if (lseek(fd, (long)gs->offset, 0) == (long)-1) {
  314. perror(STR026);
  315. return(-1);
  316. }
  317. }
  318. while (count > 0) {
  319. writesize = (unsigned int) MIN(size, count);
  320. #ifdef HIGHC
  321. if ((n = _write(fd, addr, writesize)) == -1L) {  /* ??? really?? */
  322. #else
  323. if ((n = write(fd, addr, writesize)) == -1L) {
  324. #endif
  325. perror(STR028);
  326. return(-1);
  327. }
  328. count -= (unsigned long)n;
  329. addr += n;
  330. }
  331. return(0);
  332. }
  333. int gdallo(gs) /* allocate a data buffer */
  334. GSPEC *gs;
  335. {
  336. unsigned long size;
  337. size = (unsigned long)gs->nlt *
  338. (unsigned long)gs->nlg * (unsigned long)sizeof(short);
  339. gs->base = (short *)malloc(size);
  340. if (gs->base == NULL) {
  341. puts(STR082);
  342. return(-1);
  343. } else {
  344. return(0);
  345. }
  346. }
  347. GSPEC *gsallo() /* allocate a GSPEC structure */
  348. {
  349. GSPEC *gs;
  350. gs = (GSPEC *)malloc((unsigned)sizeof(GSPEC));
  351. if (gs == NULL) {
  352. puts(STR082);
  353. return(NULL);
  354. }
  355. gs->base = NULL;
  356. return(gs);
  357. }
  358. #define MAXHEADER 4096 /* ??? might hang on very short files */
  359. #define HEADEREND "DATA=n"
  360. static char *header = 0;
  361. long getheader(fd) /* get header and seek to data */
  362. int fd;
  363. {
  364. int count;
  365. char *end;
  366. char *h;
  367. char *endstr = HEADEREND;
  368. char *temp_header;
  369. char *addr;
  370. int n;
  371. temp_header = malloc(MAXHEADER);
  372. if (lseek(fd, (long)0, 0) == -1) {
  373. perror(STR108);
  374. return(-1);
  375. }
  376. addr = temp_header;
  377. for (count = 0; count < MAXHEADER; count += n) {
  378. if ((n = read(fd, addr, (unsigned)MAXHEADER)) == -1) {
  379. perror(STR109);
  380. return(-1);
  381. }
  382. addr += n;
  383. }
  384. /* end of header is eof or endstr string */
  385. end = temp_header + count;
  386. for (h = temp_header; h < end; ++h) {
  387. if (*h == endstr[0]) {
  388. if (strncmp(endstr, h, strlen(endstr)) == 0) {
  389. end = h + strlen(endstr);
  390. break;
  391. }
  392. }
  393. }
  394. count = end - temp_header;
  395. if (header != 0) {
  396. free(header);
  397. }
  398. header = malloc((unsigned)(count+1));
  399. strncpy(header, temp_header, count);
  400. header[count] = 0; /* null terminate */
  401. free(temp_header);
  402. return(count);
  403. }
  404. int getvalue(name, dest, length)  /* copy value of name to dest or return -1 */
  405. char *name;
  406. char *dest;
  407. int length;
  408. {
  409. char *h = header;
  410. int n;
  411. char *p;
  412. if (header == 0) { /* no header, oops! */
  413. puts("getvalue: no header");
  414. exit(-1); /* fatal coding error */
  415. }
  416. n = strlen(name);
  417. while ((h = strchr(h, 'n')) != 0) { /* move to next newline */
  418. h += 1; /* skip over newline */
  419. if (strncmp(h, name, n) == 0) { /* compare names */
  420. h += strlen(name); /* skip over matched name */
  421. if (*h == '=') { /* verify assignment char */
  422. h += 1;
  423. /* no value terminator ? */
  424. if ((p = strchr(h, 'n')) == 0) {
  425. puts(STR110);
  426. return(-1);
  427. }
  428. *p = 0; /* temporary termination */
  429. strncpy(dest, h, length);
  430. *p = 'n'; /* restore terminator */
  431. return(0);
  432. }
  433. }
  434. }
  435. return(-1); /* no match */
  436. }
  437. #define STRINGLEN 24
  438. int makegsheader(gs) /* fill GSPEC structure from portable header */
  439. GSPEC *gs;
  440. {
  441. char string[STRINGLEN+1];
  442. long i;
  443. string[STRINGLEN] = 0;
  444. /* defaults */
  445. gs->flags = 0;
  446. /* mandatory items */
  447. if (getvalue("NLT", string, STRINGLEN) == -1) {
  448. printf("%s: %sn", STR111, "NLT");
  449. return(-1);
  450. }
  451. gs->nlt = atoi(string);
  452. if (getvalue("NLG", string, STRINGLEN) == -1) {
  453. printf("%s: %sn", STR111, "NLG");
  454. return(-1);
  455. }
  456. gs->nlg = atoi(string);
  457. if (getvalue("LGSHIFT", string, STRINGLEN) == -1) {
  458. printf("%s: %sn", STR111, "LGSHIFT");
  459. return(-1);
  460. }
  461. gs->lgshift = atoi(string);
  462. if (getvalue("LTINCR", string, STRINGLEN) == -1) {
  463. printf("%s: %sn", STR111, "LTINCR");
  464. return(-1);
  465. }
  466. gs->ltincr = atol(string);
  467. if (getvalue("LGINCR", string, STRINGLEN) == -1) {
  468. printf("%s: %sn", STR111, "LGINCR");
  469. return(-1);
  470. }
  471. gs->lgincr = atol(string);
  472. if (getvalue("RSHIFT", string, STRINGLEN) == -1) {
  473. printf("%s: %sn", STR111, "RSHIFT");
  474. return(-1);
  475. }
  476. gs->rshift = atoi(string);
  477. /* optional items */
  478. if (getvalue("NAME", gs->name, NAMELEN) == -1) {
  479. for (i = NAMELEN-1; i >= 0; --i) gs->name[i] = 0;
  480. }
  481. if (getvalue("LTMIN", string, STRINGLEN) == -1) {
  482. gs->ltmin = 0;
  483. } else {
  484. gs->ltmin = atoi(string);
  485. }
  486. if (getvalue("LTMAX", string, STRINGLEN) == -1) {
  487. gs->ltmax = gs->nlt - 1;
  488. } else {
  489. gs->ltmax = atoi(string);
  490. }
  491. if (getvalue("LGMIN", string, STRINGLEN) == -1) {
  492. gs->lgmin = 0;
  493. } else {
  494. gs->lgmin = atoi(string);
  495. }
  496. if (getvalue("LGMAX", string, STRINGLEN) == -1) {
  497. gs->lgmin = gs->nlg - 1;
  498. } else {
  499. gs->lgmax = atoi(string);
  500. }
  501. if (getvalue("RMIN", string, STRINGLEN) == -1) {
  502. gs->rmin = 0;
  503. } else {
  504. gs->rmin = atol(string);
  505. }
  506. if (getvalue("RMAX", string, STRINGLEN) == -1) {
  507. gs->rmax = 0;
  508. } else {
  509. gs->rmax = atol(string);
  510. }
  511. if (getvalue("SCALE", string, STRINGLEN) == -1) {
  512. gs->scale = 100.0;
  513. } else {
  514. gs->scale = atof(string);
  515. }
  516. if (getvalue("RPROP", string, STRINGLEN) == -1) {
  517. gs->rprop = 100.0;
  518. } else {
  519. gs->rprop = atof(string);
  520. }
  521. if (getvalue("FILLED", string, STRINGLEN) == -1) {
  522. gs->filled = 0;
  523. } else {
  524. gs->filled = 1;
  525. }
  526. if (getvalue("SMOOTHED", string, STRINGLEN) == -1) {
  527. gs->smoothed = 0;
  528. } else {
  529. gs->smoothed = 1;
  530. }
  531. if (getvalue("SPACE", string, STRINGLEN) == -1) {
  532. gs->flags = 0;
  533. } else {
  534. if (strcmp(string, "CARTESIAN") == 0) {
  535. gs->flags |= FLAG_CARTESIAN;
  536. } else if (strcmp(string, "CYLINDRICAL") == 0) {
  537. gs->flags &= ~FLAG_CARTESIAN;
  538. } else if (strcmp(string, "BILATERAL") == 0) {
  539. gs->flags |= FLAG_CARTESIAN;
  540. gs->flags |= FLAG_BILATERAL;
  541. } else {
  542. printf("%s: SPACEn", STR112);
  543. return(-1);
  544. }
  545. }
  546. if (getvalue("INSIDE_OUT", string, STRINGLEN) != -1) {
  547. gs->flags |= FLAG_INSIDE_OUT;
  548. }
  549. if (getvalue("COLOR", string, STRINGLEN) != -1) {
  550. gs->flags |= FLAG_COLOR;
  551. }
  552. if (getvalue("THETA_RIGHTHAND", string, STRINGLEN) != -1) {
  553. gs->flags |= FLAG_THETARIGHT;
  554. }
  555. /* forced value items */
  556. gs->time = 0;
  557. gs->camera = 0;
  558. gs->setup = 0;
  559. gs->saved = 0;
  560. gs->valid = 0;
  561. gs->ltsize = gs->nlt * gs->ltincr;
  562. gs->lgsize = gs->nlg * gs->lgincr;
  563. return(0);
  564. }
  565. int writegsheader(gs, fd) /* write a portable header from GSPEC struct */
  566. GSPEC *gs;
  567. int fd;
  568. {
  569. /* Uses 12 instead of n for the sake of DOS which outputs a
  570.  * CR-LF sequence with n !!! */
  571. /* Open a stream on a duplicate file descriptor.  The duplicate is
  572.  * necessary to allow the stream to be closed with out closing the
  573.  * callers file descriptor */
  574. FILE *fp = fdopen(dup(fd), "w");
  575. /* error status only checked on first line and last line */
  576. if (fprintf(fp, "Cyberware Digitizer Data12") < 0) {
  577. perror(STR028);
  578. fclose(fp);
  579. return(-1);
  580. }
  581. fprintf(fp, "NAME=%.40s12", gs->name);
  582. fprintf(fp, "DATE=%s", ctime(&gs->time));
  583. if (gs->flags & FLAG_CARTESIAN) {
  584. if (gs->flags & FLAG_BILATERAL) {
  585. fprintf(fp, "SPACE=BILATERAL12");
  586. } else {
  587. fprintf(fp, "SPACE=CARTESIAN12");
  588. }
  589. } else {
  590. fprintf(fp, "SPACE=CYLINDRICAL12");
  591. }
  592. if (gs->flags & FLAG_COLOR) {
  593. fprintf(fp, "COLOR=SGI12");
  594. }
  595. if (gs->flags & FLAG_INSIDE_OUT) {
  596. fprintf(fp, "INSIDE_OUT=TRUE12");
  597. }
  598. if (gs->flags & FLAG_THETARIGHT) {
  599. fprintf(fp, "THETA_RIGHTHAND=TRUE12");
  600. }
  601. fprintf(fp, "NLG=%-.1d12", gs->nlg);
  602. fprintf(fp, "LGINCR=%-.1ld12", gs->lgincr);
  603. fprintf(fp, "LGMIN=%-.1d12", gs->lgmin);
  604. fprintf(fp, "LGMAX=%-.1d12", gs->lgmax);
  605. fprintf(fp, "NLT=%-.1d12", gs->nlt);
  606. fprintf(fp, "LTINCR=%-.1ld12", gs->ltincr);
  607. fprintf(fp, "LTMIN=%-.1d12", gs->ltmin);
  608. fprintf(fp, "LTMAX=%-.1d12", gs->ltmax);
  609. fprintf(fp, "RMIN=%-.1ld12", gs->rmin);
  610. fprintf(fp, "RMAX=%-.1ld12", gs->rmax);
  611. fprintf(fp, "RSHIFT=%-.1d12", gs->rshift);
  612. fprintf(fp, "LGSHIFT=%-.1d12", gs->lgshift);
  613. fprintf(fp, "SCALE=%-.2f12", (float)gs->scale);
  614. fprintf(fp, "RPROP=%-.2f12", (float)gs->rprop);
  615. if (gs->filled) {
  616. fprintf(fp, "FILLED=112");
  617. }
  618. if (gs->smoothed) {
  619. fprintf(fp, "SMOOTHED=112");
  620. }
  621. fprintf(fp, "DATA=12");
  622. if (fflush(fp) == EOF) {
  623. perror(STR028);
  624. fclose(fp);
  625. return(-1);
  626. }
  627. fclose(fp);
  628. return(0);
  629. }