From 64481de74be6c15247ab6d9f9f8a86e8a5e7bc34 Mon Sep 17 00:00:00 2001 From: hunbernd Date: Mon, 23 Oct 2017 17:04:20 +0200 Subject: [PATCH] Set the proper size limits --- retroshare-gui/src/gui/chat/ChatWidget.cpp | 40 +++++++++++-------- retroshare-gui/src/gui/chat/ChatWidget.h | 2 + .../src/gui/common/MimeTextEdit.cpp | 2 +- retroshare-gui/src/gui/common/MimeTextEdit.h | 3 ++ retroshare-gui/src/util/HandleRichText.cpp | 9 ++--- retroshare-gui/src/util/HandleRichText.h | 4 +- retroshare-gui/src/util/imageutil.cpp | 28 ++++++++----- retroshare-gui/src/util/imageutil.h | 2 +- 8 files changed, 54 insertions(+), 36 deletions(-) diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index bc7e21de6..ba5c94af7 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -111,7 +111,7 @@ ChatWidget::ChatWidget(QWidget *parent) : ui->searchButton->setFixedSize(buttonSize); ui->searchButton->setIconSize(iconSize); ui->sendButton->setFixedHeight(iconHeight); - ui->sendButton->setIconSize(iconSize); + ui->sendButton->setIconSize(iconSize); //Initialize search iCharToStartSearch=Settings->getChatSearchCharToStartSearch(); @@ -295,6 +295,7 @@ void ChatWidget::init(const ChatId &chat_id, const QString &title) this->title = title; ui->titleLabel->setText(RsHtml::plainText(title)); + ui->chatTextEdit->setMaxBytes(this->maxMessageSize() - 200); RsPeerId ownId = rsPeers->getOwnId(); setName(QString::fromUtf8(rsPeers->getPeerName(ownId).c_str())); @@ -452,6 +453,25 @@ void ChatWidget::processSettings(bool load) Settings->endGroup(); } +uint32_t ChatWidget::maxMessageSize() +{ + uint32_t maxMessageSize = 0; + switch (chatType()) { + case CHATTYPE_UNKNOWN: + break; + case CHATTYPE_PRIVATE: + maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_PRIVATE); + break; + case CHATTYPE_LOBBY: + maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY); + break; + case CHATTYPE_DISTANT: + maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_DISTANT); + break; + } + return maxMessageSize; +} + bool ChatWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == ui->textBrowser || obj == ui->textBrowser->viewport() @@ -1169,20 +1189,7 @@ void ChatWidget::updateLenOfChatTextEdit() RsHtml::optimizeHtml(chatWidget, text); std::wstring msg = text.toStdWString(); - uint32_t maxMessageSize = 0; - switch (chatType()) { - case CHATTYPE_UNKNOWN: - break; - case CHATTYPE_PRIVATE: - maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_PRIVATE); - break; - case CHATTYPE_LOBBY: - maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY); - break; - case CHATTYPE_DISTANT: - maxMessageSize = rsMsgs->getMaxMessageSecuritySize(RS_CHAT_TYPE_DISTANT); - break; - } + uint32_t maxMessageSize = this->maxMessageSize(); int charRemains = 0; if (maxMessageSize > 0) { @@ -1561,7 +1568,8 @@ void ChatWidget::addExtraPicture() QString file; if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg *.jpeg)", file)) { QString encodedImage; - if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480)) { + uint32_t maxMessageSize = this->maxMessageSize(); + if (RsHtml::makeEmbeddedImage(file, encodedImage, 640*480, maxMessageSize - 200)) { //-200 for the html stuff QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage); ui->chatTextEdit->textCursor().insertFragment(fragment); } diff --git a/retroshare-gui/src/gui/chat/ChatWidget.h b/retroshare-gui/src/gui/chat/ChatWidget.h index 174b4d777..30f2e8427 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.h +++ b/retroshare-gui/src/gui/chat/ChatWidget.h @@ -198,6 +198,8 @@ private: void setColorAndFont(bool both); void processSettings(bool load); + uint32_t maxMessageSize(); + void completeNickname(bool reverse); QAbstractItemModel *modelFromPeers(); diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.cpp b/retroshare-gui/src/gui/common/MimeTextEdit.cpp index e3b6d1437..3ec714f0c 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.cpp +++ b/retroshare-gui/src/gui/common/MimeTextEdit.cpp @@ -69,7 +69,7 @@ void MimeTextEdit::insertFromMimeData(const QMimeData* source) QImage image = qvariant_cast(source->imageData()); if (image.isNull() == false) { QString encodedImage; - if (RsHtml::makeEmbeddedImage(image, encodedImage, 640*480)) { + if (RsHtml::makeEmbeddedImage(image, encodedImage, 640*480, mMaxBytes)) { QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(encodedImage); textCursor().insertFragment(fragment); return; diff --git a/retroshare-gui/src/gui/common/MimeTextEdit.h b/retroshare-gui/src/gui/common/MimeTextEdit.h index 2a6529ca1..463452bbf 100644 --- a/retroshare-gui/src/gui/common/MimeTextEdit.h +++ b/retroshare-gui/src/gui/common/MimeTextEdit.h @@ -50,6 +50,8 @@ public: QColor textColorQuote() const { return highliter->textColorQuote();} bool onlyPlainText() const {return mOnlyPlainText;} + void setMaxBytes(int limit) {mMaxBytes = limit;} + public slots: void setTextColorQuote(QColor textColorQuote) { highliter->setTextColorQuote(textColorQuote);} void setOnlyPlainText(bool bOnlyPlainText) {mOnlyPlainText = bOnlyPlainText;} @@ -83,6 +85,7 @@ private: QList mContextMenuActions; RsSyntaxHighlighter *highliter; bool mOnlyPlainText; + int mMaxBytes = -1; //limit content size, for pasting images }; #endif // MIMETEXTEDIT_H diff --git a/retroshare-gui/src/util/HandleRichText.cpp b/retroshare-gui/src/util/HandleRichText.cpp index 558552d19..27c48aacb 100644 --- a/retroshare-gui/src/util/HandleRichText.cpp +++ b/retroshare-gui/src/util/HandleRichText.cpp @@ -1107,7 +1107,7 @@ QString RsHtml::toHtml(QString text, bool realHtml) } /** Loads image and converts image to embedded image HTML fragment **/ -bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels) +bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels, const int maxBytes) { QImage image; @@ -1115,16 +1115,15 @@ bool RsHtml::makeEmbeddedImage(const QString &fileName, QString &embeddedImage, fprintf (stderr, "RsHtml::makeEmbeddedImage() - image \"%s\" can't be load\n", fileName.toLatin1().constData()); return false; } - return RsHtml::makeEmbeddedImage(image, embeddedImage, maxPixels); + return RsHtml::makeEmbeddedImage(image, embeddedImage, maxPixels, maxBytes); } /** Converts image to embedded image HTML fragment **/ -bool RsHtml::makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels) +bool RsHtml::makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels, const int maxBytes) { RsScopeTimer s("Embed image"); QImage opt; - ImageUtil::optimizeSize(embeddedImage, originalImage, opt, maxPixels, 6000-500); - // -500 bytes: keep space for html stuff + return ImageUtil::optimizeSize(embeddedImage, originalImage, opt, maxPixels, maxBytes); } QString RsHtml::plainText(const QString &text) diff --git a/retroshare-gui/src/util/HandleRichText.h b/retroshare-gui/src/util/HandleRichText.h index 54036b53c..a8f8d66ef 100644 --- a/retroshare-gui/src/util/HandleRichText.h +++ b/retroshare-gui/src/util/HandleRichText.h @@ -69,8 +69,8 @@ public: static void optimizeHtml(QString &text, unsigned int flag = 0, const QColor &backgroundColor = Qt::white, qreal desiredContrast = 1.0, int desiredMinimumFontSize = 10); static QString toHtml(QString text, bool realHtml = true); - static bool makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels); - static bool makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels); + static bool makeEmbeddedImage(const QString &fileName, QString &embeddedImage, const int maxPixels, const int maxBytes = -1); + static bool makeEmbeddedImage(const QImage &originalImage, QString &embeddedImage, const int maxPixels, const int maxBytes = -1); static QString plainText(const QString &text); static QString plainText(const std::string &text); diff --git a/retroshare-gui/src/util/imageutil.cpp b/retroshare-gui/src/util/imageutil.cpp index a926f770a..3bb7e38df 100644 --- a/retroshare-gui/src/util/imageutil.cpp +++ b/retroshare-gui/src/util/imageutil.cpp @@ -48,13 +48,13 @@ void ImageUtil::extractImage(QWidget *window, QTextCursor cursor) } } -void ImageUtil::optimizeSize(QString &html, const QImage& original, QImage &optimized, int maxPixels, int maxBytes) +bool ImageUtil::optimizeSize(QString &html, const QImage& original, QImage &optimized, int maxPixels, int maxBytes) { //nothing to do if it fits into the limits optimized = original; if ((maxPixels <= 0) || (optimized.width()*optimized.height() <= maxPixels)) { if(checkSize(html, optimized, maxBytes) <= maxBytes) { - return; + return true; } } @@ -71,11 +71,17 @@ void ImageUtil::optimizeSize(QString &html, const QImage& original, QImage &opti int minwidth = qSqrt(100.0 * whratio); + //if maxBytes not defined, do not reduce color space, just downscale + if(maxBytes <= 0) { + checkSize(html, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation), maxBytes); + return true; + } + //Use binary search to find a suitable image size + linear regression to guess the file size - double maxsize = (double)checkSize(html, original.scaledToWidth(maxwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes); - if(maxsize <= maxBytes) return; //success - double minsize = (double)checkSize(html, original.scaledToWidth(minwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes); - if(minsize > maxBytes) return; //impossible + double maxsize = (double)checkSize(html, optimized = original.scaledToWidth(maxwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes); + if(maxsize <= maxBytes) return true; //success + double minsize = (double)checkSize(html, optimized = original.scaledToWidth(minwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes); + if(minsize > maxBytes) return false; //impossible // std::cout << "maxS: " << maxsize << " minS: " << minsize << std::endl; // std::cout << "maxW: " << maxwidth << " minW: " << minwidth << std::endl; @@ -86,7 +92,7 @@ void ImageUtil::optimizeSize(QString &html, const QImage& original, QImage &opti double b = maxsize - m * ((double)maxwidth * (double)maxwidth / whratio); double a = ((double)(maxBytes - region/2) - b) / m; //maxBytes - region/2 target the center of the accepted region int nextwidth = qSqrt((qreal)(a * whratio)); - double nextsize = (double)checkSize(html, original.scaledToWidth(nextwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes); + double nextsize = (double)checkSize(html, optimized = original.scaledToWidth(nextwidth, Qt::SmoothTransformation).convertToFormat(QImage::Format_Indexed8, ct), maxBytes); if(nextsize <= maxBytes) { minsize = nextsize; minwidth = nextwidth; @@ -99,7 +105,7 @@ void ImageUtil::optimizeSize(QString &html, const QImage& original, QImage &opti // std::cout << "maxS: " << maxsize << " minS: " << minsize << std::endl; // std::cout << "maxW: " << maxwidth << " minW: " << minwidth << std::endl; } while(!success); - + return true; //html = html.arg(original.width()); //std::cout << html.toStdString() << std::endl; } @@ -112,15 +118,15 @@ int ImageUtil::checkSize(QString &embeddedImage, const QImage &img, int maxBytes QBuffer buffer(&bytearray); int size = 0; - std::cout << QString("Trying image: format PNG, size %1x%2, colors %3\n").arg(img.width()).arg(img.height()).arg(img.colorCount()).toStdString(); + //std::cout << QString("Trying image: format PNG, size %1x%2, colors %3\n").arg(img.width()).arg(img.height()).arg(img.colorCount()).toStdString(); if (buffer.open(QIODevice::WriteOnly)) { if (img.save(&buffer, "PNG", 0)) { size = bytearray.length() * 4/3; if((maxBytes > 0) && (size > maxBytes)) // *4/3 for base64 { - std::cout << QString("\tToo large, size: %1, limit: %2 bytes\n").arg(bytearray.length() * 4/3).arg(maxBytes).toStdString(); + //std::cout << QString("\tToo large, size: %1, limit: %2 bytes\n").arg(bytearray.length() * 4/3).arg(maxBytes).toStdString(); }else{ - std::cout << QString("\tOK, size: %1, limit: %2 bytes\n").arg(bytearray.length() * 4/3).arg(maxBytes).toStdString(); + //std::cout << QString("\tOK, size: %1, limit: %2 bytes\n").arg(bytearray.length() * 4/3).arg(maxBytes).toStdString(); QByteArray encodedByteArray = bytearray.toBase64(); //embeddedImage = "