Dual demosaic auto contrast threshold: Use adjuster with auto button, #4866
This commit is contained in:
parent
0cafab38b6
commit
392e00cd69
@ -1818,6 +1818,7 @@ TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing...
|
||||
TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement...
|
||||
TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixel Shift is for Pentax/Sony Pixel Shift files. It falls back to AMaZE for non-Pixel Shift files.
|
||||
TP_RAW_DUALDEMOSAICAUTOCONTRAST;Auto threshold
|
||||
TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP;If the check-box is checked (recommended), RawTherapee calculates an optimum value based on flat regions in the image.\nIf there is no flat region in the image or the image is too noisy, the value will be set to 0.\nTo set the value manually, uncheck the check-box first (reasonable values depend on the image).
|
||||
TP_RAW_DUALDEMOSAICCONTRAST;Contrast threshold
|
||||
TP_RAW_EAHD;EAHD
|
||||
TP_RAW_FALSECOLOR;False color suppression steps
|
||||
|
@ -40,7 +40,7 @@ void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int wi
|
||||
{
|
||||
BENCHFUN
|
||||
|
||||
if (contrast == 0.f) {
|
||||
if (contrast == 0.f && !autoContrast) {
|
||||
// contrast == 0.0 means only first demosaicer will be used
|
||||
if(isBayer) {
|
||||
if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) ) {
|
||||
|
@ -240,13 +240,13 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
|
||||
}
|
||||
}
|
||||
bool autoContrast = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicAutoContrast : params.raw.xtranssensor.dualDemosaicAutoContrast;
|
||||
double contrastThreshold = params.raw.bayersensor.dualDemosaicContrast;
|
||||
double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params.raw.bayersensor.dualDemosaicContrast : params.raw.xtranssensor.dualDemosaicContrast;
|
||||
imgsrc->demosaic(rp, autoContrast, contrastThreshold); //enabled demosaic
|
||||
|
||||
if (imgsrc->getSensorType() == ST_BAYER && bayerAutoContrastListener) {
|
||||
if (imgsrc->getSensorType() == ST_BAYER && bayerAutoContrastListener && autoContrast) {
|
||||
bayerAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0);
|
||||
}
|
||||
if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener) {
|
||||
if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener && autoContrast) {
|
||||
xtransAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0);
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ void findMinMaxPercentile(const float* data, size_t size, float minPrct, float&
|
||||
|
||||
void buildBlendMask(float** luminance, float **blend, int W, int H, float &contrastThreshold, float amount, bool autoContrast) {
|
||||
|
||||
if(contrastThreshold == 0.f) {
|
||||
if(contrastThreshold == 0.f && !autoContrast) {
|
||||
for(int j = 0; j < H; ++j) {
|
||||
for(int i = 0; i < W; ++i) {
|
||||
blend[j][i] = amount;
|
||||
|
@ -48,25 +48,16 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA
|
||||
pack_start( *hb1, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
dualDemosaicOptions = Gtk::manage(new Gtk::VBox());
|
||||
Gtk::HBox* hbAutoContrast = Gtk::manage(new Gtk::HBox());
|
||||
|
||||
dualDemosaicAutoContrast = Gtk::manage(new CheckBox(M("TP_RAW_DUALDEMOSAICAUTOCONTRAST"), multiImage));
|
||||
dualDemosaicAutoContrast->setCheckBoxListener(this);
|
||||
|
||||
dualDemosaicLabel = Gtk::manage(new Gtk::Label(""));
|
||||
|
||||
dualDemosaicContrast = Gtk::manage(new Adjuster(M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 100, 1, 20));
|
||||
dualDemosaicContrast->setAdjusterListener(this);
|
||||
|
||||
dualDemosaicContrast->addAutoButton(M("TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP"));
|
||||
dualDemosaicContrast->setAutoValue(true);
|
||||
if (dualDemosaicContrast->delay < options.adjusterMaxDelay) {
|
||||
dualDemosaicContrast->delay = options.adjusterMaxDelay;
|
||||
}
|
||||
|
||||
dualDemosaicAutoContrast->show();
|
||||
dualDemosaicContrast->show();
|
||||
hbAutoContrast->pack_start(*dualDemosaicAutoContrast);
|
||||
hbAutoContrast->pack_start(*dualDemosaicLabel);
|
||||
dualDemosaicOptions->pack_start(*hbAutoContrast);
|
||||
dualDemosaicOptions->pack_start(*dualDemosaicContrast);
|
||||
pack_start( *dualDemosaicOptions, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
@ -310,11 +301,9 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
|
||||
pixelShiftNonGreenCross->setValue (pp->raw.bayersensor.pixelShiftNonGreenCross);
|
||||
ccSteps->setValue (pp->raw.bayersensor.ccSteps);
|
||||
lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations);
|
||||
dualDemosaicAutoContrast->setValue (pp->raw.bayersensor.dualDemosaicAutoContrast);
|
||||
dualDemosaicContrast->setAutoValue(pp->raw.bayersensor.dualDemosaicAutoContrast);
|
||||
dualDemosaicContrast->setValue (pp->raw.bayersensor.dualDemosaicContrast);
|
||||
if (!batchMode) {
|
||||
dualDemosaicContrast->set_sensitive(!pp->raw.bayersensor.dualDemosaicAutoContrast);
|
||||
}
|
||||
|
||||
pixelShiftMotionMethod->set_active ((int)pp->raw.bayersensor.pixelShiftMotionCorrectionMethod);
|
||||
pixelShiftEperIso->setValue (pp->raw.bayersensor.pixelShiftEperIso);
|
||||
pixelShiftSigma->setValue (pp->raw.bayersensor.pixelShiftSigma);
|
||||
@ -338,8 +327,8 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
|
||||
pixelShiftEqualBrightChannel->setEdited (pedited->raw.bayersensor.pixelShiftEqualBrightChannel);
|
||||
pixelShiftNonGreenCross->setEdited (pedited->raw.bayersensor.pixelShiftNonGreenCross);
|
||||
lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited);
|
||||
dualDemosaicAutoContrast->setEdited ( pedited->raw.bayersensor.dualDemosaicAutoContrast ? Edited : UnEdited);
|
||||
dualDemosaicContrast->setEditedState ( pedited->raw.bayersensor.dualDemosaicContrast ? Edited : UnEdited);
|
||||
dualDemosaicContrast->setAutoInconsistent (multiImage && !pedited->raw.bayersensor.dualDemosaicAutoContrast);
|
||||
pixelShiftEperIso->setEditedState ( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited);
|
||||
pixelShiftSigma->setEditedState ( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited);
|
||||
|
||||
@ -360,6 +349,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
|
||||
}
|
||||
|
||||
}
|
||||
lastAutoContrast = pp->raw.bayersensor.dualDemosaicAutoContrast;
|
||||
|
||||
if (!batchMode) {
|
||||
dcbOptions->set_visible(pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCB) || pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::DCBVNG4));
|
||||
@ -400,7 +390,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
|
||||
pp->raw.bayersensor.dcb_enhance = dcbEnhance->getLastActive ();
|
||||
pp->raw.bayersensor.border = border->getIntValue();
|
||||
pp->raw.bayersensor.lmmse_iterations = lmmseIterations->getIntValue();
|
||||
pp->raw.bayersensor.dualDemosaicAutoContrast = dualDemosaicAutoContrast->getLastActive ();
|
||||
pp->raw.bayersensor.dualDemosaicAutoContrast = dualDemosaicContrast->getAutoValue();
|
||||
pp->raw.bayersensor.dualDemosaicContrast = dualDemosaicContrast->getValue();
|
||||
pp->raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::PSMotionCorrectionMethod)pixelShiftMotionMethod->get_active_row_number();
|
||||
pp->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getValue();
|
||||
@ -441,7 +431,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
|
||||
pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent();
|
||||
//pedited->raw.bayersensor.allEnhance = !allEnhance->get_inconsistent();
|
||||
pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState ();
|
||||
pedited->raw.bayersensor.dualDemosaicAutoContrast = !dualDemosaicAutoContrast->get_inconsistent();
|
||||
pedited->raw.bayersensor.dualDemosaicAutoContrast = !dualDemosaicContrast->getAutoInconsistent ();
|
||||
pedited->raw.bayersensor.dualDemosaicContrast = dualDemosaicContrast->getEditedState ();
|
||||
pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED");
|
||||
pedited->raw.bayersensor.pixelShiftDemosaicMethod = pixelShiftDemosaicMethod->get_active_text() != M("GENERAL_UNCHANGED");
|
||||
@ -556,10 +546,6 @@ void BayerProcess::adjusterChanged (Adjuster* a, double newval)
|
||||
}
|
||||
}
|
||||
|
||||
void BayerProcess::adjusterAutoToggled(Adjuster* a, bool newval)
|
||||
{
|
||||
}
|
||||
|
||||
void BayerProcess::methodChanged ()
|
||||
{
|
||||
const int currentSelection = method->get_active_row_number();
|
||||
@ -624,14 +610,7 @@ void BayerProcess::imageNumberChanged ()
|
||||
|
||||
void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval)
|
||||
{
|
||||
if (c == dualDemosaicAutoContrast) {
|
||||
if (!batchMode) {
|
||||
dualDemosaicContrast->set_sensitive(newval == CheckValue::off);
|
||||
}
|
||||
if (listener) {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, dualDemosaicAutoContrast->getValueAsStr ());
|
||||
}
|
||||
} else if (c == dcbEnhance) {
|
||||
if (c == dcbEnhance) {
|
||||
if (listener) {
|
||||
listener->panelChanged (EvDemosaicDCBEnhanced, dcbEnhance->getValueAsStr ());
|
||||
}
|
||||
@ -684,6 +663,33 @@ void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval)
|
||||
}
|
||||
}
|
||||
|
||||
void BayerProcess::adjusterAutoToggled(Adjuster* a, bool newval)
|
||||
{
|
||||
if (multiImage) {
|
||||
if (dualDemosaicContrast->getAutoInconsistent()) {
|
||||
dualDemosaicContrast->setAutoInconsistent (false);
|
||||
dualDemosaicContrast->setAutoValue (false);
|
||||
} else if (lastAutoContrast) {
|
||||
dualDemosaicContrast->setAutoInconsistent (true);
|
||||
}
|
||||
|
||||
lastAutoContrast = dualDemosaicContrast->getAutoValue();
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
|
||||
if (a == dualDemosaicContrast) {
|
||||
if (dualDemosaicContrast->getAutoInconsistent()) {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, M ("GENERAL_UNCHANGED"));
|
||||
} else if (dualDemosaicContrast->getAutoValue()) {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, M ("GENERAL_ENABLED"));
|
||||
} else {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, M ("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BayerProcess::pixelShiftMotionMethodChanged ()
|
||||
{
|
||||
if (!batchMode) {
|
||||
@ -750,11 +756,9 @@ void BayerProcess::autoContrastChanged (double autoContrast)
|
||||
const auto func = [](gpointer data) -> gboolean {
|
||||
Data *d = static_cast<Data *>(data);
|
||||
BayerProcess *me = d->me;
|
||||
if (d->autoContrast == -1.0) {
|
||||
me->dualDemosaicLabel->set_text("");
|
||||
} else {
|
||||
me->dualDemosaicLabel->set_text(Glib::ustring::format(std::fixed, std::setprecision(0), d->autoContrast));
|
||||
}
|
||||
me->disableListener();
|
||||
me->dualDemosaicContrast->setValue(d->autoContrast);
|
||||
me->enableListener();
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
@ -59,10 +59,8 @@ protected:
|
||||
Adjuster* pixelShiftSigma;
|
||||
Gtk::VBox *dualDemosaicOptions;
|
||||
Adjuster* dualDemosaicContrast;
|
||||
CheckBox* dualDemosaicAutoContrast;
|
||||
Gtk::Label* dualDemosaicLabel;
|
||||
int oldMethod;
|
||||
|
||||
bool lastAutoContrast;
|
||||
IdleRegister idle_register;
|
||||
|
||||
rtengine::ProcEvent EvDemosaicBorder;
|
||||
|
@ -69,25 +69,17 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP
|
||||
pack_start( *hb1, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
dualDemosaicOptions = Gtk::manage (new Gtk::VBox ());
|
||||
Gtk::HBox* hbAutoContrast = Gtk::manage(new Gtk::HBox());
|
||||
|
||||
dualDemosaicAutoContrast = Gtk::manage(new CheckBox(M("TP_RAW_DUALDEMOSAICAUTOCONTRAST"), multiImage));
|
||||
dualDemosaicAutoContrast->setCheckBoxListener(this);
|
||||
|
||||
dualDemosaicLabel = Gtk::manage(new Gtk::Label(""));
|
||||
|
||||
dualDemosaicContrast = Gtk::manage(new Adjuster (M("TP_RAW_DUALDEMOSAICCONTRAST"), 0, 100, 1, 20));
|
||||
dualDemosaicContrast->setAdjusterListener (this);
|
||||
dualDemosaicContrast->addAutoButton(M("TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP"));
|
||||
dualDemosaicContrast->setAutoValue(true);
|
||||
|
||||
if (dualDemosaicContrast->delay < options.adjusterMaxDelay) {
|
||||
dualDemosaicContrast->delay = options.adjusterMaxDelay;
|
||||
}
|
||||
|
||||
dualDemosaicAutoContrast->show();
|
||||
dualDemosaicContrast->show();
|
||||
hbAutoContrast->pack_start(*dualDemosaicAutoContrast);
|
||||
hbAutoContrast->pack_start(*dualDemosaicLabel);
|
||||
dualDemosaicOptions->pack_start(*hbAutoContrast);
|
||||
dualDemosaicOptions->pack_start(*dualDemosaicContrast);
|
||||
pack_start( *dualDemosaicOptions, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
@ -119,7 +111,7 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param
|
||||
}
|
||||
|
||||
if(pedited ) {
|
||||
dualDemosaicAutoContrast->setEdited ( pedited->raw.xtranssensor.dualDemosaicAutoContrast ? Edited : UnEdited);
|
||||
dualDemosaicContrast->setAutoInconsistent (multiImage && !pedited->raw.xtranssensor.dualDemosaicAutoContrast);
|
||||
dualDemosaicContrast->setEditedState ( pedited->raw.xtranssensor.dualDemosaicContrast ? Edited : UnEdited);
|
||||
ccSteps->setEditedState (pedited->raw.xtranssensor.ccSteps ? Edited : UnEdited);
|
||||
|
||||
@ -127,9 +119,12 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param
|
||||
method->set_active_text(M("GENERAL_UNCHANGED"));
|
||||
}
|
||||
}
|
||||
dualDemosaicAutoContrast->setValue (pp->raw.xtranssensor.dualDemosaicAutoContrast);
|
||||
dualDemosaicContrast->setAutoValue(pp->raw.xtranssensor.dualDemosaicAutoContrast);
|
||||
dualDemosaicContrast->setValue (pp->raw.xtranssensor.dualDemosaicContrast);
|
||||
ccSteps->setValue (pp->raw.xtranssensor.ccSteps);
|
||||
|
||||
lastAutoContrast = pp->raw.bayersensor.dualDemosaicAutoContrast;
|
||||
|
||||
if (!batchMode) {
|
||||
dualDemosaicOptions->set_visible(pp->raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FOUR_PASS)
|
||||
|| pp->raw.xtranssensor.method == procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::TWO_PASS));
|
||||
@ -142,7 +137,7 @@ void XTransProcess::read(const rtengine::procparams::ProcParams* pp, const Param
|
||||
|
||||
void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
pp->raw.xtranssensor.dualDemosaicAutoContrast = dualDemosaicAutoContrast->getLastActive ();
|
||||
pp->raw.xtranssensor.dualDemosaicAutoContrast = dualDemosaicContrast->getAutoValue();
|
||||
pp->raw.xtranssensor.dualDemosaicContrast = dualDemosaicContrast->getValue();
|
||||
pp->raw.xtranssensor.ccSteps = ccSteps->getIntValue();
|
||||
|
||||
@ -154,7 +149,7 @@ void XTransProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* p
|
||||
|
||||
if (pedited) {
|
||||
pedited->raw.xtranssensor.method = method->get_active_text() != M("GENERAL_UNCHANGED");
|
||||
pedited->raw.xtranssensor.dualDemosaicAutoContrast = !dualDemosaicAutoContrast->get_inconsistent();
|
||||
pedited->raw.xtranssensor.dualDemosaicAutoContrast = !dualDemosaicContrast->getAutoInconsistent ();
|
||||
pedited->raw.xtranssensor.dualDemosaicContrast = dualDemosaicContrast->getEditedState ();
|
||||
pedited->raw.xtranssensor.ccSteps = ccSteps->getEditedState ();
|
||||
}
|
||||
@ -200,17 +195,31 @@ void XTransProcess::adjusterChanged(Adjuster* a, double newval)
|
||||
}
|
||||
}
|
||||
|
||||
void XTransProcess::checkBoxToggled (CheckBox* c, CheckValue newval)
|
||||
{
|
||||
if (c == dualDemosaicAutoContrast) {
|
||||
if (listener) {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, dualDemosaicAutoContrast->getValueAsStr ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XTransProcess::adjusterAutoToggled(Adjuster* a, bool newval)
|
||||
{
|
||||
if (multiImage) {
|
||||
if (dualDemosaicContrast->getAutoInconsistent()) {
|
||||
dualDemosaicContrast->setAutoInconsistent (false);
|
||||
dualDemosaicContrast->setAutoValue (false);
|
||||
} else if (lastAutoContrast) {
|
||||
dualDemosaicContrast->setAutoInconsistent (true);
|
||||
}
|
||||
|
||||
lastAutoContrast = dualDemosaicContrast->getAutoValue();
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
|
||||
if (a == dualDemosaicContrast) {
|
||||
if (dualDemosaicContrast->getAutoInconsistent()) {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, M ("GENERAL_UNCHANGED"));
|
||||
} else if (dualDemosaicContrast->getAutoValue()) {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, M ("GENERAL_ENABLED"));
|
||||
} else {
|
||||
listener->panelChanged (EvDemosaicAutoContrast, M ("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XTransProcess::methodChanged ()
|
||||
@ -236,6 +245,10 @@ void XTransProcess::methodChanged ()
|
||||
}
|
||||
}
|
||||
|
||||
void XTransProcess::checkBoxToggled (CheckBox* c, CheckValue newval)
|
||||
{
|
||||
}
|
||||
|
||||
void XTransProcess::autoContrastChanged (double autoContrast)
|
||||
{
|
||||
struct Data {
|
||||
@ -245,11 +258,9 @@ void XTransProcess::autoContrastChanged (double autoContrast)
|
||||
const auto func = [](gpointer data) -> gboolean {
|
||||
Data *d = static_cast<Data *>(data);
|
||||
XTransProcess *me = d->me;
|
||||
if (d->autoContrast == -1.0) {
|
||||
me->dualDemosaicLabel->set_text("");
|
||||
} else {
|
||||
me->dualDemosaicLabel->set_text(Glib::ustring::format(std::fixed, std::setprecision(0), d->autoContrast));
|
||||
}
|
||||
me->disableListener();
|
||||
me->dualDemosaicContrast->setValue(d->autoContrast);
|
||||
me->enableListener();
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
|
@ -35,8 +35,7 @@ protected:
|
||||
Adjuster* ccSteps;
|
||||
Gtk::VBox *dualDemosaicOptions;
|
||||
Adjuster* dualDemosaicContrast;
|
||||
CheckBox* dualDemosaicAutoContrast;
|
||||
Gtk::Label* dualDemosaicLabel;
|
||||
bool lastAutoContrast;
|
||||
|
||||
int oldSelection;
|
||||
sigc::connection methodconn;
|
||||
|
Loading…
x
Reference in New Issue
Block a user