def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) self.setMinimumSize(axeSize, axeSize + 100) # contrast spline viewer self.contrastForm = None # options optionList1, optionNames1 = ['Multi-Mode', 'CLAHE'], ['Multi-Mode', 'CLAHE'] self.listWidget1 = optionsWidget( options=optionList1, optionNames=optionNames1, exclusive=True, changed=lambda: self.dataChanged.emit()) self.listWidget1.checkOption(self.listWidget1.intNames[0]) self.listWidget1.setStyleSheet( "QListWidget {border: 0px;} QListWidget::item {border: 0px; padding-left: 0px;}" ) optionList2, optionNames2 = ['High', 'manualCurve'], [ 'Preserve Highlights', 'Show Contrast Curve' ] def optionList2Change(item): if item.internalName == 'High': # force to recalculate the spline self.layer.autoSpline = True self.dataChanged.emit() self.listWidget2 = optionsWidget(options=optionList2, optionNames=optionNames2, exclusive=False, changed=optionList2Change) self.listWidget2.checkOption(self.listWidget2.intNames[0]) self.listWidget2.setStyleSheet( "QListWidget {border: 0px;} QListWidget::item {border: 0px; padding-left: 0px;}" ) self.options = UDict( (self.listWidget1.options, self.listWidget2.options)) # contrast slider self.sliderContrast = QbLUeSlider(Qt.Horizontal) self.sliderContrast.setStyleSheet( QbLUeSlider.bLueSliderDefaultIBWStylesheet) self.sliderContrast.setRange(0, 10) self.sliderContrast.setSingleStep(1) contrastLabel = QbLUeLabel() contrastLabel.setMaximumSize(150, 30) contrastLabel.setText("Contrast Level") contrastLabel.doubleClicked.connect( lambda: self.sliderContrast.setValue( self.contrast2Slider(self.contrastDefault))) self.contrastValue = QLabel() font = self.contrastValue.font() metrics = QFontMetrics(font) w = metrics.width("100") h = metrics.height() self.contrastValue.setMinimumSize(w, h) self.contrastValue.setMaximumSize(w, h) self.contrastValue.setText( str("{:d}".format(self.sliderContrast.value()))) # contrast changed event handler. def contrastUpdate(value): self.contrastValue.setText( str("{:d}".format(self.sliderContrast.value()))) # move not yet terminated or value not modified if self.sliderContrast.isSliderDown() or self.slider2Contrast( value) == self.contrastCorrection: return self.sliderContrast.valueChanged.disconnect() self.sliderContrast.sliderReleased.disconnect() self.contrastCorrection = self.slider2Contrast( self.sliderContrast.value()) # force to recalculate the spline self.layer.autoSpline = True self.dataChanged.emit() self.sliderContrast.valueChanged.connect(contrastUpdate) self.sliderContrast.sliderReleased.connect( lambda: contrastUpdate(self.sliderContrast.value())) self.sliderContrast.valueChanged.connect(contrastUpdate) self.sliderContrast.sliderReleased.connect( lambda: contrastUpdate(self.sliderContrast.value())) # saturation slider self.sliderSaturation = QbLUeSlider(Qt.Horizontal) self.sliderSaturation.setStyleSheet( QbLUeSlider.bLueSliderDefaultColorStylesheet) self.sliderSaturation.setRange(0, 100) self.sliderSaturation.setSingleStep(1) saturationLabel = QbLUeLabel() saturationLabel.setMaximumSize(150, 30) saturationLabel.setText("Saturation") saturationLabel.doubleClicked.connect( lambda: self.sliderSaturation.setValue( self.saturation2Slider(self.saturationDefault))) self.saturationValue = QLabel() font = self.saturationValue.font() metrics = QFontMetrics(font) w = metrics.width("100") h = metrics.height() self.saturationValue.setMinimumSize(w, h) self.saturationValue.setMaximumSize(w, h) self.saturationValue.setText( str("{:+d}".format(self.sliderContrast.value()))) # saturation changed event handler def saturationUpdate(value): self.saturationValue.setText( str("{:+d}".format( int( self.slidersaturation2User( self.sliderSaturation.value()))))) # move not yet terminated or value not modified if self.sliderSaturation.isSliderDown() or self.slider2Saturation( value) == self.satCorrection: return self.sliderSaturation.valueChanged.disconnect() self.sliderSaturation.sliderReleased.disconnect() self.satCorrection = self.slider2Saturation( self.sliderSaturation.value()) self.dataChanged.emit() self.sliderSaturation.valueChanged.connect(saturationUpdate) self.sliderSaturation.sliderReleased.connect( lambda: saturationUpdate(self.sliderSaturation.value())) self.sliderSaturation.valueChanged.connect(saturationUpdate) self.sliderSaturation.sliderReleased.connect( lambda: saturationUpdate(self.sliderSaturation.value())) # brightness slider self.sliderBrightness = QbLUeSlider(Qt.Horizontal) self.sliderBrightness.setStyleSheet( QbLUeSlider.bLueSliderDefaultBWStylesheet) self.sliderBrightness.setRange(0, 100) self.sliderBrightness.setSingleStep(1) brightnessLabel = QbLUeLabel() brightnessLabel.setMaximumSize(150, 30) brightnessLabel.setText("Brightness") brightnessLabel.doubleClicked.connect( lambda: self.sliderBrightness.setValue( self.brightness2Slider(self.brightnessDefault))) self.brightnessValue = QLabel() font = self.brightnessValue.font() metrics = QFontMetrics(font) w = metrics.width("100") h = metrics.height() self.brightnessValue.setMinimumSize(w, h) self.brightnessValue.setMaximumSize(w, h) self.brightnessValue.setText( str("{:+d}".format(self.sliderContrast.value()))) # brightness changed event handler def brightnessUpdate(value): self.brightnessValue.setText( str("{:+d}".format( int( self.sliderBrightness2User( self.sliderBrightness.value()))))) # move not yet terminated or value not modified if self.sliderBrightness.isSliderDown() or self.slider2Brightness( value) == self.brightnessCorrection: return self.sliderBrightness.valueChanged.disconnect() self.sliderBrightness.sliderReleased.disconnect() self.brightnessCorrection = self.slider2Brightness( self.sliderBrightness.value()) self.dataChanged.emit() self.sliderBrightness.valueChanged.connect(brightnessUpdate) self.sliderBrightness.sliderReleased.connect( lambda: brightnessUpdate(self.sliderBrightness.value())) self.sliderBrightness.valueChanged.connect(brightnessUpdate) self.sliderBrightness.sliderReleased.connect( lambda: brightnessUpdate(self.sliderBrightness.value())) # attributes initialized in setDefaults, declared here # for the sake of correctness self.contrastCorrection = None # range self.satCorrection = None # range -0.5..0.5 self.brightnessCorrection = None # range -0.5..0.5 # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) gb1 = QGroupBox() gb1.setStyleSheet( "QGroupBox {border: 1px solid gray; border-radius: 4px}") l1 = QVBoxLayout() ct = QLabel() ct.setText('Contrast') l.setAlignment(Qt.AlignTop) l1.addWidget(ct) l1.addWidget(self.listWidget1) gb1.setLayout(l1) l.addWidget(gb1) l.addWidget(self.listWidget2) l.addWidget(contrastLabel) hl = QHBoxLayout() hl.addWidget(self.contrastValue) hl.addWidget(self.sliderContrast) l.addLayout(hl) l.addWidget(brightnessLabel) hl3 = QHBoxLayout() hl3.addWidget(self.brightnessValue) hl3.addWidget(self.sliderBrightness) l.addLayout(hl3) l.addWidget(saturationLabel) hl2 = QHBoxLayout() hl2.addWidget(self.saturationValue) hl2.addWidget(self.sliderSaturation) l.addLayout(hl2) self.setLayout(l) self.adjustSize() self.setStyleSheet("QListWidget, QLabel {font : 7pt;}") self.setDefaults() self.setWhatsThis("""<b>Contrast Brightness Saturation</b><br> <b>Contrast</b> is enhanced using one of these two methods:<br> - <b>CLAHE</b> : increases the local contrast.<br> - <b>Multi-Mode</b> : increases the local contrast and the contrast between regions of the image.<br> For both methods the contrast slider controls the level of the correction.<br> With Multi-Mode enabled, use the option <b>Show Contrast Curve</b> to edit the correction curve and check <b>Preserve Highlights</b> for softer highlights.<br> <b>Brightness</b> and <b>Saturation</b> corrections are non linear to limit clipping.<br> Sliders are <b>reset</b> to their default value by double clicking the name of the slider.<br> """) # end setWhatsThis
class ExpForm(baseForm): defaultExpCorrection = 0.0 defaultStep = 0.1 @classmethod def getNewWindow(cls, targetImage=None, axeSize=500, layer=None, parent=None): wdgt = ExpForm(targetImage=targetImage, axeSize=axeSize, layer=layer, parent=parent) wdgt.setWindowTitle(layer.name) return wdgt def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) # options self.options = None # exposure slider self.sliderExp = QbLUeSlider(Qt.Horizontal) self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet) self.sliderExp.setRange(-20, 20) self.sliderExp.setSingleStep(1) expLabel = QbLUeLabel() expLabel.setMaximumSize(150, 30) expLabel.setText("Exposure Correction") expLabel.doubleClicked.connect( lambda: self.sliderExp.setValue(self.defaultExpCorrection)) self.expValue = QbLUeLabel() font = self.expValue.font() metrics = QFontMetrics(font) w = metrics.width("1000 ") h = metrics.height() self.expValue.setMinimumSize(w, h) self.expValue.setMaximumSize(w, h) # exp change/released slot def f(): self.expValue.setText( str("{:+.1f}".format(self.sliderExp.value() * self.defaultStep))) if self.sliderExp.isSliderDown() or (self.expCorrection == self.sliderExp.value() * self.defaultStep): return try: self.sliderExp.valueChanged.disconnect() self.sliderExp.sliderReleased.disconnect() except RuntimeError: pass self.expCorrection = self.sliderExp.value() * self.defaultStep self.dataChanged.emit() self.sliderExp.valueChanged.connect(f) self.sliderExp.sliderReleased.connect(f) self.sliderExp.valueChanged.connect(f) self.sliderExp.sliderReleased.connect(f) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(expLabel) hl = QHBoxLayout() hl.addWidget(self.expValue) hl.addWidget(self.sliderExp) l.addLayout(hl) l.setContentsMargins(20, 0, 20, 25) # left, top, right, bottom self.setLayout(l) self.adjustSize() self.setWhatsThis("""<b>Exposure Correction</b> Multiplicative correction in the linear sRGB color space.<br> Unit is the diaphragm stop.<br> """) # end setWhatsThis self.setDefaults() def updateLayer(self): self.layer.applyToStack() self.layer.parentImage.onImageChanged() def setDefaults(self): try: self.dataChanged.disconnect() except RuntimeError: pass self.sliderExp.setValue(self.defaultExpCorrection) self.expValue.setText(str("{:+.1f}".format(self.defaultExpCorrection))) self.expCorrection = self.defaultExpCorrection * self.defaultStep self.dataChanged.connect(self.updateLayer) def writeToStream(self, outStream): layer = self.layer outStream.writeQString(layer.actionName) outStream.writeQString(layer.name) outStream.writeQString(self.listWidget1.selectedItems()[0].text()) outStream.writeInt32(self.sliderExp.value()) return outStream def readFromStream(self, inStream): actionName = inStream.readQString() name = inStream.readQString() sel = inStream.readQString() temp = inStream.readInt32() for r in range(self.listWidget1.count()): currentItem = self.listWidget1.item(r) if currentItem.text() == sel: self.listWidget.select(currentItem) self.sliderExp.setValue(temp) self.update() return inStream
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) # options self.options = None # exposure slider self.sliderExp = QbLUeSlider(Qt.Horizontal) self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet) self.sliderExp.setRange(-20, 20) self.sliderExp.setSingleStep(1) expLabel = QbLUeLabel() expLabel.setMaximumSize(150, 30) expLabel.setText("Exposure Correction") expLabel.doubleClicked.connect( lambda: self.sliderExp.setValue(self.defaultExpCorrection)) self.expValue = QbLUeLabel() font = self.expValue.font() metrics = QFontMetrics(font) w = metrics.width("1000 ") h = metrics.height() self.expValue.setMinimumSize(w, h) self.expValue.setMaximumSize(w, h) # exp change/released slot def f(): self.expValue.setText( str("{:+.1f}".format(self.sliderExp.value() * self.defaultStep))) if self.sliderExp.isSliderDown() or (self.expCorrection == self.sliderExp.value() * self.defaultStep): return try: self.sliderExp.valueChanged.disconnect() self.sliderExp.sliderReleased.disconnect() except RuntimeError: pass self.expCorrection = self.sliderExp.value() * self.defaultStep self.dataChanged.emit() self.sliderExp.valueChanged.connect(f) self.sliderExp.sliderReleased.connect(f) self.sliderExp.valueChanged.connect(f) self.sliderExp.sliderReleased.connect(f) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(expLabel) hl = QHBoxLayout() hl.addWidget(self.expValue) hl.addWidget(self.sliderExp) l.addLayout(hl) l.setContentsMargins(20, 0, 20, 25) # left, top, right, bottom self.setLayout(l) self.adjustSize() self.setWhatsThis("""<b>Exposure Correction</b> Multiplicative correction in the linear sRGB color space.<br> Unit is the diaphragm stop.<br> """) # end setWhatsThis self.setDefaults()
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None): super().__init__(parent=parent) #self.targetImage = targetImage self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.setMinimumSize(axeSize, axeSize) self.setAttribute(Qt.WA_DeleteOnClose) # link back to image layer # using weak ref for back links if type(layer) in weakref.ProxyTypes: self.layer = layer else: self.layer = weakref.proxy(layer) # options self.options = None # exposure slider self.sliderExp = QbLUeSlider(Qt.Horizontal) self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet) self.sliderExp.setTickPosition(QSlider.TicksBelow) self.sliderExp.setRange(-20, 20) self.sliderExp.setSingleStep(1) expLabel = QbLUeLabel() expLabel.setMaximumSize(150, 30) expLabel.setText("Exposure Correction") expLabel.doubleClicked.connect( lambda: self.sliderExp.setValue(self.defaultExpCorrection)) self.expValue = QbLUeLabel() font = self.expValue.font() metrics = QFontMetrics(font) w = metrics.width("1000 ") h = metrics.height() self.expValue.setMinimumSize(w, h) self.expValue.setMaximumSize(w, h) # exp done event handler def f(): self.sliderExp.setEnabled(False) self.expValue.setText( str("{:+.1f}".format(self.sliderExp.value() * self.DefaultStep))) self.onUpdateExposure(self.layer, self.sliderExp.value() * self.DefaultStep) self.sliderExp.setEnabled(True) # exp value changed slot def g(): self.expValue.setText( str("{:+.1f}".format(self.sliderExp.value() * self.DefaultStep))) self.sliderExp.valueChanged.connect(g) self.sliderExp.sliderReleased.connect(f) self.sliderExp.setValue(self.defaultExpCorrection / self.DefaultStep) self.expValue.setText(str("{:+.1f}".format(self.defaultExpCorrection))) #layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(expLabel) hl = QHBoxLayout() hl.addWidget(self.expValue) hl.addWidget(self.sliderExp) l.addLayout(hl) l.setContentsMargins(20, 0, 20, 25) # left, top, right, bottom #l.addStretch(1) self.setLayout(l) self.adjustSize() self.setWhatsThis("""<b>Exposure Correction</b> Multiplicative correction in the linear sRGB color space.<br> """) # end setWhatsThis
class ExpForm(baseForm): defaultExpCorrection = 0.0 DefaultStep = 0.1 @classmethod def getNewWindow(cls, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None): wdgt = ExpForm(axeSize=axeSize, layer=layer, parent=parent, mainForm=mainForm) wdgt.setWindowTitle(layer.name) return wdgt def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None): super().__init__(parent=parent) #self.targetImage = targetImage self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.setMinimumSize(axeSize, axeSize) self.setAttribute(Qt.WA_DeleteOnClose) # link back to image layer # using weak ref for back links if type(layer) in weakref.ProxyTypes: self.layer = layer else: self.layer = weakref.proxy(layer) # options self.options = None # exposure slider self.sliderExp = QbLUeSlider(Qt.Horizontal) self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet) self.sliderExp.setTickPosition(QSlider.TicksBelow) self.sliderExp.setRange(-20, 20) self.sliderExp.setSingleStep(1) expLabel = QbLUeLabel() expLabel.setMaximumSize(150, 30) expLabel.setText("Exposure Correction") expLabel.doubleClicked.connect( lambda: self.sliderExp.setValue(self.defaultExpCorrection)) self.expValue = QbLUeLabel() font = self.expValue.font() metrics = QFontMetrics(font) w = metrics.width("1000 ") h = metrics.height() self.expValue.setMinimumSize(w, h) self.expValue.setMaximumSize(w, h) # exp done event handler def f(): self.sliderExp.setEnabled(False) self.expValue.setText( str("{:+.1f}".format(self.sliderExp.value() * self.DefaultStep))) self.onUpdateExposure(self.layer, self.sliderExp.value() * self.DefaultStep) self.sliderExp.setEnabled(True) # exp value changed slot def g(): self.expValue.setText( str("{:+.1f}".format(self.sliderExp.value() * self.DefaultStep))) self.sliderExp.valueChanged.connect(g) self.sliderExp.sliderReleased.connect(f) self.sliderExp.setValue(self.defaultExpCorrection / self.DefaultStep) self.expValue.setText(str("{:+.1f}".format(self.defaultExpCorrection))) #layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(expLabel) hl = QHBoxLayout() hl.addWidget(self.expValue) hl.addWidget(self.sliderExp) l.addLayout(hl) l.setContentsMargins(20, 0, 20, 25) # left, top, right, bottom #l.addStretch(1) self.setLayout(l) self.adjustSize() self.setWhatsThis("""<b>Exposure Correction</b> Multiplicative correction in the linear sRGB color space.<br> """) # end setWhatsThis def writeToStream(self, outStream): layer = self.layer outStream.writeQString(layer.actionName) outStream.writeQString(layer.name) outStream.writeQString(self.listWidget1.selectedItems()[0].text()) outStream.writeInt32(self.sliderExp.value()) return outStream def readFromStream(self, inStream): actionName = inStream.readQString() name = inStream.readQString() sel = inStream.readQString() temp = inStream.readInt32() for r in range(self.listWidget1.count()): currentItem = self.listWidget1.item(r) if currentItem.text() == sel: self.listWidget.select(currentItem) self.sliderExp.setValue(temp) self.update() return inStream
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) self.tempCorrection = 6500 self.tintCorrection = 1.0 self.defaultTemp = sRGBWP # ref temperature D65 self.defaultTint = 0 # options optionList, optionNames = ['Photo Filter', 'Chromatic Adaptation' ], ['Photo Filter', 'Chromatic Adaptation'] self.listWidget1 = optionsWidget( options=optionList, optionNames=optionNames, exclusive=True, changed=lambda: self.dataChanged.emit()) self.listWidget1.checkOption(self.listWidget1.intNames[1]) self.options = self.listWidget1.options # temp slider self.sliderTemp = QbLUeSlider(Qt.Horizontal) self.sliderTemp.setStyleSheet( QbLUeSlider.bLueSliderDefaultIColorStylesheet) self.sliderTemp.setRange( 17, 100 ) # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP self.sliderTemp.setSingleStep(1) tempLabel = QbLUeLabel() tempLabel.setMaximumSize(150, 30) tempLabel.setText("Filter Temperature") tempLabel.doubleClicked.connect(lambda: self.sliderTemp.setValue( self.temp2Slider(self.defaultTemp))) self.tempValue = QLabel() font = self.tempValue.font() metrics = QFontMetrics(font) w = metrics.width("00000") h = metrics.height() self.tempValue.setMinimumSize(w, h) self.tempValue.setMaximumSize(w, h) self.tempValue.setText( str("{:d}".format(self.sliderTemp2User(self.sliderTemp.value())))) # tint slider self.sliderTint = QbLUeSlider(Qt.Horizontal) self.sliderTint.setStyleSheet( QbLUeSlider.bLueSliderDefaultMGColorStylesheet) self.sliderTint.setRange( 0, 100 ) # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP self.sliderTint.setSingleStep(1) self.tintLabel = QbLUeLabel() self.tintLabel.setMaximumSize(150, 30) self.tintLabel.setText("Tint") self.tintLabel.doubleClicked.connect(lambda: self.sliderTint.setValue( self.tint2Slider(self.defaultTint))) self.tintValue = QLabel() font = self.tintValue.font() metrics = QFontMetrics(font) w = metrics.width("0000") h = metrics.height() self.tintValue.setMinimumSize(w, h) self.tintValue.setMaximumSize(w, h) self.tintValue.setText( str("{:d}".format(self.sliderTint2User(self.sliderTint.value())))) # temp change slot def tempUpdate(value): self.tempValue.setText( str("{:d}".format(self.sliderTemp2User(value)))) # move not yet terminated or values not modified if self.sliderTemp.isSliderDown() or self.slider2Temp( value) == self.tempCorrection: return try: self.sliderTemp.valueChanged.disconnect() self.sliderTemp.sliderReleased.disconnect() except RuntimeError: pass self.tempCorrection = self.slider2Temp(value) self.dataChanged.emit() self.sliderTemp.valueChanged.connect(tempUpdate) self.sliderTemp.sliderReleased.connect( lambda: tempUpdate(self.sliderTemp.value())) # tint change slot def tintUpdate(value): self.tintValue.setText( str("{:d}".format(self.sliderTint2User(value)))) # move not yet terminated or values not modified if self.sliderTint.isSliderDown() or self.slider2Tint( value) == self.tintCorrection: return try: self.sliderTint.valueChanged.disconnect() self.sliderTint.sliderReleased.disconnect() except RuntimeError: pass self.tintCorrection = self.slider2Tint(value) self.dataChanged.emit() self.sliderTint.valueChanged.connect(tintUpdate) self.sliderTint.sliderReleased.connect( lambda: tintUpdate(self.sliderTint.value())) self.sliderTemp.valueChanged.connect(tempUpdate) self.sliderTemp.sliderReleased.connect( lambda: tempUpdate(self.sliderTemp.value())) self.sliderTint.valueChanged.connect(tintUpdate) self.sliderTint.sliderReleased.connect( lambda: tintUpdate(self.sliderTint.value())) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(self.listWidget1) l.addWidget(tempLabel) hl = QHBoxLayout() hl.addWidget(self.tempValue) hl.addWidget(self.sliderTemp) l.addLayout(hl) l.addWidget(self.tintLabel) hl1 = QHBoxLayout() hl1.addWidget(self.tintValue) hl1.addWidget(self.sliderTint) l.addLayout(hl1) self.setLayout(l) self.adjustSize() self.setDefaults() self.setWhatsThis("""<b>Color Temperature</b><br> <b>Photo Filter</b> uses the multiply blending mode to mimic a warming or cooling filter put in front of the camera lens. The luminosity of the resulting image is corrected.<br> <b>Chromatic Adaptation</b> uses multipliers in the linear sRGB color space to adjust <b>temperature</b> and <b>tint</b>. """) # end of setWhatsThis
class temperatureForm(baseForm): @classmethod def getNewWindow(cls, targetImage=None, axeSize=500, layer=None, parent=None): wdgt = temperatureForm(axeSize=axeSize, layer=layer, parent=parent) wdgt.setWindowTitle(layer.name) return wdgt def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) self.tempCorrection = 6500 self.tintCorrection = 1.0 self.defaultTemp = sRGBWP # ref temperature D65 self.defaultTint = 0 # options optionList, optionNames = ['Photo Filter', 'Chromatic Adaptation' ], ['Photo Filter', 'Chromatic Adaptation'] self.listWidget1 = optionsWidget( options=optionList, optionNames=optionNames, exclusive=True, changed=lambda: self.dataChanged.emit()) self.listWidget1.checkOption(self.listWidget1.intNames[1]) self.options = self.listWidget1.options # temp slider self.sliderTemp = QbLUeSlider(Qt.Horizontal) self.sliderTemp.setStyleSheet( QbLUeSlider.bLueSliderDefaultIColorStylesheet) self.sliderTemp.setRange( 17, 100 ) # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP self.sliderTemp.setSingleStep(1) tempLabel = QbLUeLabel() tempLabel.setMaximumSize(150, 30) tempLabel.setText("Filter Temperature") tempLabel.doubleClicked.connect(lambda: self.sliderTemp.setValue( self.temp2Slider(self.defaultTemp))) self.tempValue = QLabel() font = self.tempValue.font() metrics = QFontMetrics(font) w = metrics.width("00000") h = metrics.height() self.tempValue.setMinimumSize(w, h) self.tempValue.setMaximumSize(w, h) self.tempValue.setText( str("{:d}".format(self.sliderTemp2User(self.sliderTemp.value())))) # tint slider self.sliderTint = QbLUeSlider(Qt.Horizontal) self.sliderTint.setStyleSheet( QbLUeSlider.bLueSliderDefaultMGColorStylesheet) self.sliderTint.setRange( 0, 100 ) # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP self.sliderTint.setSingleStep(1) self.tintLabel = QbLUeLabel() self.tintLabel.setMaximumSize(150, 30) self.tintLabel.setText("Tint") self.tintLabel.doubleClicked.connect(lambda: self.sliderTint.setValue( self.tint2Slider(self.defaultTint))) self.tintValue = QLabel() font = self.tintValue.font() metrics = QFontMetrics(font) w = metrics.width("0000") h = metrics.height() self.tintValue.setMinimumSize(w, h) self.tintValue.setMaximumSize(w, h) self.tintValue.setText( str("{:d}".format(self.sliderTint2User(self.sliderTint.value())))) # temp change slot def tempUpdate(value): self.tempValue.setText( str("{:d}".format(self.sliderTemp2User(value)))) # move not yet terminated or values not modified if self.sliderTemp.isSliderDown() or self.slider2Temp( value) == self.tempCorrection: return try: self.sliderTemp.valueChanged.disconnect() self.sliderTemp.sliderReleased.disconnect() except RuntimeError: pass self.tempCorrection = self.slider2Temp(value) self.dataChanged.emit() self.sliderTemp.valueChanged.connect(tempUpdate) self.sliderTemp.sliderReleased.connect( lambda: tempUpdate(self.sliderTemp.value())) # tint change slot def tintUpdate(value): self.tintValue.setText( str("{:d}".format(self.sliderTint2User(value)))) # move not yet terminated or values not modified if self.sliderTint.isSliderDown() or self.slider2Tint( value) == self.tintCorrection: return try: self.sliderTint.valueChanged.disconnect() self.sliderTint.sliderReleased.disconnect() except RuntimeError: pass self.tintCorrection = self.slider2Tint(value) self.dataChanged.emit() self.sliderTint.valueChanged.connect(tintUpdate) self.sliderTint.sliderReleased.connect( lambda: tintUpdate(self.sliderTint.value())) self.sliderTemp.valueChanged.connect(tempUpdate) self.sliderTemp.sliderReleased.connect( lambda: tempUpdate(self.sliderTemp.value())) self.sliderTint.valueChanged.connect(tintUpdate) self.sliderTint.sliderReleased.connect( lambda: tintUpdate(self.sliderTint.value())) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(self.listWidget1) l.addWidget(tempLabel) hl = QHBoxLayout() hl.addWidget(self.tempValue) hl.addWidget(self.sliderTemp) l.addLayout(hl) l.addWidget(self.tintLabel) hl1 = QHBoxLayout() hl1.addWidget(self.tintValue) hl1.addWidget(self.sliderTint) l.addLayout(hl1) self.setLayout(l) self.adjustSize() self.setDefaults() self.setWhatsThis("""<b>Color Temperature</b><br> <b>Photo Filter</b> uses the multiply blending mode to mimic a warming or cooling filter put in front of the camera lens. The luminosity of the resulting image is corrected.<br> <b>Chromatic Adaptation</b> uses multipliers in the linear sRGB color space to adjust <b>temperature</b> and <b>tint</b>. """) # end of setWhatsThis def enableSliders(self): self.sliderTemp.setEnabled(True) for item in [self.sliderTint, self.tintLabel, self.tintValue]: item.setEnabled(self.options['Chromatic Adaptation']) def setDefaults(self): # prevent multiple updates try: self.dataChanged.disconnect() except RuntimeError: pass self.listWidget1.unCheckAll() self.listWidget1.checkOption(self.listWidget1.intNames[0]) self.enableSliders() self.sliderTemp.setValue(round(self.temp2Slider(self.tempCorrection))) self.sliderTint.setValue(round(self.tint2Slider(self.defaultTint))) self.dataChanged.connect(self.updateLayer) def updateLayer(self): """ data changed slot """ self.enableSliders() self.layer.applyToStack() self.layer.parentImage.onImageChanged() @staticmethod def slider2Temp(v): return v * 100 @staticmethod def temp2Slider(v): return int(v / 100) @staticmethod def sliderTemp2User(v): return v * 100 @staticmethod def slider2Tint(v): return (v - 50) / 50 @staticmethod def tint2Slider(v): return int((1.0 + v) * 50.0) @staticmethod def sliderTint2User(v): return int((v - 50) / 5.0) def writeToStream(self, outStream): layer = self.layer outStream.writeQString(layer.actionName) outStream.writeQString(layer.name) outStream.writeQString(self.listWidget1.selectedItems()[0].text()) outStream.writeInt32(self.sliderTemp.value() * 100) return outStream def readFromStream(self, inStream): actionName = inStream.readQString() name = inStream.readQString() sel = inStream.readQString() temp = inStream.readInt32() for r in range(self.listWidget1.count()): currentItem = self.listWidget1.item(r) if currentItem.text() == sel: self.listWidget.select(currentItem) self.sliderTemp.setValue(temp // 100) self.update() return inStream
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None): super().__init__(parent=parent) self.tempCorrection = 6500 self.tintCorrection = 1.0 self.setStyleSheet( 'QRangeSlider * {border: 0px; padding: 0px; margin: 0px}') self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.setMinimumSize(axeSize, axeSize) self.setAttribute(Qt.WA_DeleteOnClose) # link back to image layer self.layer = weakProxy(layer) """ # using weak ref for back links if type(layer) in weakref.ProxyTypes: self.layer = layer else: self.layer = weakref.proxy(layer) """ self.defaultTemp = sRGBWP # ref temperature D65 self.defaultTint = 0 # options optionList, optionNames = ['Photo Filter', 'Chromatic Adaptation' ], ['Photo Filter', 'Chromatic Adaptation'] self.listWidget1 = optionsWidget( options=optionList, optionNames=optionNames, exclusive=True, changed=lambda: self.dataChanged.emit()) self.listWidget1.checkOption(self.listWidget1.intNames[1]) self.options = self.listWidget1.options # temp slider self.sliderTemp = QbLUeSlider(Qt.Horizontal) self.sliderTemp.setStyleSheet( QbLUeSlider.bLueSliderDefaultIColorStylesheet) self.sliderTemp.setRange( 17, 100 ) # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP self.sliderTemp.setSingleStep(1) tempLabel = QbLUeLabel() tempLabel.setMaximumSize(150, 30) tempLabel.setText("Color temperature") tempLabel.doubleClicked.connect(lambda: self.sliderTemp.setValue( self.temp2Slider(self.defaultTemp))) self.tempValue = QLabel() font = self.tempValue.font() metrics = QFontMetrics(font) w = metrics.width("0000") h = metrics.height() self.tempValue.setMinimumSize(w, h) self.tempValue.setMaximumSize(w, h) self.tempValue.setText( str("{:d}".format(self.sliderTemp2User(self.sliderTemp.value())))) # tint slider self.sliderTint = QbLUeSlider(Qt.Horizontal) self.sliderTint.setStyleSheet( QbLUeSlider.bLueSliderDefaultMGColorStylesheet) self.sliderTint.setRange( 0, 100 ) # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP self.sliderTint.setSingleStep(1) tintLabel = QbLUeLabel() tintLabel.setMaximumSize(150, 30) tintLabel.setText("Tint") tintLabel.doubleClicked.connect(lambda: self.sliderTint.setValue( self.tint2Slider(self.defaultTint))) self.tintValue = QLabel() font = self.tintValue.font() metrics = QFontMetrics(font) w = metrics.width("0000") h = metrics.height() self.tintValue.setMinimumSize(w, h) self.tintValue.setMaximumSize(w, h) self.tintValue.setText( str("{:d}".format(self.sliderTint2User(self.sliderTint.value())))) # temp change event handler def tempUpdate(value): self.tempValue.setText( str("{:d}".format(self.sliderTemp2User(value)))) # move not yet terminated or values not modified if self.sliderTemp.isSliderDown() or self.slider2Temp( value) == self.tempCorrection: return self.sliderTemp.valueChanged.disconnect() self.sliderTemp.sliderReleased.disconnect() self.tempCorrection = self.slider2Temp(value) self.dataChanged.emit() self.sliderTemp.valueChanged.connect(tempUpdate) self.sliderTemp.sliderReleased.connect( lambda: tempUpdate(self.sliderTemp.value())) # tint change event handler def tintUpdate(value): self.tintValue.setText( str("{:d}".format(self.sliderTint2User(value)))) # move not yet terminated or values not modified if self.sliderTint.isSliderDown() or self.slider2Tint( value) == self.tintCorrection: return self.sliderTint.valueChanged.disconnect() self.sliderTint.sliderReleased.disconnect() self.tintCorrection = self.slider2Tint(value) self.dataChanged.emit() self.sliderTint.valueChanged.connect(tintUpdate) self.sliderTint.sliderReleased.connect( lambda: tintUpdate(self.sliderTint.value())) self.sliderTemp.valueChanged.connect(tempUpdate) self.sliderTemp.sliderReleased.connect( lambda: tempUpdate(self.sliderTemp.value())) self.sliderTint.valueChanged.connect(tintUpdate) self.sliderTint.sliderReleased.connect( lambda: tintUpdate(self.sliderTint.value())) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(self.listWidget1) l.addWidget(tempLabel) hl = QHBoxLayout() hl.addWidget(self.tempValue) hl.addWidget(self.sliderTemp) l.addLayout(hl) l.addWidget(tintLabel) hl1 = QHBoxLayout() hl1.addWidget(self.tintValue) hl1.addWidget(self.sliderTint) l.addLayout(hl1) self.setLayout(l) self.adjustSize() self.dataChanged.connect( self.updateLayer) # TODO move to setDefaults 3/12/18 self.setStyleSheet("QListWidget, QLabel {font : 7pt;}") self.setDefaults() self.setWhatsThis("""<b>Color Temperature</b><br> <b>Photo Filter</b> uses the multiply blending mode to mimic a color filter in front of the camera lens.<br> <b>Chromatic Adaptation</b> uses multipliers in the linear sRGB color space to adjust <b>temperature</b> and <b>tint</b>. """) # end of setWhatsThis