diff --git a/thumbnail/icoutils_common.cpp b/thumbnail/icoutils_common.cpp --- a/thumbnail/icoutils_common.cpp +++ b/thumbnail/icoutils_common.cpp @@ -21,7 +21,17 @@ #include #include -#define abs(n) ( ( n < 0 ) ? -n : n ) +qreal distance(int width, int height, int desiredWidth, int desiredHeight) +{ + // compute difference of areas + const qreal desiredAspectRatio = (desiredHeight > 0) ? desiredWidth / static_cast(desiredHeight) : 0; + const qreal candidateAspectRatio = (height > 0) ? width / static_cast(height) : std::numeric_limits::max(); + + qreal delta = width - desiredWidth; + delta = (delta >= 0.0 ? delta : -delta * 2 ); // Penalize for scaling up + + return qAbs(candidateAspectRatio - desiredAspectRatio) * 25000 + delta; +} bool IcoUtils::loadIcoImageFromExe(QIODevice * inputDevice, QImage &image, int needWidth, int needHeight, const qint32 iconNumber) { @@ -68,28 +78,19 @@ if ( icons.empty() ) return false; - int min_w = 1024; - int min_h = 1024; int index = icons.size() - 1; - + qreal best = std::numeric_limits::max(); // we loop in reverse order because QtIcoHandler converts all images to 32-bit depth, and resources are ordered from lower depth to higher depth for ( int i_index = icons.size() - 1; i_index >= 0 ; --i_index ) { - const QImage &icon = icons.at(i_index); - int i_width = icon.width(); - int i_height = icon.height(); - int i_w = abs(i_width - needWidth); - int i_h = abs(i_height - needHeight); - if ( i_w < min_w || ( i_w == min_w && i_h < min_h ) ) - { + const qreal dist = distance(icon.width(), icon.height(), needWidth, needHeight); - min_w = i_w; - min_h = i_h; + if (dist < best) { index = i_index; - + best = dist; } }