Better handle thumbnail generation of extreme aspect ratio images (fixes #3794)
* Backport fix taken from ART * Enforce minimal thumbnail size of 1x1 px in two places, prevents divison by zero and empty image generation
This commit is contained in:
@@ -205,11 +205,6 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
|||||||
|
|
||||||
ImageIO* img = imgSrc.getImageIO();
|
ImageIO* img = imgSrc.getImageIO();
|
||||||
|
|
||||||
// agriggio -- hotfix for #3794, to be revised once a proper solution is implemented
|
|
||||||
if (std::max(img->getWidth(), img->getHeight()) / std::min(img->getWidth(), img->getHeight()) >= 10) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thumbnail* tpp = new Thumbnail ();
|
Thumbnail* tpp = new Thumbnail ();
|
||||||
|
|
||||||
unsigned char* data;
|
unsigned char* data;
|
||||||
@@ -235,15 +230,29 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
|||||||
h = img->getHeight();
|
h = img->getHeight();
|
||||||
tpp->scale = 1.;
|
tpp->scale = 1.;
|
||||||
} else {
|
} else {
|
||||||
if (fixwh == 1) {
|
if (fixwh < 0 && w > 0 && h > 0) {
|
||||||
|
const int ww = h * img->getWidth() / img->getHeight();
|
||||||
|
const int hh = w * img->getHeight() / img->getWidth();
|
||||||
|
if (ww <= w) {
|
||||||
|
w = ww;
|
||||||
|
tpp->scale = static_cast<double>(img->getHeight()) / h;
|
||||||
|
} else {
|
||||||
|
h = hh;
|
||||||
|
tpp->scale = static_cast<double>(img->getWidth()) / w;
|
||||||
|
}
|
||||||
|
} else if (fixwh == 1) {
|
||||||
w = h * img->getWidth() / img->getHeight();
|
w = h * img->getWidth() / img->getHeight();
|
||||||
tpp->scale = (double)img->getHeight() / h;
|
tpp->scale = static_cast<double>(img->getHeight()) / h;
|
||||||
} else {
|
} else {
|
||||||
h = w * img->getHeight() / img->getWidth();
|
h = w * img->getHeight() / img->getWidth();
|
||||||
tpp->scale = (double)img->getWidth() / w;
|
tpp->scale = static_cast<double>(img->getWidth()) / w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Precaution to prevent division by zero later on
|
||||||
|
if (h < 1) h = 1;
|
||||||
|
if (w < 1) w = 1;
|
||||||
|
|
||||||
// bilinear interpolation
|
// bilinear interpolation
|
||||||
if (tpp->thumbImg) {
|
if (tpp->thumbImg) {
|
||||||
delete tpp->thumbImg;
|
delete tpp->thumbImg;
|
||||||
@@ -1178,6 +1187,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||||||
rwidth = int (size_t (thumbImg->getWidth()) * size_t (rheight) / size_t (thumbImg->getHeight()));
|
rwidth = int (size_t (thumbImg->getWidth()) * size_t (rheight) / size_t (thumbImg->getHeight()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rwidth < 1) rwidth = 1;
|
||||||
|
if (rheight < 1) rheight = 1;
|
||||||
|
|
||||||
Imagefloat* baseImg = resizeTo<Imagefloat> (rwidth, rheight, interp, thumbImg);
|
Imagefloat* baseImg = resizeTo<Imagefloat> (rwidth, rheight, interp, thumbImg);
|
||||||
|
|
||||||
|
@@ -344,8 +344,9 @@ bool BatchQueue::loadBatchQueue ()
|
|||||||
|
|
||||||
auto job = rtengine::ProcessingJob::create (source, thumb->getType () == FT_Raw, pparams, fast);
|
auto job = rtengine::ProcessingJob::create (source, thumb->getType () == FT_Raw, pparams, fast);
|
||||||
|
|
||||||
const auto prevh = getMaxThumbnailHeight ();
|
auto prevh = getMaxThumbnailHeight();
|
||||||
const auto prevw = thumb->getThumbnailWidth(prevh, &pparams);
|
auto prevw = prevh;
|
||||||
|
thumb->getThumbnailSize(prevw, prevh, &pparams);
|
||||||
|
|
||||||
auto entry = new BatchQueueEntry (job, pparams, source, prevw, prevh, thumb, options.overwriteOutputFile);
|
auto entry = new BatchQueueEntry (job, pparams, source, prevw, prevh, thumb, options.overwriteOutputFile);
|
||||||
thumb->decreaseRef (); // Removing the refCount acquired by cacheMgr->getEntry
|
thumb->decreaseRef (); // Removing the refCount acquired by cacheMgr->getEntry
|
||||||
|
@@ -106,8 +106,12 @@ void BatchQueueEntry::refreshThumbnailImage ()
|
|||||||
|
|
||||||
void BatchQueueEntry::calcThumbnailSize ()
|
void BatchQueueEntry::calcThumbnailSize ()
|
||||||
{
|
{
|
||||||
|
|
||||||
prew = preh * origpw / origph;
|
prew = preh * origpw / origph;
|
||||||
|
if (prew > options.maxThumbnailWidth) {
|
||||||
|
const float s = static_cast<float>(options.maxThumbnailWidth) / prew;
|
||||||
|
prew = options.maxThumbnailWidth;
|
||||||
|
preh = std::max<int>(preh * s, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -261,9 +265,8 @@ void BatchQueueEntry::_updateImage (guint8* img, int w, int h)
|
|||||||
MYWRITERLOCK(l, lockRW);
|
MYWRITERLOCK(l, lockRW);
|
||||||
|
|
||||||
prew = w;
|
prew = w;
|
||||||
assert (preview == nullptr);
|
preview.resize(prew * preh * 3);
|
||||||
preview = new guint8 [prew * preh * 3];
|
std::copy(img, img + preview.size(), preview.begin());
|
||||||
memcpy (preview, img, prew * preh * 3);
|
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent->redrawNeeded (this);
|
parent->redrawNeeded (this);
|
||||||
|
@@ -116,9 +116,12 @@ void FileBrowserEntry::refreshQuickThumbnailImage ()
|
|||||||
|
|
||||||
void FileBrowserEntry::calcThumbnailSize ()
|
void FileBrowserEntry::calcThumbnailSize ()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
prew = thumbnail->getThumbnailWidth(preh);
|
int ow = prew, oh = preh;
|
||||||
|
thumbnail->getThumbnailSize(prew, preh);
|
||||||
|
if (ow != prew || oh != preh || preview.size() != static_cast<std::size_t>(prew * preh * 3)) {
|
||||||
|
preview.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,22 +258,16 @@ void FileBrowserEntry::_updateImage(rtengine::IImage8* img, double s, const rten
|
|||||||
bool rotated = false;
|
bool rotated = false;
|
||||||
|
|
||||||
if (preh == img->getHeight()) {
|
if (preh == img->getHeight()) {
|
||||||
const bool resize = !preview || prew != img->getWidth();
|
|
||||||
prew = img->getWidth ();
|
prew = img->getWidth ();
|
||||||
|
|
||||||
// Check if image has been rotated since last time
|
// Check if image has been rotated since last time
|
||||||
rotated = preview && newLandscape != landscape;
|
rotated = !preview.empty() && newLandscape != landscape;
|
||||||
|
|
||||||
if (resize) {
|
preview.resize(prew * preh * 3);
|
||||||
if (preview) {
|
std::copy(img->getData(), img->getData() + preview.size(), preview.begin());
|
||||||
delete [] preview;
|
|
||||||
}
|
|
||||||
preview = new guint8 [prew * preh * 3];
|
|
||||||
}
|
|
||||||
memcpy(preview, img->getData(), prew * preh * 3);
|
|
||||||
{
|
{
|
||||||
GThreadLock lock;
|
GThreadLock lock;
|
||||||
updateBackBuffer ();
|
updateBackBuffer ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,7 +598,7 @@ bool FileBrowserEntry::onArea (CursorArea a, int x, int y)
|
|||||||
{
|
{
|
||||||
|
|
||||||
MYREADERLOCK(l, lockRW);
|
MYREADERLOCK(l, lockRW);
|
||||||
if (!drawable || !preview) {
|
if (!drawable || preview.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1228,8 +1228,9 @@ void FileCatalog::developRequested(const std::vector<FileBrowserEntry*>& tbe, bo
|
|||||||
|
|
||||||
rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params, fastmode && options.fastexport_use_fast_pipeline);
|
rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (fbe->filename, th->getType() == FT_Raw, params, fastmode && options.fastexport_use_fast_pipeline);
|
||||||
|
|
||||||
const int ph = BatchQueue::calcMaxThumbnailHeight();
|
int pw;
|
||||||
const int pw = th->getThumbnailWidth(ph);
|
int ph = BatchQueue::calcMaxThumbnailHeight();
|
||||||
|
th->getThumbnailSize (pw, ph);
|
||||||
|
|
||||||
// processThumbImage is the processing intensive part, but adding to queue must be ordered
|
// processThumbImage is the processing intensive part, but adding to queue must be ordered
|
||||||
//#pragma omp ordered
|
//#pragma omp ordered
|
||||||
|
@@ -400,6 +400,7 @@ void Options::setDefaults()
|
|||||||
overwriteOutputFile = false; // if TRUE, existing output JPGs/PNGs are overwritten, instead of adding ..-1.jpg, -2.jpg etc.
|
overwriteOutputFile = false; // if TRUE, existing output JPGs/PNGs are overwritten, instead of adding ..-1.jpg, -2.jpg etc.
|
||||||
theme = "RawTherapee";
|
theme = "RawTherapee";
|
||||||
maxThumbnailHeight = 250;
|
maxThumbnailHeight = 250;
|
||||||
|
maxThumbnailWidth = 800;
|
||||||
maxCacheEntries = 20000;
|
maxCacheEntries = 20000;
|
||||||
thumbInterp = 1;
|
thumbInterp = 1;
|
||||||
autoSuffix = true;
|
autoSuffix = true;
|
||||||
@@ -1019,6 +1020,10 @@ void Options::readFromFile(Glib::ustring fname)
|
|||||||
maxThumbnailHeight = keyFile.get_integer("File Browser", "MaxPreviewHeight");
|
maxThumbnailHeight = keyFile.get_integer("File Browser", "MaxPreviewHeight");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keyFile.has_key("File Browser", "MaxPreviewWidth")) {
|
||||||
|
maxThumbnailWidth = keyFile.get_integer("File Browser", "MaxPreviewWidth");
|
||||||
|
}
|
||||||
|
|
||||||
if (keyFile.has_key("File Browser", "MaxCacheEntries")) {
|
if (keyFile.has_key("File Browser", "MaxCacheEntries")) {
|
||||||
maxCacheEntries = keyFile.get_integer("File Browser", "MaxCacheEntries");
|
maxCacheEntries = keyFile.get_integer("File Browser", "MaxCacheEntries");
|
||||||
}
|
}
|
||||||
@@ -2114,6 +2119,7 @@ void Options::saveToFile(Glib::ustring fname)
|
|||||||
keyFile.set_integer("File Browser", "ThumbnailSizeQueue", thumbSizeQueue);
|
keyFile.set_integer("File Browser", "ThumbnailSizeQueue", thumbSizeQueue);
|
||||||
keyFile.set_integer("File Browser", "SameThumbSize", sameThumbSize);
|
keyFile.set_integer("File Browser", "SameThumbSize", sameThumbSize);
|
||||||
keyFile.set_integer("File Browser", "MaxPreviewHeight", maxThumbnailHeight);
|
keyFile.set_integer("File Browser", "MaxPreviewHeight", maxThumbnailHeight);
|
||||||
|
keyFile.set_integer("File Browser", "MaxPreviewWidth", maxThumbnailWidth);
|
||||||
keyFile.set_integer("File Browser", "MaxCacheEntries", maxCacheEntries);
|
keyFile.set_integer("File Browser", "MaxCacheEntries", maxCacheEntries);
|
||||||
Glib::ArrayHandle<Glib::ustring> pext = parseExtensions;
|
Glib::ArrayHandle<Glib::ustring> pext = parseExtensions;
|
||||||
keyFile.set_string_list("File Browser", "ParseExtensions", pext);
|
keyFile.set_string_list("File Browser", "ParseExtensions", pext);
|
||||||
|
@@ -281,6 +281,7 @@ public:
|
|||||||
CPBKeyType CPBKeys; // Custom Profile Builder's key type
|
CPBKeyType CPBKeys; // Custom Profile Builder's key type
|
||||||
int editorToSendTo;
|
int editorToSendTo;
|
||||||
int maxThumbnailHeight;
|
int maxThumbnailHeight;
|
||||||
|
int maxThumbnailWidth;
|
||||||
std::size_t maxCacheEntries;
|
std::size_t maxCacheEntries;
|
||||||
int thumbInterp; // 0: nearest, 1: bilinear
|
int thumbInterp; // 0: nearest, 1: bilinear
|
||||||
std::vector<Glib::ustring> parseExtensions; // List containing all extensions type
|
std::vector<Glib::ustring> parseExtensions; // List containing all extensions type
|
||||||
|
@@ -135,7 +135,6 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) :
|
|||||||
textGap(6),
|
textGap(6),
|
||||||
sideMargin(8),
|
sideMargin(8),
|
||||||
lowerMargin(8),
|
lowerMargin(8),
|
||||||
preview(nullptr),
|
|
||||||
dispname(Glib::path_get_basename(fname)),
|
dispname(Glib::path_get_basename(fname)),
|
||||||
buttonSet(nullptr),
|
buttonSet(nullptr),
|
||||||
width(0),
|
width(0),
|
||||||
@@ -171,7 +170,6 @@ ThumbBrowserEntryBase::ThumbBrowserEntryBase (const Glib::ustring& fname) :
|
|||||||
|
|
||||||
ThumbBrowserEntryBase::~ThumbBrowserEntryBase ()
|
ThumbBrowserEntryBase::~ThumbBrowserEntryBase ()
|
||||||
{
|
{
|
||||||
delete[] preview;
|
|
||||||
delete buttonSet;
|
delete buttonSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +205,7 @@ void ThumbBrowserEntryBase::updateBackBuffer ()
|
|||||||
|
|
||||||
bbSelected = selected;
|
bbSelected = selected;
|
||||||
bbFramed = framed;
|
bbFramed = framed;
|
||||||
bbPreview = preview;
|
bbPreview = preview.data();
|
||||||
|
|
||||||
Cairo::RefPtr<Cairo::Context> cc = Cairo::Context::create(surface);
|
Cairo::RefPtr<Cairo::Context> cc = Cairo::Context::create(surface);
|
||||||
|
|
||||||
@@ -237,16 +235,20 @@ void ThumbBrowserEntryBase::updateBackBuffer ()
|
|||||||
|
|
||||||
if (buttonSet) {
|
if (buttonSet) {
|
||||||
int tmp;
|
int tmp;
|
||||||
buttonSet->getAllocatedDimensions (tmp, bsHeight);
|
buttonSet->getAllocatedDimensions(tmp, bsHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int infow, infoh;
|
||||||
|
getTextSizes(infow, infoh);
|
||||||
|
|
||||||
// draw preview frame
|
// draw preview frame
|
||||||
//backBuffer->draw_rectangle (cc, false, (exp_width-prew)/2, upperMargin+bsHeight, prew+1, preh+1);
|
//backBuffer->draw_rectangle (cc, false, (exp_width-prew)/2, upperMargin+bsHeight, prew+1, preh+1);
|
||||||
// draw thumbnail image
|
// draw thumbnail image
|
||||||
if (preview) {
|
if (!preview.empty()) {
|
||||||
prex = borderWidth + (exp_width - prew) / 2;
|
prex = borderWidth + (exp_width - prew) / 2;
|
||||||
prey = upperMargin + bsHeight + borderWidth;
|
const int hh = exp_height - (upperMargin + bsHeight + borderWidth + infoh + lowerMargin);
|
||||||
backBuffer->copyRGBCharData(preview, 0, 0, prew, preh, prew * 3, prex, prey);
|
prey = upperMargin + bsHeight + borderWidth + std::max((hh - preh) / 2, 0);
|
||||||
|
backBuffer->copyRGBCharData(preview.data(), 0, 0, prew, preh, prew * 3, prex, prey);
|
||||||
}
|
}
|
||||||
|
|
||||||
customBackBufferUpdate (cc);
|
customBackBufferUpdate (cc);
|
||||||
@@ -255,9 +257,6 @@ void ThumbBrowserEntryBase::updateBackBuffer ()
|
|||||||
bbIcons = getIconsOnImageArea ();
|
bbIcons = getIconsOnImageArea ();
|
||||||
bbSpecificityIcons = getSpecificityIconsOnImageArea ();
|
bbSpecificityIcons = getSpecificityIconsOnImageArea ();
|
||||||
|
|
||||||
int infow, infoh;
|
|
||||||
getTextSizes (infow, infoh);
|
|
||||||
|
|
||||||
int iofs_x = 4, iofs_y = 4;
|
int iofs_x = 4, iofs_y = 4;
|
||||||
int istartx = prex;
|
int istartx = prex;
|
||||||
int istarty = prey;
|
int istarty = prey;
|
||||||
@@ -356,7 +355,7 @@ void ThumbBrowserEntryBase::updateBackBuffer ()
|
|||||||
textposx_dt = 0;
|
textposx_dt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
textposy = upperMargin + bsHeight + 2 * borderWidth + preh + borderWidth + textGap;
|
textposy = exp_height - lowerMargin - infoh;
|
||||||
textw = exp_width - 2 * textGap;
|
textw = exp_width - 2 * textGap;
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@@ -556,10 +555,7 @@ void ThumbBrowserEntryBase::resize (int h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (preh != old_preh || prew != old_prew) { // if new thumbnail height or new orientation
|
if (preh != old_preh || prew != old_prew) { // if new thumbnail height or new orientation
|
||||||
if (preview) {
|
preview.clear();
|
||||||
delete [] preview;
|
|
||||||
preview = nullptr;
|
|
||||||
}
|
|
||||||
refreshThumbnailImage ();
|
refreshThumbnailImage ();
|
||||||
} else if (backBuffer) {
|
} else if (backBuffer) {
|
||||||
backBuffer->setDirty(true); // This will force a backBuffer update on queue_draw
|
backBuffer->setDirty(true); // This will force a backBuffer update on queue_draw
|
||||||
@@ -620,7 +616,7 @@ void ThumbBrowserEntryBase::draw (Cairo::RefPtr<Cairo::Context> cc)
|
|||||||
bbHeight = backBuffer->getHeight();
|
bbHeight = backBuffer->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!backBuffer || selected != bbSelected || framed != bbFramed || preview != bbPreview
|
if (!backBuffer || selected != bbSelected || framed != bbFramed || preview.data() != bbPreview
|
||||||
|| exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons
|
|| exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons
|
||||||
|| getSpecificityIconsOnImageArea() != bbSpecificityIcons || backBuffer->isDirty())
|
|| getSpecificityIconsOnImageArea() != bbSpecificityIcons || backBuffer->isDirty())
|
||||||
{
|
{
|
||||||
@@ -680,7 +676,7 @@ rtengine::Coord2D ThumbBrowserEntryBase::getPosInImgSpace (int x, int y) const
|
|||||||
{
|
{
|
||||||
rtengine::Coord2D coord(-1., -1.);
|
rtengine::Coord2D coord(-1., -1.);
|
||||||
|
|
||||||
if (preview) {
|
if (!preview.empty()) {
|
||||||
x -= ofsX + startx;
|
x -= ofsX + startx;
|
||||||
y -= ofsY + starty;
|
y -= ofsY + starty;
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ protected:
|
|||||||
|
|
||||||
MyRWMutex lockRW; // Locks access to all image thumb changing actions
|
MyRWMutex lockRW; // Locks access to all image thumb changing actions
|
||||||
|
|
||||||
guint8* preview; // holds the preview image. used in updateBackBuffer. TODO Olli: Make a cache to reduce mem significantly
|
std::vector<guint8> preview; // holds the preview image. used in updateBackBuffer.
|
||||||
|
|
||||||
Glib::ustring dispname;
|
Glib::ustring dispname;
|
||||||
|
|
||||||
|
@@ -121,7 +121,7 @@ void Thumbnail::_generateThumbnailImage ()
|
|||||||
tpp = nullptr;
|
tpp = nullptr;
|
||||||
delete [] lastImg;
|
delete [] lastImg;
|
||||||
lastImg = nullptr;
|
lastImg = nullptr;
|
||||||
tw = -1;
|
tw = options.maxThumbnailWidth;
|
||||||
th = options.maxThumbnailHeight;
|
th = options.maxThumbnailHeight;
|
||||||
imgRatio = -1.;
|
imgRatio = -1.;
|
||||||
|
|
||||||
@@ -138,20 +138,20 @@ void Thumbnail::_generateThumbnailImage ()
|
|||||||
|
|
||||||
if (ext == "jpg" || ext == "jpeg") {
|
if (ext == "jpg" || ext == "jpeg") {
|
||||||
infoFromImage (fname);
|
infoFromImage (fname);
|
||||||
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal);
|
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal);
|
||||||
|
|
||||||
if (tpp) {
|
if (tpp) {
|
||||||
cfs.format = FT_Jpeg;
|
cfs.format = FT_Jpeg;
|
||||||
}
|
}
|
||||||
} else if (ext == "png") {
|
} else if (ext == "png") {
|
||||||
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal);
|
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal);
|
||||||
|
|
||||||
if (tpp) {
|
if (tpp) {
|
||||||
cfs.format = FT_Png;
|
cfs.format = FT_Png;
|
||||||
}
|
}
|
||||||
} else if (ext == "tif" || ext == "tiff") {
|
} else if (ext == "tif" || ext == "tiff") {
|
||||||
infoFromImage (fname);
|
infoFromImage (fname);
|
||||||
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, 1, pparams->wb.equal);
|
tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal);
|
||||||
|
|
||||||
if (tpp) {
|
if (tpp) {
|
||||||
cfs.format = FT_Tiff;
|
cfs.format = FT_Tiff;
|
||||||
@@ -589,10 +589,13 @@ void Thumbnail::decreaseRef ()
|
|||||||
cachemgr->closeThumbnail (this);
|
cachemgr->closeThumbnail (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Thumbnail::getThumbnailWidth (const int h, const rtengine::procparams::ProcParams *pparams) const
|
void Thumbnail::getThumbnailSize(int &w, int &h, const rtengine::procparams::ProcParams *pparams)
|
||||||
{
|
{
|
||||||
|
MyMutex::MyLock lock(mutex);
|
||||||
|
|
||||||
int tw_ = tw;
|
int tw_ = tw;
|
||||||
int th_ = th;
|
int th_ = th;
|
||||||
|
|
||||||
float imgRatio_ = imgRatio;
|
float imgRatio_ = imgRatio;
|
||||||
|
|
||||||
if (pparams) {
|
if (pparams) {
|
||||||
@@ -617,10 +620,16 @@ int Thumbnail::getThumbnailWidth (const int h, const rtengine::procparams::ProcP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imgRatio_ > 0.f) {
|
if (imgRatio_ > 0.) {
|
||||||
return imgRatio_ * h;
|
w = imgRatio_ * static_cast<float>(h);
|
||||||
} else {
|
} else {
|
||||||
return tw_ * h / th_;
|
w = tw_ * h / th_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w > options.maxThumbnailWidth) {
|
||||||
|
const float s = static_cast<float>(options.maxThumbnailWidth) / w;
|
||||||
|
w = options.maxThumbnailWidth;
|
||||||
|
h = std::max<int>(h * s, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ public:
|
|||||||
// unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w
|
// unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w
|
||||||
rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale);
|
rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale);
|
||||||
rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale);
|
rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale);
|
||||||
int getThumbnailWidth (int h, const rtengine::procparams::ProcParams *pparams = nullptr) const;
|
void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams = nullptr);
|
||||||
void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h);
|
void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h);
|
||||||
void getOriginalSize (int& w, int& h);
|
void getOriginalSize (int& w, int& h);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user