/* File : IMAGE.C Description: Image Access for MEPIX Author : Peter H. Michalicka Environment: HP-UX 8.05 */ #include #include #ifndef WIN32 #include #endif #include #include #include "tiff.h" #include "vma.h" /* Code */ extern char *msg_fopen; extern char *msg_fwrite; extern char *msg_fread; WorkFile t; char *msg_malloc = "Cant allocate enough memory"; #ifdef ANSI int open_ibuf(char *fname); int fillbuf(void); void getbuf(int size, BYTE *ptr); int tiff_hdr(char *fnam, vma *v); int gp4_hdr(char *fnam, vma *v); int tiff_reader(vma *v); int error(char *fmt, char *str); #endif /* Code */ /* close_image() - Return Values TRUE ... success FALSE .. failure */ void close_image(v) vma *v; /* (I) .. close(v->fd) && free memory */ { int i; if (v->bl != NULL) { for (i = 0; i < v->rblocks; i++) { if (v->bl[i] != NULL) free(v->bl[i]); } free(v->bl); } if (v->ofs != NULL) free(v->ofs); if (v->mbd != NULL) free(v->mbd); if (v->fp != NULL) fclose(v->fp); if (v->fn != NULL) { unlink(v->fn); free(v->fn); } free(v); } static int age(n, v) int n; /* (I) .. dont age block n */ vma *v; /* (I) .. vma struct */ { int i; for (i = 0; i < v->rblocks; i++) { if (i != n) v->mbd[i].asu++; /* inc. the age of all except n */ } } static int write_rlf(v) vma *v; /* (I) .. v->fp && v->ImageXXX */ { char *ptr; int iblkofs, blkofs, nblk; int i, j, n, maxcol; WORD re, runs, *rb; v->mbd[0].blkno = v->nblocks = nblk = blkofs = 0; ptr = v->bl[0]; maxcol = v->ImageWidth + 1; for (i = 1; i <= v->ImageLength; i++) { #ifndef _WIN32 getbuf(sizeof(WORD), (BYTE *)&runs); #else getbuf(sizeof(WORD), (BYTE *)&re); runs = (re >> 8) + (WORD)(re << 8); /* swap run */ #endif if (runs) { n = runs << 2; /* 2 runs with 2 byte */ if ((blkofs + sizeof(WORD) + n) >= v->blocksize) { /* check if fit to block */ if (fwrite(ptr, v->blocksize, 1, v->fp) != 1) return error(msg_fwrite, v->fn); v->nblocks++; if (++nblk >= v->rblocks) /* check resident blocks */ nblk = 0; v->mbd[nblk].blkno = v->nblocks; ptr = v->bl[nblk]; blkofs = 0; } iblkofs = blkofs; memcpy(ptr + blkofs, &runs, sizeof(WORD)); blkofs += sizeof(WORD); rb = (WORD *)(ptr + blkofs); getbuf(n, (BYTE *)rb); blkofs += n; n >>= 1; /* # of runentries */ n--; for (j = 0; j < (int)runs; j++, n--) { #ifdef _WIN32 re = rb[j]; rb[j] = (re >> 8) + (WORD)(re << 8); /* swap run */ re = rb[n]; rb[n] = (re >> 8) + (WORD)(re << 8); /* swap run */ #endif re = maxcol - rb[j]; rb[j] = maxcol - rb[n]; rb[n] = re; } } else { if ((blkofs + sizeof(WORD)) >= v->blocksize) { /* check if fit to block */ if (fwrite(ptr, v->blocksize, 1, v->fp) != 1) return error(msg_fwrite, v->fn); v->nblocks++; if (++nblk >= v->rblocks) /* check resident blocks */ nblk = 0; v->mbd[nblk].blkno = v->nblocks; ptr = v->bl[nblk]; blkofs = 0; } iblkofs = blkofs; memcpy(ptr + blkofs, &runs, sizeof(WORD)); blkofs += sizeof(WORD); } v->ofs[i].blkno = (WORD)v->nblocks; v->ofs[i].offset = (WORD)iblkofs; } if (blkofs) return fwrite(ptr, v->blocksize, 1, v->fp); /* write last block */ return TRUE; } /* open_image() - Return Values vma *v ... Pointer to vma struct NULL ..... VMA failed */ vma *open_image(imagefile, tmpdir, maxmem, blksize, extension) char *imagefile; /* (I) .. filename of image */ char *tmpdir; /* (I) .. vma swap directory */ long maxmem; /* (I) .. max. memory to allocate for vma */ int blksize; /* (I) .. blocksize of vma */ char *extension; /* (I) .. Extension Type || NULL */ { WORD w, tmp; int i, ftype, failed; vma *v; if ((v = (vma *)malloc(sizeof(vma))) == NULL) { error(msg_malloc, NULL); return NULL; } if (extension == NULL) { i = strlen(imagefile); extension = imagefile + i - 3; } if (strcmp(extension, "rlc") == 0) { ftype = 1; if (! open_ibuf(imagefile) || ! fillbuf()) return NULL; #ifndef _WIN32 getbuf(sizeof(WORD), (BYTE *)&w); #else getbuf(sizeof(WORD), (BYTE *)&tmp); w = (tmp >> 8) + (WORD)(tmp << 8); /* swap run */ #endif v->ImageLength = w; #ifndef _WIN32 getbuf(sizeof(WORD), (BYTE *)&w); #else getbuf(sizeof(WORD), (BYTE *)&tmp); w = (tmp >> 8) + (WORD)(tmp << 8); /* swap run */ #endif v->ImageWidth = w; } else if (strcmp(extension, "tif") == 0) { ftype = 2; if (! tiff_hdr(imagefile, v)) return NULL; } else if (strcmp(extension, "gp4") == 0) { ftype = 2; if (! gp4_hdr(imagefile, v)) return NULL; } else { /* unknown file format */ error("Extension %s unknown", extension); return NULL; } v->bl = NULL; v->mbd = NULL; v->ofs = NULL; if (blksize < v->ImageWidth) blksize = v->ImageWidth; /* single run must be in block */ v->rblocks = maxmem / blksize; if (! v->rblocks) v->rblocks = 1; /* savety first */ v->blocksize = blksize; v->mbd = (mem_bd *)malloc(sizeof(mem_bd) * v->rblocks); v->bl = (char **)malloc(sizeof(char *) * v->rblocks); v->ofs = (RLCofs *)malloc(sizeof(RLCofs) * (1 + (int)v->ImageLength)); if (v->mbd == NULL || v->bl == NULL || v->ofs == NULL) { close_image(v); error(msg_malloc, NULL); return NULL; } /* mark all blocks as not in use */ for (i = failed = 0; i < v->rblocks; i++) { v->mbd[i].asu = 1; /* must be see image_ptr() */ v->bl[i] = (char *)malloc(blksize); if (v->bl[i] == NULL) failed = TRUE; } if (failed) { close_image(v); return NULL; } /* allocate space for a copy of filename */ v->fn = (char *)tempnam(tmpdir, "trlc"); if (v->fn == NULL) { close_image(v); error("Temporary file failed", NULL); return NULL; } if ((v->fp = fopen(v->fn, "wb")) == NULL) { error(msg_fopen, v->fn); close_image(v); return NULL; } switch (ftype) { case 1: /* RLC */ if (! write_rlf(v)) { close_image(v); return NULL; } break; case 2: /* TIFF */ if (! tiff_reader(v)) { close_image(v); return NULL; } break; } /* esac */ fclose(t.fpi); fclose(v->fp); if ((v->fp = fopen(v->fn, "rb")) == NULL) { error(msg_fopen, v->fn); close_image(v); return NULL; } return v; } WORD *image_ptr(v) vma *v; /* (I) .. v->LineNo */ { int i, n, oldest; int line, blkno, offset; mem_bd *m; line = v->LineNo; blkno = v->ofs[line].blkno; offset = v->ofs[line].offset; for (i = n = 0; i < v->rblocks; i++) { m = &v->mbd[i]; if (m->blkno == blkno) break; /* block found */ if (m->asu > n) { n = m->asu; /* find least recently used block */ oldest = i; } } if (i < v->rblocks) { age(i, v); return (WORD *)(v->bl[i] + offset); } fseek(v->fp, blkno * v->blocksize, SEEK_SET); if (fread(v->bl[oldest], v->blocksize, 1, v->fp) != 1) { error(msg_fread, v->fn); return NULL; } m = &v->mbd[oldest]; m->blkno = blkno; m->asu = 0; age(oldest, v); return (WORD *)(v->bl[oldest] + offset); }