⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gif_util.f90

📁 FDTD algorithm.
💻 F90
字号:
module gif_util!  Conversion of raster data to GIF format.!!  Version 1.0, February 1998!!  Written by Jos Bergervoet!use bin_ioimplicit none         !  Check all declarationsprivate               !  bin_io is used private, no transfer to main programpublic  :: writegif   !  Writes GIF89 image, given pixel array and color mapprivate :: giflzw, slicewrite, InitTable, flushbuffertype, public :: color  integer  :: r, g, bend type colorinteger, parameter, private     :: F_unit=92, Bufend=260character(len=Bufend), private  :: bufinteger, private  ::  ibuf                            ! output buffer varsinteger, parameter, private  ::    maxcode = 4095 integer, parameter, private  ::    nocode = maxcode+1 ! definitions for LZW! Define LZW code tables for hashing:character(len=1), private, dimension(0:maxcode+1)  :: endbyteinteger, private, dimension(0:maxcode)             :: follow, next  !  ! For any code P, which codes for a sequence af pixel-values, endbyte(P)  ! is the last pixel-value, follow(P) points to another code (if it exists)  ! which codes for this same sequence, but with one more pixel-value  ! appended.  !   For each code P, next(P) points to another code which codes for a  ! similar sequence with only the endbyte different. This is a hashing  ! pointer, for fast look-up.  !   All pointers are 'nocode' if they point to nothing  !  integer, private :: ncod, curmaxcode, EOI, CC, P, K, child, &                    maxbase, skip, slen, blen, accum, nout   ! local varscontainssubroutine flushbuffer()! Flushes up to 255 bytes to output file if buffer contains data, keeping! rest of data in buffer. If skip>0 there is a partially filled last byte! in buf[ibuf]. This byte will be written only if ibuf<256. That should be! the last call to flushbuffer.  integer  :: bl    !   number of bytes to write (to be determined)  if (ibuf > 255) then    bl = 255        !   we will write buf[1..255]  else if (skip /= 0) then    bl = ibuf       !   buf[ibuf] is partially used, write buf[1..ibuf]  else if (ibuf > 1) then    bl = ibuf-1     !   write buf[1..ibuf-1], there is no partial byte  else    return          !   nothing to write  end if  call integer_block_write (F_unit, bl, 1)  call char_block_write ( F_unit, buf(1:bl) )  buf(1:ibuf-bl) = buf(bl+1:ibuf) ! shift down remaining data  ibuf = ibuf - bl  returnend subroutine flushbuffersubroutine slicewrite(code)       ! add some bits (a 'slice') to output buffer  integer, intent(in)  :: code  if (nout == 0) then             ! initiate output buffer    ibuf = 1    skip = 0    accum = 0  end if  nout = nout+1  accum = accum + code * 2**skip  ! add bits at correct position in accum  skip = skip + slen              ! slen is current slice length, in bits  shiftout: do    buf(ibuf:ibuf) = char(modulo(accum, 256))    if (skip<8) then      exit shiftout    end if    ibuf = ibuf+1                 ! last written buffer-byte is now permanent    accum = accum / 256           ! remove that byte from accum    skip = skip-8                 ! skip points to next bit to write in accum  end do shiftout  if (ibuf>255) then    call flushbuffer()            ! won't write unfinished byte in buf[ibuf]  end if  return                          ! at most 255 bytes will be left in bufferend subroutine slicewritesubroutine InitTable()  integer :: i  do i=0,maxbase                  ! Start with defining the codes 0..maxbase    endbyte(i) = char(i)          ! for one-pixel sequences (code=pixelvalue)  end do                          ! Initially no multi-pixel codes exist  follow(0:maxbase) = nocode  next(0:maxbase) = nocode  CC = maxbase+1                  ! `clear code-tabel', a control code  EOI = maxbase+2                 ! `end of image', another control code  ncod = CC + 2                   ! ncod = number of currently defined codes  slen = blen + 1                 ! current number of bits to write one code  curmaxcode = 2**slen - 1        ! currently the highest, until slen increases  returnend subroutine InitTablesubroutine giflzw(Pixel)          ! routine for LZW coding  integer, intent(in), dimension(:,:) :: Pixel  integer                             :: i, j  nout=0                          ! for counting the codes going out  if (blen<2) then    blen=2                        ! pixel code-length, 2 is minimum for GIF  end if  call integer_block_write (F_unit, blen, 1)  maxbase = 2**blen - 1  call InitTable()  call slicewrite(CC)  do j=1, ubound(Pixel,2)   do i=1, ubound(Pixel,1)    K = modulo(Pixel(i,j), maxbase+1)    ! take next byte, prevent overflow    if (i==1 .and. j==1) then      P = K                       ! first raster byte has one-byte code P      cycle                       ! for the first byte no further action    end if                                  ! Now see if code exists for sequence [.P.]K    child = follow(P)             ! [.P.]K is "string coded by P" followed by K    childloop: do      if ((child == nocode) .or. (ichar(endbyte(child)) == K)) then        exit childloop      end if      child = next(child)    end do childloop    if (child /= nocode) then     ! If code for [.P.]K was found, store it in P      P = child    else                          ! If not: output P and create code for [.P.]K      call slicewrite(P)      if (ncod > maxcode) then    ! check if a new code can be added        call slicewrite(CC)       ! If not: tell listener to clear table        call InitTable()          ! and clear our own table      else        if (ncod > curmaxcode) then          slen = slen+1                     ! New codes will be one bit longer          curmaxcode = curmaxcode * 2 + 1   ! and more codes are possible        end if        endbyte(ncod) = char(K)   ! ncod is the new code for [.P.]K        follow(ncod) = nocode        next(ncod) = follow(P)    ! include ncod in the hashing list        follow(P) = ncod          !     of codes with same start-sequence        ncod = ncod+1      end if      P = K    end if   end do  end do  call slicewrite(P)              ! send the last code to buffer  call slicewrite(EOI)            ! send 'end of image' to buffer  call flushbuffer()              ! extra flush, including partial last byte  returnend subroutine giflzwsubroutine writegif (FileName, Pixel, ColorMap, Transparent)!! Codes pixel-map with palette into GIF format. Optional transparent color!  character(len=*), intent(in)           :: FileName  integer, intent(in), dimension(:,:)    :: Pixel  type(color), intent(in), dimension(0:) :: ColorMap  integer, intent(in), optional          :: Transparent    character(len=256) :: s  integer            :: InfoByte, nx, ny, Cblen, HasMap, maxincol,  &                        maxgifcol, Background, i    call open_for_write (F_unit, FileName)    nx = ubound(Pixel, 1)  ny = ubound(Pixel, 2)  maxincol = size(ColorMap) - 1  ! write(unit=*,fmt=*) "Nx, Ny, Ncol: ", nx,ny,maxincol+1    do i=1,8                           ! find the bitsize, blen, for pixels    blen = i    maxgifcol = 2**blen - 1          ! Number of colors has to be power of 2     if (maxgifcol >= maxincol) then      exit                           ! now blen and maxgifcol are correct    end if                           ! only op to 256 colors can be   end do    call char_block_write (F_unit, "GIF89a")         ! Signature    !  Create information for screen descriptor  Background = 0  if (present(Transparent)) then    Background = Transparent  end if  HasMap = 1  Cblen = blen  InfoByte = HasMap * 128 + (Cblen-1) * 16 + blen-1    !  Write the screen descriptor  call integer_block_write (F_unit, nx, 2)         ! write nx as 2-byte integer  call integer_block_write (F_unit, ny, 2)  call integer_block_write (F_unit, InfoByte, 1)  call integer_block_write (F_unit, Background,1)  ! background as 1-byte  call integer_block_write (F_unit, 0, 1)          ! dummy 0 required by GIF    do i=0,maxgifcol                                 ! write global colormap    call integer_block_write (F_unit, ColorMap(min(i,maxincol)) % r, 1)    call integer_block_write (F_unit, ColorMap(min(i,maxincol)) % g, 1)    call integer_block_write (F_unit, ColorMap(min(i,maxincol)) % b, 1)  end do    if (present(Transparent)) then    write(unit=*,fmt=*) "Transparent color: ", Transparent    s = "!" // char(249) // char(4) // char(1) // char(0) // char(0)  &            // char(Transparent) // char(0)    call char_block_write (F_unit, s(1:8))         ! GIF transparent extension  end if    call char_block_write (F_unit, ",")              ! Announce image    !  Now create and write image descriptor  HasMap = 0  InfoByte = HasMap * 128 + blen-1                 ! add 64, if interlaced  call integer_block_write (F_unit, 0, 2)          ! x_margin, not used  call integer_block_write (F_unit, 0, 2)          ! y_margin, not used  call integer_block_write (F_unit, nx, 2)         ! image dimensions  call integer_block_write (F_unit, ny, 2)  call integer_block_write (F_unit, InfoByte, 1)    call giflzw (Pixel)                              ! now the raster data    call integer_block_write (F_unit, 0, 1)          ! Terminating 0-block.  call char_block_write (F_unit, ";")              ! Terminating ';' for GIF  call close_block_io (F_unit)  returnend subroutine writegif  end module gif_util

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -