Skip to content

Commit

Permalink
Merge pull request #4432 from will-moore/masks_in_web_viewer
Browse files Browse the repository at this point in the history
Masks in web viewer
  • Loading branch information
jburel committed Feb 24, 2016
2 parents 49d1a2b + 2c01a57 commit 1b5ab03
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 3 deletions.
14 changes: 13 additions & 1 deletion components/tools/OmeroWeb/omeroweb/webgateway/marshal.py
Expand Up @@ -332,14 +332,26 @@ def stringToSvg(string):

def rgb_int2css(rgbint):
"""
converts a bin int number into css colour, E.g. -1006567680 to '#00ff00'
converts a bin int number into css colour and alpha fraction.
E.g. -1006567680 to '#00ff00', 0.5
"""
alpha = rgbint // 256 // 256 // 256 % 256
alpha = float(alpha) / 256
r, g, b = (rgbint // 256 // 256 % 256, rgbint // 256 % 256, rgbint % 256)
return "#%02x%02x%02x" % (r, g, b), alpha


def rgb_int2rgba(rgbint):
"""
converts a bin int number into (r, g, b, alpha) tuple.
E.g. 1694433280 to (255, 0, 0, 0.390625)
"""
alpha = rgbint // 256 // 256 // 256 % 256
alpha = float(alpha) / 256
r, g, b = (rgbint // 256 // 256 % 256, rgbint // 256 % 256, rgbint % 256)
return (r, g, b, alpha)


def chgrpMarshal(conn, rsp):
"""
Helper for marshalling a Chgrp response.
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -31,6 +31,7 @@ $.fn.roi_display = function(options) {
if (options != null) {
var orig_width = options.width;
var orig_height = options.height;
var webgateway_index = options.webgateway_index; // base url
var json_url = options.json_url;
}

Expand Down Expand Up @@ -102,6 +103,10 @@ $.fn.roi_display = function(options) {

var draw_shape = function(shape) {
var newShape = null;
if (shape['type'] == 'Mask') {
var src = webgateway_index + 'render_shape_mask/' + shape['id'] + '/';
newShape = paper.image(src, shape['x'], shape['y'], shape['width'], shape['height']);
}
if (shape['type'] == 'Ellipse') {
newShape = paper.ellipse(shape['cx'], shape['cy'], shape['rx'], shape['ry']);
}
Expand Down
Expand Up @@ -362,6 +362,7 @@
if (!viewport.viewportimg.get(0).show_rois) {
var options = {'width':{{ image.getSizeX }},
'height':{{ image.getSizeY }},
'webgateway_index':'{% url "webgateway" %}',
'json_url':'{% url 'webgateway_get_rois_json' image.id %}'};
if (viewport.loadedImg.tiles) {
options['tiles'] = true;
Expand Down Expand Up @@ -450,7 +451,8 @@
$roi_table.append($(roi_html));

get_shape_icon_src = function(type, klass) {
var shape_icons = {'Line':'line16.png', 'Ellipse':'ellipse16.png', 'Polygon':'polygon16.png', 'Rectangle':'rectangle16.png',
var shape_icons = {'Line':'line16.png', 'Ellipse':'ellipse16.png',
'Polygon':'polygon16.png', 'Rectangle':'rectangle16.png', 'Mask': 'mask16.png',
'Point':'point16.png', 'Label':'text16.png', 'PolyLine':'line16.png'}
if (type in shape_icons) {
return "<img class='"+ klass +"' src='{% static 'webgateway/img/' %}" + shape_icons[type] + "' />";
Expand Down
7 changes: 7 additions & 0 deletions components/tools/OmeroWeb/omeroweb/webgateway/urls.py
Expand Up @@ -147,6 +147,12 @@
L{views.render_shape_thumbnail}. Uses current rendering settings.
"""

render_shape_mask = (r'^render_shape_mask/(?P<shapeId>[0-9]+)/$',
'webgateway.views.render_shape_mask')
"""
Returns a mask for the specified shape
"""

render_birds_eye_view = (
r'^render_birds_eye_view/(?P<iid>[0-9]+)/(?:(?P<size>[0-9]+)/)?$',
'webgateway.views.render_birds_eye_view')
Expand Down Expand Up @@ -410,6 +416,7 @@
render_col_plot,
render_roi_thumbnail,
render_shape_thumbnail,
render_shape_mask,
render_thumbnail,
render_birds_eye_view,
render_ome_tiff,
Expand Down
67 changes: 66 additions & 1 deletion components/tools/OmeroWeb/omeroweb/webgateway/views.py
Expand Up @@ -31,7 +31,7 @@
from omero.util.ROI_utils import pointsStringToXYlist, xyListToBbox
from plategrid import PlateGrid
from omero_version import build_year
from marshal import imageMarshal, shapeMarshal
from marshal import imageMarshal, shapeMarshal, rgb_int2rgba

try:
from hashlib import md5
Expand Down Expand Up @@ -78,6 +78,13 @@
except:
logger.error('No Pillow installed')

try:
import numpy
numpyInstalled = True
except ImportError:
logger.error('No numpy installed')
numpyInstalled = False


def index(request):
""" /webgateway/ index placeholder """
Expand Down Expand Up @@ -650,6 +657,64 @@ def resizeXY(xy):
return HttpResponse(jpeg, content_type='image/jpeg')


@login_required()
def render_shape_mask(request, shapeId, conn=None, **kwargs):
""" Returns mask as a png (supports transparency) """

if not numpyInstalled:
raise NotImplementedError("numpy not installed")
params = omero.sys.Parameters()
params.map = {'id': rlong(shapeId)}
shape = conn.getQueryService().findByQuery(
"select s from Shape s where s.id = :id", params,
conn.SERVICE_OPTS)
if shape is None:
raise Http404("Shape ID: %s not found" % shapeId)
width = int(shape.getWidth().getValue())
height = int(shape.getHeight().getValue())
color = unwrap(shape.getFillColor())
fill = (255, 255, 0, 255)
if color is not None:
color = rgb_int2rgba(color)
fill = (color[0], color[1], color[2], int(color[3] * 255))
mask_packed = shape.getBytes()
# convert bytearray into something we can use
intarray = numpy.fromstring(mask_packed, dtype=numpy.uint8)
binarray = numpy.unpackbits(intarray)

# Couldn't get the 'proper' way of doing this to work,
# TODO: look at this again later. Faster than simple way below:
# E.g. takes ~2 seconds for 1984 x 1984 mask
# pixels = ""
# steps = len(binarray) / 8
# for i in range(steps):
# b = binarray[i*8: (i+1)*8]
# pixels += struct.pack("8B", b[0], b[1], b[2], b[3], b[4],
# b[5], b[6], b[7])
# for b in binarray:
# pixels += struct.pack("1B", b)
# im = Image.frombytes("1", size=(width, height), data=pixels)

# Simple approach - Just set each pixel in turn
# E.g. takes ~12 seconds for 1984 x 1984 mask with most pixels '1'
# Or ~5 seconds for same size mask with most pixels "0"
img = Image.new("RGBA", size=(width, height), color=(0, 0, 0, 0))
x = 0
y = 0
for pix in binarray:
if pix == 1:
img.putpixel((x, y), fill)
x += 1
if x > width - 1:
x = 0
y += 1
rv = StringIO()
# return a png (supports transparency)
img.save(rv, 'png', quality=int(100))
png = rv.getvalue()
return HttpResponse(png, content_type='image/png')


def _get_signature_from_request(request):
"""
returns a string that identifies this image, along with the settings
Expand Down

0 comments on commit 1b5ab03

Please sign in to comment.