def resize_photo(self): if self.pic_width: dialog_text = f'Current width {self.pic_width}px, height {self.pic_height}px\n' dialog_text += 'Enter resize parameters (width, height):' text, ok = QInputDialog.getText(self, 'Input Dialog', dialog_text) if ok: params = str(text).split(',') image = Image.open(self.temp_file) image = image.resize((int(params[0]), int(params[1])), Image.NEAREST) img_tmp = ImageQt(image.convert('RGBA')) img_tmp.save(self.temp_file) self.set_photo()
def crop_photo(self): if self.pic_width: dialog_text = f'Current width {self.pic_width}px, height {self.pic_height}px\n' dialog_text += 'Enter crop parameters (left, top, right, bottom):' text, ok = QInputDialog.getText(self, 'Input Dialog', dialog_text) if ok: params = str(text).split(',') image = Image.open(self.temp_file) image = image.crop((int(params[0]), int(params[1]), int(params[2]), int(params[3]))) img_tmp = ImageQt(image.convert('RGBA')) img_tmp.save(self.temp_file) self.set_photo()
def convert_photo(self, mode): if self.temp_file: image = Image.open(self.temp_file) draw = ImageDraw.Draw(image) width = image.size[0] height = image.size[1] pix = image.load() Editor.make_effect(mode, width, height, pix, draw) img_tmp = ImageQt(image.convert('RGBA')) img_tmp.save(self.temp_file) self.set_photo()
def toQImage(self, filepath): ibuf = ImageBuf(filepath) try: bufok = ibuf.read(subimage=0, miplevel=0, force=True, convert=oiio.UINT8) except Exception as ex: print(ex) return None if not bufok: return None spec = ibuf.spec() width = spec.width height = spec.height # Expect the channel to be RGB from the beginning. # It might not work if it is a format like ARGB. # qimage = QtGui.QImage(width, height, QtGui.QImage.Format_RGB888) roi = oiio.ROI(0, width, 0, height, 0, 1, 0, 3) try: orgimg = Image.fromarray(ibuf.get_pixels(oiio.UINT8, roi)) # for ImageQt source format error if orgimg.mode in self.mw.shot.NO_SUPPORT_IMAGEQT: orgimg = orgimg.convert('RGB') if self.mw.thumbnail_bright != self.mw.THUMB_DEFALUT_BRIGHT: eim = ImageEnhance.Brightness(orgimg) orgimg = eim.enhance(self.mw.thumbnail_bright) qimage = ImageQt(orgimg) # workaround https://bugreports.qt.io/browse/PYSIDE-884 # output QImage to a file and reRead qimage wksavepath = QStandardPaths.writableLocation( QStandardPaths.TempLocation) wksavepath = wksavepath + "/{0}/sequencegrab.jpg".format( self.mw.APPID) qimage.save(wksavepath, "jpg") wkqim = QImage(wksavepath) qimage = wkqim os.remove(wksavepath) except Exception as ex: print(ex) return None return (qimage)
class ApplicationWindow(QtWidgets.QMainWindow): @pyqtSlot() def __init__(self): self.count = 0 self.count1 = 0 self.n = 0 super(ApplicationWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.browse.clicked.connect(self.browse) self.ui.label.mousePressEvent = self.getpos self.ui.PhantomShape.currentTextChanged.connect(self.shape) self.ui.Preb.currentTextChanged.connect(self.preb) self.ui.aquise.currentTextChanged.connect(self.acquisition) self.ui.Zoom.currentTextChanged.connect(self.zoomComBox) self.ui.maxErnstAngl.clicked.connect(self.maxErnestAngleCalculated) self.ui.PhantomSize.currentTextChanged.connect(self.phantom_size) self.ui.createPhantom.clicked.connect(self.create) self.ui.ernstAngle.clicked.connect(self.drawErnstAngle) self.ui.start.clicked.connect(self.Start) self.ui.horizontalSlider.valueChanged.connect(self.slider) self.plotWindow = self.ui.T1 self.plotWindow2 = self.ui.T2 self.Acquisition = 0 self.Prepration = 0 self.viewer = PhotoViewer(self.ui.graphicsView_Image) self.viewer1 = PhotoViewer(self.ui.graphicsView_Phantom) self.ui.Artifacts.currentTextChanged.connect(self.ArtifactFun) self.AliasingFactor = 2 self.improperSampling = 0 def ArtifactFun(self, text): if text == "Normal": self.AliasingFactor = 2 self.improperSampling = 0 elif text == "Aliasing": self.AliasingFactor = 3 elif text == "ImproperSampling": self.improperSampling = 1 def browse(self): fileName, _Filter = QtWidgets.QFileDialog.getOpenFileName( None, "Select phantom", "", "self.data Files(*.dat)") if fileName: self.data = np.load(fileName) self.size = len(self.data) self.scale = np.asarray(self.data, dtype=np.uint8) image = Image.fromarray(self.scale) #print (self.scale) self.img = ImageQt(image) self.img.save("2.png") self.viewer.setPhoto(QPixmap.fromImage(self.img)) self.ui.label.setPixmap( QPixmap.fromImage(self.img).scaled(512, 512)) self.ui.label.setAlignment(QtCore.Qt.AlignCenter) self.PD = np.asarray(np.load(fileName), dtype=np.uint8) self.t1 = np.asarray(np.load(fileName), dtype=np.uint8) self.t2 = np.asarray(np.load(fileName), dtype=np.uint8) #for i in range (self.size): # self.scale[i] = self.mappingToIntensity(self.scale[i]) self.Mo = [[[0 for k in range(3)] for j in range(self.size)] for i in range(self.size)] for i in range(self.size): for j in range(self.size): self.Mo[i][j][2] = 1 if self.scale[i][j] >= 0 and self.scale[i][j] <= 50: self.t1[i][j] = 10 self.t2[i][j] = 10 elif self.scale[i][j] <= 100 and self.scale[i][j] >= 50: self.t1[i][j] = 1200 self.t2[i][j] = 100 elif self.scale[i][j] <= 150 and self.scale[i][j] >= 100: self.t1[i, j] = 1300 self.t2[i, j] = 120 elif self.scale[i, j] <= 200 and self.scale[i, j] >= 150: self.t1[i, j] = 1500 self.t2[i, j] = 150 elif self.scale[i, j] <= 255 and self.scale[i, j] >= 200: self.t1[i, j] = 2000 self.t2[i, j] = 200 else: break #self.t1 = self.mappingToIntensity(self.t1) #self.t2 = self.mappingToIntensity(self.t2) self.T1_img = gray2qimage(self.t1) self.T2_img = gray2qimage(self.t2) self.PD_img = gray2qimage(self.scale) self.ui.plainTextEdit.clear() self.ui.plainTextEdit.appendPlainText(str(np.unique(self.t1))) self.ui.plainTextEdit.appendPlainText(str(np.unique(self.t2))) self.ui.labelT1.clear() self.ui.labelT1.setPixmap( QPixmap.fromImage(self.T1_img).scaled(512, 512)) self.ui.LabelT2.clear() self.ui.LabelT2.setPixmap( QPixmap.fromImage(self.T2_img).scaled(512, 512)) def mappingToIntensity(self, array): maxx = np.max(array) minn = np.min(array) if (maxx > 255 and min < 0): array = (((255 - 2) / (maxx - minn)) * (array - minn + 2)) return array def phantom_size(self, text): print(text) self.n = int(text) def shape(self, text): print(text) #self.phantom_type if text == "Shepp-Logan": self.phantom_type = 1 elif text == "Phantom 1": #squares self.phantom_type = 2 elif text == "phantom 2": #circles self.phantom_type = 3 else: self.phantom_type = 0 def create(self): if self.n == 0 or self.phantom_type == 0: QMessageBox.about( self, "Error", "you should choose the size and shape of the phantom first.") else: print("create done ") if self.phantom_type == 1 and self.n == 32: elipse4 = (phantom(n=32)) * 1000 elipse4.dump("shepplogan(32).dat") QMessageBox.about(self, "Done", "phantom 'shepplogan(32)' created and saved ") elif self.phantom_type == 1 and self.n == 9: elipse4 = (phantom(n=9)) * 1000 elipse4.dump("shepplogan(9).dat") QMessageBox.about(self, "Done", "phantom 'shepplogan(9)' created and saved ") elif self.phantom_type == 1 and self.n == 20: elipse4 = (phantom(n=20)) * 1000 elipse4.dump("shepplogan(20).dat") QMessageBox.about(self, "Done", "phantom 'shepplogan(20)' created and saved ") elif self.phantom_type == 1 and self.n == 64: elipse4 = (phantom(n=64)) * 1000 elipse4.dump("shepplogan(64).dat") QMessageBox.about(self, "Done", "phantom 'shepplogan(64)' created and saved ") elif self.phantom_type == 1 and self.n == 512: elipse4 = phantom(n=512) * 1000 elipse4.dump("shepplogan(512).dat") QMessageBox.about(self, "Done", "phantom 'shepplogan(512)' created and saved ") elif self.phantom_type == 2 and self.n == 128: self.img1 = np.zeros((128, 128), np.uint8) reactangle1 = cv2.rectangle(self.img1, (25, 25), (75, 62), (42, 42, 42), -3) reactangle2 = cv2.rectangle(reactangle1, (62, 87), (100, 50), (32, 32, 32), -3) reactangle3 = cv2.rectangle(reactangle2, (12, 75), (50, 45), (26, 26, 26), -3) phantom1 = cv2.rectangle(reactangle3, (42, 55), (72, 30), (128, 128, 128), -3) print(type(phantom1)) phantom1.dump("squares(128).dat") QMessageBox.about(self, "Done", "phantom 'squares(128)' created and saved ") elif self.phantom_type == 2 and self.n == 256: self.img1 = np.zeros((256, 256), np.uint8) reactangle1 = cv2.rectangle(self.img1, (50, 50), (150, 120), (169, 169, 169), -3) reactangle2 = cv2.rectangle(reactangle1, (124, 180), (200, 100), (128, 128, 128), -3) reactangle3 = cv2.rectangle(reactangle2, (25, 150), (100, 90), (105, 105, 105), -3) phantom1 = cv2.rectangle(reactangle3, (80, 100), (290, 120), (255, 255, 255), -3) phantom1.dump("squares(256).dat") print(type(phantom1)) QMessageBox.about(self, "Done", "phantom 'squares(256)' created and saved ") elif self.phantom_type == 2 and self.n == 512: self.img1 = np.zeros((512, 512), np.uint8) reactangle1 = cv2.rectangle(self.img1, (100, 100), (300, 150), (169, 169, 169), -3) reactangle2 = cv2.rectangle(reactangle1, (250, 350), (400, 200), (128, 128, 128), -3) reactangle3 = cv2.rectangle(reactangle2, (50, 300), (200, 180), (105, 105, 105), -3) phantom1 = cv2.rectangle(reactangle3, (170, 220), (290, 120), (255, 255, 255), -3) phantom1.dump("squares(512).dat") print(type(phantom1)) QMessageBox.about(self, "Done", "phantom 'squares(512)' created and saved ") elif self.phantom_type == 3 and self.n == 128: self.img = np.zeros((128, 128), np.uint8) line1 = cv2.line(self.img, (100, 0), (100, 128), (255, 255, 255), 15) line2 = cv2.line(self.img, (0, 100), (128, 100), (200, 200, 200), 30) circle = cv2.circle(self.img, (64, 64), 30, (169, 169, 169), -1) ellipse = cv2.ellipse(self.img, (50, 25), (30, 15), 0, 0, 360, (255, 255, 255), -1) print(type(self.img)) self.img.dump("circles(128).dat") QMessageBox.about(self, "Done", "phantom 'circles(128)' created and saved ") elif self.phantom_type == 3 and self.n == 256: self.img = np.zeros((256, 256), np.uint8) line1 = cv2.line(self.img, (200, 0), (200, 256), (255, 255, 255), 15) line2 = cv2.line(self.img, (0, 200), (256, 200), (200, 200, 200), 30) circle = cv2.circle(self.img, (128, 128), 60, (169, 169, 169), -1) ellipse = cv2.ellipse(self.img, (100, 50), (60, 30), 0, 0, 360, (255, 255, 255), -1) print(type(self.img)) self.img.dump("circles(256).dat") QMessageBox.about(self, "Done", "phantom 'circles(256)' created and saved ") elif self.phantom_type == 3 and self.n == 512: self.img = np.zeros((512, 512), np.uint8) line1 = cv2.line(self.img, (400, 0), (400, 512), (255, 255, 255), 15) line2 = cv2.line(self.img, (0, 400), (512, 400), (200, 200, 200), 30) circle = cv2.circle(self.img, (256, 256), 120, (169, 169, 169), -1) ellipse = cv2.ellipse(self.img, (200, 100), (120, 60), 0, 0, 360, (255, 255, 255), -1) print(type(self.img)) self.img.dump("circles(512).dat") QMessageBox.about(self, "Done", "phantom 'circles(512)' created and saved ") def linkedZoom(self, event): self.viewer.zoom(event) self.viewer1.zoom(event) def zoomComBox(self): if (self.ui.Zoom.currentText() == "Linked"): self.viewer.wheelEvent = self.linkedZoom self.viewer1.wheelEvent = self.linkedZoom elif (self.ui.Zoom.currentText() == "NonLinked"): self.viewer.wheelEvent = self.viewer.zoom self.viewer2.wheelEvent = self.viewer1.zoom def slider(self): self.img2 = PIL.Image.open("2.png") b = self.ui.horizontalSlider.value() print(b) enhancer = ImageEnhance.Brightness(self.img2).enhance(b / 10) enhancer.save("out.png") self.ui.label.setPixmap(QPixmap("out.png").scaled(512, 512)) def getpos(self, event): self.x = math.floor((event.pos().x() * self.size) / self.ui.label.frameGeometry().width()) self.y = math.floor((event.pos().y() * self.size) / self.ui.label.frameGeometry().width()) self.count = self.count + 1 self.count1 = self.count1 + 1 self.plot() if self.count1 == 1: self.ui.label.clear frame = cv2.rectangle(self.scale, (self.x, self.y), (self.x + 3, self.y + 3), (0, 255, 0), 1) image = Image.fromarray(frame) self.img = ImageQt(image) self.ui.label.setPixmap( QPixmap.fromImage(self.img).scaled(512, 512)) self.ui.label.setAlignment(QtCore.Qt.AlignCenter) elif self.count1 == 2: self.ui.label.clear frame = cv2.rectangle(self.scale, (self.x, self.y), (self.x + 3, self.y + 3), (0, 0, 255), 1) image = Image.fromarray(frame) self.img = ImageQt(image) self.ui.label.setPixmap( QPixmap.fromImage(self.img).scaled(512, 512)) self.ui.label.setAlignment(QtCore.Qt.AlignCenter) elif self.count1 == 3: self.ui.label.clear frame = cv2.rectangle(self.scale, (self.x, self.y), (self.x + 3, self.y + 3), (255, 0, 0), 1) image = Image.fromarray(frame) self.img = ImageQt(image) self.ui.label.setPixmap( QPixmap.fromImage(self.img).scaled(512, 512)) self.ui.label.setAlignment(QtCore.Qt.AlignCenter) elif self.count1 == 4: self.ui.label.clear frame = cv2.rectangle(self.scale, (self.x, self.y), (self.x + 3, self.y + 3), (100, 255, 0), 1) image = Image.fromarray(frame) self.img = ImageQt(image) self.ui.label.setPixmap( QPixmap.fromImage(self.img).scaled(512, 512)) self.ui.label.setAlignment(QtCore.Qt.AlignCenter) elif self.count1 == 5: self.ui.label.clear frame = cv2.rectangle(self.scale, (self.x, self.y), (self.x + 3, self.y + 3), (0, 100, 100), 1) image = Image.fromarray(frame) self.img = ImageQt(image) self.ui.label.setPixmap( QPixmap.fromImage(self.img).scaled(512, 512)) self.ui.label.setAlignment(QtCore.Qt.AlignCenter) self.count1 = 0 else: print('end') def plot(self): arr1 = [] arr2 = [] self.FA() self.Time_span() fa = (np.pi) * self.f / 180 for t in range(self.T): self.Mz = (1 - np.exp(-t / self.t1[self.x, self.y])) Rx = np.array([[1, 0, 0], [0, (np.cos(fa)), (np.sin(fa))], [0, (-np.sin(fa)), (np.cos(fa))]]) M = np.matmul(Rx, self.Mo[self.x][self.y]) M = np.sum(M) Mxy = np.exp(-t / self.t2[self.x, self.y]) * M arr1.append(self.Mz) arr2.append(Mxy) # QtGui.QApplication.processEvents() if self.count == 1: self.plotWindow.clear() self.plotWindow2.clear() self.plotWindow.plot(arr1, pen=pg.mkPen('b', width=2)) self.plotWindow2.plot(arr2, pen=pg.mkPen('b', width=2)) elif self.count == 2: self.plotWindow.plot(arr1, pen1=pg.mkPen('r', width=2)) self.plotWindow2.plot(arr2, pen1=pg.mkPen('r', width=2)) elif self.count == 3: self.plotWindow.plot(arr1, pen2=pg.mkPen('g', width=2)) self.plotWindow2.plot(arr2, pen2=pg.mkPen('g', width=2)) elif self.count == 4: self.plotWindow.plot(arr1, pen=pg.mkPen('l', width=2)) self.plotWindow2.plot(arr2, pen=pg.mkPen('l', width=2)) elif self.count == 5: self.plotWindow.plot(arr1, pen=pg.mkPen('w', width=2)) self.plotWindow2.plot(arr2, pen=pg.mkPen('w', width=2)) self.count = 0 else: print('end') self.readInputParameters() def readInputParameters(self): self.TE() self.TR() self.FA() def IR(self, t): self.ui.preparationGraph.clear() tx = np.arange(0, t, .001) T3 = (2 * np.sin(0.75 * (tx - 20)) / (tx - 20)) #RF 180 shifted 2 self.ui.preparationGraph.plot(tx, T3, pen=pg.mkPen('b', width=2)) #self.ui.preparationGraph.setText("Prepration:IR") def T2_PREP(self, t): self.ui.preparationGraph.clear() tx = np.arange(0, t + (2 * 10), .001) T1 = (np.sin((tx - 10)) / (tx - 10)) T2 = (np.sin(-(tx - (t + 10))) / (tx - (t + 10))) self.ui.preparationGraph.plot(tx, T1, pen=[255, 0, 0]) self.ui.preparationGraph.plot(tx, T2, pen=[255, 0, 0]) #self.ui.lbl_prep.setText("Prepration:T2_PREP") def Tagging(self): self.ui.preparationGraph.clear() tx = np.arange(0, 15, .001) T3 = (0.5 * np.sin(2 * tx)) #RF 180 shifted 2 self.ui.preparationGraph.plot(tx, T3, pen=[255, 0, 0]) #self.ui.preparationGraph.setText("Prepration:Tagging") def ernstAngleFun(self): self.TR() try: data = np.average(self.PD) except: QMessageBox.about(self, "Error", "Please browse a phantom") data = np.average(self.PD) vector = np.dot(data, np.matrix([0, 0, 1])) self.step = 5 self.intensity = np.zeros(int(180 / self.step)) j = 0 self.Simulation = [] for theta in range(0, 180, 5): for i in range(10): vector = self.rotationAroundYaxisMatrix(theta, vector) vector = self.DecayRecoveryEquation(2600, 50, 1, vector, self.tr) x = np.ravel(vector)[0] y = np.ravel(vector)[1] self.intensity[j] = math.sqrt((x * x) + (y * y)) j = j + 1 def drawErnstAngle(self): self.lb = QGraphicsView() self.lb = pg.PlotWidget() self.ernstAngleFun() array = np.arange(0, 180, self.step) self.lb.plot(array, self.intensity) self.lb.show() def maxErnestAngleCalculated(self): self.step = 5 try: if self.Acquisition == 3: self.TR() print(self.tr) maxFlipAngle = math.acos(np.exp(-self.tr / 1200)) maxFlipAngle = (maxFlipAngle * 180) / math.pi print(maxFlipAngle) else: result = np.where(self.intensity == np.max(self.intensity)) maxFlipAngleIndex = result[0][0] maxFlipAngle = self.step * maxFlipAngleIndex self.ui.plainTextEdit_3.clear() self.ui.plainTextEdit_3.appendPlainText(str(int(maxFlipAngle))) except: self.ernstAngleFun() self.maxErnestAngleCalculated() def rotationAroundYaxisMatrix(self, theta, vector): vector = vector.transpose() theta = (math.pi / 180) * theta R = np.matrix([[np.cos(theta), 0, np.sin(theta)], [0, 1, 0], [-np.sin(theta), 0, np.cos(theta)]]) R = np.dot(R, vector) R = R.transpose() return np.matrix(R) def rotationAroundZaxisMatrixXY(self, TR, speed, vector, time): #time = self.time vector = vector.transpose() theta = speed * (time / TR) theta = (math.pi / 180) * theta XY = np.matrix([[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]]) XY = np.dot(XY, vector) XY = XY.transpose() return np.matrix(XY) def DecayRecoveryEquation(self, T1, T2, PD, vector, time): vector = vector.transpose() Decay = np.matrix([[np.exp(-time / T2), 0, 0], [0, np.exp(-time / T2), 0], [0, 0, np.exp(-time / T1)]]) Decay = np.dot(Decay, vector) Rec = np.dot(np.matrix([[0, 0, (1 - (np.exp(-time / T1)))]]), PD) Rec = Rec.transpose() Decay = np.matrix(Decay) Rec = np.matrix(Rec) RD = Decay + Rec RD = RD.transpose() return RD def TR(self): self.tr = self.ui.TR.value() def TE(self): self.te = self.ui.TE.value() def FA(self): self.f = self.ui.FA.value() def Time_span(self): self.T = self.ui.time_span.value() print(self.T) def SE(self): te = round(self.te / 3) self.ui.AcquisionGraph.clear() tx = np.arange(0, self.tr) Rf1 = (np.sin(((self.f * 2) / 180) * (tx - te)) / (tx - te) + 10) Rf2 = (2 * np.sin( ((self.f * 2) / 180) * (tx - (te * 2))) / (tx - (te * 2)) + 10) Gx = self.RectangularGraph(self.tr, 8, (te * 3), 1, te) Gy = self.RectangularGraph(self.tr, 6, (te * 4), 1, te) Readout = self.RectangularGraph(self.tr, 4, (te * 5), 1, te) self.ui.AcquisionGraph.plot(tx, Rf1, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Rf2, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Gx, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Gy, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Readout, pen=[255, 0, 0]) def GRE(self): te = round(self.te / 3) self.ui.AcquisionGraph.clear() tx = np.arange(0, self.tr) Rf = (np.sin(((self.f * 2) / 180) * (tx - te)) / (tx - te) + 10) Gx = self.RectangularGraph(self.tr, 8, (te * 2), 1, te) Gy = self.RectangularGraph(self.tr, 6, (te * 3), 1, te) Readout = self.RectangularGraph(self.tr, 4, (te * 4), 1, te) self.ui.AcquisionGraph.plot(tx, Rf, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Gx, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Gy, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Readout, pen=[255, 0, 0]) def SSFP(self): te = round(self.te / 3) self.ui.AcquisionGraph.clear() tx = np.arange(0, self.tr) Rf = (np.sin(((self.f * 2) / 180) * (tx - te)) / (tx - te) + 10) Gx = self.RectangularGraph(self.tr, 8, (te * 2), 1, te) Gy = self.RectangularGraph(self.tr, 6, (te * 3), 1, te) Readout = self.RectangularGraph(self.tr, 4, (te * 4), 1, te) GxReversed = self.RectangularGraph(self.tr, 8, (te * 5 + 30), -1, te) GyReversed = self.RectangularGraph(self.tr, 6, (te * 5 + 30), -1, te) self.ui.AcquisionGraph.plot(tx, Rf, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Gx, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Gy, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, Readout, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, GxReversed, pen=[255, 0, 0]) self.ui.AcquisionGraph.plot(tx, GyReversed, pen=[255, 0, 0]) def RectangularGraph(self, tR, shiftDown, shiftRight, step, width): z = [] for i in range(0, tR): if i < int(shiftRight): z.append(shiftDown) elif i >= int(shiftRight) and i < int(width + shiftRight): z.append(shiftDown + (step * 1)) else: z.append(shiftDown) return z def acquisition(self, text): self.readInputParameters() if text == "SSFP": self.Acquisition = 1 self.SSFP() elif text == "SpinEcho": self.Acquisition = 2 self.SE() elif text == "GRE": self.Acquisition = 3 self.GRE() else: self.Acquisition = 0 def preb(self, text): if text == "T1IR": self.Prepration = 1 self.nullTissue, ok = QInputDialog.getInt(self, "integer input dialog", "enter Null Tissue T1") self.IR(self.nullTissue * np.log(2)) print(self.nullTissue) elif text == "T2Preb": self.Prepration = 2 self.T2prebtime, ok = QInputDialog.getInt( self, "integer input dialog", "enter time inteval for preb") self.T2_PREP(self.T2prebtime) print(self.T2prebtime) elif text == "Tagging": self.Tagging() self.step, ok = QInputDialog.getInt( self, "integer input dialog", "enter step for tagging preparation") self.Prepration = 3 else: self.Prepration = 0 self.ui.preparationGraph.clear() def prepration(self): if (self.Prepration == 1): t = self.nullTissue * np.log(2) for i in range(self.size): for j in range(self.size): self.signal[i][j] = self.rotationAroundYaxisMatrix( 180, np.matrix(self.signal[i][j])) self.signal[i][j] = self.DecayRecoveryEquation( self.t1[i, j], self.t2[i, j], 1, np.matrix(self.signal[i][j]), t) self.signal[i][j] = [[ 0, 0, np.ravel(self.signal[i][j])[2] ]] elif (self.Prepration == 2): for i in range(self.size): for j in range(self.size): self.signal[i][j] = self.rotationAroundYaxisMatrix( 90, np.matrix(self.signal[i][j])) self.signal[i][j] = self.DecayRecoveryEquation( self.t1[i, j], self.t2[i, j], 1, np.matrix(self.signal[i][j]), self.T2prebtime) self.signal[i][j] = [[ 0, 0, np.ravel(self.signal[i][j])[2] ]] self.signal[i][j] = self.rotationAroundYaxisMatrix( -90, np.matrix(self.signal[i][j])) elif (self.Prepration == 0): print("nrg3 normal tany") self.ui.preparationGraph.clear() elif (self.Prepration == 3): for i in range(self.size): for j in range(0, self.size, self.step): self.signal[i][j][2] = np.dot( np.ravel(self.signal[i][j])[2], np.sin((np.pi * j) / (2 * self.size))) else: QMessageBox.about( self, "Error", "you should choose the Preperation sequence first") def startUpCycle(self): self.StartUpCycle = self.ui.StartUpCycle_2.value() self.signal = [[[0 for k in range(3)] for j in range(self.size)] for i in range(self.size)] for i in range(self.size): for j in range(self.size): self.signal[i][j][2] = 1 for loop in range(self.StartUpCycle): for i in range(self.size): for j in range(self.size): self.signal[i][j] = self.rotationAroundYaxisMatrix( self.f, np.matrix(self.signal[i][j])) self.signal[i][j] = self.DecayRecoveryEquation( self.t1[i, j], self.t2[i, j], 1, np.matrix(self.signal[i][j]), self.tr) self.signal[i][j] = [[ 0, 0, np.ravel(self.signal[i][j])[2] ]] def Start(self): self.readInputParameters() self.Kspace = np.zeros((self.size, self.size), dtype=np.complex_) self.startUpCycle() self.prepration() if (self.Acquisition == 1): self.Kspace = cythonfile.SSFPForLoops(self.Kspace, self.size, self.signal, self.f, self.t1, self.t2, self.te, self.tr, self.AliasingFactor) self.ReconstructionImageAndKspace() elif (self.Acquisition == 2): self.Kspace = cythonfile.SpinEchoForLoops(self.Kspace, self.size, self.signal, self.f, self.t1, self.t2, self.te, self.tr, self.AliasingFactor) self.ReconstructionImageAndKspace() elif (self.Acquisition == 3): self.Kspace = cythonfile.GREForLoops(self.Kspace, self.size, self.signal, self.f, self.t1, self.t2, self.te, self.tr, self.AliasingFactor, self.improperSampling) self.ReconstructionImageAndKspace() else: QMessageBox.about( self, "Error", "you should choose the acquisition sequence first") def ReconstructionImageAndKspace(self): print(self.Kspace) KspaceSave = abs(copy.deepcopy(self.Kspace)) print("Done") imsave('kspace.png', KspaceSave) self.ui.label_2.setPixmap(QtGui.QPixmap('kspace.png').scaled(512, 512)) Kspacefft = np.fft.fft2(self.Kspace) #Kspaceifft = np.fft.ifft2(self.Kspace) Kspacefft = abs(Kspacefft) Kspacefft = np.array(np.round_(Kspacefft)) imsave("image.png", Kspacefft) pixmap = QtGui.QPixmap("image.png") self.viewer1.setPhoto(pixmap) pixmap = pixmap.scaled(512, 512) self.ui.label_3.setPixmap(pixmap)
class ChangeAvatar(QMainWindow): def __init__(self, parent=None): super(ChangeAvatar, self).__init__(parent) self.parent = parent self.convert_img = None self.menu() def menu(self): self.menubar = self.menuBar() self.fileMenu = self.menubar.addMenu('Файл') self.editMenu = self.menubar.addMenu('Изменить изображение') self.editMenu.setEnabled(False) self.convertMenu = self.editMenu.addMenu('Изменить стиль') self.resizeMenu = self.editMenu.addMenu('Изменить размер') self.cropMenu = self.editMenu.addMenu('Обрезать аватар') self.resize(500, 500) self.openAction = QAction('Открыть изображение', self) self.openAction.triggered.connect(self.open_image) self.fileMenu.addAction(self.openAction) self.save_image_action = QAction('Сохранить', self) self.save_image_action.setEnabled(False) self.save_image_action.triggered.connect(self.save_image) self.fileMenu.addAction(self.save_image_action) convert_to_grey_action = QAction('Оттенки серого', self) convert_to_grey_action.triggered.connect(lambda: self.convert_image(self.to_grey)) self.convertMenu.addAction(convert_to_grey_action) convert_to_sepia_action = QAction('Эффект сепии', self) convert_to_sepia_action.triggered.connect(lambda: self.convert_image(self.to_sepia)) self.convertMenu.addAction(convert_to_sepia_action) convert_to_negative_action = QAction('Эффект негатива', self) convert_to_negative_action.triggered.connect(lambda: self.convert_image(self.to_negative)) self.convertMenu.addAction(convert_to_negative_action) convert_to_black_and_white_action = QAction('Черно-белое изображение', self) convert_to_black_and_white_action.triggered.connect(lambda: self.convert_image(self.to_black_and_white)) self.convertMenu.addAction(convert_to_black_and_white_action) convert_to_original_action = QAction('Отменить изменения', self) convert_to_original_action.triggered.connect(lambda: self.convert_image(self.to_original)) self.editMenu.addAction(convert_to_original_action) resize_to_500_400_action = QAction('500x400', self) resize_to_500_400_action.triggered.connect(lambda: self.convert_image(lambda: self.resize_image(500, 400))) self.resizeMenu.addAction(resize_to_500_400_action) resize_to_400_500_action = QAction('400x500', self) resize_to_400_500_action.triggered.connect(lambda: self.convert_image(lambda: self.resize_image(400, 500))) self.resizeMenu.addAction(resize_to_400_500_action) crop_action = QAction('Обрезать аватар', self) crop_action.triggered.connect(lambda: self.convert_image(self.crop_image)) self.cropMenu.addAction(crop_action) self.label = QLabel() self.setCentralWidget(self.label) def open_image(self): self.image_path = QFileDialog.getOpenFileName(self, 'Open file', '/', "Images (*.png *.xpm *.jpg)")[0] self.convert_image(lambda: self.convert_image(self.to_original)) if self.image_path: self.editMenu.setEnabled(True) self.save_image_action.setEnabled(True) def convert_image(self, convert_action): self.image = Image.open(self.image_path) if self.convert_img is not None: self.image = self.convert_img self.draw = ImageDraw.Draw(self.image) self.width = self.image.size[0] self.height = self.image.size[1] self.pix = self.image.load() convert_action() self.convert_img = self.image self.img_tmp = ImageQt(self.image.convert('RGBA')) self.pixmap = QPixmap.fromImage(self.img_tmp) self.label.setPixmap(self.pixmap) self.resize(self.pixmap.size()) self.adjustSize() def to_grey(self): for i in range(self.width): for j in range(self.height): a = self.pix[i, j][0] b = self.pix[i, j][1] c = self.pix[i, j][2] S = (a + b + c) // 3 self.draw.point((i, j), (S, S, S)) def to_sepia(self): depth = 30 for i in range(self.width): for j in range(self.height): a = self.pix[i, j][0] b = self.pix[i, j][1] c = self.pix[i, j][2] S = (a + b + c) a = S + depth * 2 b = S + depth c = S if (a > 255): a = 255 if (b > 255): b = 255 if (c > 255): c = 255 self.draw.point((i, j), (a, b, c)) def to_negative(self): for i in range(self.width): for j in range(self.height): a = self.pix[i, j][0] b = self.pix[i, j][1] c = self.pix[i, j][2] self.draw.point((i, j), (255 - a, 255 - b, 255 - c)) def to_black_and_white(self): factor = 50 for i in range(self.width): for j in range(self.height): a = self.pix[i, j][0] b = self.pix[i, j][1] c = self.pix[i, j][2] S = a + b + c if S > (((255 + factor) // 2) * 3): a, b, c = 255, 255, 255 else: a, b, c = 0, 0, 0 self.draw.point((i, j), (a, b, c)) def to_original(self): self.image = Image.open(self.image_path) def resize_image(self, width, height): self.image = self.image.resize((width, height), Image.BICUBIC) def crop_image(self): self.image = self.image.crop((0, 0, 150, 150)) async def save_image_to_dir(self): # TODO обновление аватара во всех окнах (переписать?) name = self.parent.parent.client_name self.new_img_name = os.path.join(STATIC_PATH, name + '.png') self.img_tmp.save(self.new_img_name, 'PNG') await asyncio.sleep(1) self.parent.label_avatar.setPixmap(QPixmap(self.new_img_name)) self.parent.parent.label_avatar.setPixmap(QPixmap(self.new_img_name)) self.close() async def save_image_to_db(self): ba = QByteArray() buff = QBuffer(ba) buff.open(QIODevice.WriteOnly) ok = self.pixmap.save(buff, "PNG") assert ok pixmap_bytes = ba.data() self.parent.parent.database.add_client_info(pixmap_bytes) await asyncio.sleep(1) def save_image(self): ioloop = asyncio.get_event_loop() tasks = [ ioloop.create_task(self.save_image_to_dir()), ioloop.create_task(self.save_image_to_db()), ] ioloop.run_until_complete(asyncio.wait(tasks)) ioloop.close()
class Drawer(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setAttribute(Qt.WA_StaticContents) self.h = 720 self.w = 1280 self.Font_Color = Qt.white self.myPenWidth = 15 self.myPenColor = Qt.black self.image = QImage(self.w, self.h, QImage.Format_RGB32) self.path = QPainterPath() self.clearImage() def setPenColor(self, newColor): self.path = QPainterPath() self.myPenColor = newColor def setPenWidth(self): i, okBtnPressed = QInputDialog.getInt(self, "Размер кисти", "Введите размер кисти", self.myPenWidth, 1, 100, 1) if okBtnPressed: self.path = QPainterPath() self.myPenWidth = i self.myCursor() def setFont(self): color = QColorDialog.getColor() self.Font_Color = color self.clearImage() def clearImage(self): self.path = QPainterPath() self.image.fill(self.Font_Color) self.update() def saveImage(self): try: fname = QFileDialog.getSaveFileName(self, 'Выбор файла', '.')[0] self.image.save(fname, fname.split(".")[1].upper()) except Exception: pass def loadImage(self): self.path = QPainterPath() try: fname = QFileDialog.getOpenFileName(self, 'Выбор файла', '.')[0] self.image = QImage(fname, fname.split(".")[1].upper()) except Exception: pass def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self.image, self.rect()) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.flag = True self.path.moveTo(event.pos()) def mouseMoveEvent(self, event): if self.flag: self.path.lineTo(event.pos()) p = QPainter(self.image) p.setPen( QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) p.drawPath(self.path) p.end() self.update() else: self.path = QPainterPath() def sizeHint(self): if self.w == 1280 and self.h == 720: return QSize(1280, 720) return QSize(640, 480) self.update() def ChangeRes(self): if self.w == 1280 and self.h == 720: self.w = 640 self.h = 480 else: self.w = 1280 self.h = 720 self.update() self.image = QImage(self.w, self.h, QImage.Format_RGB32) self.path = QPainterPath() self.clearImage() def myCursor(self): cmap = QPixmap("cursor.png") cmap = cmap.scaled(self.myPenWidth + 50 * (1 + self.myPenWidth // 100), self.myPenWidth + 50 * (1 + self.myPenWidth // 100)) color = self.myPenColor self.setCursor(QCursor(cmap)) def run(self): color = QColorDialog.getColor() if color.isValid(): self.setPenColor(color) self.path = QPainterPath() def filter_invert_color(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] pixels2[i, j] = 255 - r, 255 - g, 255 - b self.image = ImageQt(im2) self.update() self.path = QPainterPath() def filter_black_and_white(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] bw = (r + g + b) // 3 pixels2[i, j] = bw, bw, bw self.image = ImageQt(im2) self.update() self.path = QPainterPath() def filter_left(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] pixels2[i, j] = r, g, b im2 = im2.transpose(Image.ROTATE_90) self.image = ImageQt(im2) self.update() def filter_right(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] pixels2[i, j] = r, g, b im2 = im2.transpose(Image.ROTATE_270) self.image = ImageQt(im2) self.update()
class SequenceGrabber(QtCore.QObject): frame_ready = Signal(object, object) # update_frame_range = Signal() def __init__(self, parent=None, mw=None, seq=None, refimage=None): super(SequenceGrabber, self).__init__(parent) self.mw = mw self.seq = seq self.frame = None self.active_time = None try: ibuf = ImageBuf(self.seq[0].path) except Exception as ex: print(ex) return spec = ibuf.spec() im = Image.new("RGB", (spec.width, spec.height), (0, 0, 0)) draw = ImageDraw.Draw(im) font = ImageFont.truetype('/Library/Fonts/Arial Bold.ttf', 48) draw.text((spec.width / 3, spec.height / 2), "No Image", font=font) self.blank_qimage = ImageQt(im) wksavepath = "/tmp" wksavepath = wksavepath + "/sequencemissing.jpg".format(self.mw.APPID) self.blank_qimage.save(wksavepath) wkqim = QImage(wksavepath) self.blank_qimage = wkqim @QtCore.Slot(object) def request_time(self, framenum): frame = self.get_frame(framenum) if not frame: return self.frame_ready.emit(frame, framenum) def get_frame(self, target_frame): # framenumber convert to Sequence index offset_frame = int(target_frame - self.seq.start()) offset_active = int(self.active_time - self.seq.start()) if offset_frame != offset_active: return if not self.seq[offset_frame].exists: return self.blank_qimage qimage = self.toQImage(self.seq[offset_frame].path) return qimage def get_frame_count(self): return len(self.seq) - 1 def toQImage(self, filepath): ibuf = ImageBuf(filepath) try: bufok = ibuf.read(subimage=0, miplevel=0, force=True, convert=oiio.UINT8) except Exception as ex: print(ex) return None if not bufok: return None spec = ibuf.spec() width = spec.width height = spec.height # Expect the channel to be RGB from the beginning. # It might not work if it is a format like ARGB. # qimage = QtGui.QImage(width, height, QtGui.QImage.Format_RGB888) roi = oiio.ROI(0, width, 0, height, 0, 1, 0, 3) try: orgimg = Image.fromarray(ibuf.get_pixels(oiio.UINT8, roi)) # for ImageQt source format error if orgimg.mode in self.mw.shot.NO_SUPPORT_IMAGEQT: orgimg = orgimg.convert('RGB') if self.mw.thumbnail_bright != self.mw.THUMB_DEFALUT_BRIGHT: eim = ImageEnhance.Brightness(orgimg) orgimg = eim.enhance(self.mw.thumbnail_bright) qimage = ImageQt(orgimg) # workaround https://bugreports.qt.io/browse/PYSIDE-884 # output QImage to a file and reRead qimage wksavepath = QStandardPaths.writableLocation( QStandardPaths.TempLocation) wksavepath = wksavepath + "/{0}/sequencegrab.jpg".format( self.mw.APPID) qimage.save(wksavepath, "jpg") wkqim = QImage(wksavepath) qimage = wkqim os.remove(wksavepath) except Exception as ex: print(ex) return None return (qimage)
class Drawer(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setAttribute(Qt.WA_StaticContents) self.h = 720 self.w = 1280 self.Font_Color = Qt.white self.myPenWidth = 15 self.myPenColor = Qt.black self.image = QImage(self.w, self.h, QImage.Format_RGB32) self.path = QPainterPath() self.clearImage() self.flag = False self.colors = [[100, 0, 0], [150, 0, 0], [200, 0, 0], [0, 100, 0], [0, 150, 0], [0, 200, 0], [0, 0, 100], [0, 0, 150], [0, 0, 200]] self.color = 0 def setPenColor(self, newColor): self.path = QPainterPath() self.myPenColor = newColor def setPenWidth(self): i, okBtnPressed = QInputDialog.getInt(self, "Размер кисти", "Введите размер кисти", self.myPenWidth, 1, 100, 1) if okBtnPressed: self.path = QPainterPath() self.myPenWidth = i self.myCursor() def setFont(self): color = QColorDialog.getColor() self.Font_Color = color self.clearImage() def clearImage(self): self.path = QPainterPath() self.image.fill(self.Font_Color) self.update() def saveImage(self): i, okBtnPressed = QInputDialog.getText(self, "Название файла", "Введите название файла") if okBtnPressed: name = i if "." in name: self.image.save(name, name.split(".")[1].upper()) else: i1, okBtnPressed1 = QInputDialog.getItem( self, "Расширение", "Выберите расширение", ("jpg", "png")) self.image.save(f"{name}.{i1}", i1.upper()) def loadImage(self): i, okBtnPressed = QInputDialog.getText(self, "Название файла", "Введите название файла") if okBtnPressed: name = i if "." in name: self.image = QImage(name, name.split(".")[1].upper()) else: i1, okBtnPressed1 = QInputDialog.getItem( self, "Расширение", "Выберите расширение", ("jpg", "png"), 1, False) self.image = QImage(f"{name}.{i1}", i1.upper()) def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self.image, self.rect()) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.flag = True self.path.moveTo(event.pos()) def mouseMoveEvent(self, event): if self.flag: self.path.lineTo(event.pos()) p = QPainter(self.image) p.setPen( QPen(self.myPenColor, self.myPenWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) p.drawPath(self.path) p.end() self.update() else: self.path = QPainterPath() def sizeHint(self): if self.w == 1280 and self.h == 720: return QSize(1280, 720) return QSize(640, 480) self.update() def ChangeRes(self): if self.w == 1280 and self.h == 720: self.w = 640 self.h = 480 else: self.w = 1280 self.h = 720 self.update() self.image = QImage(self.w, self.h, QImage.Format_RGB32) self.path = QPainterPath() self.clearImage() def myCursor(self): cmap = QPixmap("cursor.png") cmap = cmap.scaled(self.myPenWidth + 50 * (1 + self.myPenWidth // 100), self.myPenWidth + 50 * (1 + self.myPenWidth // 100)) color = self.myPenColor self.setCursor(QCursor(cmap)) def run(self): color = QColorDialog.getColor() if color.isValid(): self.setPenColor(color) self.path = QPainterPath() def filter_invert_color(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] pixels2[i, j] = 255 - r, 255 - g, 255 - b self.image = ImageQt(im2) self.update() self.path = QPainterPath() def filter_black_and_white(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] bw = (r + g + b) // 3 pixels2[i, j] = bw, bw, bw self.image = ImageQt(im2) self.update() self.path = QPainterPath() def filter_(self): x, y = self.image.width(), self.image.height() im2 = Image.new("RGB", (x, y), (0, 0, 0)) pixels2 = im2.load() for i in range(x): for j in range(y): r, g, b = self.image.pixelColor(i, j).getRgb()[:-1] bw = (r + g + b) // 3 pixels2[i, j] = bw, bw, bw self.image = ImageQt(im2) self.update() self.path = QPainterPath()
class DrawingArea(QWidget): loadSignal = pyqtSignal() profileSignal = pyqtSignal(list) def __init__(self): super(DrawingArea, self).__init__() self.image_path = None self.loadImage() self.drawing = False self.last_point = QPoint() self.lines = [] self.profiles = [] self.setUpPen() # Main drawing functionalities def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.last_point = event.pos() self.drawing = True def mouseMoveEvent(self, event): if self.drawing and (event.buttons() & Qt.LeftButton): self.updateImage() self.drawLineOnImage(self.last_point, event.pos()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.drawing: self.image_lastdrawn = self.image.copy() self.drawing = False self.lines.append((self.last_point, event.pos())) self.extractLine() emit_value = [self.profiles[-1], self.lines[-1]] self.profileSignal.emit(emit_value) # Auxilliary drawing functionalities def updateImage(self): self.image = self.image_lastdrawn.copy() self.update() def drawLineOnImage(self, start, end): # Setting canvas painter = QPainter(self.image) painter.drawImage(self.rect(), self.image) painter.setPen(self.pen) # Draw line painter.drawLine(start, end) self.update() def paintEvent(self, event): painter = QPainter(self) painter.drawImage(event.rect(), self.image) painter.setPen(self.pen) # for line in self.lines: # start, end = line # painter.drawLine(start, end) self.update() def setUpPen(self, width=5, color='orange'): self.pen = QPen(QColor(color), width, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) # Line profile functionalities def extractLine(self): start, end = self.lines[-1] x0, y0 = max(start.x(), 0), max(start.y(), 0) x1, y1 = min(end.x(), self.image_grayscale.shape[1] - 1), min( end.y(), self.image_grayscale.shape[0] - 1) num = int(np.hypot(x1 - x0, y1 - y0)) rows, cols = np.linspace(y0, y1, num), np.linspace(x0, x1, num) profile = self.image_grayscale[rows.astype(np.int), cols.astype(np.int)] self.profiles.append(list(profile)) # Other functionalities def loadImage(self): # Unfix widget size self.setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) self.setMinimumSize(0, 0) # Load image # if self.image_path is None, create dummy image if self.image_path == None: self.image_grayscale = np.array(Image.new('L', (600, 400), 255)) self.image = ImageQt(Image.new('RGB', (600, 400), (255, 255, 255))) self.image_lastdrawn = self.image.copy() else: # Store grayscale image to self.image_grayscale self.image_grayscale = np.array( Image.open(self.image_path).convert('L')) image = QImage(self.image_path) if image.isGrayscale(): # Create RGB version using PIL image_rgb = Image.open(self.image_path).convert('RGB') # Store RGB version of image in self.image, self.image_original self.image = ImageQt(image_rgb) self.image_lastdrawn = self.image.copy() else: # Store original and drawn image as it is self.image = image self.image_lastdrawn = image.copy() # Refix widget size self.setFixedSize(self.image.width(), self.image.height()) # Flush lines self.lines = [] self.profiles = [] self.loadSignal.emit() self.update() def saveImage(self, file_name): self.image.save(file_name, 'PNG', -1) # def main(): # app = QApplication(sys.argv) # demo = DrawingArea() # demo.show() # sys.exit(app.exec_()) # main()
class ZXSpectrumBuffer(object): """ This class defines a buffer for the ZX Spectrum. """ def __init__(self, fgIndex=0, bgIndex=7, paletteIndex=0): self._paper = Image.new("RGB", self.size.toTuple()) self._ink = Image.new("RGB", self.size.toTuple()) self._mask = Image.new("1", self.size.toTuple()) self._final = None self._needsUpdate = True # Set up attribute colors self._attributes = dict() for y in range(0, self.sizeAttr.height()): for x in range(0, self.sizeAttr.width()): self._attributes[(x, y)] = ZXAttribute() self.clear(fgIndex, bgIndex, paletteIndex) def _update(self): if self._needsUpdate: self._final = ImageQt( Image.composite(self._ink, self._paper, self._mask)) self._needsUpdate = False @property def size(self): return QSize(256, 192) @property def sizeAttr(self): return QSize(32, 24) @property def qpixmap(self): self._update() return QtGui.QPixmap.fromImage(self._final) @staticmethod def inRange(point, range): if point.x() >= 0 and point.x() < range.width() and \ point.y() >= 0 and point.y() < range.height(): return True return False def clear(self, fgIndex, bgIndex, paletteIndex=0): for y in range(0, self.sizeAttr.height()): for x in range(0, self.sizeAttr.width()): self._attributes[(x, y)].ink = fgIndex self._attributes[(x, y)].paper = bgIndex self._attributes[(x, y)].palette = paletteIndex im_ink = ImageDraw.Draw(self._ink) im_ink.rectangle( [0, 0, self.size.width() - 1, self.size.height() - 1], fill=ZXAttribute.getPaletteColor(fgIndex, paletteIndex)) im_paper = ImageDraw.Draw(self._paper) im_paper.rectangle( [0, 0, self.size.width() - 1, self.size.height() - 1], fill=ZXAttribute.getPaletteColor(bgIndex, paletteIndex)) im_mask = ImageDraw.Draw(self._mask) im_mask.rectangle( [0, 0, self.size.width() - 1, self.size.height() - 1], fill=0) self._needsUpdate = True def setAttr(self, x, y, fgIndex, bgIndex, paletteIndex): x = x // 8 y = y // 8 pos = (x * 8, y * 8) if not ZXSpectrumBuffer.inRange(QPoint(x, y), self.sizeAttr): return attr = self._attributes[(x, y)] paletteChanged = False if attr.palette != paletteIndex: paletteChanged = True attr.palette = paletteIndex if attr.ink != fgIndex or paletteChanged: attr.ink = fgIndex im_ink = ImageDraw.Draw(self._ink) im_ink.rectangle([pos[0], pos[1], pos[0] + 7, pos[1] + 7], fill=ZXAttribute.getPaletteColor( fgIndex, paletteIndex)) self._needsUpdate = True if attr.paper != bgIndex or paletteChanged: attr.paper = bgIndex im_paper = ImageDraw.Draw(self._paper) im_paper.rectangle([pos[0], pos[1], pos[0] + 7, pos[1] + 7], fill=ZXAttribute.getPaletteColor( bgIndex, paletteIndex)) self._needsUpdate = True def setPixel(self, x, y, fgIndex, bgIndex, paletteIndex): if not ZXSpectrumBuffer.inRange(QPoint(x, y), self.size): return self.setAttr(x, y, fgIndex, bgIndex, paletteIndex) self._mask.putpixel((int(x), int(y)), 1) self._needsUpdate = True def erasePixel(self, x, y, fgIndex, bgIndex, paletteIndex): self.setAttr(x, y, fgIndex, bgIndex, paletteIndex) self._mask.putpixel((int(x), int(y)), 0) self._needsUpdate = True def drawLine(self, x1, y1, x2, y2, fgIndex, bgIndex, paletteIndex): for x, y in BresenhamLine((x1, y1), (x2, y2)): self.setAttr(x, y, fgIndex, bgIndex, paletteIndex) pos = QPoint(int(x), int(y)) if ZXSpectrumBuffer.inRange(pos, self.size): self._mask.putpixel(pos.toTuple(), 1) self._needsUpdate = True def saveBuffer(self, filename, format=None): self._update() self._final.save(filename, format) def encodeToJSON(self): rdict = dict() rdict["mask"] = np.array(self._mask, dtype='uint8').tolist() for y in range(0, self.sizeAttr.height()): for x in range(0, self.sizeAttr.width()): key = "{},{}".format(x, y) rdict[key] = self._attributes[(x, y)].encodeToJSON() return rdict def decodeFromJSON(self, json): # Load image as B&W image first and then convert to bitmask # There may be a solution to create the 1-bit pixmap directly but this can be looked at later image_data = np.array(json["mask"], dtype='uint8') * 255 image = Image.fromarray(image_data, mode="L") self._mask = image.convert("1") for y in range(0, self.sizeAttr.height()): for x in range(0, self.sizeAttr.width()): # As we need to update the image with the attribute, go via setAttr rather than # directly updating the screen attributes attr = ZXAttribute() attr.decodeFromJSON(json["{},{}".format(x, y)]) self.setAttr(x * 8, y * 8, attr.ink, attr.paper, attr.palette) self._needsUpdate = True