Commit 6c17dbc3 authored by Robert's avatar Robert Committed by Robert Ohmacht

-fixed: in OpticalScan mode the scenePyramid was called twice to update the...

-fixed: in OpticalScan mode the scenePyramid was called twice to update the scene after each successful scan of one stack of (scan)tiles
 * this may have lead to buffer overflows and null pointer exceptions (in qt5 and cv2) on Win10
parent fa0c8b64
......@@ -42,13 +42,16 @@ def cv2imread_fix(fname, flags=cv2.IMREAD_COLOR):
def cv2imwrite_fix(fname, img, params=None):
if skimsave is not None:
skimsave(fname, img)
return True
pathname, ext = os.path.splitext(fname)
if params is None:
ret, data = cv2.imencode(ext, img)
else:
ret, data = cv2.imencode(ext, img, params)
with open(fname, "wb") as fp:
fp.write(data.tobytes())
fp.write(data.tobytes())
return ret
def polygoncovering(boundary, wx, wy):
......
......@@ -160,6 +160,7 @@ def loadAndPasteImage(srcnames, pyramid, fullzval, width, height,
if 0 == len(colimgs):
logger.warning(f'no src image(s) found to paste in loadAndPasteImage()')
return None, fullzval
img, zval = imageStacking(colimgs)
......@@ -754,7 +755,7 @@ class OpticalScan(QtWidgets.QWidget):
self.process.join()
self.dataqueue.close()
self.dataqueue.join_thread()
self.pyramid.toDataset()
self.ramanctrl.connect()
......@@ -765,6 +766,7 @@ class OpticalScan(QtWidgets.QWidget):
self.progressbar.disable()
self.close()
return
self.timer.start(100.)
def closeEvent(self, event):
......
......@@ -80,7 +80,7 @@ class SampleView(QtWidgets.QGraphicsView):
self.drag = None
self.mode = None
self.dataset = None
self.pyramid = ScenePyramid(self)
self.pyramid = ScenePyramid(self, self.logger)
self.particleEditor = None
self.fititems = []
self.boundaryitems = [[],[]]
......@@ -202,8 +202,10 @@ class SampleView(QtWidgets.QGraphicsView):
self.oscanwidget.setVisible(False)
self.ramanwidget.setVisible(False)
self.mode = mode
self.pyramid.endScanMode()
self.loadPixmap(self.microscopeMode)
if mode == "OpticalScan":
self.pyramid.startScanMode()
self.oscanwidget.setVisible(True)
self.oscanwidget.resetDataset(self.dataset)
self.oscanwidget.setPyramid(self.pyramid)
......@@ -222,6 +224,7 @@ class SampleView(QtWidgets.QGraphicsView):
elif mode == "RamanScan":
self.removeSeedPointMarkers()
self.resetParticleContours()
self.ramanwidget.resetDataset(self.dataset)
self.ramanwidget.updateRamanParameters()
self.ramanwidget.setVisible(True)
......@@ -842,5 +845,3 @@ class SampleView(QtWidgets.QGraphicsView):
for seedpoint in self.seedPoints:
self.scene().removeItem(seedpoint)
self.seedPoints = []
\ No newline at end of file
......@@ -43,7 +43,7 @@ class ScenePyramid:
:return:
"""
return {
'preScanModeComplete': False,
'scanModeComplete': False,
'maxSliceNumber': 0,
'tileDim': (1000, 1000), # as np.ndarray.shape (i.e. (height, width))
'scalingFactor': .5,
......@@ -52,11 +52,12 @@ class ScenePyramid:
'fullImageHeight': 0
}
def __init__(self, view: QtWidgets.QGraphicsView):
def __init__(self, view: QtWidgets.QGraphicsView, logger):
# references to other objects
self.view: QtWidgets.QGraphicsView = view
self.scene = self.view.scene()
self.dataset = None
self.logger = logger
#
self.opacity = 1
......@@ -69,7 +70,7 @@ class ScenePyramid:
self.currentTiles = None
self.tileWorkingSets = None
self.preScanModeComplete = None
self.scanModeComplete = None
self.maxSliceNumber = None
self.tileDim = None # as np.ndarray.shape (i.e. (height, width))
self.scalingFactor = None
......@@ -79,7 +80,7 @@ class ScenePyramid:
# params to be saved to dataset
self.datasetParams = [
'preScanModeComplete',
'scanModeComplete',
'maxSliceNumber',
'tileDim',
'scalingFactor',
......@@ -100,12 +101,28 @@ class ScenePyramid:
self.currentTiles = []
self.tileWorkingSets = {}
def startScanMode(self):
"""
:return:
"""
self.scanModeComplete = False
return self
def endScanMode(self):
"""
:return:
"""
self.scanModeComplete = True
return self
def onScale(self):
"""
gets called on zoom event in QGraphicsView
:return:
"""
if self.preScanModeComplete:
if self.scanModeComplete:
self.updateScene()
def onMove(self):
......@@ -113,11 +130,11 @@ class ScenePyramid:
gets called on scroll event in QGraphicsView
:return:
"""
if self.preScanModeComplete:
if self.scanModeComplete:
self.updateScene()
def initScene(self):
if self.preScanModeComplete:
if self.scanModeComplete:
self.updateScene()
def updateScene(self):
......@@ -143,7 +160,6 @@ class ScenePyramid:
view_max_x_y = self.view.mapToScene(self.view.width(), self.view.height())
# get scene origin (given in microscope coords) in pixel coords
p = self.dataset.maxdim[:2]
scene_origin_x, scene_origin_y = (0, 0) # self.dataset.mapToPixel(p, self.microscopeMode, force=True)
# default width, height of view tiles
......@@ -197,6 +213,7 @@ class ScenePyramid:
"""
if 0 == self.fullImageWidth:
self.currentSlice = 0
return
# tiles get added to the (theoretically infinite) scene which can be zoomed and translated
# full image width and height are width and height in scene coordinates
......@@ -440,7 +457,9 @@ class ScenePyramid:
self.reset()
else:
for i in self.datasetParams:
setattr(self, i, pyramid_params[i])
if i in pyramid_params:
setattr(self, i, pyramid_params[i])
self.tileWorkingSets = copy.deepcopy(self.tileSets)
self.fixMissingTiles()
......@@ -533,16 +552,14 @@ class ScenePyramid:
# if src tile dim < view tile dim, a single src tile s may be part of up to 4 view tiles v(i, j)
while max(current_full_image_width, current_full_image_height) > breakof_pixel_count:
current_src_img = img.copy()
# resize from original image, when adding src tile to scaled pyramid slices
if slice_nr > 0:
current_src_img = cv2.resize(
img,
None,
fx=current_scaling_factor,
fy=current_scaling_factor,
interpolation=cv2.INTER_AREA
)
current_src_img = cv2.resize(
img,
None,
fx=current_scaling_factor,
fy=current_scaling_factor,
interpolation=cv2.INTER_AREA
)
pos_x_scaled = current_scaling_factor * pos_x
pos_y_scaled = current_scaling_factor * pos_y
......@@ -627,15 +644,18 @@ class ScenePyramid:
:return:
"""
tile = None
tile_path = os.path.join(self.dataset.getTilePath(), f"tile_{slice_nr}_{i}_{j}.tif")
if not os.path.exists(tile_path):
# fallback for datasets still using *.bmp
tile_path = os.path.join(self.dataset.getTilePath(), f"tile_{slice_nr}_{i}_{j}.bmp")
try:
tile = cv2imread_fix(tile_path)
except OSError:
tile = None
if os.path.exists(tile_path):
try:
tile = cv2imread_fix(tile_path)
except OSError:
None
# as full image size might not be divisible by tile dimensions, we have to determine correct tile size
# tile numbering is 0 based
......@@ -914,7 +934,6 @@ class ScenePyramid:
scaling *= self.scalingFactor
def destruct(self):
"""
removes all graphics items from scene
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment