much better quality image size handling
This commit is contained in:
parent
6fc0bdd988
commit
b8f2295bc9
@ -18,6 +18,8 @@ function filterMessage() { }
|
||||
|
||||
The function should be fast and must return values which belong to enumeration [`FilteringAction`](#filteringaction-enum).
|
||||
|
||||
Supported set of built-in "standard library" adheres to [ECMA-262](https://ecma-international.org/publications-and-standards/standards/ecma-262).
|
||||
|
||||
Each article is accessible in your script via global variable named `msg` of type `MessageObject`, see [this file](https://github.com/martinrotter/rssguard/blob/master/src/librssguard/core/messageobject.h) for the declaration. Some properties are writeable, allowing you to change contents of the article before it is written to RSS Guard DB. You can mark article important, change its description, perhaps change author name or even assign some [label](labels) to it!!!
|
||||
|
||||
```{note}
|
||||
|
@ -2,7 +2,6 @@ $os = $args[0]
|
||||
$use_webengine = $args[1]
|
||||
$use_qt5 = $args[2]
|
||||
|
||||
|
||||
if ($use_webengine -eq "ON") {
|
||||
$not_use_webengine = "OFF"
|
||||
}
|
||||
|
@ -358,7 +358,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="m_lblHeightImageAttachments">
|
||||
<property name="text">
|
||||
<string>Limit height of pictures</string>
|
||||
<string>Limit height of all pictures</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_spinHeightImageAttachments</cstring>
|
||||
|
@ -78,13 +78,17 @@ QVariant TextBrowserViewer::loadOneResource(int type, const QUrl& name) {
|
||||
img = QImage::fromData(m_loadedResources.value(resolved_name));
|
||||
}
|
||||
|
||||
int acceptable_width = int(width() * 0.9);
|
||||
int acceptable_width = int(width() * ACCEPTABLE_IMAGE_PERCENTUAL_WIDTH);
|
||||
|
||||
if (img.width() > acceptable_width) {
|
||||
qWarningNN << LOGSEC_GUI << "Picture" << QUOTE_W_SPACE(name)
|
||||
<< "is too wide, down-scaling to prevent horizontal scrollbars.";
|
||||
QElapsedTimer tmr;
|
||||
|
||||
img = img.scaledToWidth(acceptable_width);
|
||||
tmr.start();
|
||||
img = img.scaledToWidth(acceptable_width, Qt::TransformationMode::SmoothTransformation);
|
||||
|
||||
qWarningNN << LOGSEC_GUI << "Picture" << QUOTE_W_SPACE(name)
|
||||
<< "is too wide, down-scaling to prevent horizontal scrollbars. Scaling took"
|
||||
<< NONQUOTE_W_SPACE(tmr.elapsed()) << "miliseconds.";
|
||||
}
|
||||
|
||||
return img;
|
||||
@ -198,32 +202,8 @@ void TextBrowserViewer::loadMessages(const QList<Message>& messages, RootItem* r
|
||||
emit loadingStarted();
|
||||
m_root = root;
|
||||
|
||||
auto html_messages = qApp->skins()->generateHtmlOfArticles(messages, root);
|
||||
|
||||
static QRegularExpression exp_replace_wide_stuff(QSL("width=\"([^\"]+)\""));
|
||||
|
||||
// html_messages.m_html = html_messages.m_html.replace(exp_replace_wide_stuff, QSL("width=\"%1\"").arg(width() *
|
||||
// 0.9));
|
||||
|
||||
// Replace too wide pictures.
|
||||
QRegularExpressionMatch exp_match;
|
||||
qsizetype match_offset = 0;
|
||||
int acceptable_width = int(width() * 0.9);
|
||||
|
||||
while ((exp_match = exp_replace_wide_stuff.match(html_messages.m_html, match_offset)).hasMatch()) {
|
||||
int found_width = exp_match.captured(1).toInt();
|
||||
|
||||
if (found_width > acceptable_width) {
|
||||
qWarningNN << LOGSEC_GUI << "Element" << QUOTE_W_SPACE(exp_match.captured())
|
||||
<< "is too wide, setting smaller value to prevent horizontal scrollbars.";
|
||||
|
||||
html_messages.m_html = html_messages.m_html.replace(exp_match.capturedStart(1),
|
||||
exp_match.capturedLength(1),
|
||||
QString::number(acceptable_width));
|
||||
}
|
||||
|
||||
match_offset = exp_match.capturedEnd();
|
||||
}
|
||||
auto html_messages =
|
||||
qApp->skins()->generateHtmlOfArticles(messages, root, width() * ACCEPTABLE_IMAGE_PERCENTUAL_WIDTH);
|
||||
|
||||
// Remove other characters which cannot be displayed properly.
|
||||
static QRegularExpression exp_symbols("[0-9A-F]{3};");
|
||||
|
@ -50,7 +50,8 @@ WebEnginePage* WebEngineViewer::page() const {
|
||||
}
|
||||
|
||||
void WebEngineViewer::loadMessages(const QList<Message>& messages, RootItem* root) {
|
||||
auto html_messages = qApp->skins()->generateHtmlOfArticles(messages, root);
|
||||
auto html_messages =
|
||||
qApp->skins()->generateHtmlOfArticles(messages, root, width() * ACCEPTABLE_IMAGE_PERCENTUAL_WIDTH);
|
||||
|
||||
m_root = root;
|
||||
m_messageContents = html_messages.m_html;
|
||||
|
@ -26,6 +26,8 @@ struct ContextMenuData {
|
||||
QUrl m_mediaUrl;
|
||||
};
|
||||
|
||||
#define ACCEPTABLE_IMAGE_PERCENTUAL_WIDTH 0.97
|
||||
|
||||
// Interface for web/article viewers.
|
||||
class WebViewer {
|
||||
public:
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/settings.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "services/abstract/rootitem.h"
|
||||
|
||||
#include <QDir>
|
||||
@ -228,11 +229,13 @@ PreparedHtml SkinFactory::prepareHtml(const QString& inner_html, const QUrl& bas
|
||||
return {currentSkin().m_layoutMarkupWrapper.arg(QString(), inner_html), base_url};
|
||||
}
|
||||
|
||||
PreparedHtml SkinFactory::generateHtmlOfArticles(const QList<Message>& messages, RootItem* root) const {
|
||||
PreparedHtml SkinFactory::generateHtmlOfArticles(const QList<Message>& messages,
|
||||
RootItem* root,
|
||||
int desired_width) const {
|
||||
Skin skin = currentSkin();
|
||||
QString messages_layout;
|
||||
QString single_message_layout = skin.m_layoutMarkup;
|
||||
const auto forced_img_size =
|
||||
const int forced_img_height =
|
||||
qApp->settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt();
|
||||
|
||||
auto* feed = root != nullptr
|
||||
@ -261,7 +264,7 @@ PreparedHtml SkinFactory::generateHtmlOfArticles(const QList<Message>& messages,
|
||||
enclosure_images +=
|
||||
skin.m_enclosureImageMarkup.arg(enclosure.m_url,
|
||||
enclosure.m_mimeType,
|
||||
forced_img_size <= 0 ? QString() : QString::number(forced_img_size));
|
||||
forced_img_height <= 0 ? QString() : QString::number(forced_img_height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,15 +277,19 @@ PreparedHtml SkinFactory::generateHtmlOfArticles(const QList<Message>& messages,
|
||||
: qApp->localization()->loadedLocale().toString(message.m_created.toLocalTime(),
|
||||
QLocale::FormatType::ShortFormat);
|
||||
|
||||
QString msg_contents = is_plain ? Qt::convertFromPlainText(message.m_contents, Qt::WhiteSpaceMode::WhiteSpaceNormal)
|
||||
: message.m_contents;
|
||||
|
||||
if (!is_plain) {
|
||||
msg_contents = qApp->web()->limitSizeOfHtmlImages(msg_contents, desired_width, forced_img_height);
|
||||
}
|
||||
|
||||
messages_layout.append(single_message_layout.arg(message.m_title,
|
||||
tr("Written by ") + (message.m_author.isEmpty()
|
||||
? tr("unknown author")
|
||||
: message.m_author),
|
||||
message.m_url,
|
||||
is_plain
|
||||
? Qt::convertFromPlainText(message.m_contents,
|
||||
Qt::WhiteSpaceMode::WhiteSpaceNormal)
|
||||
: message.m_contents,
|
||||
msg_contents,
|
||||
msg_date,
|
||||
enclosures,
|
||||
enclosure_images,
|
||||
|
@ -103,7 +103,7 @@ class RSSGUARD_DLLSPEC SkinFactory : public QObject {
|
||||
QString adBlockedPage(const QString& url, const QString& filter);
|
||||
|
||||
PreparedHtml prepareHtml(const QString& inner_html, const QUrl& base_url);
|
||||
PreparedHtml generateHtmlOfArticles(const QList<Message>& messages, RootItem* root) const;
|
||||
PreparedHtml generateHtmlOfArticles(const QList<Message>& messages, RootItem* root, int desired_width) const;
|
||||
|
||||
// Gets skin about a particular skin.
|
||||
Skin skinInfo(const QString& skin_name, bool lite, bool* ok = nullptr) const;
|
||||
|
@ -258,6 +258,111 @@ QString WebFactory::unescapeHtml(const QString& html) {
|
||||
return output;
|
||||
}
|
||||
|
||||
QString WebFactory::limitSizeOfHtmlImages(const QString& html, int desired_width, int desired_max_height) const {
|
||||
static QRegularExpression exp_image_tag(QSL("<img ([^>]+)>"));
|
||||
static QRegularExpression exp_image_attrs(QSL("(\\w+)=\"([^\"]+)\""));
|
||||
|
||||
// Replace too big pictures. What it exactly does:
|
||||
// - find all <img> tags and check for existence of height/width attributes:
|
||||
// - both found -> keep aspect ratio and change to fit width if too big (or limit height if configured)
|
||||
// - height found only -> limit height if configured
|
||||
// - width found only -> change to fit width if too big
|
||||
// - nothing found (image dimensions are taken directly from picture) -> limit height if configured,
|
||||
QRegularExpressionMatch exp_match;
|
||||
qsizetype match_offset = 0;
|
||||
QString my_html = html;
|
||||
QElapsedTimer tmr;
|
||||
|
||||
IOFactory::writeFile("a.html", html.toUtf8());
|
||||
|
||||
tmr.start();
|
||||
|
||||
while ((exp_match = exp_image_tag.match(my_html, match_offset)).hasMatch()) {
|
||||
QString img_reconstructed = QSL("<img");
|
||||
|
||||
// QString full = exp_match.captured();
|
||||
// auto aa = exp_match.capturedLength();
|
||||
|
||||
QString img_tag_inner_text = exp_match.captured(1);
|
||||
|
||||
// We found image, now we parse its attributes and process them.
|
||||
QRegularExpressionMatchIterator attrs_match_iter = exp_image_attrs.globalMatch(img_tag_inner_text);
|
||||
QMap<QString, QString> attrs;
|
||||
|
||||
while (attrs_match_iter.hasNext()) {
|
||||
QRegularExpressionMatch attrs_match = attrs_match_iter.next();
|
||||
|
||||
QString attr_name = attrs_match.captured(1);
|
||||
QString attr_value = attrs_match.captured(2);
|
||||
|
||||
attrs.insert(attr_name, attr_value);
|
||||
}
|
||||
|
||||
if (attrs.contains("height") && attrs.contains("width")) {
|
||||
double ratio = attrs.value("width").toDouble() / attrs.value("height").toDouble();
|
||||
|
||||
if (desired_max_height > 0) {
|
||||
// We limit height.
|
||||
attrs.insert("height", QString::number(desired_max_height));
|
||||
attrs.insert("width", QString::number(int(ratio * desired_max_height)));
|
||||
}
|
||||
|
||||
// We fit width.
|
||||
if (attrs.value("width").toInt() > desired_width) {
|
||||
attrs.insert("width", QString::number(desired_width));
|
||||
attrs.insert("height", QString::number(int(desired_width / ratio)));
|
||||
}
|
||||
}
|
||||
else if (attrs.contains("width")) {
|
||||
// Only width.
|
||||
if (attrs.value("width").toInt() > desired_width) {
|
||||
attrs.insert("width", QString::number(desired_width));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No dimensions given or just height.
|
||||
if (desired_max_height > 0) {
|
||||
attrs.insert("height", QString::number(desired_max_height));
|
||||
}
|
||||
/*
|
||||
else {
|
||||
// We do not know image dimensions and size limitting is not there.
|
||||
attrs.insert("width", QString::number(desired_width / 2));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Re-insert all attributes.
|
||||
while (!attrs.isEmpty()) {
|
||||
auto first_key = attrs.firstKey();
|
||||
auto first_value = attrs.first();
|
||||
|
||||
img_reconstructed += QSL(" %1=\"%2\"").arg(first_key, first_value);
|
||||
|
||||
attrs.remove(first_key);
|
||||
}
|
||||
|
||||
img_reconstructed += QSL(">");
|
||||
|
||||
my_html = my_html.replace(exp_match.capturedStart(), exp_match.capturedLength(), img_reconstructed);
|
||||
|
||||
/*if (found_width > desired_width) {
|
||||
qWarningNN << LOGSEC_GUI << "Element" << QUOTE_W_SPACE(exp_match.captured())
|
||||
<< "is too wide, setting smaller value to prevent horizontal scrollbars.";
|
||||
|
||||
my_html =
|
||||
my_html.replace(exp_match.capturedStart(1), exp_match.capturedLength(1), QString::number(desired_width));
|
||||
}*/
|
||||
|
||||
match_offset = exp_match.capturedStart() + img_reconstructed.size();
|
||||
}
|
||||
|
||||
IOFactory::writeFile("b.html", my_html.toUtf8());
|
||||
|
||||
qDebugNN << LOGSEC_GUI << "HTML image resizing took" << NONQUOTE_W_SPACE(tmr.elapsed()) << "miliseconds.";
|
||||
return my_html;
|
||||
}
|
||||
|
||||
QString WebFactory::processFeedUriScheme(const QString& url) {
|
||||
if (url.startsWith(QSL(URI_SCHEME_FEED))) {
|
||||
return QSL(URI_SCHEME_HTTPS) + url.mid(QSL(URI_SCHEME_FEED).size());
|
||||
|
@ -38,6 +38,7 @@ class WebFactory : public QObject {
|
||||
// ∀ = ∀ (entity name), ∀ (base-10 entity), ∀ (base-16 entity)
|
||||
QString unescapeHtml(const QString& html);
|
||||
|
||||
QString limitSizeOfHtmlImages(const QString& html, int desired_width, int images_max_height) const;
|
||||
QString processFeedUriScheme(const QString& url);
|
||||
|
||||
AdBlockManager* adBlock() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user