Skip to content

Commit

Permalink
Merge pull request #119 from jhuapl-boss/tiff-tiles
Browse files Browse the repository at this point in the history
Adds TIFF Renderer to Boss Tiles
  • Loading branch information
sandyhider authored Oct 28, 2024
2 parents c720f4c + 3a1c9e4 commit 9aea47c
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 3 deletions.
31 changes: 31 additions & 0 deletions django/bosstiles/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,34 @@ def render(self, data, media_type=None, renderer_context=None):
file_obj.seek(0)
return file_obj.read()

class TIFFRenderer(renderers.BaseRenderer):
""" A DRF renderer for rendering an image as a TIFF file """
media_type = 'image/tiff'
format = 'tiff'
charset = None
render_style = 'binary'

@check_for_403
@check_for_429
def render(self, data, media_type=None, renderer_context=None):
file_obj = io.BytesIO()
# Save the image data as TIFF instead of JPEG
data.save(file_obj, "TIFF")
file_obj.seek(0)
return file_obj.read()

class JPEG2000Renderer(renderers.BaseRenderer):
""" A DRF renderer for rendering an image as a JPEG2000 file """
media_type = 'image/jp2'
format = 'jp2'
charset = None
render_style = 'binary'

@check_for_403
@check_for_429
def render(self, data, media_type=None, renderer_context=None):
file_obj = io.BytesIO()
# Save the image data as JPEG2000
data.save(file_obj, "JP2")
file_obj.seek(0)
return file_obj.read()
44 changes: 44 additions & 0 deletions django/bosstiles/test/int_test_tiles_view_uint8.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,50 @@ def test_no_cache_read(self):

np.testing.assert_equal(test_img, self.test_data_8[3, 300:800, 400:700])

def test_no_cache_read_tiff(self):
"""Test no-cache option when reading an image"""
factory = APIRequestFactory()

# Get an image file
request = factory.get('/' + version + '/image/col1/exp1/channel1/xy/0/400:700/300:800/3/?no-cache=true',
Accept='image/tiff')
force_authenticate(request, user=self.user)

time.sleep(10)

# Make request
response = CutoutTile.as_view()(request, collection='col1', experiment='exp1', channel='channel1',
orientation='xy', resolution='0', x_args='400:700', y_args='300:800',
z_args='3')
self.assertEqual(response.status_code, status.HTTP_200_OK)

# Check data is correct (this is pre-renderer)
test_img = np.array(response.data, dtype="uint8")

np.testing.assert_equal(test_img, self.test_data_8[3, 300:800, 400:700])

def test_no_cache_read_jp2(self):
"""Test no-cache option when reading an image"""
factory = APIRequestFactory()

# Get an image file
request = factory.get('/' + version + '/image/col1/exp1/channel1/xy/0/400:700/300:800/3/?no-cache=true',
Accept='image/jp2')
force_authenticate(request, user=self.user)

time.sleep(10)

# Make request
response = CutoutTile.as_view()(request, collection='col1', experiment='exp1', channel='channel1',
orientation='xy', resolution='0', x_args='400:700', y_args='300:800',
z_args='3')
self.assertEqual(response.status_code, status.HTTP_200_OK)

# Check data is correct (this is pre-renderer)
test_img = np.array(response.data, dtype="uint8")

np.testing.assert_equal(test_img, self.test_data_8[3, 300:800, 400:700])


class TileViewIntegrationTests(TileInterfaceViewTestMixin, APITestCase):
layer = DjangoSetupLayer
Expand Down
61 changes: 61 additions & 0 deletions django/bosstiles/test/tiles_view_uint8.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,67 @@ def test_png_uint8_yz(self):

np.testing.assert_equal(test_img, np.squeeze(self.test_data_8[8:12, 28:32, 0]))

def test_tiff_uint8_xy(self):
""" Test a png xy slice"""
# Post data to the database
factory = APIRequestFactory()

# Get an image file
request = factory.get('/' + version + '/tile/col1/exp1/channel1/xy/512/0/0/0/5/',
Accept='image/tiff')
force_authenticate(request, user=self.user)
# Make request
response = Tile.as_view()(request, collection='col1', experiment='exp1', channel='channel1',
orientation='xy', tile_size='512', resolution='0',
x_idx='0', y_idx='0', z_idx='5')
self.assertEqual(response.status_code, status.HTTP_200_OK)

# Check data is correct (this is pre-renderer)
test_img = np.array(response.data, dtype="uint8")

np.testing.assert_equal(test_img, self.test_data_8[5, 0:512, 0:512])

def test_tiff_uint16_xy(self):
""" Test a png xy slice"""
# Post data to the database
factory = APIRequestFactory()

# Get an image file
request = factory.get('/' + version + '/tile/col1/exp1/channel2/xy/512/0/0/0/5/',
Accept='image/tiff')
force_authenticate(request, user=self.user)
# Make request
response = Tile.as_view()(request, collection='col1', experiment='exp1', channel='channel1',
orientation='xy', tile_size='512', resolution='0',
x_idx='0', y_idx='0', z_idx='5')
self.assertEqual(response.status_code, status.HTTP_200_OK)

# Check data is correct (this is pre-renderer)
test_img = np.array(response.data, dtype="uint16")

np.testing.assert_equal(test_img, self.test_data_8[5, 0:512, 0:512])


def test_jp2_uint8_xy(self):
""" Test a png xy slice"""
# Post data to the database
factory = APIRequestFactory()

# Get an image file
request = factory.get('/' + version + '/tile/col1/exp1/channel1/xy/512/0/0/0/5/',
Accept='image/jp2')
force_authenticate(request, user=self.user)
# Make request
response = Tile.as_view()(request, collection='col1', experiment='exp1', channel='channel1',
orientation='xy', tile_size='512', resolution='0',
x_idx='0', y_idx='0', z_idx='5')
self.assertEqual(response.status_code, status.HTTP_200_OK)

# Check data is correct (this is pre-renderer)
test_img = np.array(response.data, dtype="uint8")

np.testing.assert_equal(test_img, self.test_data_8[5, 0:512, 0:512])


class TestTileInterfaceView(TileInterfaceViewTestMixin, APITestCase):

Expand Down
6 changes: 3 additions & 3 deletions django/bosstiles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

import bossutils

from .renderers import PNGRenderer, JPEGRenderer
from .renderers import PNGRenderer, JPEGRenderer, TIFFRenderer, JPEG2000Renderer


class CutoutTile(APIView):
Expand All @@ -38,7 +38,7 @@ class CutoutTile(APIView):
* Requires authentication.
"""
renderer_classes = (PNGRenderer, JPEGRenderer)
renderer_classes = (PNGRenderer, JPEGRenderer, TIFFRenderer, JPEG2000Renderer)

def __init__(self):
super().__init__()
Expand Down Expand Up @@ -182,7 +182,7 @@ class Tile(APIView):
* Requires authentication.
"""
renderer_classes = (PNGRenderer, JPEGRenderer)
renderer_classes = (PNGRenderer, JPEGRenderer, TIFFRenderer, JPEG2000Renderer)

def __init__(self):
super().__init__()
Expand Down

0 comments on commit 9aea47c

Please sign in to comment.