Exemplo n.º 1
0
QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *accuracyPtr)
{
    // First, glob patterns are evaluated. If there is a match with max weight,
    // this one is selected and we are done. Otherwise, the file contents are
    // evaluated and the match with the highest value (either a magic priority or
    // a glob pattern weight) is selected. Matching starts from max level (most
    // specific) in both cases, even when there is already a suffix matching candidate.
    *accuracyPtr = 0;

    // Pass 1) Try to match on the file name
    QStringList candidatesByName = mimeTypeForFileName(fileName);
    if (candidatesByName.count() == 1) {
        *accuracyPtr = 100;
        const QMimeType mime = mimeTypeForName(candidatesByName.at(0));
        if (mime.isValid())
            return mime;
        candidatesByName.clear();
    }

    // Extension is unknown, or matches multiple mimetypes.
    // Pass 2) Match on content, if we can read the data
    if (device->isOpen()) {

        // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
        // This is much faster than seeking back and forth into QIODevice.
        const QByteArray data = device->peek(16384);

        int magicAccuracy = 0;
        QMimeType candidateByData(findByData(data, &magicAccuracy));

        // Disambiguate conflicting extensions (if magic matching found something)
        if (candidateByData.isValid() && magicAccuracy > 0) {
            // "for glob_match in glob_matches:"
            // "if glob_match is subclass or equal to sniffed_type, use glob_match"
            const QString sniffedMime = candidateByData.name();
            foreach (const QString &m, candidatesByName) {
                if (inherits(m, sniffedMime)) {
                    // We have magic + pattern pointing to this, so it's a pretty good match
                    *accuracyPtr = 100;
                    return mimeTypeForName(m);
                }
            }
            *accuracyPtr = magicAccuracy;
            return candidateByData;
        }
    }

    if (candidatesByName.count() > 1) {
        *accuracyPtr = 20;
        candidatesByName.sort(); // to make it deterministic
        const QMimeType mime = mimeTypeForName(candidatesByName.at(0));
        if (mime.isValid())
            return mime;
    }

    return mimeTypeForName(defaultMimeType());
}
Exemplo n.º 2
0
/*!
    Returns a MIME type for \a url.

    If the URL is a local file, this calls mimeTypeForFile.

    Otherwise the matching is done based on the file name only,
    except for schemes where file names don't mean much, like HTTP.
    This method always returns the default mimetype for HTTP URLs,
    use QNetworkAccessManager to handle HTTP URLs properly.

    A valid MIME type is always returned. If \a url doesn't match any
    known MIME type data, the default MIME type (application/octet-stream)
    is returned.
*/
QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const
{
    if (url.isLocalFile())
        return mimeTypeForFile(url.toLocalFile());

    const QString scheme = url.scheme();
    if (scheme.startsWith(QLatin1String("http")))
        return mimeTypeForName(d->defaultMimeType());

    return mimeTypeForFile(url.path());
}
Exemplo n.º 3
0
QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracyPtr)
{
    if (data.isEmpty()) {
        *accuracyPtr = 100;
        return mimeTypeForName(QLatin1String("application/x-zerosize"));
    }

    *accuracyPtr = 0;
    QMimeType candidate = provider()->findByMagic(data, accuracyPtr);

    if (candidate.isValid())
        return candidate;

    if (isTextFile(data)) {
        *accuracyPtr = 5;
        return mimeTypeForName(QLatin1String("text/plain"));
    }

    return mimeTypeForName(defaultMimeType());
}
/*!
    Returns a MIME type for \a url.

    If the URL is a local file, this calls mimeTypeForFile.

    Otherwise the matching is done based on the file name only,
    except for schemes where file names don't mean much, like HTTP.
    This method always returns the default mimetype for HTTP URLs,
    use QNetworkAccessManager to handle HTTP URLs properly.

    A valid MIME type is always returned. If \a url doesn't match any
    known MIME type data, the default MIME type (application/octet-stream)
    is returned.
*/
QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const
{
    if (url.scheme().compare( "file", Qt::CaseInsensitive ) == 0)
        return mimeTypeForFile(url.toLocalFile());

    const QString scheme = url.scheme();
    if (scheme.startsWith(QLatin1String("http")))
        return mimeTypeForName(d->defaultMimeType());

    return mimeTypeForFile(url.path());
}
Exemplo n.º 5
0
/*!
    Returns a MIME type for \a url.

    If the URL is a local file, this calls mimeTypeForFile.

    Otherwise the matching is done based on the file name only,
    except for schemes where file names don't mean much, like HTTP.
    This method always returns the default mimetype for HTTP URLs,
    use QNetworkAccessManager to handle HTTP URLs properly.

    A valid MIME type is always returned. If \a url doesn't match any
    known MIME type data, the default MIME type (application/octet-stream)
    is returned.
*/
QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const
{
#if QT_VERSION >= 0x040800
    if (url.isLocalFile())
#else
    if (url.scheme().isEmpty())
#endif
        return mimeTypeForFile(url.toLocalFile());

    const QString scheme = url.scheme();
    if (scheme.startsWith(QLatin1String("http")))
        return mimeTypeForName(d->defaultMimeType());

    return mimeTypeForFile(url.path());
}
Exemplo n.º 6
0
void Result::createDocument() {
	if (_document) return;

	if (!_thumb_url.isEmpty()) {
		_thumb = ImagePtr(_thumb_url, QSize(90, 90));
	}

	QString mime = _content_type;

	QVector<MTPDocumentAttribute> attributes;
	QSize dimensions(_width, _height);
	if (_type == Type::Gif) {
		const char *filename = (mime == qstr("video/mp4") ? "animation.gif.mp4" : "animation.gif");
		attributes.push_back(MTP_documentAttributeFilename(MTP_string(filename)));
		attributes.push_back(MTP_documentAttributeAnimated());
		attributes.push_back(MTP_documentAttributeVideo(MTP_int(_duration), MTP_int(_width), MTP_int(_height)));
	} else if (_type == Type::Video) {
		attributes.push_back(MTP_documentAttributeVideo(MTP_int(_duration), MTP_int(_width), MTP_int(_height)));
	} else if (_type == Type::Audio) {
		MTPDdocumentAttributeAudio::Flags flags = 0;
		if (mime == qstr("audio/ogg")) {
			flags |= MTPDdocumentAttributeAudio::Flag::f_voice;
		} else {
			QStringList p = mimeTypeForName(mime).globPatterns();
			QString pattern = p.isEmpty() ? QString() : p.front();
			QString extension = pattern.isEmpty() ? qsl(".unknown") : pattern.replace('*', QString());
			QString filename = filedialogDefaultName(qsl("inline"), extension, QString(), true);
			attributes.push_back(MTP_documentAttributeFilename(MTP_string(filename)));
		}
		attributes.push_back(MTP_documentAttributeAudio(MTP_flags(flags), MTP_int(_duration), MTPstring(), MTPstring(), MTPbytes()));
	}

	auto documentId = rand_value<DocumentId>();
	_document = App::documentSet(documentId, nullptr, 0, 0, unixtime(), attributes, mime, _thumb, MTP::maindc(), 0, StorageImageLocation());
	_document->setContentUrl(_content_url);
}
Exemplo n.º 7
0
void LocalImageLoaderPrivate::prepareImages() {
	QString file, filename, mime, stickerMime = qsl("image/webp");
    int32 filesize = 0;
	QImage img;
	QByteArray data;
	PeerId peer;
    uint64 id, thumbId = 0;
	int32 duration = 0;
	QString thumbExt = "jpg";
	ToPrepareMediaType type;
	bool animated = false;
	bool ctrlShiftEnter = false;
	MsgId replyTo = 0;
	{
		QMutexLocker lock(loader->toPrepareMutex());
		ToPrepareMedias &list(loader->toPrepareMedias());
		if (list.isEmpty()) return;

		file = list.front().file;
		img = list.front().img;
		data = list.front().data;
		peer = list.front().peer;
		id = list.front().id;
		type = list.front().type;
		duration = list.front().duration;
		ctrlShiftEnter = list.front().ctrlShiftEnter;
		replyTo = list.front().replyTo;
	}

	if (img.isNull()) {
		if (!file.isEmpty()) {
			QFileInfo info(file);
			if (type == ToPrepareAuto) {
				QString lower(file.toLower());
				const QStringList &photoExtensions(cPhotoExtensions());
				for (QStringList::const_iterator i = photoExtensions.cbegin(), e = photoExtensions.cend(); i != e; ++i) {
					if (lower.lastIndexOf(*i) == lower.size() - i->size()) {
						if (info.size() < MaxUploadPhotoSize) {
							type = ToPreparePhoto;
							break;
						}
					}
				}
				if (type == ToPrepareAuto && info.size() < MaxUploadDocumentSize) {
					type = ToPrepareDocument;
				}
			}
			if (type == ToPrepareDocument) {
				mime = mimeTypeForFile(info).name();
			}
			if (type != ToPrepareAuto && info.size() < MaxUploadPhotoSize) {
				bool opaque = (mime != stickerMime);
				img = App::readImage(file, 0, opaque, &animated);
			}
			filename = info.fileName();
			filesize = info.size();
		} else if (!data.isEmpty()) {
			if (type != ToPrepareAudio) {
				img = App::readImage(data, 0, true, &animated);
				if (type == ToPrepareAuto) {
					if (!img.isNull() && data.size() < MaxUploadPhotoSize) {
						type = ToPreparePhoto;
					} else if (data.size() < MaxUploadDocumentSize) {
						type = ToPrepareDocument;
					} else {
						img = QImage();
					}
				}
			}
			MimeType mimeType = mimeTypeForData(data);
			if (type == ToPrepareDocument || type == ToPrepareAudio) {
				mime = mimeType.name();
			}
			if (mime == "image/jpeg") {
				filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
			} else if (type == ToPrepareAudio) {
				filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
				mime = "audio/ogg";
			} else {
				QString ext;
				QStringList patterns = mimeType.globPatterns();
				if (!patterns.isEmpty()) {
					ext = patterns.front().replace('*', QString());
				}
				filename = filedialogDefaultName((type == ToPrepareAudio) ? qsl("audio") : qsl("doc"), ext, QString(), true);
			}
			filesize = data.size();
		}
	} else {
		if (type == ToPrepareDocument) {
			filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
			mime = mimeTypeForName("image/png").name();
			data = QByteArray();
			{
				QBuffer b(&data);
				img.save(&b, "PNG");
			}
			filesize = data.size();
		} else {
			if (img.hasAlphaChannel()) {
				QImage solid(img.width(), img.height(), QImage::Format_ARGB32_Premultiplied);
				solid.fill(st::white->c);
				{
					QPainter(&solid).drawImage(0, 0, img);
				}
				img = solid;
			}
			type = ToPreparePhoto;
			filename = qsl("Untitled.jpg");
			filesize = 0;
		}
	}

	if ((img.isNull() && ((type != ToPrepareDocument && type != ToPrepareAudio) || !filesize)) || type == ToPrepareAuto || (img.isNull() && file.isEmpty() && data.isEmpty())) { // if could not decide what type
		{
			QMutexLocker lock(loader->toPrepareMutex());
			ToPrepareMedias &list(loader->toPrepareMedias());
			list.pop_front();
		}

		QTimer::singleShot(1, this, SLOT(prepareImages()));

		emit imageFailed(id);
	} else {
		PreparedPhotoThumbs photoThumbs;
		QVector<MTPPhotoSize> photoSizes;

		QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));

		MTPPhotoSize thumb(MTP_photoSizeEmpty(MTP_string("")));
		MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
		MTPDocument document(MTP_documentEmpty(MTP_long(0)));
		MTPAudio audio(MTP_audioEmpty(MTP_long(0)));

		QByteArray jpeg;
		if (type == ToPreparePhoto) {
			int32 w = img.width(), h = img.height();

			QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(img.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
			photoThumbs.insert('s', thumb);
			photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));

			QPixmap medium = (w > 320 || h > 320) ? QPixmap::fromImage(img.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
			photoThumbs.insert('m', medium);
			photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));

			QPixmap full = (w > 1280 || h > 1280) ? QPixmap::fromImage(img.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img);
			photoThumbs.insert('y', full);
			photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

			{
				QBuffer jpegBuffer(&jpeg);
				full.save(&jpegBuffer, "JPG", 77);
			}
			if (!filesize) filesize = jpeg.size();
		
			photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));

			thumbId = id;
		} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull()) {
			int32 w = img.width(), h = img.height();
			QByteArray thumbFormat = "JPG";
			int32 thumbQuality = 87;
			if (animated) {
				attributes.push_back(MTP_documentAttributeAnimated());
			} else if (mime == stickerMime && w > 0 && h > 0 && w <= StickerMaxSize && h <= StickerMaxSize && filesize < StickerInMemory) {
				attributes.push_back(MTP_documentAttributeSticker(MTP_string(""), MTP_inputStickerSetEmpty()));
				thumbFormat = "webp";
				thumbExt = qsl("webp");
			}
			attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
			if (w < 20 * h && h < 20 * w) {
				QPixmap full = (w > 90 || h > 90) ? QPixmap::fromImage(img.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(img, Qt::ColorOnly);

				{
					QBuffer jpegBuffer(&jpeg);
					full.save(&jpegBuffer, thumbFormat, thumbQuality);
				}

				photoThumbs.insert('0', full);
				thumb = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

				thumbId = MTP::nonce<uint64>();
			}
		}

		if (type == ToPrepareDocument) {
			document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
		} else if (type == ToPrepareAudio) {
			audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
		}

		{
			QMutexLocker lock(loader->readyMutex());
			loader->readyList().push_back(ReadyLocalMedia(type, file, filename, filesize, data, id, thumbId, thumbExt, peer, photo, audio, photoThumbs, document, jpeg, ctrlShiftEnter, replyTo));
		}

		{
			QMutexLocker lock(loader->toPrepareMutex());
			ToPrepareMedias &list(loader->toPrepareMedias());
			list.pop_front();
		}

		QTimer::singleShot(1, this, SLOT(prepareImages()));

		emit imageReady();
	}
}
Exemplo n.º 8
0
void FileLoadTask::process() {
	const QString stickerMime = qsl("image/webp");

	_result = FileLoadResultPtr(new FileLoadResult(_id, _to, _originalText));

	QString filename, filemime;
	qint64 filesize = 0;
	QByteArray filedata;

	uint64 thumbId = 0;
	QString thumbname = "thumb.jpg";
	QByteArray thumbdata;

	bool animated = false, song = false, gif = false, voice = (_type == PrepareAudio);
	QImage fullimage = _image;

	if (!_filepath.isEmpty()) {
		QFileInfo info(_filepath);
		if (info.isDir()) {
			_result->filesize = -1;
			return;
		}
		filesize = info.size();
		filemime = mimeTypeForFile(info).name();
		filename = info.fileName();
		if (filesize <= MaxUploadPhotoSize && !voice) {
			bool opaque = (filemime != stickerMime);
			fullimage = App::readImage(_filepath, 0, opaque, &animated);
		}
	} else if (!_content.isEmpty()) {
		filesize = _content.size();
		if (voice) {
			filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
			filemime = "audio/ogg";
		} else {
			MimeType mimeType = mimeTypeForData(_content);
			filemime = mimeType.name();
			if (filesize <= MaxUploadPhotoSize && !voice) {
				bool opaque = (filemime != stickerMime);
				fullimage = App::readImage(_content, 0, opaque, &animated);
			}
			if (filemime == "image/jpeg") {
				filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
			} else {
				QString ext;
				QStringList patterns = mimeType.globPatterns();
				if (!patterns.isEmpty()) {
					ext = patterns.front().replace('*', QString());
				}
				filename = filedialogDefaultName(qsl("file"), ext, QString(), true);
			}
		}
	} else if (!_image.isNull()) {
		_image = QImage();

		filemime = mimeTypeForName("image/png").name();
		filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
		{
			QBuffer buffer(&_content);
			fullimage.save(&buffer, "PNG");
		}
		filesize = _content.size();

		if (fullimage.hasAlphaChannel()) {
			QImage solid(fullimage.width(), fullimage.height(), QImage::Format_ARGB32_Premultiplied);
			solid.fill(st::white->c);
			{
				QPainter(&solid).drawImage(0, 0, fullimage);
			}
			fullimage = solid;
		}
	}
	_result->filesize = (int32)qMin(filesize, qint64(INT_MAX));

	if (!filesize || filesize > MaxUploadDocumentSize) {
		return;
	}

	PreparedPhotoThumbs photoThumbs;
	QVector<MTPPhotoSize> photoSizes;
	QPixmap thumb;

	QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));

	MTPPhotoSize thumbSize(MTP_photoSizeEmpty(MTP_string("")));
	MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
	MTPDocument document(MTP_documentEmpty(MTP_long(0)));

	if (!voice) {
		if (filemime == qstr("audio/mp3") || filemime == qstr("audio/m4a") || filemime == qstr("audio/aac") || filemime == qstr("audio/ogg") || filemime == qstr("audio/flac") ||
			filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
			filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
			filename.endsWith(qstr(".flac"), Qt::CaseInsensitive)) {
			QImage cover;
			QByteArray coverBytes, coverFormat;
			MTPDocumentAttribute audioAttribute = audioReadSongAttributes(_filepath, _content, cover, coverBytes, coverFormat);
			if (audioAttribute.type() == mtpc_documentAttributeAudio) {
				attributes.push_back(audioAttribute);
				song = true;
				if (!cover.isNull()) { // cover to thumb
					int32 cw = cover.width(), ch = cover.height();
					if (cw < 20 * ch && ch < 20 * cw) {
						QPixmap full = (cw > 90 || ch > 90) ? QPixmap::fromImage(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(cover, Qt::ColorOnly);
						{
							QByteArray thumbFormat = "JPG";
							int32 thumbQuality = 87;

							QBuffer buffer(&thumbdata);
							full.save(&buffer, thumbFormat, thumbQuality);
						}

						thumb = full;
						thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

						thumbId = rand_value<uint64>();
					}
				}
			}
		}
		if (filemime == qstr("video/mp4") || filename.endsWith(qstr(".mp4"), Qt::CaseInsensitive) || animated) {
			QImage cover;
			MTPDocumentAttribute animatedAttribute = clipReadAnimatedAttributes(_filepath, _content, cover);
			if (animatedAttribute.type() == mtpc_documentAttributeVideo) {
				int32 cw = cover.width(), ch = cover.height();
				if (cw < 20 * ch && ch < 20 * cw) {
					attributes.push_back(MTP_documentAttributeAnimated());
					attributes.push_back(animatedAttribute);
					gif = true;

					QPixmap full = (cw > 90 || ch > 90) ? QPixmap::fromImage(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(cover, Qt::ColorOnly);
					{
						QByteArray thumbFormat = "JPG";
						int32 thumbQuality = 87;

						QBuffer buffer(&thumbdata);
						full.save(&buffer, thumbFormat, thumbQuality);
					}

					thumb = full;
					thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

					thumbId = rand_value<uint64>();

					if (filename.endsWith(qstr(".mp4"), Qt::CaseInsensitive)) {
						filemime = qstr("video/mp4");
					}
				}
			}
		}
	}

	if (!fullimage.isNull() && fullimage.width() > 0 && !song && !gif && !voice) {
		int32 w = fullimage.width(), h = fullimage.height();
		attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));

		if (w < 20 * h && h < 20 * w) {
			if (animated) {
				attributes.push_back(MTP_documentAttributeAnimated());
			} else if (_type != PrepareDocument) {
				QPixmap thumb = (w > 100 || h > 100) ? QPixmap::fromImage(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
				photoThumbs.insert('s', thumb);
				photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));

				QPixmap medium = (w > 320 || h > 320) ? QPixmap::fromImage(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
				photoThumbs.insert('m', medium);
				photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));

				QPixmap full = (w > 1280 || h > 1280) ? QPixmap::fromImage(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage);
				photoThumbs.insert('y', full);
				photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

				{
					QBuffer buffer(&filedata);
					full.save(&buffer, "JPG", 77);
				}

				photo = MTP_photo(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
			}

			QByteArray thumbFormat = "JPG";
			int32 thumbQuality = 87;
			if (!animated && filemime == stickerMime && w > 0 && h > 0 && w <= StickerMaxSize && h <= StickerMaxSize && filesize < StickerInMemory) {
				attributes.push_back(MTP_documentAttributeSticker(MTP_string(""), MTP_inputStickerSetEmpty()));
				thumbFormat = "webp";
				thumbname = qsl("thumb.webp");
			}

			QPixmap full = (w > 90 || h > 90) ? QPixmap::fromImage(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::ColorOnly) : QPixmap::fromImage(fullimage, Qt::ColorOnly);

			{
				QBuffer buffer(&thumbdata);
				full.save(&buffer, thumbFormat, thumbQuality);
			}

			thumb = full;
			thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

			thumbId = rand_value<uint64>();
		}
	}

	if (voice) {
		attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform)));
		attributes.resize(1);
		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
	} else {
		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
		if (photo.type() == mtpc_photoEmpty) {
			_type = PrepareDocument;
		}
	}

	_result->type = _type;
	_result->filepath = _filepath;
	_result->content = _content;

	_result->filename = filename;
	_result->filemime = filemime;
	_result->setFileData(filedata);

	_result->thumbId = thumbId;
	_result->thumbname = thumbname;
	_result->setThumbData(thumbdata);
	_result->thumb = thumb;

	_result->photo = photo;
	_result->document = document;
	_result->photoThumbs = photoThumbs;
}
Exemplo n.º 9
0
void FileLoadTask::process() {
	const QString stickerMime = qsl("image/webp");

	_result = MakeShared<FileLoadResult>(_id, _to, _caption);

	QString filename, filemime;
	qint64 filesize = 0;
	QByteArray filedata;

	uint64 thumbId = 0;
	QString thumbname = "thumb.jpg";
	QByteArray thumbdata;

	auto animated = false;
	auto song = false;
	auto gif = false;
	auto voice = (_type == SendMediaType::Audio);
	auto fullimage = base::take(_image);
	auto info = _filepath.isEmpty() ? QFileInfo() : QFileInfo(_filepath);
	if (info.exists()) {
		if (info.isDir()) {
			_result->filesize = -1;
			return;
		}
		filesize = info.size();
		filemime = mimeTypeForFile(info).name();
		filename = info.fileName();
		auto opaque = (filemime != stickerMime);
		fullimage = App::readImage(_filepath, 0, opaque, &animated);
	} else if (!_content.isEmpty()) {
		filesize = _content.size();
		if (voice) {
			filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
			filemime = "audio/ogg";
		} else {
			auto mimeType = mimeTypeForData(_content);
			filemime = mimeType.name();
			if (filemime != stickerMime) {
				fullimage = Images::prepareOpaque(std_::move(fullimage));
			}
			if (filemime == "image/jpeg") {
				filename = filedialogDefaultName(qsl("photo"), qsl(".jpg"), QString(), true);
			} else if (filemime == "image/png") {
				filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
			} else {
				QString ext;
				QStringList patterns = mimeType.globPatterns();
				if (!patterns.isEmpty()) {
					ext = patterns.front().replace('*', QString());
				}
				filename = filedialogDefaultName(qsl("file"), ext, QString(), true);
			}
		}
	} else if (!fullimage.isNull() && fullimage.width() > 0) {
		if (_type == SendMediaType::Photo) {
			auto w = fullimage.width(), h = fullimage.height();
			if (w >= 20 * h || h >= 20 * w) {
				_type = SendMediaType::File;
			} else {
				filesize = -1; // Fill later.
				filemime = mimeTypeForName("image/jpeg").name();
				filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
			}
		}
		if (_type == SendMediaType::File) {
			filemime = mimeTypeForName("image/png").name();
			filename = filedialogDefaultName(qsl("image"), qsl(".png"), QString(), true);
			{
				QBuffer buffer(&_content);
				fullimage.save(&buffer, "PNG");
			}
			filesize = _content.size();
		}
		fullimage = Images::prepareOpaque(std_::move(fullimage));
	}
	_result->filesize = (int32)qMin(filesize, qint64(INT_MAX));

	if (!filesize || filesize > App::kFileSizeLimit) {
		return;
	}

	PreparedPhotoThumbs photoThumbs;
	QVector<MTPPhotoSize> photoSizes;
	QPixmap thumb;

	QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));

	MTPPhotoSize thumbSize(MTP_photoSizeEmpty(MTP_string("")));
	MTPPhoto photo(MTP_photoEmpty(MTP_long(0)));
	MTPDocument document(MTP_documentEmpty(MTP_long(0)));

	if (!voice) {
		if (filemime == qstr("audio/mp3") || filemime == qstr("audio/m4a") || filemime == qstr("audio/aac") || filemime == qstr("audio/ogg") || filemime == qstr("audio/flac") ||
			filename.endsWith(qstr(".mp3"), Qt::CaseInsensitive) || filename.endsWith(qstr(".m4a"), Qt::CaseInsensitive) ||
			filename.endsWith(qstr(".aac"), Qt::CaseInsensitive) || filename.endsWith(qstr(".ogg"), Qt::CaseInsensitive) ||
			filename.endsWith(qstr(".flac"), Qt::CaseInsensitive)) {
			QImage cover;
			QByteArray coverBytes, coverFormat;
			MTPDocumentAttribute audioAttribute = audioReadSongAttributes(_filepath, _content, cover, coverBytes, coverFormat);
			if (audioAttribute.type() == mtpc_documentAttributeAudio) {
				attributes.push_back(audioAttribute);
				song = true;
				if (!cover.isNull()) { // cover to thumb
					int32 cw = cover.width(), ch = cover.height();
					if (cw < 20 * ch && ch < 20 * cw) {
						QPixmap full = (cw > 90 || ch > 90) ? App::pixmapFromImageInPlace(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : App::pixmapFromImageInPlace(std_::move(cover));
						{
							QByteArray thumbFormat = "JPG";
							int32 thumbQuality = 87;

							QBuffer buffer(&thumbdata);
							full.save(&buffer, thumbFormat, thumbQuality);
						}

						thumb = full;
						thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

						thumbId = rand_value<uint64>();
					}
				}
			}
		}
		if (filemime == qstr("video/mp4") || filename.endsWith(qstr(".mp4"), Qt::CaseInsensitive) || animated) {
			QImage cover;
			MTPDocumentAttribute animatedAttribute = Media::Clip::readAttributes(_filepath, _content, cover);
			if (animatedAttribute.type() == mtpc_documentAttributeVideo) {
				int32 cw = cover.width(), ch = cover.height();
				if (cw < 20 * ch && ch < 20 * cw) {
					attributes.push_back(MTP_documentAttributeAnimated());
					attributes.push_back(animatedAttribute);
					gif = true;

					QPixmap full = (cw > 90 || ch > 90) ? App::pixmapFromImageInPlace(cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : App::pixmapFromImageInPlace(std_::move(cover));
					{
						QByteArray thumbFormat = "JPG";
						int32 thumbQuality = 87;

						QBuffer buffer(&thumbdata);
						full.save(&buffer, thumbFormat, thumbQuality);
					}

					thumb = full;
					thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

					thumbId = rand_value<uint64>();

					if (filename.endsWith(qstr(".mp4"), Qt::CaseInsensitive)) {
						filemime = qstr("video/mp4");
					}
				}
			}
		}
	}

	if (!fullimage.isNull() && fullimage.width() > 0 && !song && !gif && !voice) {
		auto w = fullimage.width(), h = fullimage.height();
		attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));

		if (w < 20 * h && h < 20 * w) {
			if (animated) {
				attributes.push_back(MTP_documentAttributeAnimated());
			} else if (_type != SendMediaType::File) {
				auto thumb = (w > 100 || h > 100) ? App::pixmapFromImageInPlace(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
				photoThumbs.insert('s', thumb);
				photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));

				auto medium = (w > 320 || h > 320) ? App::pixmapFromImageInPlace(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
				photoThumbs.insert('m', medium);
				photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));

				auto full = (w > 1280 || h > 1280) ? App::pixmapFromImageInPlace(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
				photoThumbs.insert('y', full);
				photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

				{
					QBuffer buffer(&filedata);
					full.save(&buffer, "JPG", 87);
				}

				MTPDphoto::Flags photoFlags = 0;
				photo = MTP_photo(MTP_flags(photoFlags), MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));

				if (filesize < 0) {
					filesize = _result->filesize = filedata.size();
				}
			}

			QByteArray thumbFormat = "JPG";
			int32 thumbQuality = 87;
			if (!animated && filemime == stickerMime && w > 0 && h > 0 && w <= StickerMaxSize && h <= StickerMaxSize && filesize < StickerInMemory) {
				MTPDdocumentAttributeSticker::Flags stickerFlags = 0;
				attributes.push_back(MTP_documentAttributeSticker(MTP_flags(stickerFlags), MTP_string(""), MTP_inputStickerSetEmpty(), MTPMaskCoords()));
				thumbFormat = "webp";
				thumbname = qsl("thumb.webp");
			}

			QPixmap full = (w > 90 || h > 90) ? App::pixmapFromImageInPlace(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage, Qt::ColorOnly);

			{
				QBuffer buffer(&thumbdata);
				full.save(&buffer, thumbFormat, thumbQuality);
			}

			thumb = full;
			thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));

			thumbId = rand_value<uint64>();
		}
	}

	if (voice) {
		attributes[0] = MTP_documentAttributeAudio(MTP_flags(MTPDdocumentAttributeAudio::Flag::f_voice | MTPDdocumentAttributeAudio::Flag::f_waveform), MTP_int(_duration), MTPstring(), MTPstring(), MTP_bytes(documentWaveformEncode5bit(_waveform)));
		attributes.resize(1);
		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
	} else if (_type != SendMediaType::Photo) {
		document = MTP_document(MTP_long(_id), MTP_long(0), MTP_int(unixtime()), MTP_string(filemime), MTP_int(filesize), thumbSize, MTP_int(MTP::maindc()), MTP_int(0), MTP_vector<MTPDocumentAttribute>(attributes));
		_type = SendMediaType::File;
	}

	_result->type = _type;
	_result->filepath = _filepath;
	_result->content = _content;

	_result->filename = filename;
	_result->filemime = filemime;
	_result->setFileData(filedata);

	_result->thumbId = thumbId;
	_result->thumbname = thumbname;
	_result->setThumbData(thumbdata);
	_result->thumb = thumb;

	_result->photo = photo;
	_result->document = document;
	_result->photoThumbs = photoThumbs;
}