123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281 |
- # uHDR: HDR image editing software
- # Copyright (C) 2021 remi cozot
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # hdrCore project 2020
- # author: remi.cozot@univ-littoral.fr
- # -----------------------------------------------------------------------------
- # --- Package hdrGUI ---------------------------------------------------------
- # -----------------------------------------------------------------------------
- """
- package hdrGUI consists of the classes for GUI.
- """
- # -----------------------------------------------------------------------------
- # --- Import ------------------------------------------------------------------
- # -----------------------------------------------------------------------------
- import enum, sys, subprocess, copy, colour, time, os, shutil, datetime, ctypes
- import numpy as np
- # pyQT5 import
- from PyQt5.QtWidgets import QFileDialog, QApplication
- from PyQt5.QtWidgets import QMessageBox
- from . import model, view, thread
- import hdrCore.image, hdrCore.processing, hdrCore.utils
- import hdrCore.coreC
- import preferences.preferences as pref
- # zj add for semi-auto curve
- import torch
- from hdrCore.net import Net
- from torch.autograd import Variable
- # -----------------------------------------------------------------------------
- # --- package methods ---------------------------------------------------------
- # -----------------------------------------------------------------------------
- def getScreenSize(app):
- screens = app.screens()
- res = list(map(lambda x: x.size(), screens))
- return res
- # -----------------------------------------------------------------------------
- # --- Class GalleryMode -------------------------------------------------------
- # -----------------------------------------------------------------------------
- class GalleryMode(enum.Enum):
- """ Enum """
- _1x1 = 0 #
- _3x2 = 1 #
- _6x4 = 2 #
- _9x6 = 3 #
-
- _2x1 = 4
- def nbRow(m):
- if m == GalleryMode._1x1: return 1
- if m == GalleryMode._3x2: return 2
- if m == GalleryMode._6x4: return 4
- if m == GalleryMode._9x6: return 6
- if m == GalleryMode._2x1: return 1
- def nbCol(m):
- if m == GalleryMode._1x1: return 1
- if m == GalleryMode._3x2: return 3
- if m == GalleryMode._6x4: return 6
- if m == GalleryMode._9x6: return 9
- if m == GalleryMode._2x1: return 2
- # -----------------------------------------------------------------------------
- # --- Class ImageWidgetController ---------------------------------------------
- # -----------------------------------------------------------------------------
- class ImageWidgetController:
- """ image widget controller """
- def __init__(self, image=None,id = -1):
- self.model = model.ImageWidgetModel(self)
- self.view = view.ImageWidgetView(self)
- self._id = id # store an (unique) id
- if isinstance(image, (np.ndarray, hdrCore.image.Image)):
- self.model.setImage(image)
- self.view.setPixmap(self.model.getColorData())
- def setImage(self, image):
- self.model.setImage(image)
- return self.view.setPixmap(self.model.getColorData())
- def setQPixmap(self, qPixmap):
- self.view.setQPixmap(qPixmap)
- def id(self): return self._id
- # -----------------------------------------------------------------------------
- # --- Class ImageGalleryController --------------------------------------------
- # -----------------------------------------------------------------------------
- class ImageGalleryController():
- """ image gallery controller """
- def __init__(self, parent):
- if pref.verbose: print(" [CONTROL] >> ImageGalleryController.__init__()")
- self.parent = parent # AppView
- self.view = view.ImageGalleryView(self)
- self.model = model.ImageGalleryModel(self)
- def setImages(self, imageFiles): self.model.setImages(imageFiles)
- def updateImages(self):
- """ called by ImageGalleryModel to ask for update images """
- self.view.pageNumber = 0 # reset page number
- self.view.updateImages()
- def callBackButton_previousPage(self):
- self.view.changePageNumber(-1)
- if self.view.shapeMode == GalleryMode._1x1 : self.selectImage(0)
- def callBackButton_nextPage(self):
- self.view.changePageNumber(+1)
- if self.view.shapeMode == GalleryMode._1x1 : self.selectImage(0)
- def computePageNumberOnGalleryModeChange(self,newGalleryMode):
- currentPage = self.view.pageNumber
- nbImagePerPage = GalleryMode.nbRow(self.view.shapeMode)*GalleryMode.nbCol(self.view.shapeMode)
- selectedImage = self.model.selectedImage() if (self.model.selectedImage()!=-1) else currentPage*nbImagePerPage
- newNbImagePerPage = GalleryMode.nbRow(newGalleryMode)*GalleryMode.nbCol(newGalleryMode)
- newPageNumber = selectedImage//newNbImagePerPage
- return newPageNumber
- def callBackButton_1x1(self):
- if self.view.shapeMode != GalleryMode._1x1:
- self.view.resetGridLayoutWidgets()
- self.view.pageNumber = self.computePageNumberOnGalleryModeChange(GalleryMode._1x1)
- self.view.shapeMode = GalleryMode._1x1
- self.view.buildGridLayoutWidgets()
- self.view.updateImages()
- self.model.loadPage(self.view.pageNumber)
- self.view.repaint()
- def callBackButton_3x2(self):
- if self.view.shapeMode != GalleryMode._3x2:
- self.view.resetGridLayoutWidgets()
- self.view.pageNumber = self.computePageNumberOnGalleryModeChange(GalleryMode._3x2)
- self.view.shapeMode = GalleryMode._3x2
- self.view.buildGridLayoutWidgets()
- self.view.updateImages()
- self.model.loadPage(self.view.pageNumber)
- self.view.repaint()
- def callBackButton_6x4(self):
- if self.view.shapeMode != GalleryMode._6x4:
- self.view.resetGridLayoutWidgets()
- self.view.pageNumber = self.computePageNumberOnGalleryModeChange(GalleryMode._6x4)
- self.view.shapeMode = GalleryMode._6x4
- self.view.buildGridLayoutWidgets()
- self.view.updateImages()
- self.model.loadPage(self.view.pageNumber)
- self.view.repaint()
- def callBackButton_9x6(self):
- if self.view.shapeMode != GalleryMode._9x6:
- self.view.resetGridLayoutWidgets()
- self.view.pageNumber = self.computePageNumberOnGalleryModeChange(GalleryMode._9x6)
- self.view.shapeMode = GalleryMode._9x6
- self.view.buildGridLayoutWidgets()
- self.view.updateImages()
- self.model.loadPage(self.view.pageNumber)
- self.view.repaint()
- def callBackButton_2x1(self):
- if self.view.shapeMode != GalleryMode._2x1:
- self.view.resetGridLayoutWidgets()
- self.view.pageNumber = self.computePageNumberOnGalleryModeChange(GalleryMode._2x1)
- self.view.shapeMode = GalleryMode._2x1
- self.view.buildGridLayoutWidgets()
- self.view.updateImages()
- self.model.loadPage(self.view.pageNumber)
- self.view.repaint()
- def selectImage(self, id):
- if pref.verbose: print(" [CONTROL] >> ImageGalleryController.selectImage()")
- nbImagePage = GalleryMode.nbRow(self.view.shapeMode)*GalleryMode.nbCol(self.view.shapeMode)
- idxImage = self.view.pageNumber*nbImagePage+id
- # check id
- if (idxImage < len(self.model.processPipes)):
- # update selected image
- processPipe = self.model.processPipes[idxImage]
- if processPipe:
- if self.parent.dock.setProcessPipe(processPipe):
- self.model.setSelectedImage(idxImage)
- def getSelectedProcessPipe(self):
- if pref.verbose: print(" [CONTROL] >> ImageGalleryController.getSelectedProcessPipe()")
- return self.model.getSelectedProcessPipe()
- def setProcessPipeWidgetQPixmap(self, qPixmap):
- idxProcessPipe = self.model.selectedImage()
- nbImagePage = GalleryMode.nbRow(self.view.shapeMode)*GalleryMode.nbCol(self.view.shapeMode)
- idxImageWidget = idxProcessPipe%nbImagePage
- if pref.verbose: print(" >> ImageGalleryController.setProcessPipeWidgetQPixmap(...)[ image id:",idxProcessPipe,">> image widget controller:",idxImageWidget,"]")
- self.view.imagesControllers[idxImageWidget].setQPixmap(qPixmap)
- def save(self):
- if pref.verbose: print(" [CONTROL] >> ImageGalleryController.save()")
- self.model.save()
- def currentPage(self): return self.view.currentPage()
- def pageIdx(self):
- nb = self.currentPage()
- nbImagePage = GalleryMode.nbRow(self.view.shapeMode)*GalleryMode.nbCol(self.view.shapeMode)
- return (nb*nbImagePage), ((nb+1)*nbImagePage)
- def getFilenamesOfCurrentPage(self): return self.model.getFilenamesOfCurrentPage()
- def getProcessPipeById(self,i) : return self.model.getProcessPipeById(i)
- def getProcessPipes(self): return self.model.processPipes
- # -----------------------------------------------------------------------------
- # --- Class AppController -----------------------------------------------------
- # -----------------------------------------------------------------------------
- class AppController(object):
- """controller for MainWindow
-
- Attributes:
- screenSize
- hdrDisplay
- view
- model
-
- Methods:
- callBackSelectDir(self)
- callBackSave(self)
- callBackDisplayHDR(self)
- callBackEndDisplay(self, img)
- callBackCloseDisplayHDR(self)
- callBackCompareRawEditedHDR(self)
- callBackExportHDR(self)
- callBackEndExportHDR(self, img)
- callBackExportAllHDR(self)
- callBackEndAllExportHDR(self, img)
- """
- def __init__(self, app):
- if pref.verbose: print(" [CONTROL] >> AppController.__init__()")
- self.screenSize = getScreenSize(app)# get screens size
- # attributes
- self.hdrDisplay = HDRviewerController(self)
- self.view = view.AppView(self, HDRcontroller = self.hdrDisplay)
- self.model = model.AppModel(self)
- self.dirName = None
- self.imagesName = []
-
- self.view.show()
- # -----------------------------------------------------------------------------
- def callBackSelectDir(self):
- """Callback of export HDR menu: open file dialog, store image filenames (self.imagesName), set directory to model
- """
- if pref.verbose: print(" [CONTROL] >> AppController.callBackSelectDir()")
- dirName = QFileDialog.getExistingDirectory(None, 'Select Directory', self.model.directory)
- if dirName != "":
- # save current images (metadata)
- self.view.imageGalleryController.save()
- # get images in the selected directory
- self.imagesName = []; self.imagesName = list(self.model.setDirectory(dirName))
- self.view.imageGalleryController.setImages(self.imagesName)
- self.hdrDisplay.displaySplash()
- # -----------------------------------------------------------------------------
- def callBackSave(self): self.view.imageGalleryController.save()
- # -----------------------------------------------------------------------------
- def callBackQuit(self):
- if pref.verbose: print(" [CB] >> AppController.callBackQuit()")
- self.view.imageGalleryController.save()
- self.hdrDisplay.close()
- sys.exit()
- # -----------------------------------------------------------------------------
- def callBackDisplayHDR(self):
- if pref.verbose: print(" [CONTROL] >> AppController.callBackDisplayHDR()")
- selectedProcessPipe = self.view.imageGalleryController.model.getSelectedProcessPipe()
- if selectedProcessPipe:
- self.view.statusBar().showMessage('displaying HDR image, full size image computation: start, please wait !')
- self.view.statusBar().repaint()
- # save current processpipe metada
- originalImage = copy.deepcopy(selectedProcessPipe.originalImage)
- originalImage.metadata.metadata['processpipe'] = selectedProcessPipe.toDict()
- originalImage.metadata.save()
- # load full size image
- img = hdrCore.image.Image.read(originalImage.path+'/'+originalImage.name)
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = False
- # make a copy of selectedProcessPipe
- processpipe = copy.deepcopy(selectedProcessPipe)
- # set size to display size
- size = pref.getDisplayShape()
- img = img.process(hdrCore.processing.resize(),size=(None, size[1]))
- # set image to process-pipe
- processpipe.setImage(img)
- thread.cCompute(self.callBackEndDisplay, processpipe, toneMap=False, progress=self.view.statusBar().showMessage)
- # -----------------------------------------------------------------------------
- def callBackEndDisplay(self, img):
- if pref.verbose: print(" [CONTROL] >> AppController.callBackEndDisplay()")
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = True
-
- self.view.statusBar().showMessage('displaying HDR image, full size image computation: done !')
- # clip, scale
- img = img.process(hdrCore.processing.clip())
- img.colorData = img.colorData*pref.getDisplayScaling()
- colour.write_image(img.colorData,"temp.hdr", method='Imageio') # local copy for display
- self.hdrDisplay.displayFile("temp.hdr")
- # -----------------------------------------------------------------------------
- def callBackCloseDisplayHDR(self):
- if pref.verbose: print(" [CONTROL] >> AppController.callBackCloseDisplayHDR()")
- self.hdrDisplay.displaySplash()
- # -----------------------------------------------------------------------------
- def callBackCompareRawEditedHDR(self):
- """
- Callback of compare raw/edited HDR menu
- Display side by side original image and edited version.
- """
- if pref.verbose: print(" [CONTROL] >> AppController.callBackCompareOriginalInputHDR()")
- # process real size image
- # get selected process pipe
- selectedProcessPipe = self.view.imageGalleryController.model.getSelectedProcessPipe()
- if selectedProcessPipe: # check if a process pipe is selected
- # read original image
- img = hdrCore.image.Image.read(selectedProcessPipe.originalImage.path+'/'+selectedProcessPipe.originalImage.name)
- # resize
- screenY, screenX = pref.getDisplayShape()
- imgY, imgX,_ = img.shape
- marginY = int((screenY - imgY/2)/2)
- marginX = int(marginY/4)
- imgXp = int((screenX - 3*marginX)/2)
- img = img.process(hdrCore.processing.resize(),size=(None,imgXp))
- imgY, imgX, _ = img.shape
- # original image after resize
- ori = copy.deepcopy(img)
- # build process pipe from selected one them compute
- pp = hdrCore.processing.ProcessPipe()
- hdrCore.processing.ProcessPipe.autoResize = False # stop autoResize
- params= []
- for p in selectedProcessPipe.processNodes:
- pp.append(copy.deepcopy(p.process),paramDict=None, name=copy.deepcopy(p.name))
- params.append({p.name:p.params})
- img.metadata.metadata['processpipe'] = params
- pp.setImage(img)
- res = hdrCore.coreC.coreCcompute(img, pp)
- res = res.process(hdrCore.processing.clip())
-
- imgYres, imgXres, _ = res.colorData.shape
- hdrCore.processing.ProcessPipe.autoResize = True # return to autoResize
- # make comparison image
- oriColorData = ori.colorData*pref.getDisplayScaling()
- resColorData = res.colorData*pref.getDisplayScaling()
- display = np.ones((screenY,screenX,3))*0.2
- marginY = int((screenY - imgY)/2)
- marginYres = int((screenY - imgYres)/2)
- display[marginY:marginY+imgY, marginX:marginX+imgX,:] = oriColorData
- display[marginYres:marginYres+imgYres, 2*marginX+imgX:2*marginX+imgX+imgXres,:] = resColorData
-
- # save as compOrigFinal.hdr
- colour.write_image(display,'compOrigFinal.hdr', method='Imageio')
- self.hdrDisplay.displayFile('compOrigFinal.hdr')
- # -----------------------------------------------------------------------------
- def callBackExportHDR(self):
- """
- Callback of export HDR menu
- Export the image associated to selected process pipe
- """
- if pref.verbose: print(" [CONTROL] >> AppController.callBackExportHDR()")
- selectedProcessPipe = self.view.imageGalleryController.model.getSelectedProcessPipe()
- if selectedProcessPipe:
- # select dir where to save export
- self.dirName = QFileDialog.getExistingDirectory(None, 'Select Directory where to export HDR file', self.model.directory)
- # show export message
- self.view.statusBar().showMessage('exporting HDR image ('+pref.getHDRdisplay()['tag']+'), full size image computation: start, please wait !')
- self.view.statusBar().repaint()
- # save current processpipe metada
- originalImage = copy.deepcopy(selectedProcessPipe.originalImage)
- originalImage.metadata.metadata['processpipe'] = selectedProcessPipe.toDict()
- originalImage.metadata.save()
- # load full size image
- img = hdrCore.image.Image.read(originalImage.path+'/'+originalImage.name)
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = False
- # make a copy of selectedProcessPipe
- processpipe = copy.deepcopy(selectedProcessPipe)
- # set image to process-pipe
- processpipe.setImage(img)
- thread.cCompute(self.callBackEndExportHDR, processpipe, toneMap=False, progress=self.view.statusBar().showMessage)
- # -----------------------------------------------------------------------------
- def callBackEndExportHDR(self, img):
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = True
-
- self.view.statusBar().showMessage('exporting HDR image ('+pref.getHDRdisplay()['tag']+'), full size image computation: done !')
- # clip, scale
- img = img.process(hdrCore.processing.clip())
- img.colorData = img.colorData*pref.getDisplayScaling()
- if self.dirName:
- pathExport = os.path.join(self.dirName, img.name[:-4]+pref.getHDRdisplay()['post']+'.hdr')
- img.type = hdrCore.image.imageType.HDR
- img.metadata.metadata['processpipe'] = None
- img.metadata.metadata['display'] = pref.getHDRdisplay()['tag']
- img.write(pathExport)
- colour.write_image(img.colorData,"temp.hdr", method='Imageio') # local copy for display
- self.hdrDisplay.displayFile("temp.hdr")
- # -----------------------------------------------------------------------------
- def callBackExportAllHDR(self):
- if pref.verbose: print(" [CONTROL] >> AppController.callBackExportAllHDR()")
- self.processPipes = self.view.imageGalleryController.getProcessPipes()
- # select dir where to save export
- self.dirName = QFileDialog.getExistingDirectory(None, 'Select Directory where to export HDR file', self.model.directory)
- self.view.statusBar().showMessage('exporting '+str(len(self.processPipes))+' HDR images ... please wait')
- self.view.statusBar().repaint()
- self.imageToExport = len(self.processPipes) ; self.imageExportDone = 0
- pp = self.processPipes[0]
- # save current processpipe metada
- originalImage = copy.deepcopy(pp.originalImage)
- originalImage.metadata.metadata['processpipe'] = pp.toDict()
- originalImage.metadata.save()
- # load full size image
- img = hdrCore.image.Image.read(originalImage.path+'/'+originalImage.name)
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = False
- # make a copy of selectedProcessPipe
- processpipe = copy.deepcopy(pp)
- # set image to process-pipe
- processpipe.setImage(img)
- thread.cCompute(self.callBackEndAllExportHDR, processpipe, toneMap=False, progress=self.view.statusBar().showMessage)
- # -----------------------------------------------------------------------------
- def callBackEndAllExportHDR(self, img):
- # last image ?
- self.imageExportDone +=1
- self.view.statusBar().showMessage('exporting HDR images ('+pref.getHDRdisplay()['tag']+'):'+str(int(100*self.imageExportDone/self.imageToExport))+'% done !')
- # clip, scale
- img = img.process(hdrCore.processing.clip())
- img.colorData = img.colorData*pref.getDisplayScaling()
- if self.dirName:
- pathExport = os.path.join(self.dirName, img.name[:-4]+pref.getHDRdisplay()['post']+'.hdr')
- img.type = hdrCore.image.imageType.HDR
- img.metadata.metadata['processpipe'] = None
- img.metadata.metadata['display'] = pref.getHDRdisplay()['tag']
- img.write(pathExport)
- if self.imageExportDone == self.imageToExport :
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = True
- else:
- pp = self.processPipes[self.imageExportDone]
- if not pp:
- img = hdrCore.image.Image.read(self.imagesName[self.imageExportDone], thumb=True)
- pp = model.EditImageModel.buildProcessPipe()
- pp.setImage(img)
- # save current processpipe metada
- originalImage = copy.deepcopy(pp.originalImage)
- originalImage.metadata.metadata['processpipe'] = pp.toDict()
- originalImage.metadata.save()
- # load full size image
- img = hdrCore.image.Image.read(originalImage.path+'/'+originalImage.name)
- # turn off: autoResize
- hdrCore.processing.ProcessPipe.autoResize = False
- # make a copy of selectedProcessPipe
- processpipe = copy.deepcopy(pp)
- # set image to process-pipe
- processpipe.setImage(img)
- thread.cCompute(self.callBackEndAllExportHDR, processpipe, toneMap=False, progress=self.view.statusBar().showMessage)
- # ------------------------------------------------------------------------------------------
- # --- class MultiDockController() ----------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class MultiDockController():
- def __init__(self,parent=None, HDRcontroller = None):
- if pref.verbose: print(" [CONTROL] >> MultiDockController.__init__()")
- self.parent = parent
- self.view = view.MultiDockView(self, HDRcontroller)
- self.model = None
- # ---------------------------------------------------------------------------------------
- def activateEDIT(self): self.switch(0)
- def activateINFO(self): self.switch(1)
- def activateMIAM(self): self.switch(2)
- # ---------------------------------------------------------------------------------------
- def switch(self,nb):
- if pref.verbose: print(" [CONTROL] >> MultiDockController.switch()")
- self.view.switch(nb)
- # --------------------------------------------------------------------------------------
- def setProcessPipe(self, processPipe):
- if pref.verbose: print(" [CONTROL] >> MultiDockController.setProcessPipe(",processPipe.getImage().name,")")
- return self.view.setProcessPipe(processPipe)
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class EditImageController:
- def __init__(self, parent=None, HDRcontroller = None):
- if pref.verbose: print(" [CONTROL] >> EditImageController.__init__(",")")
- self.parent = parent
- self.previewHDR = True
- self.controllerHDR = HDRcontroller
- self.view = view.EditImageView(self)
- self.model = model.EditImageModel(self)
- # -----------------------------------------------------------------------------
- def setProcessPipe(self, processPipe):
- if pref.verbose: print(" [CONTROL] >> EditImageController.setProcessPipe(",")")
- if self.model.setProcessPipe(processPipe):
- # update view
- self.view.setProcessPipe(processPipe)
- self.view.imageWidgetController.setImage(processPipe.getImage())
- self.view.plotToneCurve()
- # update hdr viewer
- self.controllerHDR.displaySplash()
- return True
- else:
- return False
- # -----------------------------------------------------------------------------
- def getProcessPipe(self) : return self.model.getProcessPipe()
- # -----------------------------------------------------------------------------
- def buildView(self,processPipe=None):
- if pref.verbose: print(" [CONTROL] >> EditImageController.buildView(",")")
- """ called when MultiDockController recall a controller/view """
- self.view = view.EditImageView(self, build=True)
- if processPipe: self.setProcessPipe(processPipe)
- # -----------------------------------------------------------------------------
- def autoExposure(self):
- if pref.verbose: print(" [CONTROL] >> EditImageController.autoExposure(",")")
- if self.model.processpipe:
-
- img = self.model.autoExposure()
- # update view with computed EV
- paramDict = self.model.getEV()
- self.view.exposure.setValue(paramDict['EV'])
- qPixmap = self.view.setImage(img)
- self.parent.controller.parent.controller.view.imageGalleryController.setProcessPipeWidgetQPixmap(qPixmap)
- # -----------------------------------------------------------------------------
- def changeExposure(self,value):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeExposure(",value,")")
- if self.model.processpipe: self.model.changeExposure(value)
- # -----------------------------------------------------------------------------
- def changeContrast(self,value):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeContrast(",value,")")
- if self.model.processpipe: self.model.changeContrast(value)
- # -----------------------------------------------------------------------------
- def changeToneCurve(self,controlPoints):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeToneCurve("")")
- if self.model.processpipe: self.model.changeToneCurve(controlPoints)
- # -----------------------------------------------------------------------------
- def changeLightnessMask(self, maskValues):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeLightnessMask(",maskValues,")")
- if self.model.processpipe: self.model.changeLightnessMask(maskValues)
- # -----------------------------------------------------------------------------
- def changeSaturation(self,value):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeSaturation(",value,")")
- if self.model.processpipe: self.model.changeSaturation(value)
- # -----------------------------------------------------------------------------
- def changeColorEditor(self,values, idName):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeColorEditor(",values,")")
- if self.model.processpipe: self.model.changeColorEditor(values, idName)
- # -----------------------------------------------------------------------------
- def changeGeometry(self,values):
- if pref.verbose: print(" [CONTROL] >> EditImageController.changeGeometry(",values,")")
- if self.model.processpipe: self.model.changeGeometry(values)
- # -----------------------------------------------------------------------------
- def updateImage(self,imgTM):
- """
- updateImage: called when process-pipe computation is done
-
- Args:
- imgTM (hdrCoreimage.Image, required): tone mapped image (resized) for GUI display
- """
- qPixmap = self.view.setImage(imgTM)
- self.parent.controller.parent.controller.view.imageGalleryController.setProcessPipeWidgetQPixmap(qPixmap)
- self.view.plotToneCurve()
- # if aesthetics model > notify required update
- if self.previewHDR and self.model.autoPreviewHDR:
- self.controllerHDR.callBackUpdate()
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class ImageInfoController:
- def __init__(self, parent=None):
- if pref.verbose: print(" [CONTROL] >> ImageInfoController.__init__()")
- self.parent = parent
- self.view = view.ImageInfoView(self)
- self.model = model.ImageInfoModel(self)
- self.callBackActive = True
- # -----------------------------------------------------------------------------
- def setProcessPipe(self, processPipe):
- if pref.verbose: print(" [CONTROL] >> ImageInfoController.setProcessPipe(",processPipe.getImage().name,")")
- self.model.setProcessPipe(processPipe)
- self.view.setProcessPipe(processPipe)
- return True
- # -----------------------------------------------------------------------------
- def buildView(self,processPipe=None):
- if pref.verbose: print(" [CONTROL] >> ImageInfoController.buildView()")
- """ called when MultiDockController recall a controller/view """
- self.view = view.ImageInfoView(self)
- if processPipe: self.setProcessPipe(processPipe)
- # -----------------------------------------------------------------------------
- def metadataChange(self,metaGroup,metaTag, on_off):
- if pref.verbose: print(" [CONTROL] >> ImageInfoController.useCaseChange(",metaGroup,",", metaTag,",", on_off,")")
- self.model.changeMeta(metaGroup,metaTag, on_off)
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class AdvanceSliderController():
- def __init__(self, parent,name, defaultValue, range, step,callBackValueChange=None,callBackAutoPush= None):
- if pref.verbose: print(" [CONTROL] >> AdvanceSliderController.__init__(",") ")
- self.parent = parent
- self.view = view.AdvanceSliderView(self, name, defaultValue, range, step)
- self.model = model.AdvanceSliderModel(self, value=defaultValue)
- self.step = step
- self.defaultValue = defaultValue
- self.range = range
- self.callBackActive = True
- self.callBackValueChange = callBackValueChange
- self.callBackAutoPush = callBackAutoPush
- # -----------------------------------------------------------------------------
- def sliderChange(self):
- value = self.view.slider.value()*self.step
- if pref.verbose: print(" [CB] >> AdvanceSliderController.sliderChange(",value,")[callBackActive:",self.callBackActive,"] ")
- self.model.value = value
- self.view.editValue.setText(str(value))
- if self.callBackActive and self.callBackValueChange: self.callBackValueChange(value)
- # -----------------------------------------------------------------------------
- def setValue(self, value, callBackActive = True):
- if pref.verbose: print(" [CONTROL] >> AdvanceSliderController.setValue(",value,") ")
- """ set value value in 'model' range"""
- self.callBackActive = callBackActive
- self.view.slider.setValue(int(value/self.step))
- self.view.editValue.setText(str(value))
- self.model.setValue(int(value))
- self.callBackActive = True
- # -----------------------------------------------------------------------------
- def reset(self):
- if pref.verbose : print(" [CB] >> AdvanceSliderController.reset(",") ")
- self.setValue(self.defaultValue,callBackActive = False)
- if self.callBackValueChange: self.callBackValueChange(self.defaultValue)
- # -----------------------------------------------------------------------------
- def auto(self):
- if pref.verbose: print(" [CB] >> AdvanceSliderController.auto(",") ")
- if self.callBackAutoPush: self.callBackAutoPush()
- # ------------------------------------------------------------------------------------------
- # --- class AdvanceSliderController --------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class ToneCurveController():
- def __init__(self, parent):
- self.parent = parent
- self.model = model.ToneCurveModel()
- self.view = view.ToneCurveView(self)
- self.callBackActive = True
- # tone curve display control
- self.showInput =False
- self.showbefore = False
- self.showAfter = False
- self.showOutput = True
- # zj add semi-auto curve
- # machine learning network and weight file
- self.weightFile = 'MSESig505_0419.pth'
- self.networkModel = None
- # -----------------------------------------------------------------------------
- def sliderChange(self, key, value):
- if pref.verbose: print(" [CB] >> ToneCurveController.sliderChange(",key,",",value,")[callBackActive:",self.callBackActive,"] ")
- if self.callBackActive:
- newValues = self.model.setValue(key, value, autoScale = False)
- self.parent.controller.changeToneCurve(newValues)
-
- points = self.model.evaluate()
- self.callBackActive = False
- self.view.sliderShadows.setValue(int(newValues["shadows"][1]))
- self.view.editShadows.setText(str(newValues["shadows"][1]))
- self.view.sliderBlacks.setValue(int(newValues["blacks"][1]))
- self.view.editBlacks.setText(str(newValues["blacks"][1]))
- self.view.sliderMediums.setValue(int(newValues["mediums"][1]))
- self.view.editMediums.setText(str(newValues["mediums"][1]))
- self.view.sliderWhites.setValue(int(newValues["whites"][1]))
- self.view.editWhites.setText(str(newValues["whites"][1]))
- self.view.sliderHighlights.setValue(int(newValues["highlights"][1]))
- self.view.editHighlights.setText(str(newValues["highlights"][1]))
- self.callBackActive = True
- # -----------------------------------------------------------------------------
- def setValues(self, valuesDict,callBackActive = False):
- if pref.verbose: print(" [CONTROL] >> ToneCurveController.setValue(",valuesDict,") ")
- self.callBackActive = callBackActive
- self.model.setValues(valuesDict)
- points = self.model.evaluate()
- self.view.sliderShadows.setValue(int(valuesDict["shadows"][1]))
- self.view.editShadows.setText(str(valuesDict["shadows"][1]))
- self.view.sliderBlacks.setValue(int(valuesDict["blacks"][1]))
- self.view.editBlacks.setText(str(valuesDict["blacks"][1]))
- self.view.sliderMediums.setValue(int(valuesDict["mediums"][1]))
- self.view.editMediums.setText(str(valuesDict["mediums"][1]))
- self.view.sliderWhites.setValue(int(valuesDict["whites"][1]))
- self.view.editWhites.setText(str(valuesDict["whites"][1]))
- self.view.sliderHighlights.setValue(int(valuesDict["highlights"][1]))
- self.view.editHighlights.setText(str(valuesDict["highlights"][1]))
- self.callBackActive = True
- # -----------------------------------------------------------------------------
- # zj add for semi-auto curve begin
- def autoCurve(self):
- processPipe = self.parent.controller.model.getProcessPipe()
- if processPipe != None :
- idExposure = processPipe.getProcessNodeByName("tonecurve")
- bins = np.linspace(0,1,50+1)
- imageBeforeColorData = processPipe.processNodes[idExposure-1].outputImage.colorData
- imageBeforeColorData[imageBeforeColorData>1]=1
- imageBeforeY = colour.sRGB_to_XYZ(imageBeforeColorData, apply_cctf_decoding=False)[:,:,1]
- nphistBefore = np.histogram(imageBeforeY, bins)[0]
- nphistBefore = nphistBefore/np.amax(nphistBefore)
- npImgHistCumuNorm = np.empty_like(nphistBefore)
- npImgHistCumu = np.cumsum(nphistBefore)
- npImgHistCumuNorm = npImgHistCumu/np.max(npImgHistCumu)
-
- #predict keypoint value
- if self.networkModel == None:
- self.networkModel = Net(50,5)
- self.networkModel.load_state_dict(torch.load(self.weightFile))
- self.networkModel.eval()
- with torch.no_grad():
- x = Variable(torch.FloatTensor([npImgHistCumuNorm.tolist(),]), requires_grad=True)
- y_predict = self.networkModel(x)
- kpc = (y_predict[0]*100).tolist()
- kpcDict = {'start':[0.0,0.0], 'shadows': [10.0,kpc[0]], 'blacks': [30.0,kpc[1]], 'mediums': [50.0,kpc[2]], 'whites': [70.0,kpc[3]], 'highlights': [90.0,kpc[4]], 'end': [100.0,100.0]}
- self.setValues(kpcDict,callBackActive = True)
- self.parent.controller.changeToneCurve(kpcDict)
-
- # zj add for semi-auto curve end
- # -----------------------------------------------------------------------------
- def reset(self, key):
- if pref.verbose: print(" [CONTROL] >> ToneCurveController.reset(",key,") ")
- valuesDefault = copy.deepcopy(self.model.default[key])[1]
- controls = self.model.setValue(key, valuesDefault)
- self.setValues(controls,callBackActive = False)
- self.parent.controller.changeToneCurve(controls)
- # -----------------------------------------------------------------------------
- def plotCurve(self):
- try:
- self.view.curve.plot([0,100],[0,100],'r--', clear=True)
- self.view.curve.plot([20,20],[0,100],'r--', clear=False)
- self.view.curve.plot([40,40],[0,100],'r--', clear=False)
- self.view.curve.plot([60,60],[0,100],'r--', clear=False)
- self.view.curve.plot([80,80],[0,100],'r--', clear=False)
- processPipe = self.parent.controller.model.getProcessPipe()
- idExposure = processPipe.getProcessNodeByName("tonecurve")
- bins = np.linspace(0,1,50+1)
- if self.showInput:
- imageInput = copy.deepcopy(processPipe.getInputImage())
- if imageInput.linear: imageInputColorData =colour.cctf_encoding(imageInput.colorData, function='sRGB')
- else: imageInputColorData = imageInput.colorData
- imageInputColorData[imageInputColorData>1]=1
- imageInputY = colour.sRGB_to_XYZ(imageInputColorData, apply_cctf_decoding=False)[:,:,1]
- nphistInput = np.histogram(imageInputY, bins)[0]
- nphistInput = nphistInput/np.amax(nphistInput)
- self.view.curve.plot(bins[:-1]*100,nphistInput*100,'k--', clear=False)
- if self.showbefore:
- imageBeforeColorData = processPipe.processNodes[idExposure-1].outputImage.colorData
- imageBeforeColorData[imageBeforeColorData>1]=1
- imageBeforeY = colour.sRGB_to_XYZ(imageBeforeColorData, apply_cctf_decoding=False)[:,:,1]
- nphistBefore = np.histogram(imageBeforeY, bins)[0]
- nphistBefore = nphistBefore/np.amax(nphistBefore)
- self.view.curve.plot(bins[:-1]*100,nphistBefore*100,'b--', clear=False)
- if self.showAfter:
- imageAftercolorData = processPipe.processNodes[idExposure].outputImage.colorData
- imageAftercolorData[imageAftercolorData>1]=1
- imageAfterY = colour.sRGB_to_XYZ(imageAftercolorData, apply_cctf_decoding=False)[:,:,1]
- nphistAfter = np.histogram(imageAfterY, bins)[0]
- nphistAfter =nphistAfter/np.amax(nphistAfter)
- self.view.curve.plot(bins[:-1]*100,nphistAfter*100,'b', clear=False)
- if self.showOutput:
- imageAftercolorData = processPipe.getImage(toneMap=True).colorData
- imageAftercolorData[imageAftercolorData>1]=1
- imageAfterY = colour.sRGB_to_XYZ(imageAftercolorData, apply_cctf_decoding=False)[:,:,1]
- nphistAfter = np.histogram(imageAfterY, bins)[0]
- nphistAfter =nphistAfter/np.amax(nphistAfter)
- self.view.curve.plot(bins[:-1]*100,nphistAfter*100,'b', clear=False)
- controlPointCoordinates= np.asarray(list(self.model.control.values()))
- self.view.curve.plot(controlPointCoordinates[1:-1,0],controlPointCoordinates[1:-1,1],'ro', clear=False)
- points = np.asarray(self.model.curve.evalpts)
- x = points[:,0]
- self.view.curve.plot(points[x<100,0],points[x<100,1],'r',clear=False)
- except:
- time.sleep(0.5)
- self.plotCurve()
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class LightnessMaskController():
- def __init__(self, parent):
- if pref.verbose: print(" [CONTROL] >> MaskLightnessController.__init__(",")")
- self.parent= parent
- self.model = model.LightnessMaskModel(self)
- self.view = view.LightnessMaskView(self)
- self.callBackActive = True
- # -----------------------------------------------------------------------------
- def maskChange(self,key, on_off):
- if pref.verbose: print(" [CB] >> MaskLightnessController.maskChange(",key,",",on_off,")[callBackActive:",self.callBackActive,"] ")
- maskState = self.model.maskChange(key, on_off)
- self.parent.controller.changeLightnessMask(maskState)
- # -----------------------------------------------------------------------------
- def setValues(self, values,callBackActive = False):
- if pref.verbose: print(" [CONTROL] >> LightnessMaskController.setValue(",values,") ")
- self.callBackActive = callBackActive
- self.model.setValues(values)
- self.view.checkboxShadows.setChecked(values["shadows"])
- self.view.checkboxBlacks.setChecked(values["blacks"])
- self.view.checkboxMediums.setChecked(values["mediums"])
- self.view.checkboxWhites.setChecked(values["whites"])
- self.view.checkboxHighlights.setChecked(values["highlights"])
- self.callBackActive = True
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class HDRviewerController():
- def __init__(self, parent):
- if pref.verbose: print(" [CONTROL] >> HDRviewerController.__init__(",")")
- self.parent= parent
- self.model = model.HDRviewerModel(self)
- self.view = None
- self.viewerProcess = None
- self.displaySplash()
- def setView(self, view): self.view = view
- def callBackUpdate(self):
- selectedProcessPipe = self.parent.view.imageGalleryController.model.getSelectedProcessPipe()
- img = selectedProcessPipe.getImage(toneMap = False)
- self.displayIMG(img)
- self.model.currentIMG = img
- def callBackAuto(self,on_off):
- self.parent.view.dock.view.childControllers[0].model.autoPreviewHDR = on_off
- def callBackCompare(self):
- if self.model.currentIMG:
- old = self.model.currentIMG
- old = old.process(hdrCore.processing.clip())
- sp = self.parent.view.imageGalleryController.model.getSelectedProcessPipe()
- img = sp.getImage(toneMap = False)
- img = img.process(hdrCore.processing.clip())
- h1, w1, _ = old.colorData.shape
- h2, w2, _ = img.colorData.shape
- hD, wD = self.model.displayModel['shape']
- hM = int((hD - max(h1,h2))/2)
- wM = int((wD - (w1+w2))/3)
- back = np.ones((hD,wD,3))*0.2
- back[hM:hM+h1,wM:wM+w1,:] = old.colorData*self.model.displayModel['scaling']
- back[hM:hM+h2,2*wM+w1:2*wM+w1+w2,:] = img.colorData*self.model.displayModel['scaling']
- # save as temp.hdr
- colour.write_image(back,'temp.hdr', method='Imageio')
- self.displayFile('temp.hdr')
- self.model.currentIMG = img
- else: self.callBackUpdate()
- def displayFile(self, HDRfilename):
- """
- HDRviewerController display file: run HDRImageViewer process ti display HDR image (from filename)
- Args:
- HDRfilename: string
- Required : hdr image filename
-
- """
- # check that no current display process already open
- if self.viewerProcess:
- # the display HDR process is already running
- # close current
- subprocess.run(['taskkill', '/F', '/T', '/IM', "HDRImageViewer*"],capture_output=False)
- time.sleep(0.05)
- # run display HDR process
- self.viewerProcess = subprocess.Popen(["HDRImageViewer.exe","-f", "-input:"+HDRfilename, "-f", "-h"], shell=True)
- time.sleep(0.10)
- psData = subprocess.run(['tasklist'], capture_output=True, universal_newlines=True).stdout
- if not 'HDRImageViewer' in psData:
- # re-run display HDR process
- self.viewerProcess = subprocess.Popen(["HDRImageViewer.exe","-f", "-input:"+HDRfilename, "-f", "-h"], shell=True)
- def displayIMG(self, img):
- img = img.process(hdrCore.processing.clip())
- colorData = img.colorData*self.model.displayModel['scaling']
- h,w, _ = colorData.shape
- hD, wD = self.model.displayModel['shape']
- if w<wD:
- back = np.ones((hD,wD,3))*0.2
- marginW = int((wD-w)/2)
- marginH = int((hD-h)/2)
- back[marginH:marginH+h,marginW:marginW+w,:]=colorData
- # save as temp.hdr
- colour.write_image(back,'temp.hdr', method='Imageio')
- self.displayFile('temp.hdr')
- def displaySplash(self):
- self.model.currentIMG = None
- self.displayFile('grey.hdr')
- def close(self):
- # check that no current display process already open
- if self.viewerProcess:
- # the display HDR process is already running
- # close current
- subprocess.run(['taskkill', '/F', '/T', '/IM', "HDRImageViewer*"],capture_output=False)
- self.viewerProcess = None
- # ------------------------------------------------------------------------------------------
- # ---- Class LchColorSelectorController ----------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class LchColorSelectorController:
- def __init__(self, parent, idName = None):
- if pref.verbose: print(" [CONTROL] >> LchColorSelectorController.__init__(",") ")
- self.parent = parent
- self.model = model.LchColorSelectorModel(self)
- self.view = view.LchColorSelectorView(self)
- self.idName = idName
- self.callBackActive = True
- def sliderHueChange(self, vMin, vMax):
- values = self.model.setHueSelection(vMin,vMax)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def sliderChromaChange(self, vMin, vMax):
- values = self.model.setChromaSelection(vMin,vMax)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def sliderLightnessChange(self, vMin, vMax):
- values = self.model.setLightnessSelection(vMin,vMax)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def sliderExposureChange(self, ev):
- values = self.model.setExposure(ev)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def sliderSaturationChange(self, sat):
- values = self.model.setSaturation(sat)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def sliderContrastChange(self, cc):
- values = self.model.setContrast(cc)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def sliderHueShiftChange(self, hs):
- values = self.model.setHueShift(hs)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def checkboxMaskChange(self,value):
- values = self.model.setMask(value)
- if self.callBackActive : self.parent.controller.changeColorEditor(values, self.idName)
- def setValues(self, values, callBackActive = False):
- if pref.verbose: print(" [CONTROL] >> LchColorSelectorController.setValue(",values,") ")
- self.callBackActive = callBackActive
- # slider hue selection
- v = values['selection']['hue'] if 'hue' in values['selection'].keys() else (0,360)
- self.view.sliderHueMin.setValue(int(v[0]))
- self.view.sliderHueMax.setValue(int(v[1]))
- # slider chroma selection
- v = values['selection']['chroma'] if 'chroma' in values['selection'].keys() else (0,100)
- self.view.sliderChromaMin.setValue(v[0])
- self.view.sliderChromaMax.setValue(v[1])
- # slider lightness
- v = values['selection']['lightness'] if 'lightness' in values['selection'].keys() else (0,100)
- self.view.sliderLightMin.setValue(int(v[0]*3))
- self.view.sliderLightMax.setValue(int(v[1]*3))
- # hue shift editor
- v = values['edit']['hue'] if 'hue' in values['edit'].keys() else 0
- self.view.sliderHueShift.setValue(int(v))
- self.view.valueHueShift.setText(str(v))
- # exposure editor
- v : int = values['edit']['exposure'] if 'exposure' in values['edit'].keys() else 0
- self.view.sliderExposure.setValue(int(v*30))
- self.view.valueExposure.setText(str(v))
- # contrast editor
- v : int = values['edit']['contrast'] if 'contrast' in values['edit'].keys() else 0
- self.view.sliderContrast.setValue(int(v))
- self.view.valueContrast.setText(str(v))
- # saturation editor
- v : int = values['edit']['saturation'] if 'saturation' in values['edit'].keys() else 0
- self.view.sliderSaturation.setValue(int(v))
- self.view.valueSaturation.setText(str(v))
- # mask
- v : bool = values['mask'] if 'mask' in values.keys() else False
- self.view.checkboxMask.setChecked(values['mask'])
- self.model.setValues(values)
- self.callBackActive = True
- # -----
- def resetSelection(self):
- if pref.verbose: print(" [CONTROL] >> LchColorSelectorController.resetSelection(",") ")
- default = copy.deepcopy(self.model.default)
- current = copy.deepcopy(self.model.getValues())
-
- current['selection'] = default['selection']
- self.setValues(current,callBackActive = True)
- self.callBackActive = True
- def resetEdit(self):
- if pref.verbose: print(" [CONTROL] >> LchColorSelectorController.resetEdit(",") ")
- default = copy.deepcopy(self.model.default)
- current = copy.deepcopy(self.model.getValues())
-
- current['edit'] = default['edit']
- self.setValues(current,callBackActive = True)
- self.callBackActive = True
- # ------------------------------------------------------------------------------------------
- # ---- Class LchColorSelectorController ----------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class GeometryController:
- def __init__(self, parent ):
- if pref.verbose: print(" [CONTROL] >> GeometryController.__init__(",") ")
- self.parent = parent
- self.model = model.GeometryModel(self)
- self.view = view.GeometryView(self)
- self.callBackActive = True
- # callbacks
- def sliderCroppingVerticalAdjustementChange(self,v):
- values = self.model.setCroppingVerticalAdjustement(v)
- if self.callBackActive : self.parent.controller.changeGeometry(values)
- def sliderRotationChange(self,v):
- values = self.model.setRotation(v)
- if self.callBackActive : self.parent.controller.changeGeometry(values)
- def setValues(self, values, callBackActive = False):
- if pref.verbose: print(" [CONTROL] >> GeometryController.setValue(",values,") ")
- up = values['up'] if 'up' in values.keys() else 0.0
- rotation = values['rotation'] if 'rotation' in values.keys() else 0.0
- self.callBackActive = callBackActive
- self.view.sliderCroppingVerticalAdjustement.setValue(int(up))
- self.view.sliderRotation.setValue(int(rotation*6))
-
- self.model.setValues(values)
- self.callBackActive = True
- # ------------------------------------------------------------------------------------------
- # ---- Class AestheticsImageController -----------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class ImageAestheticsController:
- def __init__(self, parent=None, HDRcontroller = None):
- if pref.verbose: print(" [CONTROL] >> AestheticsImageController.__init__(",")")
- self.parent = parent
- self.model = model.ImageAestheticsModel(self)
- self.view = view.ImageAestheticsView(self)
- # --------------------------------------------------------------------------------------
- def buildView(self,processPipe=None):
- if pref.verbose: print(" [CONTROL] >> AestheticsImageController.buildView()")
- # called when MultiDockController recall a controller/view
- self.view = view.ImageAestheticsView(self)
- if processPipe: self.setProcessPipe(processPipe)
- # --------------------------------------------------------------------------------------
- def setProcessPipe(self, processPipe):
- if pref.verbose: print(" [CONTROL] >> AestheticsImageController.setProcessPipe()")
- self.model.setProcessPipe(processPipe)
- self.view.setProcessPipe(processPipe, self.model.getPaletteImage())
- return True
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # --- message widget functions -------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- # ------------------------------------------------------------------------------------------
- def messageBox(title, text):
- msg = QMessageBox()
- msg.setText(text)
- msg.setStandardButtons(QMessageBox.Ok)
- msg.setWindowTitle(title)
- msg.setStandardButtons(QMessageBox.Ok)
- msg.setEscapeButton(QMessageBox.Close)
- msg.exec_()
- # -----------------------------------------------------------------------------
- def okCancelBox(title, text):
- msg = QMessageBox()
- msg.setText(text)
- msg.setWindowTitle(title)
- msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
- msg.setEscapeButton(QMessageBox.Close)
- return msg.exec_()
- # ------------------------------------------------------------------------------------------
- # ---- Class ColorEditorsAutoController ----------------------------------------------------
- # ------------------------------------------------------------------------------------------
- class ColorEditorsAutoController:
- def __init__(self, parent, controlledColorEditors, stepName ):
- if pref.verbose: print(" [CONTROL] >> ColorEditorsAutoController.__init__(",") ")
- self.parent = parent
- self.controlled = controlledColorEditors
- self.stepName =stepName
- self.model = model.ColorEditorsAutoModel(self, stepName,len(controlledColorEditors), removeBlack= True)
- self.view = view.ColorEditorsAutoView(self)
- self.callBackActive = True
- # callbacks
- def auto(self):
- if pref.verbose: print(" [CONTROL] >> ColorEditorsAutoController.auto(",") ")
- for ce in self.controlled: ce.resetSelection(); ce.resetEdit()
- values = self.model.compute()
- if values != None:
- for i,v in enumerate(values): self.controlled[i].setValues(v, callBackActive = False)
|