Merge branch 'dev' into psgtk3

This commit is contained in:
heckflosse
2017-03-23 22:52:35 +01:00
6 changed files with 145 additions and 78 deletions

View File

@@ -1086,6 +1086,8 @@ PREFERENCES_PRTPROFILE;Color profile
PREFERENCES_PSPATH;Adobe Photoshop installation directory
PREFERENCES_REMEMBERZOOMPAN;Remember zoom % and pan offset
PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3".
PREFERENCES_EXTENDEDZOOMLEVELS;Use finer-grained zoom levels for "fit to screen" zooming
PREFERENCES_EXTENDEDZOOMLEVELS_TOOLTIP;This allows to better fill the editor window when using one of the "fit to screen" zoom modes. However, the preview quality might be slightly degraded, depending on the actual zoom factor computed.
PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels
PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements.
PREFERENCES_SELECTFONT;Select main font

View File

@@ -1076,6 +1076,17 @@ void Crop::freeAll ()
cropAllocated = false;
}
namespace {
bool check_need_larger_crop_for_lcp_distortion(const ProcParams &params)
{
return (params.lensProf.lcpFile.length() > 0 &&
params.lensProf.useDist);
}
} // namespace
/** @brief Handles crop's image buffer reallocation and trigger sizeChanged of SizeListener[s]
* If the scale changes, this method will free all buffers and reallocate ones of the new size.
* It will then tell to the SizeListener that size has changed (sizeChanged)
@@ -1130,6 +1141,23 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
int orW, orH;
parent->imgsrc->getSize (cp, orW, orH);
if (check_need_larger_crop_for_lcp_distortion(parent->params)) {
int fW, fH;
parent->imgsrc->getFullSize(fW, fH);
double dW = double(fW) * 0.15; // TODO - this is hardcoded ATM!
double dH = double(fH) * 0.15; // this is an estimate of the max
// distortion relative to the image
// size. BUT IS 15% REALLY ENOUGH?
// In fact, is there a better way??
orW = min(int(orW + dW), fW);
orH = min(int(orH + dH), fH);
trafx = max(int(orx - dW/2.0), 0);
trafy = max(int(ory - dH/2.0), 0);
} else {
trafx = orx;
trafy = ory;
}
int cw = skips(bw, skip);
int ch = skips(bh, skip);
@@ -1226,8 +1254,6 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
cropx = bx1;
cropy = by1;
trafx = orx;
trafy = ory;
if (settings->verbose) {
printf ("setsizes ends\n");

View File

@@ -83,6 +83,19 @@ float normn(float a, float b, int n)
return pow_F(pown(a, n) + pown(b, n), 1.f / n);
}
}
void correct_distortion(const rtengine::LCPMapper *lcp, double &x, double &y,
int cx, int cy)
{
assert(lcp);
x += cx;
y += cy;
lcp->correctDistortion(x, y);
x -= cx;
y -= cy;
}
}
namespace rtengine
@@ -142,7 +155,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector<Coord2D> &src,
double x_d = src[i].x, y_d = src[i].y;
if (pLCPMap && params->lensProf.useDist) {
pLCPMap->correctDistortion(x_d, y_d); // must be first transform
correct_distortion(pLCPMap, x_d, y_d, 0, 0);
}
y_d = ascale * (y_d - h2);
@@ -297,8 +310,12 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed,
if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip
LCPProfile *pLCPProf = lcpStore->getProfile(params->lensProf.lcpFile);
if (pLCPProf) pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm, focusDist, 0, false, params->lensProf.useDist,
original->getWidth(), original->getHeight(), params->coarse, rawRotationDeg);
if (pLCPProf) {
pLCPMap = new LCPMapper(pLCPProf, focalLen, focalLen35mm,
focusDist, 0, false,
params->lensProf.useDist,
oW, oH, params->coarse, rawRotationDeg);
}
}
if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient())) {
@@ -705,7 +722,6 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat*
void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH,
const LCPMapper *pLCPMap, bool fullImage)
{
double w2 = (double) oW / 2.0 - 0.5;
double h2 = (double) oH / 2.0 - 0.5;
@@ -762,11 +778,11 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
oH * tan(hpalpha) * sqrt(SQR(4 * maxRadius) + SQR(oH * tan(hpalpha)))) / (SQR(maxRadius) * 8)));
double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta);
double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, fullImage ? pLCPMap : nullptr) : 1.0;
double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, true /*fullImage*/ ? pLCPMap : nullptr) : 1.0;
// smaller crop images are a problem, so only when processing fully
bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage && pLCPMap->enableCA;
bool enableLCPDist = pLCPMap && params->lensProf.useDist && fullImage;
bool enableLCPDist = pLCPMap && params->lensProf.useDist; // && fullImage;
if (enableLCPCA) {
enableLCPDist = false;
@@ -783,7 +799,7 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
double x_d = x, y_d = y;
if (enableLCPDist) {
pLCPMap->correctDistortion(x_d, y_d); // must be first transform
correct_distortion(pLCPMap, x_d, y_d, cx, cy); // must be first transform
}
x_d = ascale * (x_d + cx - w2); // centering x coord & scale
@@ -960,7 +976,7 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf
double x_d = x, y_d = y;
if (pLCPMap && params->lensProf.useDist) {
pLCPMap->correctDistortion(x_d, y_d); // must be first transform
correct_distortion(pLCPMap, x_d, y_d, cx, cy); // must be first transform
}
y_d = ascale * (y_d + cy - h2); // centering y coord & scale

View File

@@ -30,7 +30,7 @@
using namespace rtengine;
CropHandler::CropHandler ()
: zoom(10), ww(0), wh(0), imx(-1), imy(-1), imw(0), imh(0), cax(-1), cay(-1),
: zoom(100), ww(0), wh(0), imx(-1), imy(-1), imw(0), imh(0), cax(-1), cay(-1),
cx(0), cy(0), cw(0), ch(0), cropX(0), cropY(0), cropW(0), cropH(0), enabled(false),
cropimg(nullptr), cropimgtrue(nullptr), cropimg_width(0), cropimg_height(0),
cix(0), ciy(0), ciw(0), cih(0), cis(1),
@@ -145,8 +145,8 @@ void CropHandler::setZoom (int z, int centerx, int centery)
assert (ipc);
int oldZoom = zoom;
float oldScale = zoom >= 1000 ? float(zoom / 1000) : 1.f / float(zoom);
float newScale = z >= 1000 ? float(z / 1000) : 1.f / float(z);
float oldScale = zoom >= 1000 ? float(zoom / 1000) : 10.f / float(zoom);
float newScale = z >= 1000 ? float(z / 1000) : 10.f / float(z);
int oldcax = cax;
int oldcay = cay;
@@ -176,8 +176,8 @@ void CropHandler::setZoom (int z, int centerx, int centery)
cw = ww * 1000 / zoom;
ch = wh * 1000 / zoom;
} else {
cw = ww * zoom;
ch = wh * zoom;
cw = ww * (zoom / 10);
ch = wh * (zoom / 10);
}
cx = cax - cw / 2;
@@ -206,7 +206,7 @@ float CropHandler::getZoomFactor ()
if (zoom >= 1000) {
return zoom / 1000;
} else {
return 1.f / (float)zoom;
return 10.f / (float)zoom;
}
}
@@ -221,8 +221,8 @@ void CropHandler::setWSize (int w, int h)
cw = ww * 1000 / zoom;
ch = wh * 1000 / zoom;
} else {
cw = ww * zoom;
ch = wh * zoom;
cw = ww * (zoom / 10);
ch = wh * (zoom / 10);
}
compDim ();
@@ -320,7 +320,7 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp
cropimgtrue = nullptr;
if (ax == cropX && ay == cropY && aw == cropW && ah == cropH && askip == (zoom >= 1000 ? 1 : zoom)) {
if (ax == cropX && ay == cropY && aw == cropW && ah == cropH && askip == (zoom >= 1000 ? 1 : zoom / 10)) {
cropimg_width = im->getWidth ();
cropimg_height = im->getHeight ();
cropimg = new unsigned char [3 * cropimg_width * cropimg_height];
@@ -362,11 +362,13 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp
}
if (ch->cropimg) {
if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom)) {
if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom / 10)) {
// calculate final image size
int czoom = ch->zoom < 1000 ? 1000 : ch->zoom;
int imw = ch->cropimg_width * czoom / 1000;
int imh = ch->cropimg_height * czoom / 1000;
float czoom = ch->zoom >= 1000 ?
ch->zoom / 1000.f :
float((ch->zoom/10) * 10) / float(ch->zoom);
int imw = ch->cropimg_width * czoom;
int imh = ch->cropimg_height * czoom;
if (imw > ch->ww) {
imw = ch->ww;
@@ -378,12 +380,12 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, ch->cropimg_height, 3 * ch->cropimg_width);
ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST);
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom, czoom, Gdk::INTERP_TILES);
tmpPixbuf.clear ();
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, ch->cropimg_height, 3 * ch->cropimg_width);
ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom / 1000.0, czoom / 1000.0, Gdk::INTERP_NEAREST);
tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom, czoom, Gdk::INTERP_TILES);
tmpPixbuftrue.clear ();
}
@@ -432,7 +434,7 @@ bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip)
cwh = 32;
}
cskip = zoom >= 1000 ? 1 : zoom;
cskip = zoom >= 1000 ? 1 : zoom/10;
return true;
}
@@ -615,12 +617,12 @@ void CropHandler::compDim ()
scaledCAX = cax * (zoom/1000);
scaledCAY = cay * (zoom/1000);
} else {
wwImgSpace = int(float(ww) * float(zoom) + 0.5f);
whImgSpace = int(float(wh) * float(zoom) + 0.5f);
wwImgSpace = int(float(ww) * (float(zoom)/10.f) + 0.5f);
whImgSpace = int(float(wh) * (float(zoom)/10.f) + 0.5f);
//scaledFullW = fullW / zoom;
//scaledFullH = fullH / zoom;
scaledCAX = cax / zoom;
scaledCAY = cay / zoom;
scaledCAX = int(float(cax) / (float(zoom)/10.f));
scaledCAY = int(float(cay) / (float(zoom)/10.f));
}
imgX = ww / 2 - scaledCAX;

View File

@@ -34,39 +34,6 @@
using namespace rtengine;
struct ZoomStep {
Glib::ustring label;
double zoom;
int czoom;
};
ZoomStep zoomSteps[] = {
{" 1%", 0.01, 100},
{" 2%", 0.02, 50},
{" 5%", 0.05, 20},
{"6.7%", 1.0 / 15.0, 15},
{" 8%", 1.0 / 12.0, 12},
{" 10%", 0.1, 10},
{"12.5%", 0.125, 8},
{" 14%", 1.0 / 7.0, 7},
{"16.6%", 1.0 / 6.0, 6},
{" 20%", 0.2, 5},
{" 25%", 0.25, 4},
{" 33%", 1.0 / 3.0, 3},
{" 50%", 0.5, 2},
{"100%", 1.0, 1000},
{"200%", 2.0, 2000},
{"300%", 3.0, 3000},
{"400%", 4.0, 4000},
{"500%", 5.0, 5000},
{"600%", 6.0, 6000},
{"700%", 7.0, 7000},
{"800%", 8.0, 8000},
{"1600%", 16.0, 16000}
};
#define MAXZOOMSTEPS 21
#define ZOOM11INDEX 13
CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow)
: ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false),
fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), hoveredPicker(nullptr), cropLabel(Glib::ustring("100%")),
@@ -75,6 +42,8 @@ CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDet
imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(nullptr),
pmlistener(nullptr), pmhlistener(nullptr), observedCropWin(nullptr)
{
initZoomSteps();
Glib::RefPtr<Pango::Context> context = parent->get_pango_context () ;
Pango::FontDescription fontd = context->get_font_description ();
fontd.set_weight (Pango::WEIGHT_BOLD);
@@ -121,6 +90,29 @@ CropWindow::~CropWindow ()
}
}
void CropWindow::initZoomSteps()
{
zoomSteps.push_back(ZoomStep(" 1%", 0.01, 999, true));
zoomSteps.push_back(ZoomStep(" 2%", 0.02, 500, true));
zoomSteps.push_back(ZoomStep(" 5%", 0.05, 200, true));
zoomSteps.push_back(ZoomStep(" 6%", 1.0/15.0, 150, true));
zoomSteps.push_back(ZoomStep(" 8%", 1.0/12.0, 120, true));
char lbl[64];
for (int s = 100; s >= 11; --s) {
float z = 10./float(s);
sprintf(lbl, "% 2d%%", int(z * 100));
bool is_major = (s == s/10 * 10);
zoomSteps.push_back(ZoomStep(lbl, z, s, is_major));
}
zoom11index = zoomSteps.size();
for (int s = 1; s <= 8; ++s) {
sprintf(lbl, "%d00%%", s);
zoomSteps.push_back(ZoomStep(lbl, s, s * 1000, true));
}
zoomSteps.push_back(ZoomStep("1600%", 16, 16000, true));
}
void CropWindow::enable()
{
cropHandler.setEnabled (true);
@@ -317,7 +309,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
state = SNormal;
zoomVersion = exposeVersion;
screenCoordToImage (x, y, action_x, action_y);
changeZoom (ZOOM11INDEX, true, action_x, action_y);
changeZoom (zoom11index, true, action_x, action_y);
fitZoom = false;
} else {
zoomFit ();
@@ -1940,7 +1932,11 @@ void CropWindow::zoomIn (bool toCursor, int cursorX, int cursorY)
}
}
changeZoom (cropZoom + 1, true, x, y);
int z = cropZoom + 1;
while (z < int(zoomSteps.size()) && !zoomSteps[z].is_major) {
++z;
}
changeZoom (z, true, x, y);
fitZoom = false;
}
@@ -1953,10 +1949,16 @@ void CropWindow::zoomOut (bool toCursor, int cursorX, int cursorY)
if (toCursor) {
x = cursorX;
y = cursorY;
} else {
screenCoordToImage(xpos + imgX + imgW / 2, ypos + imgY + imgH / 2, x, y);
}
zoomVersion = exposeVersion;
changeZoom (cropZoom - 1, true, x, y);
int z = cropZoom - 1;
while (z >= 0 && !zoomSteps[z].is_major) {
--z;
}
changeZoom (z, true, x, y);
fitZoom = false;
}
@@ -1978,9 +1980,11 @@ void CropWindow::zoom11 ()
}
zoomVersion = exposeVersion;
} else {
screenCoordToImage(xpos + imgX + imgW / 2, ypos + imgY + imgH / 2, x, y);
}
changeZoom (ZOOM11INDEX, true, x, y);
changeZoom (zoom11index, true, x, y);
fitZoom = false;
}
@@ -1997,17 +2001,17 @@ bool CropWindow::isMinZoom ()
bool CropWindow::isMaxZoom ()
{
return cropZoom >= MAXZOOMSTEPS;
return cropZoom >= int(zoomSteps.size())-1;
}
void CropWindow::setZoom (double zoom)
{
int cz = MAXZOOMSTEPS;
int cz = int(zoomSteps.size())-1;
if (zoom < zoomSteps[0].zoom) {
cz = 0;
} else
for (int i = 0; i < MAXZOOMSTEPS; i++)
for (int i = 0; i < int(zoomSteps.size())-1; i++)
if (zoomSteps[i].zoom <= zoom && zoomSteps[i + 1].zoom > zoom) {
cz = i;
break;
@@ -2019,12 +2023,12 @@ void CropWindow::setZoom (double zoom)
double CropWindow::getZoomFitVal ()
{
double z = cropHandler.getFitZoom ();
int cz = MAXZOOMSTEPS;
int cz = int(zoomSteps.size())-1;
if (z < zoomSteps[0].zoom) {
cz = 0;
} else
for (int i = 0; i < MAXZOOMSTEPS; i++)
for (int i = 0; i < int(zoomSteps.size())-1; i++)
if (zoomSteps[i].zoom <= z && zoomSteps[i + 1].zoom > z) {
cz = i;
break;
@@ -2038,12 +2042,12 @@ void CropWindow::zoomFit ()
{
double z = cropHandler.getFitZoom ();
int cz = MAXZOOMSTEPS;
int cz = int(zoomSteps.size())-1;
if (z < zoomSteps[0].zoom) {
cz = 0;
} else
for (int i = 0; i < MAXZOOMSTEPS; i++)
for (int i = 0; i < int(zoomSteps.size())-1; i++)
if (zoomSteps[i].zoom <= z && zoomSteps[i + 1].zoom > z) {
cz = i;
break;
@@ -2058,12 +2062,12 @@ void CropWindow::zoomFitCrop ()
{
if(cropHandler.cropParams.enabled) {
double z = cropHandler.getFitCropZoom ();
int cz = MAXZOOMSTEPS;
int cz = int(zoomSteps.size())-1;
if (z < zoomSteps[0].zoom) {
cz = 0;
} else
for (int i = 0; i < MAXZOOMSTEPS; i++)
for (int i = 0; i < int(zoomSteps.size())-1; i++)
if (zoomSteps[i].zoom <= z && zoomSteps[i + 1].zoom > z) {
cz = i;
break;
@@ -2076,6 +2080,8 @@ void CropWindow::zoomFitCrop ()
setCropAnchorPosition(centerX, centerY);
changeZoom (cz, true, centerX, centerY);
fitZoom = false;
} else {
zoomFit();
}
}
@@ -2138,8 +2144,8 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery)
if (zoom < 0) {
zoom = 0;
} else if (zoom > MAXZOOMSTEPS) {
zoom = MAXZOOMSTEPS;
} else if (zoom > int(zoomSteps.size())-1) {
zoom = int(zoomSteps.size())-1;
}
cropZoom = zoom;

View File

@@ -114,6 +114,21 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed
// Used by the mainCropWindow only
void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw = 0, int rh = 0);
struct ZoomStep {
Glib::ustring label;
double zoom;
int czoom;
bool is_major;
explicit ZoomStep(const Glib::ustring &l="", double z=0.0,
int cz=0, bool m=false):
label(l), zoom(z), czoom(cz), is_major(m) {}
};
std::vector<ZoomStep> zoomSteps;
size_t zoom11index;
void initZoomSteps();
public:
CropHandler cropHandler;
CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow);