A
Ara.T.Howard
thought some of you out there might be interested in generating imagery with
ruby, if so check out
http://codeforpeople.com/katrina/fast/
the looper is java - but the individual images were generated from binary
grids using this ruby program (the ENVI class is just a thin wrapper on narray
which reads headers to determine types, etc.)
file: katrina.rb
#!/dmsp/reference/bin/ruby
#
# ara's lib
#
require 'alib'
require 'mmap'
require 'narray'
require 'envi'
#
# main program class
#
class Main < ALib::SimpleMain
version '0.0.0'
author '(e-mail address removed)'
usage <<-usage
NAME
#{ prognam } v#{ version }
SYNOPSIS
#{ prognam } [options]+ vis_grid tir_grid rgb_grid
usage
arguments 'vis_grid', 'tir_grid', 'rgb_grid'
def main
load_grids
gen_rgb
write_rgb
write_rgb_header
end
def load_grids
grid_opts = {
'cast' => 'int',
'mmap' => {'mode' => 'r', 'flags' => Mmap::MAP_SHARED}
}
@rg = ENVI::Grid::new vis_grid, grid_opts
@gg = ENVI::Grid::new vis_grid, grid_opts
@bg = ENVI::Grid::new tir_grid, grid_opts
end
def gen_rgb
r = @rg.narray
g = @gg.narray
b = @bg.narray
r[ (r.eq 255).where ] = 0 # hide missing
g[ (g.eq 255).where ] = 0 # hide missing
linear_stretch r, 7 .. 30
linear_stretch g, 7 .. 30
linear_stretch b, 175 .. 230
r[] = r * (1 << 24)
g[] = g * (1 << 16)
b[] = (255 - b) * (1 << 8) # invert blue channel
@rgb = r | g | b
@rgb = @rgb.hton
r = g = b = nil
end
def linear_stretch na, irange, orange = (0..255)
fna = NArray::float(*na.shape)
fna[] = na
imax, imin = irange.max, irange.min
isize = imax - imin + 1
omax, omin = orange.max, orange.min
osize = omax - omin + 1
# floor input
lte_imin, gt_imin = (fna <= imin).where2
fna[ lte_imin ] = 0
fna[ gt_imin ] = fna[ gt_imin ] - imin + 1
# ceil input
gt_imax = (fna > isize).where
fna[ gt_imax ] = isize + 1
# percentage of in range
fna[] = fna / (isize + 1)
# scale into out range
fna[] = fna * (osize - 1)
na[] = fna
end
def write_rgb
open(rgb_grid, 'w'){|f| f.write @rgb.to_s}
end
def write_rgb_header
h = @rg.header
open(rgb_grid + ".hdr", 'w') do |f|
hdr = <<-hdr
ENVI
description = { R (#{ vis_grid }), G (#{ vis_grid }), B (#{ tir_grid }), A (alpha) }
samples = #{ h.samples }
lines = #{ h.lines }
bands = 4
header offset = 0
file type = ENVI Standard
data type = 1
interleave = bip
sensor type = Unknown
byte order = 1
map info = #{ h.map_info }
wavelength units = Unknown
default stretch = 0.000000 255.000000 linear
data origin = NGDC
band names = { R (Band 1:#{ vis_grid }), G (Band 2:#{ vis_grid }), B (Band 3:#{ tir_grid }), A (Band 4:alpha) }
hdr
hdr.each do |line|
f.puts line.strip
end
end
end
end
#
# run unless included as a lib
#
Main::new.run if $0 == __FILE__
only takes about 3 seconds per image for 3001x3001 byte grids too ;-) the
output images are raw and converted to jpg using something like (i forget
syntax)
convert -depth 8 -size 3001x3001 rgba:filename.rgba filename.jpg
convert being and image magick utility. now that tim has made updates to im
though - the narray/mmap could be used directy to set the pixels of an image
from within ruby... i'll figure that out next week. ;-)
-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
ruby, if so check out
http://codeforpeople.com/katrina/fast/
the looper is java - but the individual images were generated from binary
grids using this ruby program (the ENVI class is just a thin wrapper on narray
which reads headers to determine types, etc.)
file: katrina.rb
#!/dmsp/reference/bin/ruby
#
# ara's lib
#
require 'alib'
require 'mmap'
require 'narray'
require 'envi'
#
# main program class
#
class Main < ALib::SimpleMain
version '0.0.0'
author '(e-mail address removed)'
usage <<-usage
NAME
#{ prognam } v#{ version }
SYNOPSIS
#{ prognam } [options]+ vis_grid tir_grid rgb_grid
usage
arguments 'vis_grid', 'tir_grid', 'rgb_grid'
def main
load_grids
gen_rgb
write_rgb
write_rgb_header
end
def load_grids
grid_opts = {
'cast' => 'int',
'mmap' => {'mode' => 'r', 'flags' => Mmap::MAP_SHARED}
}
@rg = ENVI::Grid::new vis_grid, grid_opts
@gg = ENVI::Grid::new vis_grid, grid_opts
@bg = ENVI::Grid::new tir_grid, grid_opts
end
def gen_rgb
r = @rg.narray
g = @gg.narray
b = @bg.narray
r[ (r.eq 255).where ] = 0 # hide missing
g[ (g.eq 255).where ] = 0 # hide missing
linear_stretch r, 7 .. 30
linear_stretch g, 7 .. 30
linear_stretch b, 175 .. 230
r[] = r * (1 << 24)
g[] = g * (1 << 16)
b[] = (255 - b) * (1 << 8) # invert blue channel
@rgb = r | g | b
@rgb = @rgb.hton
r = g = b = nil
end
def linear_stretch na, irange, orange = (0..255)
fna = NArray::float(*na.shape)
fna[] = na
imax, imin = irange.max, irange.min
isize = imax - imin + 1
omax, omin = orange.max, orange.min
osize = omax - omin + 1
# floor input
lte_imin, gt_imin = (fna <= imin).where2
fna[ lte_imin ] = 0
fna[ gt_imin ] = fna[ gt_imin ] - imin + 1
# ceil input
gt_imax = (fna > isize).where
fna[ gt_imax ] = isize + 1
# percentage of in range
fna[] = fna / (isize + 1)
# scale into out range
fna[] = fna * (osize - 1)
na[] = fna
end
def write_rgb
open(rgb_grid, 'w'){|f| f.write @rgb.to_s}
end
def write_rgb_header
h = @rg.header
open(rgb_grid + ".hdr", 'w') do |f|
hdr = <<-hdr
ENVI
description = { R (#{ vis_grid }), G (#{ vis_grid }), B (#{ tir_grid }), A (alpha) }
samples = #{ h.samples }
lines = #{ h.lines }
bands = 4
header offset = 0
file type = ENVI Standard
data type = 1
interleave = bip
sensor type = Unknown
byte order = 1
map info = #{ h.map_info }
wavelength units = Unknown
default stretch = 0.000000 255.000000 linear
data origin = NGDC
band names = { R (Band 1:#{ vis_grid }), G (Band 2:#{ vis_grid }), B (Band 3:#{ tir_grid }), A (Band 4:alpha) }
hdr
hdr.each do |line|
f.puts line.strip
end
end
end
end
#
# run unless included as a lib
#
Main::new.run if $0 == __FILE__
only takes about 3 seconds per image for 3001x3001 byte grids too ;-) the
output images are raw and converted to jpg using something like (i forget
syntax)
convert -depth 8 -size 3001x3001 rgba:filename.rgba filename.jpg
convert being and image magick utility. now that tim has made updates to im
though - the narray/mmap could be used directy to set the pixels of an image
from within ruby... i'll figure that out next week. ;-)
-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================