From 24855300629cde5cf4f44e6d46b137014adade24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Tue, 9 Jul 2024 16:52:42 +0200 Subject: [PATCH 01/30] Add outline icon and outline image ROI (full image) --- src/css/figure.css | 3 ++ src/images/outline-icon-16.png | Bin 0 -> 87 bytes src/js/shape_editor/rect.js | 2 +- src/js/shape_editor/shape_manager.js | 29 ++++++++++++++++++ src/js/views/roi_modal_view.js | 6 +++- .../shapes/shape_toolbar.template.html | 5 +++ 6 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/images/outline-icon-16.png diff --git a/src/css/figure.css b/src/css/figure.css index 9ae08c934..074ff3f27 100644 --- a/src/css/figure.css +++ b/src/css/figure.css @@ -1265,6 +1265,9 @@ .polyline-icon{ background-image: url("../images/polyline-icon-16.png"); } + .outline-icon { + background-image: url("../images/outline-icon-16.png"); + } .roiModalRoiItem { cursor: pointer; } diff --git a/src/images/outline-icon-16.png b/src/images/outline-icon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..e966d8928b521f49942969a64aef60d5cd1e7fad GIT binary patch literal 87 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx*Bp9q_EZ7UA}1Cmdk-AIRXr;40QL j@d^7*hFzC0+P1SXlrl`utgsH72GZf_>gTe~DWM4fQwA3- literal 0 HcmV?d00001 diff --git a/src/js/shape_editor/rect.js b/src/js/shape_editor/rect.js index 95ee30d8d..2b6e3dc3c 100644 --- a/src/js/shape_editor/rect.js +++ b/src/js/shape_editor/rect.js @@ -494,4 +494,4 @@ CreateRect.prototype.stopDrag = function stopDrag() { this.manager.addShape(this.rect); }; -export { CreateRect, Rect }; +export { CreateRect, Rect}; diff --git a/src/js/shape_editor/shape_manager.js b/src/js/shape_editor/shape_manager.js index 78d8daa20..9a4c7639a 100644 --- a/src/js/shape_editor/shape_manager.js +++ b/src/js/shape_editor/shape_manager.js @@ -103,6 +103,10 @@ ShapeManager.prototype.startDrag = function startDrag(x, y, event) { startX = x - offset.left, startY = y - offset.top; + console.log("x:" +x) + console.log("y:" +y) + console.log("startX:" +startX) + console.log("startY:" +startY) if (this.getState() === "SELECT") { this._dragStart = { x: startX, y: startY }; @@ -276,6 +280,31 @@ ShapeManager.prototype.setShapesJson = function setShapesJson(jsonShapes) { }); }; +ShapeManager.prototype.createOutline = function createOutline() { + console.log(this.paper) + console.log(this._zoom) + console.log(this._strokeWidth) + console.log(this._strokeColor) + console.log(this.selectRegion.attr()) + console.log(this.$el.offset()) + console.log(this._orig_width) + console.log(this._orig_height) + var outline = new Rect({ + manager: this, + paper: this.paper, + x: 0, + y: 0, + width: this._orig_width, + height: this._orig_height, + area: 0, + strokeWidth: this._strokeWidth, + zoom: this._zoom, + strokeColor: this._strokeColor, + }); + outline.setSelected(true); + this.addShape(outline); +} + ShapeManager.prototype.regionToPath = function regionToPath(region, zoom) { var f = zoom ? zoom / 100 : this._zoom / 100, x = parseInt(region.x * f, 10), diff --git a/src/js/views/roi_modal_view.js b/src/js/views/roi_modal_view.js index 447595c65..0700a2236 100644 --- a/src/js/views/roi_modal_view.js +++ b/src/js/views/roi_modal_view.js @@ -73,7 +73,6 @@ export const RoiModalView = Backbone.View.extend({ // Here we handle init of the dialog when it's shown... document.getElementById('roiModal').addEventListener('shown.bs.modal', () => { - console.log("ROI modal shown...") // Clone the 'first' selected panel as our reference for everything self.m = self.model.getSelected().head().clone(); @@ -127,6 +126,7 @@ export const RoiModalView = Backbone.View.extend({ "click .roisJumpPage": "roisJumpPage", "click .revert_theZ": "revertTheZ", "click .revert_theT": "revertTheT", + "click .outline":"outlineView" }, revertTheZ: function() { @@ -141,6 +141,10 @@ export const RoiModalView = Backbone.View.extend({ this.renderImagePlane(); }, + outlineView: function(){ + this.shapeManager.createOutline() + }, + checkForRois: function() { var url = BASE_WEBFIGURE_URL + 'roiCount/' + this.m.get('imageId') + '/'; diff --git a/src/templates/shapes/shape_toolbar.template.html b/src/templates/shapes/shape_toolbar.template.html index 0922086c8..8839992c7 100644 --- a/src/templates/shapes/shape_toolbar.template.html +++ b/src/templates/shapes/shape_toolbar.template.html @@ -6,6 +6,11 @@ +
+ +
+ +
+
Outline Panel
+ + + +
+ + +
+ +
+ +
+ + +
+ <% } %> From a8341cdce28cb9a1650713574b355e08bdb92a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Tue, 27 Aug 2024 13:08:10 +0200 Subject: [PATCH 08/30] handle dynamic change of color and stroke width --- src/js/models/panel_model.js | 20 ++++++++++++++++++++ src/js/views/right_panel_view.js | 27 +++++++++++++++++++++++++-- src/templates/rois_form.template.html | 17 +++++++++++++++-- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/js/models/panel_model.js b/src/js/models/panel_model.js index a42d2b17f..09491ae9e 100644 --- a/src/js/models/panel_model.js +++ b/src/js/models/panel_model.js @@ -166,6 +166,26 @@ this.save('outline', outline); }, + setOutlineColor: function(color){ + var outline = this.get('outline'); + if(outline != undefined){ + var xtra = {}; + xtra['color'] = '#'+color; + var new_outline = $.extend(true, {}, outline, xtra); + this.save('outline', new_outline); + } + }, + + setOutlineStrokeWidth: function(strokewidth){ + var outline = this.get('outline'); + if(outline != undefined){ + var xtra = {}; + xtra['strokewidth'] = strokewidth; + var new_outline = $.extend(true, {}, outline, xtra); + this.save('outline', new_outline); + } + }, + remove_outline: function(){ this.save('outline', undefined); }, diff --git a/src/js/views/right_panel_view.js b/src/js/views/right_panel_view.js index 435642261..a761fcedb 100644 --- a/src/js/views/right_panel_view.js +++ b/src/js/views/right_panel_view.js @@ -110,6 +110,8 @@ "click .edit_rois": "editRois", "click .show_outline": "showOutline", "click .remove_outline": "removeOutline", + "change .outline-color": "changeOutlineColor", + "change .outline-width": "changeOutlineStrokeWidth", "click .copyROIs": "copyROIs", "click .pasteROIs": "pasteROIs", "click .deleteROIs": "deleteROIs", @@ -137,6 +139,25 @@ }); }, + changeOutlineColor: function() { + var color = $('button.outline-color span:first', this.$el).attr('data-color'), + sel = this.model.getSelected(); + + sel.forEach(function(panel){ + panel.setOutlineColor(color); + }); + }, + + changeOutlineStrokeWidth: function() { + var width = $('button.outline-width span:first', this.$el).attr('data-line-width'), + sel = this.model.getSelected(); + width = parseFloat(width, 10); + + sel.forEach(function(panel){ + panel.setOutlineStrokeWidth(width); + }); + }, + copyROIs: function(event) { event.preventDefault(); var sel = this.model.getSelected(), @@ -265,7 +286,8 @@ clipboard_data = this.model.get('clipboard'), canPaste = clipboard_data && ('SHAPES' in clipboard_data || 'CROP' in clipboard_data), color, - width; + width, + outline; sel.forEach(function(panel){ var rois = panel.get('shapes'); @@ -290,7 +312,7 @@ }); } - var outline = panel.get("outline") + outline = panel.get("outline") if(outline){ panel.show_outline(outline.color.replace('#',''), parseFloat(outline.strokewidth, 10)) } @@ -302,6 +324,7 @@ 'lineWidth': width || 2, 'roiCount': roiCount, 'canPaste': canPaste, + 'outline': outline, } $('#edit_rois_form').html(this.roisTemplate(json)); }, diff --git a/src/templates/rois_form.template.html b/src/templates/rois_form.template.html index 70bafbaf2..3925d1d63 100644 --- a/src/templates/rois_form.template.html +++ b/src/templates/rois_form.template.html @@ -98,7 +98,11 @@
Outline Panel
-
-
- -
-
@@ -139,17 +139,17 @@
Outline Panel
- @@ -163,12 +163,12 @@
Outline Panel
-
- From c0c20fced6baea362f5c6fe62196018783fadcf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Thu, 29 Aug 2024 09:15:02 +0200 Subject: [PATCH 11/30] remove extra space and commented code --- src/js/views/roi_modal_view.js | 5 ----- src/templates/shapes/shape_toolbar.template.html | 1 + vite.config.js | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/js/views/roi_modal_view.js b/src/js/views/roi_modal_view.js index f53ea62a2..aea9ac0f9 100644 --- a/src/js/views/roi_modal_view.js +++ b/src/js/views/roi_modal_view.js @@ -140,11 +140,6 @@ export const RoiModalView = Backbone.View.extend({ this.renderImagePlane(); }, - /* outlineView: function(){ - var viewport = this.m.getViewportAsRect() - this.shapeManager.createOutline(viewport) - },*/ - checkForRois: function() { var url = BASE_WEBFIGURE_URL + 'roiCount/' + this.m.get('imageId') + '/'; diff --git a/src/templates/shapes/shape_toolbar.template.html b/src/templates/shapes/shape_toolbar.template.html index dfb2916cd..0922086c8 100644 --- a/src/templates/shapes/shape_toolbar.template.html +++ b/src/templates/shapes/shape_toolbar.template.html @@ -6,6 +6,7 @@ +
-
- -
- + +
+ <% if (showBorder){ %> + + <% } else { %> + + <% } %>
- - <% } %> From 830d988a5385713ec837530db20ccd081ea82cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Fri, 30 Aug 2024 08:32:57 +0200 Subject: [PATCH 15/30] Fixing showBorder logic --- src/js/models/panel_model.js | 4 ++-- src/js/views/panel_view.js | 4 ++-- src/js/views/right_panel_view.js | 8 ++++---- src/templates/rois_form.template.html | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/js/models/panel_model.js b/src/js/models/panel_model.js index 36ec9c91e..927193d44 100644 --- a/src/js/models/panel_model.js +++ b/src/js/models/panel_model.js @@ -162,13 +162,13 @@ var border = { 'color': '#'+color, 'strokeWidth': strokeWidth, - 'showBorder':false + 'showBorder':true } this.save('border', border); }, remove_border: function(){ - this.setBorderAttr('showBorder', true) + this.setBorderAttr('showBorder', false) }, setBorderColor: function(color){ diff --git a/src/js/views/panel_view.js b/src/js/views/panel_view.js index a6594841e..01c865c2b 100644 --- a/src/js/views/panel_view.js +++ b/src/js/views/panel_view.js @@ -64,7 +64,7 @@ if (w == this.model.get('width') && h == this.model.get('height')) { // If we're only dragging - simply update position var border = this.model.get('border'); - if (border != undefined) { + if (border?.showBorder) { let sw = border.strokeWidth; x = x - sw y = y - sw @@ -95,7 +95,7 @@ var border = this.model.get('border'); var page_w = w; var page_h = h; - if (border != undefined && !border.showBorder) { + if (border?.showBorder) { let sw = border.strokeWidth; this.$el.css({'border': `solid ${sw}px ${border.color}`}) x = x - sw; diff --git a/src/js/views/right_panel_view.js b/src/js/views/right_panel_view.js index 1d0fe2140..12d16a75a 100644 --- a/src/js/views/right_panel_view.js +++ b/src/js/views/right_panel_view.js @@ -289,7 +289,7 @@ color, width, border, - show_border = false; + show_btn_state = false; sel.forEach(function(panel){ var rois = panel.get('shapes'); @@ -315,10 +315,10 @@ } border = panel.get("border") - if(border != undefined && !border.showBorder){ + if(border?.showBorder){ panel.show_border(border.color.replace('#',''), parseFloat(border.strokeWidth, 10)) }else{ - show_border = true; + show_btn_state = true; } }); @@ -330,7 +330,7 @@ 'canPaste': canPaste, 'borderWidth': border ? border.strokeWidth : 2, 'borderColor': border ? border.color.replace('#', '') : 'FFFFFF', - 'showBorder': show_border, + 'showState': show_btn_state, } $('#edit_rois_form').html(this.roisTemplate(json)); }, diff --git a/src/templates/rois_form.template.html b/src/templates/rois_form.template.html index 4105ad65a..2e2ebdae0 100644 --- a/src/templates/rois_form.template.html +++ b/src/templates/rois_form.template.html @@ -93,7 +93,7 @@
ROIs
-
Outline Panel
+
Border
- <% if (showBorder){ %> + <% if (showState){ %> <% } else { %> From f2013b1856389327753c4b2368d9ff590250b13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Fri, 30 Aug 2024 13:36:35 +0200 Subject: [PATCH 16/30] Update figure_to_pdf --- .../omero/figure_scripts/Figure_To_Pdf.py | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 265f4b5e5..4532b5540 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -216,7 +216,10 @@ def apply_transform(tf, point): point[0] * tf['A10'] + point[1] * tf['A11'] + tf['A12'], ] if tf else point - def draw_rectangle(self, shape): + def draw_outline(self, shape): + self.draw_rectangle(shape, False) + + def draw_rectangle(self, shape, inPanelCheck=True): # to support rotation/transforms, convert rectangle to a simple # four point polygon and draw that instead s = deepcopy(shape) @@ -229,7 +232,7 @@ def draw_rectangle(self, shape): ] s['points'] = ' '.join(','.join( map(str, self.apply_transform(t, point))) for point in points) - self.draw_polygon(s) + self.draw_polygon(s, closed=True, inPanelCheck=inPanelCheck) def draw_point(self, shape): s = deepcopy(shape) @@ -407,8 +410,8 @@ def draw_arrow(self, shape): self.draw_shape_label(shape, Bounds((x1, y1), (x2, y2))) - def draw_polygon(self, shape, closed=True): - polygon_in_viewport = False + def draw_polygon(self, shape, closed=True, inPanelCheck=True): + polygon_in_viewport = not inPanelCheck points = [] for point in shape['points'].split(" "): # Older polygons/polylines may be 'x,y,' @@ -451,7 +454,7 @@ def draw_polygon(self, shape, closed=True): self.draw_shape_label(shape, Bounds(*points)) def draw_polyline(self, shape): - self.draw_polygon(shape, False) + self.draw_polygon(shape, closed=False) def draw_ellipse(self, shape): stroke_width = float(shape.get('strokeWidth', 1)) @@ -1126,6 +1129,25 @@ def add_rois(self, panel, page): """ Add any Shapes """ + if 'border' in panel and not panel['border'].get('showBorder'): + crop = self.get_crop_region(panel) + sw = panel['border'].get('strokeWidth') + shift_pos = sw / (float(panel['zoom'])/100) + + shape = {} + shape['strokeColor'] = panel['border'].get('color') + shape['strokeWidth'] = sw + shape['x'] = crop['x'] - shift_pos + shape['y'] = crop['y'] - shift_pos + shape['width'] = crop['width'] + 2*shift_pos + shape['height'] = crop['height'] + 2*shift_pos + shape['type'] = "outline" + + if "shapes" not in panel: + panel['shapes'] = [shape] + else: + panel['shapes'].append(shape) + if "shapes" not in panel: return From a368b28b0e7fa10cc6c5abbdfa1fd52ff23c79d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Fri, 30 Aug 2024 13:38:57 +0200 Subject: [PATCH 17/30] fix bug on showBorder --- omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 4532b5540..139082cf0 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -1129,7 +1129,7 @@ def add_rois(self, panel, page): """ Add any Shapes """ - if 'border' in panel and not panel['border'].get('showBorder'): + if 'border' in panel and panel['border'].get('showBorder'): crop = self.get_crop_region(panel) sw = panel['border'].get('strokeWidth') shift_pos = sw / (float(panel['zoom'])/100) From 08bc8d5ebd74e6532c68ea4e4d2e8a13a22c70ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Fri, 30 Aug 2024 14:22:50 +0200 Subject: [PATCH 18/30] Add tiff export border support --- .../omero/figure_scripts/Figure_To_Pdf.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 139082cf0..5ed1b6526 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -523,6 +523,24 @@ def __init__(self, pil_img, panel, crop): self.scale = pil_img.size[0] / crop['width'] self.draw = ImageDraw.Draw(pil_img) + if 'border' in panel and panel['border'].get('showBorder'): + sw = panel['border'].get('strokeWidth') + shift_pos = sw / (float(panel['zoom'])/100) + + shape = {} + shape['strokeColor'] = panel['border'].get('color') + shape['strokeWidth'] = sw + shape['x'] = crop['x'] - shift_pos + shape['y'] = crop['y'] - shift_pos + shape['width'] = crop['width'] + 2*shift_pos + shape['height'] = crop['height'] + 2*shift_pos + shape['type'] = "outline" + + if "shapes" not in panel: + panel['shapes'] = [shape] + else: + panel['shapes'].append(shape) + super(ShapeToPilExport, self).__init__(panel) def get_panel_coords(self, shape_x, shape_y): @@ -628,7 +646,7 @@ def draw_arrow(self, shape): # Override to not just call draw_polygon, because we want square corners # for rectangles and not the rounded corners draw_polygon creates - def draw_rectangle(self, shape): + def draw_rectangle(self, shape, inPanelCheck=True): points = [ (shape['x'], shape['y']), (shape['x'] + shape['width'], shape['y']), @@ -646,7 +664,6 @@ def draw_rectangle(self, shape): stroke_width = scale_to_export_dpi(float(shape.get('strokeWidth', 2))) buffer = int(ceil(stroke_width) * 1.5) - # if fill, draw filled polygon without outline, then add line later # with correct stroke width rgba = self.get_rgba_int(shape.get('fillColor', '#00000000')) From 11e92dcbd5f1911769828c7338bbf0319e0f191d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Tue, 3 Sep 2024 13:14:40 +0200 Subject: [PATCH 19/30] Fix flake8 errors --- .gitignore | 2 ++ .../scripts/omero/figure_scripts/Figure_To_Pdf.py | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 661c9605a..69f8c16e9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ dist omero_figure.egg-info omero_figure/templates/ omero_figure/static/ +.vscode +.idea diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 5ed1b6526..0958cfe27 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -219,7 +219,7 @@ def apply_transform(tf, point): def draw_outline(self, shape): self.draw_rectangle(shape, False) - def draw_rectangle(self, shape, inPanelCheck=True): + def draw_rectangle(self, shape, in_panel_check=True): # to support rotation/transforms, convert rectangle to a simple # four point polygon and draw that instead s = deepcopy(shape) @@ -232,7 +232,7 @@ def draw_rectangle(self, shape, inPanelCheck=True): ] s['points'] = ' '.join(','.join( map(str, self.apply_transform(t, point))) for point in points) - self.draw_polygon(s, closed=True, inPanelCheck=inPanelCheck) + self.draw_polygon(s, closed=True, in_panel_check=in_panel_check) def draw_point(self, shape): s = deepcopy(shape) @@ -410,8 +410,8 @@ def draw_arrow(self, shape): self.draw_shape_label(shape, Bounds((x1, y1), (x2, y2))) - def draw_polygon(self, shape, closed=True, inPanelCheck=True): - polygon_in_viewport = not inPanelCheck + def draw_polygon(self, shape, closed=True, in_panel_check=True): + polygon_in_viewport = not in_panel_check points = [] for point in shape['points'].split(" "): # Older polygons/polylines may be 'x,y,' @@ -524,7 +524,7 @@ def __init__(self, pil_img, panel, crop): self.draw = ImageDraw.Draw(pil_img) if 'border' in panel and panel['border'].get('showBorder'): - sw = panel['border'].get('strokeWidth') + sw = panel['border'].get('strokeWidth') shift_pos = sw / (float(panel['zoom'])/100) shape = {} @@ -646,7 +646,7 @@ def draw_arrow(self, shape): # Override to not just call draw_polygon, because we want square corners # for rectangles and not the rounded corners draw_polygon creates - def draw_rectangle(self, shape, inPanelCheck=True): + def draw_rectangle(self, shape, in_panel_check=True): points = [ (shape['x'], shape['y']), (shape['x'] + shape['width'], shape['y']), @@ -1148,7 +1148,7 @@ def add_rois(self, panel, page): """ if 'border' in panel and panel['border'].get('showBorder'): crop = self.get_crop_region(panel) - sw = panel['border'].get('strokeWidth') + sw = panel['border'].get('strokeWidth') shift_pos = sw / (float(panel['zoom'])/100) shape = {} From ec73abbe8819648c50a27d7ad32cf9d17b7f2ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 9 Sep 2024 08:35:09 +0200 Subject: [PATCH 20/30] Fixing margin-top --- src/templates/rois_form.template.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/rois_form.template.html b/src/templates/rois_form.template.html index b783acac2..5266642f4 100644 --- a/src/templates/rois_form.template.html +++ b/src/templates/rois_form.template.html @@ -178,7 +178,7 @@
Inset Panel
-
+
Border
From d538c6d66d4f9aa5206e9a235acfa9a1aa951529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 9 Sep 2024 08:46:57 +0200 Subject: [PATCH 21/30] Fix method name --- omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index b309f1f51..6ddcbfad8 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -216,7 +216,8 @@ def apply_transform(tf, point): point[0] * tf['A10'] + point[1] * tf['A11'] + tf['A12'], ] if tf else point - def draw_outline(self, shape): + def draw_border(self, shape): + # to support panel border drawing self.draw_rectangle(shape, False) def draw_rectangle(self, shape, in_panel_check=True): @@ -1158,7 +1159,7 @@ def add_rois(self, panel, page): shape['y'] = crop['y'] - shift_pos shape['width'] = crop['width'] + 2*shift_pos shape['height'] = crop['height'] + 2*shift_pos - shape['type'] = "outline" + shape['type'] = "border" if "shapes" not in panel: panel['shapes'] = [shape] From e5a5963c061372846c438152942411704aaf3e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 9 Sep 2024 10:07:13 +0200 Subject: [PATCH 22/30] Fixing tiff export --- .../omero/figure_scripts/Figure_To_Pdf.py | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 6ddcbfad8..5a81b1b93 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -523,25 +523,6 @@ def __init__(self, pil_img, panel, crop): self.crop = crop self.scale = pil_img.size[0] / crop['width'] self.draw = ImageDraw.Draw(pil_img) - - if 'border' in panel and panel['border'].get('showBorder'): - sw = panel['border'].get('strokeWidth') - shift_pos = sw / (float(panel['zoom'])/100) - - shape = {} - shape['strokeColor'] = panel['border'].get('color') - shape['strokeWidth'] = sw - shape['x'] = crop['x'] - shift_pos - shape['y'] = crop['y'] - shift_pos - shape['width'] = crop['width'] + 2*shift_pos - shape['height'] = crop['height'] + 2*shift_pos - shape['type'] = "outline" - - if "shapes" not in panel: - panel['shapes'] = [shape] - else: - panel['shapes'].append(shape) - super(ShapeToPilExport, self).__init__(panel) def get_panel_coords(self, shape_x, shape_y): @@ -665,6 +646,7 @@ def draw_rectangle(self, shape, in_panel_check=True): stroke_width = scale_to_export_dpi(float(shape.get('strokeWidth', 2))) buffer = int(ceil(stroke_width) * 1.5) + # if fill, draw filled polygon without outline, then add line later # with correct stroke width rgba = self.get_rgba_int(shape.get('fillColor', '#00000000')) @@ -2288,10 +2270,24 @@ def paste_image(self, pil_img, img_name, panel, page, dpi=None): # Now at full figure resolution - Good time to add shapes... crop = self.get_crop_region(panel) - ShapeToPilExport(pil_img, panel, crop) + exporter = ShapeToPilExport(pil_img, panel, crop) width, height = pil_img.size - box = (x, y, x + width, y + height) + + # Add border if needed - Rectangle around the whole panel + if 'border' in panel and panel['border'].get('showBorder'): + sw = panel['border'].get('strokeWidth') + border_width = scale_to_export_dpi(sw) + border_color = panel['border'].get('color') + padding = border_width * 2 + + canvas = Image.new("RGB", (width + padding, height + padding), exporter.get_rgb(border_color)) + canvas.paste(pil_img, (border_width, border_width)) + pil_img = canvas + box = (x - border_width, y - border_width, x + width + border_width, y + height + border_width) + else: + box = (x, y, x + width, y + height) + self.tiff_figure.paste(pil_img, box) def draw_scalebar_line(self, x, y, x2, y2, width, rgb): From 526f3b6560dc4b441a47513d222c9f52dba306ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 9 Sep 2024 10:19:06 +0200 Subject: [PATCH 23/30] Fix flake8 errors --- .../omero/figure_scripts/Figure_To_Pdf.py | 146 +++++++++--------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 5a81b1b93..9d33c7a49 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -36,8 +36,8 @@ from omero.rtypes import rstring, robject from omero.model.enums import UnitsLength - from io import BytesIO + try: from PIL import Image, ImageDraw, ImageFont except ImportError: @@ -48,6 +48,7 @@ try: import markdown + markdown_imported = True except ImportError: markdown_imported = False @@ -60,6 +61,7 @@ from reportlab.lib.colors import Color from reportlab.platypus import Paragraph from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT + reportlab_installed = True except ImportError: reportlab_installed = False @@ -109,7 +111,7 @@ def scale_to_export_dpi(pixels): Original figure coordinates assume 72 dpi figure, but we want to export at 300 dpi, so everything needs scaling accordingly """ - return pixels * 300//72 + return pixels * 300 // 72 def compress(target, base): @@ -242,7 +244,6 @@ def draw_point(self, shape): class ShapeToPdfExport(ShapeExport): - point_radius = 5 def __init__(self, canvas, panel, page, crop, page_height): @@ -269,8 +270,8 @@ def panel_to_page_coords(self, shape_x, shape_y): rotation = self.panel['rotation'] if rotation != 0: # img coords: centre of rotation - cx = self.crop['x'] + (self.crop['width']/2) - cy = self.crop['y'] + (self.crop['height']/2) + cx = self.crop['x'] + (self.crop['width'] / 2) + cy = self.crop['y'] + (self.crop['height'] / 2) dx = cx - shape_x dy = cy - shape_y # distance of point from centre of rotation @@ -338,9 +339,9 @@ def draw_line(self, shape): return rgb = self.get_rgb(shape['strokeColor']) - r = float(rgb[0])/255 - g = float(rgb[1])/255 - b = float(rgb[2])/255 + r = float(rgb[0]) / 255 + g = float(rgb[1]) / 255 + b = float(rgb[2]) / 255 self.canvas.setStrokeColorRGB(r, g, b) stroke_width = float(shape.get('strokeWidth', 1)) self.canvas.setLineWidth(stroke_width) @@ -365,9 +366,9 @@ def draw_arrow(self, shape): return rgb = self.get_rgb(shape['strokeColor']) - r = float(rgb[0])/255 - g = float(rgb[1])/255 - b = float(rgb[2])/255 + r = float(rgb[0]) / 255 + g = float(rgb[1]) / 255 + b = float(rgb[2]) / 255 self.canvas.setStrokeColorRGB(r, g, b) self.canvas.setFillColorRGB(r, g, b) @@ -535,8 +536,8 @@ def get_panel_coords(self, shape_x, shape_y): rotation = self.panel['rotation'] if rotation != 0: # img coords: centre of rotation - cx = self.crop['x'] + (self.crop['width']/2) - cy = self.crop['y'] + (self.crop['height']/2) + cx = self.crop['x'] + (self.crop['width'] / 2) + cy = self.crop['y'] + (self.crop['height'] / 2) dx = cx - shape_x dy = cy - shape_y # distance of point from centre of rotation @@ -727,7 +728,7 @@ def draw_polygon(self, shape, closed=True): temp_draw.line(points, fill=rgba, width=int(round(stroke_width))) # Draw ellipse at each corner # see https://stackoverflow.com/questions/33187698/ - r = (stroke_width/2) * 0.9 # seems to look OK with this size + r = (stroke_width / 2) * 0.9 # seems to look OK with this size if closed: corners = points[:] else: @@ -779,8 +780,8 @@ def draw_ellipse(self, shape): temp_ellipse = temp_ellipse.rotate(rotation, resample=Image.BICUBIC, expand=True) # Use ellipse as mask, so transparent part is not pasted - paste_x = cx - (temp_ellipse.size[0]/2) - paste_y = cy - (temp_ellipse.size[1]/2) + paste_x = cx - (temp_ellipse.size[0] / 2) + paste_y = cy - (temp_ellipse.size[1] / 2) self.pil_img.paste(temp_ellipse, (int(paste_x), int(paste_y)), mask=temp_ellipse) self.draw_shape_label(shape, Bounds((cx, cy))) @@ -848,7 +849,7 @@ def version_transform_json(self, figure_json): if p.get('shapes') and len(p['shapes']) > 0: image_pixels_width = self.get_crop_region(p)['width'] page_coords_width = float(p.get('width')) - stroke_width_scale = page_coords_width/image_pixels_width + stroke_width_scale = page_coords_width / image_pixels_width for shape in p['shapes']: stroke_width = float(shape.get('strokeWidth', 1)) stroke_width = stroke_width * stroke_width_scale @@ -1051,7 +1052,7 @@ def apply_rdefs(self, image, channels): for i, c in enumerate(channels): if c['active']: - c_idxs.append(i+1) + c_idxs.append(i + 1) windows.append([c['window']['start'], c['window']['end']]) colors.append(c['color']) reverses.append(c.get('reverseIntensity', False)) @@ -1074,8 +1075,8 @@ def get_crop_region(self, panel): # need tile_x, tile_y, tile_w, tile_h - tile_w = orig_w / (zoom/100) - tile_h = orig_h / (zoom/100) + tile_w = orig_w / (zoom / 100) + tile_h = orig_h / (zoom / 100) orig_ratio = float(orig_w) / orig_h wh = float(frame_w) / frame_h @@ -1087,8 +1088,8 @@ def get_crop_region(self, panel): else: tile_w = tile_h * wh - cropx = ((orig_w - tile_w)/2) - dx - cropy = ((orig_h - tile_h)/2) - dy + cropx = ((orig_w - tile_w) / 2) - dx + cropy = ((orig_h - tile_h) / 2) - dy return {'x': cropx, 'y': cropy, 'width': tile_w, 'height': tile_h} @@ -1120,8 +1121,8 @@ def get_time_label_text(self, delta_t, format, dec_prec=0): else: # Format unknown return "" dec_str = "" if dec_prec == 0 else "." + "0" * dec_prec - if text in ["0"+dec_str+" s", "0:00"+dec_str, - "0"+dec_str+" mins", "0:00:00"+dec_str]: + if text in ["0" + dec_str + " s", "0:00" + dec_str, + "0" + dec_str + " mins", "0:00:00" + dec_str]: is_negative = False return ('-' if is_negative else '') + text @@ -1132,15 +1133,15 @@ def add_rois(self, panel, page): if 'border' in panel and panel['border'].get('showBorder'): crop = self.get_crop_region(panel) sw = panel['border'].get('strokeWidth') - shift_pos = sw / (float(panel['zoom'])/100) + shift_pos = sw / (float(panel['zoom']) / 100) shape = {} shape['strokeColor'] = panel['border'].get('color') shape['strokeWidth'] = sw shape['x'] = crop['x'] - shift_pos shape['y'] = crop['y'] - shift_pos - shape['width'] = crop['width'] + 2*shift_pos - shape['height'] = crop['height'] + 2*shift_pos + shape['width'] = crop['width'] + 2 * shift_pos + shape['height'] = crop['height'] + 2 * shift_pos shape['type'] = "border" if "shapes" not in panel: @@ -1216,7 +1217,7 @@ def draw_labels(self, panel, page): d_t = timestamps[the_t] if offset is not None: if 1 <= offset <= len(timestamps): - d_t -= timestamps[offset-1] + d_t -= timestamps[offset - 1] # Set the default precision value (0) if not given precision = 0 if precision is None else precision @@ -1275,7 +1276,7 @@ def draw_labels(self, panel, page): z_symbol = "\xB5m" if ("z_projection" in panel.keys() - and panel["z_projection"]): + and panel["z_projection"]): z_start, z_end = panel["z_start"], panel["z_end"] if format == "pixel": label_value = (str(z_start + 1) + "-" @@ -1336,7 +1337,7 @@ def draw_labels(self, panel, page): new_text.append(label['text'][last_idx:]) label['text'] = "".join(new_text) pos = label['position'] - label['size'] = int(label['size']) # make sure 'size' is number + label['size'] = int(label['size']) # make sure 'size' is number # If page is black and label is black, make label white page_color = self.figure_json.get('page_color', 'ffffff').lower() label_color = label['color'].lower() @@ -1392,14 +1393,14 @@ def draw_lab(label, lx, ly, align='left'): ly = ly - label['size'] - spacer draw_lab(label, lx, ly, align='right') elif key == 'top': - lx = x + (width/2) + lx = x + (width / 2) ly = y labels.reverse() for label in labels: ly = ly - label['size'] - spacer draw_lab(label, lx, ly, align='center') elif key == 'bottom': - lx = x + (width/2) + lx = x + (width / 2) ly = y + height + spacer for label in labels: label_h = draw_lab(label, lx, ly, align='center') @@ -1407,29 +1408,29 @@ def draw_lab(label, lx, ly, align='left'): elif key == 'left': lx = x - spacer sizes = [label['size'] for label in labels] - total_h = sum(sizes) + spacer * (len(labels)-1) - ly = y + (height-total_h)/2 + total_h = sum(sizes) + spacer * (len(labels) - 1) + ly = y + (height - total_h) / 2 for label in labels: label_h = draw_lab(label, lx, ly, align='right') ly += label_h + spacer elif key == 'right': lx = x + width + spacer sizes = [label['size'] for label in labels] - total_h = sum(sizes) + spacer * (len(labels)-1) - ly = y + (height-total_h)/2 + total_h = sum(sizes) + spacer * (len(labels) - 1) + ly = y + (height - total_h) / 2 for label in labels: label_h = draw_lab(label, lx, ly) ly += label_h + spacer elif key == 'leftvert': lx = x - spacer - ly = y + (height/2) + ly = y + (height / 2) labels.reverse() for label in labels: lx = lx - label['size'] - spacer draw_lab(label, lx, ly, align='left-vertical') elif key == 'rightvert': lx = x + width + spacer - ly = y + (height/2) + ly = y + (height / 2) labels.reverse() for label in labels: lx = lx + label['size'] + spacer @@ -1539,9 +1540,9 @@ def draw_scalebar(self, panel, region_width, page): ly = ly + 5 self.draw_text( - label, (lx + lx_end)/2, - ly + ((-1 if position in ["bottomleft", "bottomright"] - else 1) * half_height), + label, (lx + lx_end) / 2, + ly + ((-1 if position in ["bottomleft", "bottomright"] + else 1) * half_height), font_size, (red, green, blue), align="center") @@ -1656,8 +1657,8 @@ def get_panel_big_image(self, image, panel): max_length = 1.5 * max(vp_w, vp_h) extra_w = max_length - vp_w extra_h = max_length - vp_h - viewport_region = {'x': vp_x - (extra_w/2), - 'y': vp_y - (extra_h/2), + viewport_region = {'x': vp_x - (extra_w / 2), + 'y': vp_y - (extra_h / 2), 'width': vp_w + extra_w, 'height': vp_h + extra_h} max_width = max_width * (viewport_region['width'] / vp_w) @@ -1741,8 +1742,8 @@ def get_panel_image(self, image, panel, orig_name=None): return pil_img # Need to crop around centre before rotating... - cx = size_x/2 - cy = size_y/2 + cx = size_x / 2 + cy = size_y / 2 dx = panel['dx'] dy = panel['dy'] @@ -1872,7 +1873,7 @@ def add_para_with_thumb(self, text, page_y, style, thumb_src=None): logger.error("Couldn't add paragraph to PDF: %s" % text) text = "[Failed to format paragraph - not shown]" para = Paragraph(text, style) - w, h = para.wrap(aw, page_y) # find required space + w, h = para.wrap(aw, page_y) # find required space if thumb_src is not None: parah = max(h, imgh) else: @@ -1880,7 +1881,7 @@ def add_para_with_thumb(self, text, page_y, style, thumb_src=None): # If there's not enough space, start a new page if parah > (page_y - margin): c.showPage() - page_y = maxh # reset to top of new page + page_y = maxh # reset to top of new page if thumb_src is not None: c.drawImage(thumb_src, margin, page_y - imgh, imgw, imgh) margin = margin + imgw + spacer @@ -1960,7 +1961,7 @@ def add_info_page(self, panels_json): symbol = unit_symbols[sb_units]['symbol'] scalebars.append("%s %s" % (sb_length, symbol)) if iid in img_ids: - continue # ignore images we've already handled + continue # ignore images we've already handled img_ids.add(iid) thumb_src = self.get_thumbnail(iid) # thumb = " Date: Mon, 9 Sep 2024 10:27:12 +0200 Subject: [PATCH 24/30] Fix flake8 errors --- omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 9d33c7a49..035eb0eb6 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -1541,8 +1541,8 @@ def draw_scalebar(self, panel, region_width, page): self.draw_text( label, (lx + lx_end) / 2, - ly + ((-1 if position in ["bottomleft", "bottomright"] - else 1) * half_height), + ly + ((-1 if position in ["bottomleft", "bottomright"] + else 1) * half_height), font_size, (red, green, blue), align="center") From 88de8391291aa209747b74cbad817de8656d0750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 9 Sep 2024 17:37:29 +0200 Subject: [PATCH 25/30] fix rotation issue on pdf --- .../omero/figure_scripts/Figure_To_Pdf.py | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 035eb0eb6..355b3fb82 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -218,21 +218,66 @@ def apply_transform(tf, point): point[0] * tf['A10'] + point[1] * tf['A11'] + tf['A12'], ] if tf else point + @staticmethod + def apply_rotation(point, centre, rotation): + cx = centre[0] + cy = centre[1] + x = point[0] + y = point[1] + + dx = cx - x + dy = cy - y + # distance of point from centre of rotation + h = sqrt(dx * dx + dy * dy) + # and the angle + angle1 = atan2(dx, dy) + + # Add the rotation to the angle and calculate new + # opposite and adjacent lengths from centre of rotation + angle2 = angle1 - radians(rotation) + newo = sin(angle2) * h + newa = cos(angle2) * h + # to give correct x and y within cropped panel + x = cx - newo + y = cy - newa + return x, y + def draw_border(self, shape): # to support panel border drawing - self.draw_rectangle(shape, False) - - def draw_rectangle(self, shape, in_panel_check=True): - # to support rotation/transforms, convert rectangle to a simple - # four point polygon and draw that instead s = deepcopy(shape) - t = shape.get('transform') points = [ (shape['x'], shape['y']), (shape['x'] + shape['width'], shape['y']), (shape['x'] + shape['width'], shape['y'] + shape['height']), (shape['x'], shape['y'] + shape['height']), ] + + if shape.get('rotation', 0) != 0: + rotation = shape.get('rotation') + # rotate around centre of rectangle + cx = shape['x'] + shape['width'] / 2 + cy = shape['y'] + shape['height'] / 2 + s['points'] = [ + self.apply_rotation(point, [cx, cy], rotation) + for point in points + ] + self.draw_rectangle(s, False) + + def draw_rectangle(self, shape, in_panel_check=True): + # to support rotation/transforms, convert rectangle to a simple + # four point polygon and draw that instead + s = deepcopy(shape) + t = shape.get('transform') + + if shape.get('points', None) != None: + points = shape['points'] + else: + points = [ + (shape['x'], shape['y']), + (shape['x'] + shape['width'], shape['y']), + (shape['x'] + shape['width'], shape['y'] + shape['height']), + (shape['x'], shape['y'] + shape['height']), + ] s['points'] = ' '.join(','.join( map(str, self.apply_transform(t, point))) for point in points) self.draw_polygon(s, closed=True, in_panel_check=in_panel_check) @@ -1143,6 +1188,9 @@ def add_rois(self, panel, page): shape['width'] = crop['width'] + 2 * shift_pos shape['height'] = crop['height'] + 2 * shift_pos shape['type'] = "border" + rotation = panel['rotation'] + if rotation != 0: + shape['rotation'] = 360 - rotation if "shapes" not in panel: panel['shapes'] = [shape] From 5a5063c6d22fe914c660c2619ad8a446a731e2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Wed, 11 Sep 2024 09:11:02 +0200 Subject: [PATCH 26/30] Fix rotation issue --- .../omero/figure_scripts/Figure_To_Pdf.py | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 355b3fb82..c0ebe988c 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -243,8 +243,14 @@ def apply_rotation(point, centre, rotation): return x, y def draw_border(self, shape): - # to support panel border drawing + self.draw_rectangle(shape, False) + + def draw_rectangle(self, shape, in_panel_check=True): + # to support rotation/transforms, convert rectangle to a simple + # four point polygon and draw that instead s = deepcopy(shape) + t = shape.get('transform') + points = [ (shape['x'], shape['y']), (shape['x'] + shape['width'], shape['y']), @@ -257,27 +263,11 @@ def draw_border(self, shape): # rotate around centre of rectangle cx = shape['x'] + shape['width'] / 2 cy = shape['y'] + shape['height'] / 2 - s['points'] = [ + points = [ self.apply_rotation(point, [cx, cy], rotation) for point in points ] - self.draw_rectangle(s, False) - - def draw_rectangle(self, shape, in_panel_check=True): - # to support rotation/transforms, convert rectangle to a simple - # four point polygon and draw that instead - s = deepcopy(shape) - t = shape.get('transform') - if shape.get('points', None) != None: - points = shape['points'] - else: - points = [ - (shape['x'], shape['y']), - (shape['x'] + shape['width'], shape['y']), - (shape['x'] + shape['width'], shape['y'] + shape['height']), - (shape['x'], shape['y'] + shape['height']), - ] s['points'] = ' '.join(','.join( map(str, self.apply_transform(t, point))) for point in points) self.draw_polygon(s, closed=True, in_panel_check=in_panel_check) @@ -682,6 +672,15 @@ def draw_rectangle(self, shape, in_panel_check=True): (shape['x'], shape['y'] + shape['height']), ] p = [] + if shape.get('rotation', 0) != 0: + rotation = shape.get('rotation') + # rotate around centre of rectangle + cx = shape['x'] + shape['width'] / 2 + cy = shape['y'] + shape['height'] / 2 + points = [ + self.apply_rotation(point, [cx, cy], rotation) + for point in points + ] t = shape.get('transform') for point in points: transformed = self.apply_transform(t, point) From cfcbf359daa80eb4f4824f16c1d57e8db959672d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Wed, 11 Sep 2024 09:12:22 +0200 Subject: [PATCH 27/30] Fix border width rounding --- omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index c0ebe988c..0ae048097 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -2325,7 +2325,7 @@ def paste_image(self, pil_img, img_name, panel, page, dpi=None): # Add border if needed - Rectangle around the whole panel if 'border' in panel and panel['border'].get('showBorder'): sw = panel['border'].get('strokeWidth') - border_width = scale_to_export_dpi(sw) + border_width = int(round(scale_to_export_dpi(sw))) border_color = panel['border'].get('color') padding = border_width * 2 From 243ea0cf6ee3b040b93543ddddf0458dd05d8cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Fri, 13 Sep 2024 10:14:37 +0200 Subject: [PATCH 28/30] try fixing padding --- omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 0ae048097..7a2ec3e10 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -1177,7 +1177,7 @@ def add_rois(self, panel, page): if 'border' in panel and panel['border'].get('showBorder'): crop = self.get_crop_region(panel) sw = panel['border'].get('strokeWidth') - shift_pos = sw / (float(panel['zoom']) / 100) + shift_pos = 1.5*sw shape = {} shape['strokeColor'] = panel['border'].get('color') From e636d32d85fd58a3a5be8d11ae78252f5e015f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 4 Nov 2024 12:39:57 +0100 Subject: [PATCH 29/30] Fix PDF borders according to will suggestion --- .../omero/figure_scripts/Figure_To_Pdf.py | 71 +++++++++++-------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 1ea38267a..63be8de86 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -242,10 +242,7 @@ def apply_rotation(point, centre, rotation): y = cy - newa return x, y - def draw_border(self, shape): - self.draw_rectangle(shape, False) - - def draw_rectangle(self, shape, in_panel_check=True): + def draw_rectangle(self, shape): # to support rotation/transforms, convert rectangle to a simple # four point polygon and draw that instead s = deepcopy(shape) @@ -270,7 +267,7 @@ def draw_rectangle(self, shape, in_panel_check=True): s['points'] = ' '.join(','.join( map(str, self.apply_transform(t, point))) for point in points) - self.draw_polygon(s, closed=True, in_panel_check=in_panel_check) + self.draw_polygon(s, True) def draw_point(self, shape): s = deepcopy(shape) @@ -447,8 +444,8 @@ def draw_arrow(self, shape): self.draw_shape_label(shape, Bounds((x1, y1), (x2, y2))) - def draw_polygon(self, shape, closed=True, in_panel_check=True): - polygon_in_viewport = not in_panel_check + def draw_polygon(self, shape, closed=True): + polygon_in_viewport = False points = [] for point in shape['points'].split(" "): # Older polygons/polylines may be 'x,y,' @@ -491,7 +488,7 @@ def draw_polygon(self, shape, closed=True, in_panel_check=True): self.draw_shape_label(shape, Bounds(*points)) def draw_polyline(self, shape): - self.draw_polygon(shape, closed=False) + self.draw_polygon(shape, False) def draw_ellipse(self, shape): stroke_width = float(shape.get('strokeWidth', 1)) @@ -664,7 +661,7 @@ def draw_arrow(self, shape): # Override to not just call draw_polygon, because we want square corners # for rectangles and not the rounded corners draw_polygon creates - def draw_rectangle(self, shape, in_panel_check=True): + def draw_rectangle(self, shape): points = [ (shape['x'], shape['y']), (shape['x'] + shape['width'], shape['y']), @@ -1177,26 +1174,40 @@ def add_rois(self, panel, page): Add any Shapes """ if 'border' in panel and panel['border'].get('showBorder'): - crop = self.get_crop_region(panel) - sw = panel['border'].get('strokeWidth') - shift_pos = 1.5*sw - - shape = {} - shape['strokeColor'] = panel['border'].get('color') - shape['strokeWidth'] = sw - shape['x'] = crop['x'] - shift_pos - shape['y'] = crop['y'] - shift_pos - shape['width'] = crop['width'] + 2 * shift_pos - shape['height'] = crop['height'] + 2 * shift_pos - shape['type'] = "border" - rotation = panel['rotation'] - if rotation != 0: - shape['rotation'] = 360 - rotation - - if "shapes" not in panel: - panel['shapes'] = [shape] - else: - panel['shapes'].append(shape) + stroke_width = panel['border'].get('strokeWidth') + r, g, b, a = ShapeExport.get_rgba(panel['border'].get('color')) + canvas = self.figure_canvas + canvas.setStrokeColorRGB(r, g, b, alpha=a) + canvas.setLineWidth(stroke_width) + + # by default, line is drawn in the middle of the path + # we want it to be on the outside of the xywh coords + shift_pos = stroke_width / 2 + + p = canvas.beginPath() + x = panel['x'] - shift_pos + y = panel['y'] - shift_pos + width = panel['width'] + (shift_pos * 2) + height = panel['height'] + (shift_pos * 2) + + # Handle page offsets + x = x - page['x'] + y = y - page['y'] + + # rectangle around the panel + points = [[x, y], [x + width, y], [x + width, y + height], [x, y + height]] + + # flip the y coordinate + for point in points: + point[1] = self.page_height - point[1] + + # same logic as draw_polygon() + p.moveTo(points[0][0], points[0][1]) + for point in points[1:]: + p.lineTo(point[0], point[1]) + for point in points[0:2]: + p.lineTo(point[0], point[1]) + canvas.drawPath(p, fill=0, stroke=1) if "shapes" not in panel: return @@ -2182,7 +2193,7 @@ def draw_scalebar_line(self, x, y, x2, y2, width, rgb): c = self.figure_canvas c.setLineWidth(width) c.setStrokeColorRGB(red, green, blue, 1) - c.line(x, y, x2, y2, ) + c.line(x, y, x2, y2) def paste_image(self, pil_img, img_name, panel, page, dpi): """ Adds the PIL image to the PDF figure. Overwritten for TIFFs """ From 13071e27a9700511bbb0732acaf20749bd8702d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Dornier?= Date: Mon, 4 Nov 2024 12:56:52 +0100 Subject: [PATCH 30/30] Fix flake8 errors --- omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py index 63be8de86..175398872 100644 --- a/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py +++ b/omero_figure/scripts/omero/figure_scripts/Figure_To_Pdf.py @@ -1195,7 +1195,10 @@ def add_rois(self, panel, page): y = y - page['y'] # rectangle around the panel - points = [[x, y], [x + width, y], [x + width, y + height], [x, y + height]] + points = [[x, y], + [x + width, y], + [x + width, y + height], + [x, y + height]] # flip the y coordinate for point in points: @@ -1833,7 +1836,7 @@ def get_panel_image(self, image, panel, orig_name=None): pil_img = pil_img.crop((crop_left, crop_top, crop_right, crop_bottom)) # Optional rotation - if ('rotation' in panel and panel['rotation'] > 0): + if 'rotation' in panel and panel['rotation'] > 0: rotation = -int(panel['rotation']) pil_img = pil_img.rotate(rotation, Image.BICUBIC)