include include include include include # These routines maintain an arbitrary number of indexed "open" images which # must be READ_ONLY. The calling program may use the returned pointer for # header accesses but must call xt_opix before I/O. Subsequent calls to # xt_opix may invalidate the pointer. The xt_imunmap call will free memory. define MAX_OPENIM (LAST_FD-16) # Maximum images kept open define MAX_OPENPIX 45 # Maximum pixel files kept open define XT_SZIMNAME 99 # Size of IMNAME string define XT_LEN 56 # Structure length define XT_IMNAME Memc[P2C($1)] # Image name define XT_ARG Memi[$1+50] # IMMAP header argument define XT_BUFSIZE Memi[$1+51] # Buffer size define XT_IM Memi[$1+52] # IMIO pointer define XT_HDR Memi[$1+53] # Copy of IMIO pointer define XT_CLOSEFD Memi[$1+54] # Close FD? define XT_FLAG Memi[$1+55] # Flag # Options define XT_MAPUNMAP 1 # Map and unmap images. # XT_IMMAP -- Map an image and save it as an indexed open image. # The returned pointer may be used for header access but not I/O. # The indexed image is closed by xt_imunmap. pointer procedure xt_immap (imname, acmode, hdr_arg, index) char imname[ARB] #I Image name int acmode #I Access mode int hdr_arg #I Header argument int index #I Save index pointer im #O Image pointer (returned) int i, envgeti() pointer xt, xt_opix() errchk xt_opix int first_time data first_time /YES/ include "xtimmap.com" begin if (acmode != READ_ONLY) call error (1, "XT_IMMAP: Only READ_ONLY allowed") # Initialize once per process. if (first_time == YES) { iferr (option = envgeti ("imcombine_option")) option = 0 min_open = 1 nopen = 0 nopenpix = 0 nalloc = MAX_OPENIM call calloc (ims, nalloc, TY_POINTER) first_time = NO } # Free image if needed. call xt_imunmap (NULL, index) # Allocate structure. if (index > nalloc) { i = nalloc nalloc = index + MAX_OPENIM call realloc (ims, nalloc, TY_STRUCT) call amovki (NULL, Memi[ims+i], nalloc-i) } call calloc (xt, XT_LEN, TY_STRUCT) Memi[ims+index-1] = xt # Initialize. call strcpy (imname, XT_IMNAME(xt), XT_SZIMNAME) XT_ARG(xt) = hdr_arg XT_BUFSIZE(xt) = INDEFI XT_IM(xt) = NULL XT_HDR(xt) = NULL # Open image. last_flag = 0 im = xt_opix (NULL, index, 0) # Make copy of IMIO pointer for header keyword access. call malloc (XT_HDR(xt), IMU+IM_HDRLEN(im), TY_STRUCT) call amovi (Memi[im], Memi[XT_HDR(xt)], IMD+IM_HDRLEN(im)) return (XT_HDR(xt)) end # XT_OPIX -- Open the image for I/O. # If the image has not been mapped return the default pointer. pointer procedure xt_opix (imdef, index, flag) int index #I index pointer imdef #I Default pointer int flag #I Flag int i, open() pointer xt, xt1, immap() errchk open, immap, imunmap include "xtimmap.com" begin xt = NULL if (index <= nalloc && index > 0) xt = Memi[ims+index-1] # Return default if index has not been opened. if (xt == NULL) return (imdef) # Close images not accessed during previous flag value. if (flag != last_flag) { do i = 1, nalloc { xt1 = Memi[ims+i-1] if (xt1 == NULL) next if (XT_IM(xt1) == NULL || XT_FLAG(xt1) == last_flag) next call imunmap (XT_IM(xt1)) XT_IM(xt1) = NULL nopen = nopen - 1 if (XT_CLOSEFD(xt1) == NO) nopenpix = nopenpix - 1 } # Optimize the file I/O. do i = nalloc, 1, -1 { xt1 = Memi[ims+i-1] if (xt1 == NULL) next if (XT_IM(xt1) == NULL) next min_open = i if (nopenpix < MAX_OPENPIX) { if (XT_CLOSEFD(xt1) == NO) next XT_CLOSEFD(xt1) = NO call imseti (XT_IM(xt1), IM_CLOSEFD, NO) call imseti (XT_IM(xt1), IM_ADVICE, SEQUENTIAL) nopenpix = nopenpix + 1 } } last_flag = flag } # Return pointer for already opened images. if (XT_IM(xt) != NULL) { XT_FLAG(xt) = flag return (XT_IM(xt)) } # Handle more images than the maximum that can be open at one time. if (nopen >= MAX_OPENIM) { if (option == XT_MAPUNMAP || flag == 0) { do i = min_open, nalloc { xt1 = Memi[ims+i-1] if (xt1 == NULL) next if (XT_IM(xt1) == NULL) next call imunmap (XT_IM(xt1)) nopen = nopen - 1 if (XT_CLOSEFD(xt1) == NO) nopenpix = nopenpix - 1 min_open = i + 1 break } if (index <= min_open) min_open = index else { do i = min_open, nalloc { xt1 = Memi[ims+i-1] if (xt1 == NULL) next if (XT_IM(xt1) == NULL) next min_open = i break } } } else { # Check here because we can't catch error in immap. i = open ("dev$null", READ_ONLY, BINARY_FILE) call close (i) if (i == LAST_FD - 1) call error (SYS_FTOOMANYFILES, "Too many open files") } } # Open image. XT_IM(xt) = immap (XT_IMNAME(xt), READ_ONLY, XT_ARG(xt)) if (!IS_INDEFI(XT_BUFSIZE(xt))) call imseti (XT_IM(xt), IM_BUFSIZE, XT_BUFSIZE(xt)) nopen = nopen + 1 XT_CLOSEFD(xt) = YES if (nopenpix < MAX_OPENPIX) { XT_CLOSEFD(xt) = NO nopenpix = nopenpix + 1 } if (XT_CLOSEFD(xt) == YES) call imseti (XT_IM(xt), IM_CLOSEFD, YES) XT_FLAG(xt) = flag return (XT_IM(xt)) end # XT_CPIX -- Close image. pointer procedure xt_cpix (index) int index #I index pointer xt errchk imunmap include "xtimmap.com" begin xt = NULL if (index <= nalloc && index > 0) xt = Memi[ims+index-1] if (xt == NULL) return if (XT_IM(xt) != NULL) { call imunmap (XT_IM(xt)) nopen = nopen - 1 if (XT_CLOSEFD(xt) == NO) nopenpix = nopenpix - 1 } end # XT_IMSETI -- Set IMIO value. procedure xt_imseti (index, param, value) int index #I index int param #I IMSET parameter int value #I Value pointer xt bool streq() include "xtimmap.com" begin xt = NULL if (index <= nalloc && index > 0) xt = Memi[ims+index-1] if (xt == NULL) { if (streq (param, "option")) option = value } else { if (streq (param, "bufsize")) { XT_BUFSIZE(xt) = value if (XT_IM(xt) != NULL) call imseti (XT_IM(xt), IM_BUFSIZE, value) } } end # XT_IMUNMAP -- Unmap indexed open image. # The header pointer is set to NULL to indicate the image has been closed. procedure xt_imunmap (im, index) int im #U IMIO header pointer int index #I index pointer xt errchk imunmap include "xtimmap.com" begin # Check for an indexed image. If it is not unmap the pointer # as a regular IMIO pointer. xt = NULL if (index <= nalloc && index > 0) xt = Memi[ims+index-1] if (xt == NULL) { if (im != NULL) call imunmap (im) return } # Close indexed image. if (XT_IM(xt) != NULL) { iferr (call imunmap (XT_IM(xt))) { XT_IM(xt) = NULL call erract (EA_WARN) } nopen = nopen - 1 if (XT_CLOSEFD(xt) == NO) nopenpix = nopenpix - 1 if (index == min_open) min_open = 1 } # Free header pointer. Note that if the supplied pointer is not # header pointer then it is not set to NULL. if (XT_HDR(xt) == im) im = NULL call mfree (XT_HDR(xt), TY_STRUCT) # Free save structure. call mfree (Memi[ims+index-1], TY_STRUCT) end # XT_REINDEX -- Reindex open images. # This is used when some images are closed by xt_imunmap. It is up to # the calling program to reindex the header pointers and to subsequently # use the new index values. procedure xt_reindex () int old, new include "xtimmap.com" begin new = 0 do old = 0, nalloc-1 { if (Memi[ims+old] == NULL) next Memi[ims+new] = Memi[ims+old] new = new + 1 } do old = new, nalloc-1 Memi[ims+old] = NULL end