Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Jonny Schäfer
radolan
Commits
5db65a8d
Commit
5db65a8d
authored
Dec 22, 2017
by
Jonny Schäfer
Browse files
Move imaging functions to radolan2png
parent
dcbf6482
Changes
2
Hide whitespace changes
Inline
Side-by-side
radolan2png/radolan2png.go
View file @
5db65a8d
...
@@ -5,11 +5,13 @@ package main
...
@@ -5,11 +5,13 @@ package main
import
(
import
(
"fmt"
"fmt"
"gitlab.cs.fau.de/since/radolan/radolan2png/vis"
"gitlab.cs.fau.de/since/radolan"
"gitlab.cs.fau.de/since/radolan"
"image/color"
"image/color"
"image/png"
"image/png"
"log"
"log"
"os"
"os"
"time"
)
)
var
(
var
(
...
@@ -38,20 +40,35 @@ func convert(in, out string) {
...
@@ -38,20 +40,35 @@ func convert(in, out string) {
comp
,
err
:=
radolan
.
NewComposite
(
infile
)
comp
,
err
:=
radolan
.
NewComposite
(
infile
)
care
(
err
)
care
(
err
)
// choose color function
fmt
.
Printf
(
"%s-Image (%s) showing %s
\n
"
,
comp
.
Product
,
comp
.
DataUnit
,
comp
.
ForecastTime
)
heatmap
:=
radolan
.
HeatmapReflectivity
switch
comp
.
Product
[
0
]
{
var
heatmap
vis
.
ColorFunc
case
'R'
,
'W'
,
'S'
,
'E'
:
switch
comp
.
DataUnit
{
if
comp
.
Product
[
1
]
!=
'X'
{
case
radolan
.
Unit_mm
:
heatmap
=
radolan
.
HeatmapAccumulatedDay
max
:=
200.0
if
comp
.
Interval
<=
time
.
Hour
{
max
=
100.0
}
if
comp
.
Interval
>=
time
.
Hour
*
24
*
7
{
max
=
400.0
}
}
heatmap
=
vis
.
Heatmap
(
0.1
,
max
,
vis
.
Log
)
case
radolan
.
Unit_dBZ
:
heatmap
=
vis
.
HeatmapReflectivity
case
radolan
.
Unit_km
:
heatmap
=
vis
.
Graymap
(
0
,
15
,
vis
.
Id
)
case
radolan
.
Unit_mps
:
heatmap
=
vis
.
HeatmapRadialVelocity
}
}
// convert composite to image using the color function
// convert composite to image using the color function
img
:=
comp
.
Image
(
heatmap
)
img
:=
vis
.
Image
(
heatmap
,
comp
,
0
)
// TODO: select layer
// draw borders
// draw borders
if
comp
.
HasProjection
{
if
comp
.
HasProjection
{
// print grid dimensions
fmt
.
Printf
(
"detected grid: %.1f km * %.1f km
\n
"
,
float64
(
comp
.
Dx
)
*
comp
.
Rx
,
float64
(
comp
.
Dy
)
*
comp
.
Ry
)
for
_
,
b
:=
range
border
{
for
_
,
b
:=
range
border
{
// convert border points to data indices
// convert border points to data indices
x
,
y
:=
comp
.
Translate
(
b
[
0
],
b
[
1
])
x
,
y
:=
comp
.
Translate
(
b
[
0
],
b
[
1
])
...
...
radolan2png/vis/vis.go
0 → 100644
View file @
5db65a8d
package
vis
import
(
"image"
"image/color"
"math"
"gitlab.cs.fau.de/since/radolan"
)
// A ColorFunc can be used to assign colors to data values for image creation.
type
ColorFunc
func
(
val
float64
)
color
.
RGBA
// Sample color and grayscale gradients for visualization with the image method.
var
(
// HeatmapReflectivityShort is a color gradient for cloud reflectivity
// composites between 5dBZ and 75dBZ.
HeatmapReflectivityShort
=
Heatmap
(
5.0
,
75.0
,
Id
)
// HeatmapReflectivity is a color gradient for cloud reflectivity
// composites between 5dBZ and 75dBZ.
HeatmapReflectivity
=
Heatmap
(
1.0
,
75.0
,
Id
)
// HeatmapReflectivityWide is a color gradient for cloud reflectivity
// composites between -32.5dBZ and 75dBZ.
HeatmapReflectivityWide
=
Heatmap
(
-
32.5
,
75.0
,
Id
)
// HeatmapAccumulatedHour is a color gradient for accumulated rainfall
// composites (e.g RW) between 0.1mm/h and 100 mm/h using logarithmic
// compression.
HeatmapAccumulatedHour
=
Heatmap
(
0.1
,
100
,
Log
)
// HeatmapAccumulatedDay is a color gradient for accumulated rainfall
// composites (e.g. SF) between 0.1mm and 200mm using logarithmic
// compression.
HeatmapAccumulatedDay
=
Heatmap
(
0.1
,
200
,
Log
)
HeatmapRadialVelocity
=
Radialmap
(
-
31.5
,
31.5
,
Log
)
// GraymapLinear is a linear grayscale gradient between the (raw) rvp-6
// values 0 and 409.5.
GraymapLinear
=
Graymap
(
0
,
409.5
,
Id
)
// GraymapLinearWide is a linear grayscale gradient between the (raw)
// rvp-6 values 0 and 4095.
GraymapLinearWide
=
Graymap
(
0
,
4095
,
Id
)
)
// Id is the identity (no compression)
func
Id
(
x
float64
)
float64
{
return
x
}
// Log is the natural logarithm (logarithmic compression)
func
Log
(
x
float64
)
float64
{
return
math
.
Log
(
x
)
}
// Image creates an image by evaluating the color function fn for each data
// value in the given z-layer.
func
Image
(
fn
ColorFunc
,
c
*
radolan
.
Composite
,
layer
int
)
*
image
.
RGBA
{
rec
:=
image
.
Rect
(
0
,
0
,
c
.
Dx
,
c
.
Dy
)
img
:=
image
.
NewRGBA
(
rec
)
if
layer
<
0
||
layer
>=
c
.
Dz
{
return
img
}
for
y
:=
0
;
y
<
c
.
Dy
;
y
++
{
for
x
:=
0
;
x
<
c
.
Dx
;
x
++
{
img
.
Set
(
x
,
y
,
fn
(
float64
(
c
.
DataZ
[
layer
][
y
][
x
])))
}
}
return
img
}
// Graymap returns a grayscale gradient between min and max. A compression function is used to
// make logarithmic scales possible.
func
Graymap
(
min
,
max
float64
,
compression
func
(
float64
)
float64
)
ColorFunc
{
min
=
compression
(
min
)
max
=
compression
(
max
)
return
func
(
val
float64
)
color
.
RGBA
{
val
=
compression
(
val
)
if
val
<
min
{
return
color
.
RGBA
{
0x00
,
0x00
,
0x00
,
0xFF
}
// black
}
p
:=
(
val
-
min
)
/
(
max
-
min
)
if
p
>
1
{
p
=
1
}
l
:=
uint8
(
0xFF
*
p
)
return
color
.
RGBA
{
l
,
l
,
l
,
0xFF
}
}
}
// Radialmap returns a dichromatic gradient from min to 0 to max which can
// be used for doppler radar radial velocity products.
func
Radialmap
(
min
,
max
float64
,
compression
func
(
float64
)
float64
)
ColorFunc
{
return
func
(
val
float64
)
color
.
RGBA
{
if
val
!=
val
{
return
color
.
RGBA
{
0x00
,
0x00
,
0x00
,
0xFF
}
// black
}
base
:=
math
.
Max
(
math
.
Abs
(
min
),
math
.
Abs
(
max
))
p
:=
compression
(
math
.
Abs
(
val
))
/
compression
(
base
)
if
p
>
1
{
p
=
1
}
lev
:=
uint8
(
0xFF
*
p
)
var
non
byte
=
0x00
if
math
.
Abs
(
val
)
<=
1
{
lev
=
0xFF
non
=
0xCC
}
if
val
<
0
{
return
color
.
RGBA
{
non
,
lev
,
lev
,
0xFF
}
}
return
color
.
RGBA
{
lev
,
non
,
non
,
0xFF
}
}
}
// Heatmap returns a colour gradient between min and max. A compression function is used to
// make logarithmic scales possible.
func
Heatmap
(
min
,
max
float64
,
compression
func
(
float64
)
float64
)
ColorFunc
{
min
=
compression
(
min
)
max
=
compression
(
max
)
return
func
(
val
float64
)
color
.
RGBA
{
val
=
compression
(
val
)
if
val
<
min
{
return
color
.
RGBA
{
0x00
,
0x00
,
0x00
,
0xFF
}
// black
}
p
:=
(
val
-
min
)
/
(
max
-
min
)
if
p
>
1
{
// limit
p
=
1
}
h
:=
math
.
Mod
(
360
-
(
330
*
p
)
+
240
,
360
)
s
:=
1.0
// saturation
l
:=
0.5
*
p
+
0.25
// lightness
// adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL
c
:=
(
1
-
math
.
Abs
(
2
*
l
-
1
))
*
s
// calculate chroma
hh
:=
h
/
60
x
:=
c
*
(
1
-
math
.
Abs
(
math
.
Mod
(
hh
,
2
)
-
1
))
if
math
.
IsNaN
(
hh
)
{
hh
=
-
1
}
var
rr
,
gg
,
bb
float64
switch
int
(
hh
)
{
case
0
:
rr
,
gg
,
bb
=
c
,
x
,
0
case
1
:
rr
,
gg
,
bb
=
x
,
c
,
0
case
2
:
rr
,
gg
,
bb
=
0
,
c
,
x
case
3
:
rr
,
gg
,
bb
=
0
,
x
,
c
case
4
:
rr
,
gg
,
bb
=
x
,
0
,
c
case
5
:
rr
,
gg
,
bb
=
c
,
0
,
x
}
m
:=
l
-
c
/
2
r
,
g
,
b
:=
uint8
(
0xFF
*
(
rr
+
m
)),
uint8
(
0xFF
*
(
gg
+
m
)),
uint8
(
0xFF
*
(
bb
+
m
))
return
color
.
RGBA
{
r
,
g
,
b
,
0xFF
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment