Skip to content

Commit

Permalink
Improved the RGB endpoint by allowing more dynamic scaling and making…
Browse files Browse the repository at this point in the history
… the alpha channel optional.
  • Loading branch information
yellowcap committed Oct 23, 2017
1 parent df646e3 commit d8b9a29
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 17 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
django-raster change log
========================

0.6
---
* Changed alpha channel handling on RGB endpoint. The alpha channel is now
switched off by default. To activate it, add the ``alpha`` query parameter
to the rgb request.

0.5
---
* Added ``memory_efficient`` flag to value count aggregator. The value counts
Expand Down
8 changes: 6 additions & 2 deletions docs/algebra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,15 @@ If the raw data in the tiles is not already scaled to the range [0, 255], an
additional scaling factor can be specified, which will be used to rescale
all three bands to the default RGB color range. For instance, the following
query would assume that the input bands have values in the range of
[0, 10000], and would rescale them to the RGB color space.
[5, 10000], and would rescale them to the RGB color space.

::

/raster/algebra/{z}/{x}/{y}.png?layers=r=1,g=3,b=6&scale=1e4
/raster/algebra/{z}/{x}/{y}.png?layers=r=1,g=3,b=6&scale=5,10000

An alpha channel can be activated by passing the ``alpha`` query parameter. The
alpha parameter makes all the pixels transparent that have values equal to
``0`` in all three RGB channels.

Formula parser
--------------
Expand Down
55 changes: 40 additions & 15 deletions raster/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,24 +254,49 @@ def get_rgb(self, data):
green = green.bands[0].data()
blue = blue.bands[0].data()

scale = float(self.request.GET.get('scale', 255))

red[red > scale] = scale
green[green > scale] = scale
blue[blue > scale] = scale

red = red * 255.0 / scale
green = green * 255.0 / scale
blue = blue * 255.0 / scale

# Create zeros array.
alpha = 255 * (red > 0) * (blue > 0) * (green > 0)
# Get scale for the image value range.
if 'scale' in self.request.GET:
# The scale is either a number or two numbers separated by comma.
scale = self.request.GET.get('scale').split(',')
if len(scale) == 1:
scale_min = 0
scale_max = float(scale[0])
else:
# Get min an max scale from
scale_min = float(scale[0])
scale_max = float(scale[1])

# Clip the image minimum.
red[red < scale_min] = scale_min
green[green < scale_min] = scale_min
blue[blue < scale_min] = scale_min

# Clip the image maximum.
red[red > scale_max] = scale_max
green[green > scale_max] = scale_max
blue[blue > scale_max] = scale_max

# Scale the image.
red = 255 * (red - scale_min) / scale_max
green = 255 * (green - scale_min) / scale_max
blue = 255 * (blue - scale_min) / scale_max

if 'alpha' in self.request.GET:
mode = 'RGBA'
reshape = 4
# Create the alpha channel.
alpha = 255 * (red > 0) * (blue > 0) * (green > 0)
img_array = numpy.array((red.ravel(), green.ravel(), blue.ravel(), alpha.ravel()))
else:
mode = 'RGB'
reshape = 3
img_array = numpy.array((red.ravel(), green.ravel(), blue.ravel()))

rgba = numpy.array((red.ravel(), green.ravel(), blue.ravel(), alpha.ravel())).T
rgba = rgba.reshape(WEB_MERCATOR_TILESIZE, WEB_MERCATOR_TILESIZE, 4).astype('uint8')
# Reshape array into tile size.
img_array = img_array.T.reshape(WEB_MERCATOR_TILESIZE, WEB_MERCATOR_TILESIZE, reshape).astype('uint8')

# Create image from array
img = Image.fromarray(rgba)
img = Image.fromarray(img_array, mode=mode)
stats = {}

# Return rendered image
Expand Down
2 changes: 2 additions & 0 deletions tests/test_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,5 @@ def test_band_level_algebra_request(self):
def test_rgb_request(self):
response = self.client.get(self.algebra_tile_url + '?layers=r={0},g={0},b={0}'.format(self.rasterlayer.id))
self.assertEqual(response.status_code, 200)
response = self.client.get(self.algebra_tile_url + '?layers=r={0},g={0},b={0}&alpha'.format(self.rasterlayer.id))
self.assertEqual(response.status_code, 200)

0 comments on commit d8b9a29

Please sign in to comment.