Changeset View
Standalone View
thumbnail/icoutils_common.cpp
Show All 15 Lines | |||||
16 | #include "icoutils.h" | 16 | #include "icoutils.h" | ||
17 | 17 | | |||
18 | #include <QList> | 18 | #include <QList> | ||
19 | #include <QString> | 19 | #include <QString> | ||
20 | #include <QTemporaryFile> | 20 | #include <QTemporaryFile> | ||
21 | #include <QImage> | 21 | #include <QImage> | ||
22 | #include <QImageReader> | 22 | #include <QImageReader> | ||
23 | 23 | | |||
24 | #define abs(n) ( ( n < 0 ) ? -n : n ) | 24 | #include <algorithm> | ||
25 | | ||||
26 | qreal distance(int width, int height, int desiredWidth, int desiredHeight, int depth) | ||||
27 | { | ||||
28 | // We want as high of a depth as possible (32-bit) | ||||
bruns: Can not see an area calculation here ... | |||||
29 | auto targetSamples = desiredWidth * desiredHeight * 32; | ||||
30 | auto xscale = (1.0 * desiredWidth) / width; | ||||
31 | auto yscale = (1.0 * desiredHeight) / height; | ||||
32 | | ||||
33 | // clamp to the lower of the two scales | ||||
ngraham: Where does this magic number come from? | |||||
broulik: No idea, really. | |||||
I think the formula is a little bit to ad-hoc, and actually wrong. We have 2 different notable cases. desiredAspectRatio obviously is a constant, this leaves us with candidateAspectRatio and delta
Think of e.g. a requested size of 96x96, and two candidates, 32x32 and 128x64. The small one has a distance of 128, while the second one has a distance 25032. I don't think that's wanted here. bruns: I think the formula is a little bit to ad-hoc, and actually wrong.
We have 2 different notable… | |||||
I'm open to suggestions … also technically you cannot assume the icon is square broulik: I'm open to suggestions … also technically you cannot assume the icon is square | |||||
bruns: Where do you see any assumption about square icons? | |||||
anthonyfieroni: It should be qFuzzyIsNull no? | |||||
@anthonyfieroni Why? bruns: @anthonyfieroni Why? | |||||
anthonyfieroni: Comparing doubles should be done by epsilon not by <= 0.0 | |||||
Not in general. There is nothing inexact here. Also, if difference ~= 0, it does not matter if you scale by 1, 2, -1 or -2. bruns: Not in general. There is nothing inexact here. Also, if difference ~= 0, it does not matter if… | |||||
34 | // also clamp to one, as scaling up adds no effective | ||||
35 | // samples, only interpolated samples | ||||
36 | auto sampleScale = std::min(1.0, std::min(xscale, yscale)); | ||||
37 | | ||||
38 | // number of effective source samles in the target | ||||
39 | auto effectiveSamples = width * height * sampleScale * sampleScale * depth; | ||||
40 | // scale down another time, to account for loss of fidelity when | ||||
41 | // using a downscaled image, biases towards smaller downscaling ratios | ||||
42 | effectiveSamples *= sampleScale; | ||||
43 | | ||||
44 | return targetSamples - effectiveSamples; | ||||
45 | } | ||||
25 | 46 | | |||
26 | bool IcoUtils::loadIcoImageFromExe(QIODevice * inputDevice, QImage &image, int needWidth, int needHeight, const qint32 iconNumber) | 47 | bool IcoUtils::loadIcoImageFromExe(QIODevice * inputDevice, QImage &image, int needWidth, int needHeight, const qint32 iconNumber) | ||
27 | { | 48 | { | ||
28 | 49 | | |||
29 | QTemporaryFile inputFile; | 50 | QTemporaryFile inputFile; | ||
30 | 51 | | |||
31 | if ( ! inputFile.open() ) | 52 | if ( ! inputFile.open() ) | ||
32 | return false; | 53 | return false; | ||
Show All 30 Lines | 80 | { | |||
63 | 84 | | |||
64 | QList <QImage> icons; | 85 | QList <QImage> icons; | ||
65 | do icons << reader.read(); | 86 | do icons << reader.read(); | ||
66 | while ( reader.jumpToNextImage() ); | 87 | while ( reader.jumpToNextImage() ); | ||
67 | 88 | | |||
68 | if ( icons.empty() ) | 89 | if ( icons.empty() ) | ||
69 | return false; | 90 | return false; | ||
70 | 91 | | |||
71 | int min_w = 1024; | | |||
72 | int min_h = 1024; | | |||
73 | int index = icons.size() - 1; | 92 | int index = icons.size() - 1; | ||
93 | qreal best = std::numeric_limits<qreal>::max(); | ||||
74 | 94 | | |||
95 | for (int i = 0; i < icons.size(); ++i) { | ||||
96 | const QImage &icon = icons.at(i); | ||||
75 | 97 | | |||
76 | // we loop in reverse order because QtIcoHandler converts all images to 32-bit depth, and resources are ordered from lower depth to higher depth | 98 | // QtIcoHandler converts all images to 32-bit depth, | ||
77 | for ( int i_index = icons.size() - 1; i_index >= 0 ; --i_index ) | 99 | // but it stores the actual depth of the icon extracted in custom text: | ||
grammatical nitpick:
i.e. missing , in the first line, and third person otherwise it's good to go bruns: grammatical nitpick:
> // QtIcoHandler converts all images to 32 bit depth**,**
> // but **it… | |||||
78 | { | 100 | // qtbase/src/plugins/imageformats/ico/qicohandler.cpp:455 | ||
bruns: qico_handler.cpp (no "n")
| |||||
broulik: No, that is the actual file name on qtbase git dev | |||||
bruns: https://github.com/qt/qtbase/blob/5.11/src/plugins/imageformats/ico/qicohandler.cpp | |||||
79 | 101 | int depth = icon.text(QStringLiteral("_q_icoOrigDepth")).toInt(); | |||
80 | const QImage &icon = icons.at(i_index); | 102 | if (depth == 0) { | ||
81 | int i_width = icon.width(); | 103 | depth = icon.depth(); | ||
82 | int i_height = icon.height(); | 104 | } | ||
bruns: either Qt handler for "Ico" files or qicohandler | |||||
83 | int i_w = abs(i_width - needWidth); | | |||
84 | int i_h = abs(i_height - needHeight); | | |||
85 | | ||||
86 | if ( i_w < min_w || ( i_w == min_w && i_h < min_h ) ) | | |||
87 | { | | |||
88 | 105 | | |||
89 | min_w = i_w; | 106 | const qreal dist = distance(icon.width(), icon.height(), needWidth, needHeight, depth); | ||
90 | min_h = i_h; | | |||
91 | index = i_index; | | |||
92 | 107 | | |||
108 | if (dist < best) { | ||||
109 | index = i; | ||||
110 | best = dist; | ||||
93 | } | 111 | } | ||
94 | | ||||
95 | } | 112 | } | ||
96 | 113 | | |||
97 | image = icons.at(index); | 114 | image = icons.at(index); | ||
98 | return true; | 115 | return true; | ||
99 | 116 | | |||
100 | } | 117 | } | ||
101 | 118 | | |||
102 | bool IcoUtils::loadIcoImage(QIODevice * inputDevice, QImage &image, int needWidth, int needHeight) | 119 | bool IcoUtils::loadIcoImage(QIODevice * inputDevice, QImage &image, int needWidth, int needHeight) | ||
Show All 14 Lines |
Can not see an area calculation here ...