/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the WebP plugins in the Qt ImageFormats module.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qheifhandler_p.h"
#include <QtGui/QImage>
#include <QtCore/QSize>
#include <QtCore/QVariant>
#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <type_traits>
constexpr int kDefaultQuality = 50; // TODO: maybe adjust this
QHeifHandler::QHeifHandler() :
QImageIOHandler(),
_device{nullptr},
_readState{nullptr},
_quality{kDefaultQuality}
{
}
QHeifHandler::~QHeifHandler()
{
}
void QHeifHandler::updateDevice()
{
// !_device ==> !_readState
Q_ASSERT(_device || !_readState);
if (!device()) {
qWarning("QHeifHandler::updateDevice() device is null");
}
if (device() != _device) {
// new device; re-read data
_device = device();
_readState.reset();
}
}
QHeifHandler::Format QHeifHandler::canReadFrom(QIODevice& device)
{
// read beginning of ftyp box at beginning of file
constexpr int kHeaderSize = 12;
QByteArray header = device.peek(kHeaderSize);
if (header.size() != kHeaderSize) {
return Format::None;
}
// skip first four bytes, which contain box size
const QByteArray w1 = header.mid(4, 4);
const QByteArray w2 = header.mid(8, 4);
if (w1 != "ftyp") {
// not an ftyp box
return Format::None;
}
// brand follows box name, determines format
if (w2 == "mif1") {
return Format::Heif;
} else if (w2 == "msf1") {
return Format::HeifSequence;
} else if (w2 == "heic" || w2 == "heix") {
return Format::Heic;
} else if (w2 == "hevc" || w2 == "hevx") {
return Format::HeicSequence;
} else {
return Format::None;
}
}
bool QHeifHandler::canRead() const
{
if (!device()) {
return false;
}
auto mimeFormat = canReadFrom(*device());
// Other image plugins set the format here. Not sure if it is really
// necessary or what it accomplishes.
switch (mimeFormat) {
case Format::Heif:
setFormat("heif");
return true;
case Format::HeifSequence:
setFormat("heifs");
return true;
case Format::Heic:
setFormat("heic");
return true;
case Format::HeicSequence:
setFormat("heics");
return true;
default:
return false;
}
}
namespace {
static_assert(heif_error_Ok == 0, "heif_error_Ok assumed to be 0");
template<class T, class D>
std::unique_ptr<T, D> wrapPointer(T* ptr, D deleter)
{
return std::unique_ptr<T, D>(ptr, deleter);
}
template<class... As>
heif_error readContext(As... as)
{
#if LIBHEIF_NUMERIC_VERSION >= 0x01030000
return heif_context_read_from_memory_without_copy(as...);
#else
return heif_context_read_from_memory(as...);
#endif
}
} // namespace
QHeifHandler::ReadState::ReadState(QByteArray&& data,
std::shared_ptr<heif_context>&& ctx,
std::vector<heif_item_id>&& ids,
int index) :
fileData(std::move(data)),
context(std::move(ctx)),
idList(std::move(ids)),
currentIndex(index)
{
}
void QHeifHandler::loadContext()
{
updateDevice();
if (!device()) {
return;
}
if (_readState) {
// context already loaded
return;
}
// read file
auto fileData = device()->readAll();
if (fileData.isEmpty()) {
qDebug("QHeifHandler::loadContext() failed to read file data");
return;
}
// set up new context
std::shared_ptr<heif_context> context(heif_context_alloc(), heif_context_free);
if (!context) {
qDebug("QHeifHandler::loadContext() failed to alloc context");
return;
}
auto error = readContext(context.get(),
fileData.constData(), fileData.size(), nullptr);
if (error.code) {
qDebug("QHeifHandler::loadContext() failed to read context: %s", error.message);
return;
}
int numImages = heif_context_get_number_of_top_level_images(context.get());
std::vector<heif_item_id> idList(numImages, 0);
int numIdsStored = heif_context_get_list_of_top_level_image_IDs(context.get(),
idList.data(),
numImages);
Q_UNUSED(numIdsStored);
Q_ASSERT(numIdsStored == numImages);
// find primary image in sequence; no ordering guaranteed for id values
heif_item_id id{};
error = heif_context_get_primary_image_ID(context.get(), &id);
if (error.code) {
qDebug("QHeifHandler::loadContext() failed to get primary ID: %s", error.message);
return;
}
auto iter = std::find(idList.begin(), idList.end(), id);
if (iter == idList.end()) {
qDebug("QHeifHandler::loadContext() primary image not found in id list");
return;
}
int currentIndex = static_cast<int>(iter - idList.begin());
_readState.reset(new ReadState{std::move(fileData),
std::move(context),
std::move(idList),
currentIndex});
}
bool QHeifHandler::read(QImage* destImage)
{
if (!destImage) {
qWarning("QHeifHandler::read() QImage to read into is null");
return false;
}
loadContext();
if (!_readState) {
qWarning("QHeifHandler::read() failed to create context");
return false;
}
int idIndex = _readState->currentIndex;
Q_ASSERT(idIndex >= 0 && static_cast<size_t>(idIndex) < _readState->idList.size());
auto id = _readState->idList[idIndex];
// get image handle
heif_image_handle* handlePtr = nullptr;
auto error = heif_context_get_image_handle(_readState->context.get(), id, &handlePtr);
auto handle = wrapPointer(handlePtr, heif_image_handle_release);
if (error.code || !handle) {
qDebug("QHeifHandler::read() failed to get image handle: %s", error.message);
return false;
}
// decode image
heif_image* srcImagePtr = nullptr;
error = heif_decode_image(handle.get(),
&srcImagePtr,
heif_colorspace_RGB,
heif_chroma_interleaved_RGBA,
nullptr);
auto srcImage = wrapPointer(srcImagePtr, heif_image_release);
if (error.code || !srcImage) {
qDebug("QHeifHandler::read() failed to decode image: %s", error.message);
return false;
}
auto channel = heif_channel_interleaved;
QSize imgSize(heif_image_get_width(srcImage.get(), channel),
heif_image_get_height(srcImage.get(), channel));
if (!imgSize.isValid()) {
qWarning("QHeifHandler::read() invalid image size: %d x %d",
imgSize.width(), imgSize.height());
return false;
}
int stride = 0;
const uint8_t* data = heif_image_get_plane_readonly(srcImage.get(), channel, &stride);
if (!data) {
qWarning("QHeifHandler::read() pixel data not found");
return false;
}
if (stride <= 0) {
qW
没有合适的资源?快使用搜索试试~ 我知道了~
windows 中 qt 支持 heic 图片的显示
共539个文件
idx:448个
h:16个
tlog:12个
需积分: 0 0 下载量 35 浏览量
2024-05-13
15:15:21
上传
评论
收藏 10.47MB RAR 举报
温馨提示
windows 中 qt 支持 heic 图片的显示 (vs2019 )
资源推荐
资源详情
资源评论
收起资源包目录
windows 中 qt 支持 heic 图片的显示 (539个子文件)
moc_predefs.h.cbt 61B
qheifhandler.cpp 15KB
moc_imageioplugin.cpp 4KB
moc_imageioplugin.cpp 4KB
moc_imageioplugin.cpp 4KB
imageioplugin.cpp 1KB
Makefile.Debug 35KB
Makefile.Debug 35KB
libx265.dll 4.71MB
libx265.dll 2.77MB
heif.dll 1.73MB
libde265.dll 1.41MB
heif.dll 566KB
libde265.dll 407KB
qheifd.dll 99KB
qheif.dll 99KB
qheif.dll 26KB
qheif.exp 847B
qheif.exp 845B
qheif.vcxproj.filters 3KB
x265.h 101KB
heif.h 83KB
heif_cxx.h 39KB
heif_regions.h 39KB
de265.h 18KB
heif_plugin.h 10KB
en265.h 7KB
heif_properties.h 6KB
qheifhandler_p.h 3KB
x265_config.h 1KB
heif_version.h 1KB
de265-version.h 1KB
imageioplugin.h 535B
moc_predefs.h 229B
moc_predefs.h 212B
moc_predefs.h 212B
qnamespace.h.4DA8987AB74B060C.idx 146KB
qnamespace.h.4DA8987AB74B060C.idx 146KB
emmintrin.h.0F1714170A3FF0E7.idx 146KB
emmintrin.h.0F1714170A3FF0E7.idx 146KB
qstring.h.131E25B294E0C4D4.idx 136KB
qstring.h.131E25B294E0C4D4.idx 136KB
qmetatype.h.BB7B5EA729B8EEA2.idx 135KB
qmetatype.h.BB7B5EA729B8EEA2.idx 135KB
vector.610F395AB97B92D1.idx 114KB
qhash.h.BBBCC1954C4470C9.idx 113KB
qhash.h.BBBCC1954C4470C9.idx 113KB
heif.h.FA2801BD5C7D45F2.idx 104KB
heif.h.FA2801BD5C7D45F2.idx 104KB
qmap.h.AD973884825E9079.idx 101KB
qmap.h.AD973884825E9079.idx 100KB
qvector.h.E0A200BD03F18499.idx 100KB
qvector.h.E0A200BD03F18499.idx 99KB
xstring.F6345EDE92FD6CF4.idx 97KB
vector.610F395AB97B92D1.idx 90KB
xstring.F6345EDE92FD6CF4.idx 90KB
qlocale.h.539EC634C562C95D.idx 83KB
qlocale.h.539EC634C562C95D.idx 83KB
qlist.h.625D3C8481596775.idx 83KB
xmmintrin.h.4A6644DDE4BCA210.idx 82KB
xmmintrin.h.4A6644DDE4BCA210.idx 82KB
qlist.h.625D3C8481596775.idx 82KB
algorithm.47B0A28676103868.idx 70KB
algorithm.47B0A28676103868.idx 70KB
cmath.9FB35E880B1DCCFB.idx 61KB
cmath.9FB35E880B1DCCFB.idx 61KB
qtypeinfo.h.F4619EF857AE99E0.idx 60KB
qvarlengtharray.h.E7EE52B9E15CAE8A.idx 59KB
qvarlengtharray.h.E7EE52B9E15CAE8A.idx 59KB
memory.E2F88BD585DFF414.idx 54KB
memory.E2F88BD585DFF414.idx 54KB
qset.h.B4AFD6308D98C4E2.idx 53KB
stdio.h.ADAD2C1D42B3C22A.idx 53KB
qset.h.B4AFD6308D98C4E2.idx 53KB
stdio.h.ADAD2C1D42B3C22A.idx 53KB
qtypeinfo.h.F4619EF857AE99E0.idx 51KB
qsharedpointer_impl.h.1739CA4B222EDCB8.idx 50KB
qsharedpointer_impl.h.1739CA4B222EDCB8.idx 50KB
mmintrin.h.26B0D25A7EA48FFE.idx 48KB
mmintrin.h.26B0D25A7EA48FFE.idx 48KB
list.3EB9A5832DE15266.idx 48KB
corecrt_wstdio.h.CC2BCD844E5A11A9.idx 46KB
corecrt_wstdio.h.CC2BCD844E5A11A9.idx 46KB
stdlib.h.84708FBEA2C9D65A.idx 44KB
qvariant.h.61E3B5CAEACDCED4.idx 44KB
qvariant.h.61E3B5CAEACDCED4.idx 44KB
stdlib.h.84708FBEA2C9D65A.idx 44KB
xutility.D4556C0CC3F31192.idx 44KB
qbytearray.h.9D9984CA49ABBE4E.idx 44KB
xutility.D4556C0CC3F31192.idx 44KB
xhash.B811207C2C2F51B1.idx 43KB
qbytearray.h.9D9984CA49ABBE4E.idx 43KB
qchar.h.BEB6DF51F201C3A2.idx 43KB
qchar.h.BEB6DF51F201C3A2.idx 43KB
functional.C310489C88D94A98.idx 43KB
functional.C310489C88D94A98.idx 43KB
corecrt_math.h.A5085DE3200F2DAD.idx 42KB
corecrt_math.h.A5085DE3200F2DAD.idx 42KB
qcolor.h.2E29CDE70150A9DC.idx 42KB
qcolor.h.2E29CDE70150A9DC.idx 42KB
共 539 条
- 1
- 2
- 3
- 4
- 5
- 6
资源评论
__网瘾少年
- 粉丝: 120
- 资源: 17
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功