next up previous
Next: Software Sites Up: Animating the Evolution of Previous: Data Extraction Routine

Routines for Converting to PNM Format

The main routine used to convert the raw files to PGM or PPM files is rw2pnm. (As mention previously, it is important to note that the C version of this code, which is available from the Web site, is much simpler and significantly faster than this Fortran code.) This program relies upon the subroutines cmap1 and cmap2 to generate the one-sided and two-sided color maps, respectively. The subroutine hsvrgb is used to convert from values in HSV space to RGB values. The complete program listing for rw2pnm and its subroutines follows:

      program rw2pnm                                                          1
C.....                                                                        2
C     This program converts "raw" binary files to pgm or ppm files.           3
C     Log compression can be used.                                            4
C.....                                                                        5
      implicit real (a-h,o-z)                                                 6
      character base*1024, filein*1024, filout*1024,                          7
     &     frmt*20, ccol*4, crow*4, tail(2)*4                                 8
      logical input, output                                                   9
      data tail /'.pgm', '.ppm'/                                             10
C.....                                                                       11
C     h,s,v    = hue, saturation, and brightness (or "value") for pixel      12
C     ir,ig,ib = corresponding red, green, and blue values for pixel         13
C     eps      = "small" number added to data to prevent underflows          14
C     xnorm    = number used to normalize all input                          15
C     xpnt     = the current field value obtained from the input file        16
C     i,j      = dummy counters                                              17
C     iin,iout = record pointers for the input and output files              18
C     irow,icol= number of rows and columns of data (integers)               19
C     crow,ccol= number of rows and columns of data (characters)             20
C     nframe   = current frame number                                        21
C     ndigit   = number of decimal digits in the current frame number        22
C     ndec     = number of decades of compression                            23
C     input,output = true if input/output file exists (logical)              24
C     base     = base input and output file names                            25
C     filein,filout = complete input and output file names                   26
C     frmt     = internal file used to construct file names                  27
C     iside    = indicates two-sided or one-sided data                       28
C     icolor   = indicates color or grayscale                                29
C     tail     = contains possible extensions for output file names          30
C     xtmp     = temporary variable for holding result                       31
C.....                                                                       32
      write(6,*)'Enter the base name of the raw files.'                      33
      read(5,'(a)')base                                                      34
C.....Determine the location of last character in the base name.             35
      ilen = index(base,' ') - 1                                             36
 10   write(6,*)'Enter the normalization.'                                   37
      read(5,*)xnorm                                                         38
      if (xnorm .le. 0.) goto 10                                             39
 20   write(6,*)'Enter the number of decades (0 = linear scale).'            40
      read(5,*)ndec                                                          41
      if (ndec .lt. 0) goto 20                                               42
 30   write(6,*)'Do you want color or grayscale output?  (1 = ',             43
     &     'grayscale; 2 = color)'                                           44
      read(5,*)icolor                                                        45
      if (icolor .eq. 2) then                                                46
 40      write(6,*)'Do you want to obtain "one-sided" output by',            47
     &        ' taking the absolute value'                                   48
         write(6,*)'of the input data?  (1 = one-sided; 2 = two-sided)'      49
         read(5,*)iside                                                      50
         if (iside .ne. 1 .and. iside .ne. 2) goto 40                        51
      elseif (icolor .ne. 1) then                                            52
         goto 30                                                             53
      endif                                                                  54
      nframe = 0                                                             55
 1000 nframe = nframe + 1                                                    56
C........Calculate the number of digits in the current frame number.         57
         ndigit = log10(real(nframe)+0.01) + 1                               58
C........Construct the proper format field for the input file name.          59
         write(frmt,'(a2,i2,a5,i9,a1)')'(a',ilen,',a1,i',ndigit,')'          60
C........Put this together to obtain the input file name.                    61
         write(filein,frmt)base,'.',nframe                                   62
C........Construct the output file name.                                     63
         filout = filein                                                     64
         filout(ilen+ndigit+2:ilen+ndigit+6) = tail(icolor)                  65
C........Check if input file is available.  Terminate if not.                66
         inquire(file=filein,exist=input)                                    67
         if (.not. input) then                                               68
            write(6,*)'Input not found: ',filein(1:index(filein,' '))        69
            stop                                                             70
         endif                                                               71
C........If output file already exists, skip to next file.                   72
         inquire(file=filout,exist=output)                                   73
         if (output) then                                                    74
            write(6,*)'Skipping:',filout(1:index(filout,' '))                75
            goto 1000                                                        76
         endif                                                               77
         write(6,*)'Processing: ',filein(1:index(filein,' '))                78
C........Open the input file and read the size of the image.                 79
         open(55,file=filein,form='unformatted',status='old',                80
     &        access='direct',recl=4)                                        81
         read(55,rec=1)xtmp                                                  82
         icol = int(xtmp)+10                                                 83
         read(55,rec=2)xtmp                                                  84
         irow = int(xtmp)                                                    85
         write(ccol,'(i4)')icol                                              86
         write(crow,'(i4)')irow                                              87
C........Open the output file and write the header information.              88
         open(66,file=filout,form='unformatted',status='new',                89
     &        access='direct',recl=1)                                        90
         write(66,rec=1)'P'                                                  91
         write(66,rec=2)char(52+icolor)                                      92
         write(66,rec=3)char(10)                                             93
         write(66,rec=4)ccol(1:1)                                            94
         write(66,rec=5)ccol(2:2)                                            95
         write(66,rec=6)ccol(3:3)                                            96
         write(66,rec=7)ccol(4:4)                                            97
         write(66,rec=8)' '                                                  98
         write(66,rec=9)crow(1:1)                                            99
         write(66,rec=10)crow(2:2)                                          100
         write(66,rec=11)crow(3:3)                                          101
         write(66,rec=12)crow(4:4)                                          102
         write(66,rec=13)char(10)                                           103
         write(66,rec=14)'2'                                                104
         write(66,rec=15)'5'                                                105
         write(66,rec=16)'5'                                                106
         write(66,rec=17)char(10)                                           107
C........Initialize record pointers                                         108
         iout=18                                                            109
         iin =3                                                             110
C........Calculate "epsilon" that is added to values if compressing.        111
         if (ndec.ne.0) eps = 10.0**(-ndec)*xnorm/(1.0-10.0**(-ndec))       112
C........Loop through all pixels in the image.                              113
         do 200 j=1,irow                                                    114
            do 100 i=1,icol                                                 115
               if (i .le. 10) then                                          116
C..............Draw the color map if within the first 10 columns.           117
                  if (icolor .eq. 1 .or. iside .eq. 1) then                 118
                     xpnt = real(irow-j)/real(irow-1)*xnorm                 119
                  else                                                      120
                     xpnt = (-2./real(irow-1)*real(j)                       121
     &                    + real(irow+1)/real(irow-1))*xnorm                122
                  endif                                                     123
               else                                                         124
C..............If not in first 10 columns, get data from file.              125
                  read(55,rec=iin,err=2000)xpnt                             126
                  iin = iin+1                                               127
               endif                                                        128
C..............If the point is out of range, whack it down to size.         129
               if (abs(xpnt) .gt. xnorm) xpnt = xpnt/abs(xpnt)*xnorm        130
C..............Use log scaling if requested.                                131
               if (ndec .ne. 0) then                                        132
                  xtmp = log10((abs(xpnt)+eps)/(xnorm+eps))/                133
     &                 real(ndec)+1.                                        134
               else                                                         135
                  xtmp = abs(xpnt/xnorm)                                    136
               endif                                                        137
               if (icolor .eq. 1) then                                      138
C.................Grayscale output.                                         139
                  write(66,rec=iout)char(int(255*xtmp))                     140
                  iout = iout+1                                             141
               else                                                         142
                  if (iside .eq. 1) then                                    143
C.................Use color map #1 for one-sided data.                      144
                     call cmap1(h,s,v,xtmp)                                 145
                  else                                                      146
C.................Reconstruct sign & use color map #2 for two-sided.        147
                     if (xpnt .lt. 0.) xtmp = -xtmp                         148
                     call cmap2(h,s,v,xtmp)                                 149
                  endif                                                     150
C.................Convert (h,s,v) to (r,g,b) and write output.              151
                  call hsvrgb(h,s,v,ir,ig,ib)                               152
                  write(66,rec=iout)char(ir)                                153
                  write(66,rec=iout+1)char(ig)                              154
                  write(66,rec=iout+2)char(ib)                              155
                  iout = iout+3                                             156
               endif                                                        157
 100           continue                                                     158
 200        continue                                                        159
 2000    close(55)                                                          160
         close(66)                                                          161
      goto 1000                                                             162
      end                                                                   163
C**********************************************************************     164
C.....Color mapping appropriate for one-sided data.                         165
      subroutine cmap1(h,s,v,xpnt)                                          166
      real h, s, v, xpnt, pi                                                167
      parameter (pi=3.141593)                                               168
      if (xpnt .gt. 0.8) then                                               169
         h = 330. + 30*(1.-xpnt)/0.2                                        170
         s = (1.-xpnt)/0.2                                                  171
         v = 1.0                                                            172
      elseif (xpnt .gt. 0.2) then                                           173
         t = 2.0*pi*((xpnt-0.2)/.6)                                         174
         h = 240.0*(0.8-xpnt)/0.6 + 5.0*sin(t)                              175
         s = 1.0                                                            176
         v = 1.0                                                            177
      else                                                                  178
         h = 270.0*(.2-xpnt)+240.0                                          179
         s = 1.0                                                            180
         v = xpnt/0.2                                                       181
      endif                                                                 182
      return                                                                183
      end                                                                   184
C**********************************************************************     185
C.....Color mapping appropriate for two-sided data.  Zero = black.          186
      subroutine cmap2(h,s,v,xpnt)                                          187
      real h, s, v, xpnt                                                    188
      if (xpnt .gt. 0.8) then                                               189
         h = 30. - 30.*(xpnt-0.8)*(xpnt-0.8)/0.04                           190
         s = (1.0-xpnt)/0.2                                                 191
         v = 1.0                                                            192
      else if (xpnt .gt. .3) then                                           193
         h = 135.0 - 105.*(xpnt-.3)/.5                                      194
         s = 1.0                                                            195
         v = 1.0                                                            196
      else if (xpnt .gt. 0.) then                                           197
         h = 180.0 - 45.*xpnt/.3                                            198
         s = 1.0                                                            199
         v = xpnt/.3                                                        200
      else if (xpnt .gt. -.3) then                                          201
         h = (180. - 45.*xpnt/.3)                                           202
         s = 1.0                                                            203
         v = abs(xpnt)/.3                                                   204
      else                                                                  205
         h = 225. - 135.*(xpnt+.3)/.7                                       206
         s = 1.0                                                            207
         v = 1.0                                                            208
      endif                                                                 209
      return                                                                210
      end                                                                   211
C**********************************************************************     212
C.....Subroutine to convert (h,s,v) values to (r,g,b) values.               213
      subroutine hsvrgb(h,s,v,ir,ig,ib)                                     214
      implicit real (a-h,o-z)                                               215
      real pqvt(4)                                                          216
      integer irpnt(6),  igpnt(6),  ibpnt(6)                                217
      data irpnt/3,2,1,1,4,3/,igpnt/4,3,3,2,1,1/,ibpnt/1,1,4,3,3,2/         218
C.....                                                                      219
C     input:   0 <= h <= 360    (hue)                                       220
C              0 <= v <= 1.0    (value or brightness)                       221
C              0 <= s <= 1.0    (saturation)                                222
C     output:  0 <= ir,ig,ib <= maxval                                      223
C.....                                                                      224
      if (s .eq. 0.0) then                                                  225
         ir = 255.0*v                                                       226
         ig = ir                                                            227
         ib = ir                                                            228
         return                                                             229
      endif                                                                 230
      if (h .eq. 360.0) h=0.0                                               231
      h = h / 60.0                                                          232
      i = int(h)                                                            233
      f = h-i                                                               234
      pqvt(3) = 255.0*v                                                     235
      pqvt(1) = pqvt(3)*(1.0-s)                                             236
      pqvt(2) = pqvt(3)*(1.0-s*f)                                           237
      pqvt(4) = pqvt(3)*(1.0-s*(1.0-f))                                     238
      i  = i + 1                                                            239
      ir = pqvt(irpnt(i))                                                   240
      ig = pqvt(igpnt(i))                                                   241
      ib = pqvt(ibpnt(i))                                                   242
      return                                                                243
      end                                                                   244
C**********************************************************************     245

After the input and output files names have been constructed based on the current frame number and the given base name, the status of these files is checked. If the input file is not found, the program terminates (lines 67 to 71). If the input file exists and the output file already exists, another output file is not created. Instead, the frame number is advanced and the next set of input and output files is checked (lines 73 to 77). Only if the input file exists and the output file does not exist is a new output file created. This is done in order to permit parallel processing of the data---this program may be invoked more than once to work on the same set of files and the file handling should insure that separate invocations do not interfere with each other.

The majority of code should be easy to understand by experienced Fortran programmers. However, the use of the Fortran intrinsic function char in lines 140, 153, 154, and 155 to convert an integer value (which is between 0 and 255) to the corresponding single byte value (characters are inherently one byte long) may be unfamiliar.

The subroutine cmap1 (ref. lines 165-185) maps a one-sided field to a color. The fields are assumed to be between zero and unity and the subroutine returns the corresponding location in the HSV color space.

The subroutine cmap2 (ref. lines 186-211) maps a two-sided field to a color. The fields are assumed to be between -1 and 1 and the subroutine returns the corresponding location in the HSV color space.

The subroutine hsvrgb (ref. lines 213-244) converts from HSV values to RGB values.



next up previous
Next: Software Sites Up: Animating the Evolution of Previous: Data Extraction Routine



John Schneider
Sun Sep 22 11:57:43 PDT 1996