aboutsummaryrefslogtreecommitdiff
path: root/noao/imred/dtoi/hdtoi.x
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /noao/imred/dtoi/hdtoi.x
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'noao/imred/dtoi/hdtoi.x')
-rw-r--r--noao/imred/dtoi/hdtoi.x407
1 files changed, 407 insertions, 0 deletions
diff --git a/noao/imred/dtoi/hdtoi.x b/noao/imred/dtoi/hdtoi.x
new file mode 100644
index 00000000..5b550ea8
--- /dev/null
+++ b/noao/imred/dtoi/hdtoi.x
@@ -0,0 +1,407 @@
+include <imhdr.h>
+include <mach.h>
+include <math/curfit.h>
+include <error.h>
+include "hdicfit/hdicfit.h"
+
+# T_HDTOI -- transform an image from density to intensity, according
+# to an hd curve described in an input database. A look up table of
+# all possible values is generated with the curfit package, and
+# then the image is transformed line by line. A fog value is subtracted
+# from the image prior to transformation, and it can be entered as either
+# a number or a list of fog images from which the fog value is calculated.
+# If a fog value has not been entered by the user, it is read from the database.
+
+procedure t_hdtoi ()
+
+pointer sp, cv, fog, db, im_in, lut, im_out, imageout, imagein, option
+bool verbose
+int minval, maxval, in_list, rec, ip, out_list, fog_list, ngpix
+int datatype, nluv, updatedb, nfpix
+real sigma, floor, scale, fog_val, sdev
+
+char clgetc()
+bool streq(), clgetb()
+pointer ddb_map(), immap()
+int imtopenp(), ddb_locate(), ctor(), imtlen(), imtgetim()
+int get_data_type(), imtopen()
+real clgetr(), ddb_getr()
+
+begin
+ call smark (sp)
+ call salloc (cv, SZ_FNAME, TY_CHAR)
+ call salloc (fog, SZ_LINE, TY_CHAR)
+ call salloc (imageout, SZ_FNAME, TY_CHAR)
+ call salloc (imagein, SZ_FNAME, TY_CHAR)
+
+ # Get cl parameters
+ in_list = imtopenp ("input")
+ out_list = imtopenp ("output")
+ call clgstr ("database", Memc[cv], SZ_FNAME)
+ call clgstr ("fog", Memc[fog], SZ_LINE)
+ sigma = clgetr ("sigma")
+ floor = clgetr ("floor")
+ verbose = clgetb ("verbose")
+ updatedb = NO
+
+ datatype = get_data_type (clgetc ("datatype"))
+ if (datatype == ERR)
+ call eprintf ("Using input pixel datatype for output\n")
+
+ db = ddb_map (Memc[cv], READ_ONLY)
+ rec = ddb_locate (db, "common")
+ scale = ddb_getr (db, rec, "scale")
+
+ # If not specified by user, get fog value from database. User can
+ # specify fog as a real number or a list of fog file names.
+
+ if (streq (Memc[fog], "")) {
+ rec = ddb_locate (db, "fog")
+ fog_val = ddb_getr (db, rec, "density")
+ } else {
+ ip = 1
+ if (ctor (Memc[fog], ip, fog_val) == 0) {
+ if (verbose)
+ call eprintf ("Calculating fog value ...\n")
+ fog_list = imtopen (Memc[fog])
+ call salloc (option, SZ_FNAME, TY_CHAR)
+ call clgstr ("option", Memc[option], SZ_FNAME)
+ call hd_fogcalc (fog_list, fog_val, sdev, ngpix, scale, sigma,
+ Memc[option], nfpix)
+
+ call eprintf ("Fog density = %f, sdev = %f, ngpix = %d\n")
+ call pargr (fog_val)
+ call pargr (sdev)
+ call pargi (ngpix)
+
+ updatedb = YES
+ }
+ }
+
+ # Generate look up table. First, the range of input values to
+ # calculate output values for must be determined. Arguments
+ # minval and maxval are integers because we assume all input
+ # images are short integers.
+
+ call hd_glimits (in_list, minval, maxval)
+ nluv = (maxval - minval) + 1
+ call salloc (lut, nluv, TY_REAL)
+
+ if (verbose)
+ call eprintf ("Generating look up table ...\n")
+ call hd_wlut (db, Memr[lut], minval, maxval, fog_val, floor)
+
+ # Loop through input images, applying transform
+ if (imtlen (in_list) != imtlen (out_list)) {
+ call imtclose (in_list)
+ call imtclose (out_list)
+ call error (0, "Number of input and output images not the same")
+ }
+
+ while ((imtgetim (in_list, Memc[imagein], SZ_FNAME) != EOF) &&
+ (imtgetim (out_list, Memc[imageout], SZ_FNAME) != EOF)) {
+
+ iferr (im_in = immap (Memc[imagein], READ_ONLY, 0)) {
+ call erract (EA_WARN)
+ next
+ }
+
+ iferr (im_out = immap (Memc[imageout], NEW_COPY, im_in)) {
+ call imunmap (im_in)
+ call erract (EA_WARN)
+ next
+ }
+
+ if (verbose) {
+ call eprintf ("Density to Intensity Transform: %s ===> %s\n")
+ call pargstr (Memc[imagein])
+ call pargstr (Memc[imageout])
+ }
+
+ call hd_transform (im_in, im_out, Memr[lut], nluv, minval, datatype)
+
+ call imunmap (im_in)
+ call imunmap (im_out)
+ }
+
+ call ddb_unmap (db)
+ call imtclose (in_list)
+ call imtclose (out_list)
+
+ if (updatedb == YES) {
+ db = ddb_map (Memc[cv], APPEND)
+ # Write fog information to database as single record
+ call ddb_prec (db, "fog")
+ call ddb_putr (db, "density", fog_val)
+ call ddb_putr (db, "sdev", sdev)
+ call ddb_puti (db, "ngpix", ngpix)
+ call ddb_pstr (db, "option", Memc[option])
+ call ddb_unmap (db)
+ }
+
+ call sfree (sp)
+end
+
+
+# HD_TRANSFORM -- Apply transformation to image.
+
+procedure hd_transform (im, im_out, lu_table, nvals, minval, datatype)
+
+pointer im # Input image header pointer
+pointer im_out # Transformed image header pointer
+real lu_table[ARB] # Array of intensity values
+int nvals # Number of values in the lut
+int minval # Offset to first value in look up table
+int datatype # Pixel type on output
+
+int j, ncols
+pointer ptr_in, ptr_out, sp, luti
+pointer impl2r(), imgl2i(), impl2i()
+
+begin
+ if (datatype == ERR)
+ IM_PIXTYPE(im_out) = IM_PIXTYPE(im)
+ else
+ IM_PIXTYPE(im_out) = datatype
+
+ ncols = IM_LEN(im,1)
+
+ switch (datatype) {
+ case TY_REAL, TY_DOUBLE:
+ # Loop over input image rows. The look up table is left as
+ # a real array and a floating point image is written out.
+
+ do j = 1, IM_LEN(im,2) {
+ ptr_in = imgl2i (im, j)
+ ptr_out = impl2r (im_out, j)
+ call asubki (Memi[ptr_in], minval, Memi[ptr_in], ncols)
+ call alutr (Memi[ptr_in], Memr[ptr_out], ncols, lu_table)
+ }
+
+ default:
+ # Loop over input image rows. The look up table is truncated
+ # to type integer.
+
+ call smark (sp)
+ call salloc (luti, nvals, TY_INT)
+ call achtri (lu_table, Memi[luti], nvals)
+
+ do j = 1, IM_LEN(im,2) {
+ ptr_in = imgl2i (im, j)
+ ptr_out = impl2i (im_out, j)
+ call asubki (Memi[ptr_in], minval, Memi[ptr_in], ncols)
+ call aluti (Memi[ptr_in], Memi[ptr_out], ncols, Memi[luti])
+ }
+
+ call sfree (sp)
+ }
+end
+
+
+# HD_WLUT -- write look up table, such that intensity = lut [a/d output].
+# An entry is made in the look up table for every possible input value,
+# from minval to maxval.
+
+procedure hd_wlut (db, lut, minval, maxval, fog_val, floor)
+
+pointer db # Pointer to database file
+real lut[ARB] # Pointer to look up table, which gets filled here
+int minval # Minimum value to transform
+int maxval # Maximum value to transform
+real fog_val # Fog value to be subtracted from densities
+real floor # Value assigned to densities below fog
+
+bool zerofloor
+pointer sp, trans, fcn, save, cv, dens, ind_var, value
+int rec, nsave, i, function, nneg, npos, nvalues
+real scale, maxcvval, factor, maxexp, maxden, maxdenaf
+
+bool fp_equalr()
+int strncmp(), ddb_locate(), ddb_geti(), cvstati()
+real ddb_getr(), clgetr(), cveval()
+extern hd_powerr()
+
+begin
+ call smark (sp)
+ call salloc (trans, SZ_FNAME, TY_CHAR)
+ call salloc (fcn, SZ_FNAME, TY_CHAR)
+
+ nvalues = (maxval - minval) + 1
+ call salloc (ind_var, nvalues, TY_REAL)
+ call salloc (dens, nvalues, TY_REAL)
+ call salloc (value, nvalues, TY_REAL)
+
+ rec = ddb_locate (db, "common")
+ scale = ddb_getr (db, rec, "scale")
+ maxden = ddb_getr (db, rec, "maxden")
+
+ rec = ddb_locate (db, "cv")
+ nsave = ddb_geti (db, rec, "save")
+ call salloc (save, nsave, TY_REAL)
+ call ddb_gar (db, rec, "save", Memr[save], nsave, nsave)
+ call ddb_gstr (db, rec, "transformation", Memc[trans], SZ_LINE)
+
+ call cvrestore (cv, Memr[save])
+ function = cvstati (cv, CVTYPE)
+
+ if (function == USERFNC) {
+ # Need to restablish choice of user function
+ call ddb_gstr (db, rec, "function", Memc[fcn], SZ_FNAME)
+ if (strncmp (Memc[fcn], "power", 1) == 0)
+ call cvuserfnc (cv, hd_powerr)
+ else
+ call error (0, "Unknown user function in database")
+ }
+
+ maxdenaf = maxden - fog_val
+ call hd_aptrans (maxdenaf, maxcvval, 1, Memc[trans])
+ maxcvval = 10.0 ** (cveval (cv, maxcvval))
+ factor = clgetr ("ceiling") / maxcvval
+ maxexp = real (MAX_EXPONENT) - (log10 (factor) + 1.0)
+
+ zerofloor = false
+ if (fp_equalr (0.0, floor))
+ zerofloor = true
+
+ do i = 1, nvalues
+ Memr[value+i-1] = real (minval + i - 1)
+
+ # Scale all posible voltage values to density above fog
+ call altmr (Memr[value], Memr[dens], nvalues, scale, -fog_val)
+
+ # Find index of first value greater than MIN_DEN. Values less than
+ # this must be handled as the user specified with the floor parameter.
+
+ for (nneg=0; Memr[dens+nneg] < MIN_DEN; nneg=nneg+1)
+ ;
+ npos = nvalues - nneg
+
+ # Generate independent variable vector and then lut values. The
+ # logic is different if there are values below fog. Evaluating
+ # the polynomial fit with cvvector yields the log exposure. This
+ # is then converted to intensity and scaled by a user supplied factor.
+
+ if (nneg > 0) {
+ if (zerofloor) {
+ call amovkr (0.0, lut, nneg)
+ call hd_aptrans (Memr[dens+nneg],Memr[ind_var],npos,Memc[trans])
+ call cvvector (cv, Memr[ind_var], lut[nneg+1], npos)
+ call argtr (lut[nneg+1], npos, maxexp, maxexp)
+ do i = nneg+1, nvalues
+ lut[i] = (10. ** lut[i]) * factor
+
+ } else {
+ call amulkr (Memr[dens], -1.0, Memr[dens], nneg)
+
+ # Care must be taken so that no density of value 0.0 is
+ # passed to hd_aptrans. This would cause an overflow.
+
+ do i = 1, nneg {
+ if (fp_equalr (Memr[dens], 0.0))
+ Memr[dens] = MIN_DEN
+ }
+
+ call hd_aptrans (Memr[dens],Memr[ind_var], nvalues, Memc[trans])
+ call cvvector (cv, Memr[ind_var], lut, nvalues)
+ call argtr (lut, nvalues, maxexp, maxexp)
+ do i = 1, nvalues
+ lut[i] = (10.0 ** lut[i]) * factor
+ call amulkr (lut, -1.0, lut, nneg)
+ }
+
+ } else {
+ call hd_aptrans (Memr[dens], Memr[ind_var], nvalues, Memc[trans])
+ call cvvector (cv, Memr[ind_var], lut, nvalues)
+ call argtr (lut, nvalues, maxexp, maxexp)
+ do i = 1, nvalues
+ lut[i] = (10.0 ** lut[i]) * factor
+ }
+
+ call cvfree (cv)
+ call sfree (sp)
+end
+
+
+# HD_APTRANS -- Apply transformation, generating a vector of independent
+# variables from a density vector. It is assummed all values in the
+# input density vector are valid and will not cause arithmetic errors.
+# No checking for out of bounds values is performed.
+
+procedure hd_aptrans (density, ind_var, nvalues, transform)
+
+real density[nvalues] # Density vector - input
+real ind_var[nvalues] # Ind variable vector - filled on output
+int nvalues # Length of vectors
+char transform[ARB] # String containing transformation type
+
+int i
+int strncmp()
+
+begin
+ if (strncmp (transform, "logopacitance", 1) == 0) {
+ do i = 1, nvalues
+ ind_var[i] = log10 ((10. ** density[i]) - 1.0)
+
+ } else if (strncmp (transform, "k75", 2) == 0) {
+ do i = 1, nvalues
+ ind_var[i] = density[i] + .75 * log10(1. - 10. ** (-density[i]))
+
+ } else if (strncmp (transform, "k50", 2) == 0) {
+ do i = 1, nvalues
+ ind_var[i] = density[i] + .50 * log10(1. - 10. ** (-density[i]))
+
+ } else if (strncmp (transform, "none", 1) == 0) {
+ do i = 1, nvalues
+ ind_var[i] = density[i]
+
+ } else
+ call error (0, "Unrecognized transformation in database file")
+end
+
+
+# HD_GLIMITS -- Determinine the range of max and min values for a list
+# of images.
+
+procedure hd_glimits (in_list, minval, maxval)
+
+int in_list # File descriptor for list of images
+int minval # Smallest pixel value - returned
+int maxval # Largest pixel value - returned
+
+pointer im
+char image[SZ_FNAME]
+real current_min, current_max, min, max
+pointer immap()
+int imtgetim()
+errchk imtgetim, im_minmax, imtrew
+
+begin
+ current_min = MAX_REAL
+ current_max = EPSILONR
+
+ while (imtgetim (in_list, image, SZ_FNAME) != EOF) {
+ iferr (im = immap (image, READ_ONLY, 0))
+ # Just ignore it, warning will be printed by t_hdtoi
+ next
+
+ # Update min max values if necessary
+ if (IM_LIMTIME(im) < IM_MTIME(im))
+ call im_minmax (im, IM_MIN(im), IM_MAX(im))
+
+ min = IM_MIN(im)
+ max = IM_MAX(im)
+
+ if (min < current_min)
+ current_min = min
+
+ if (max > current_max)
+ current_max = max
+
+ call imunmap (im)
+ }
+
+ minval = int (current_min)
+ maxval = int (current_max)
+
+ call imtrew (in_list)
+end