Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qsharedimageloader.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <private/qobject_p.h>
6#include <private/qimage_p.h>
7#include <QSharedMemory>
8
9#include <memory>
10
12
13Q_LOGGING_CATEGORY(lcSharedImage, "qt.quick.sharedimage");
14
23};
25
26#if QT_CONFIG(sharedmemory)
27struct SharedImageInfo {
30};
31
32void cleanupSharedImage(void *cleanupInfo)
33{
34 if (!cleanupInfo)
35 return;
36 SharedImageInfo *sii = static_cast<SharedImageInfo *>(cleanupInfo);
37 qCDebug(lcSharedImage) << "Cleanup called for" << sii->path;
38 if (sii->shmp.isNull()) {
39 qCDebug(lcSharedImage) << "shm is 0 for" << sii->path;
40 return;
41 }
42 QSharedMemory *shm = sii->shmp.data();
43 sii->shmp.clear();
44 delete shm; // destructor detaches
45 delete sii;
46}
47#else
48void cleanupSharedImage(void *) {}
49#endif
50
52{
53 Q_DECLARE_PUBLIC(QSharedImageLoader)
54
55public:
57
59
60 void storeImageToMem(void *data, const QImage &img);
61
62 bool verifyMem(const void *data, int size);
63
64 QImage createImageFromMem(const void *data, void *cleanupInfo);
65
66};
67
68
70{
71 Q_ASSERT(data && !img.isNull());
72
73 SharedImageHeader *h = static_cast<SharedImageHeader *>(data);
74 h->magic = 'Q';
75 h->version = 1;
76 h->offset = sizeof(SharedImageHeader);
77 h->width = img.width();
78 h->height = img.height();
79 h->bpl = img.bytesPerLine();
80 h->format = img.format();
81
82 uchar *p = static_cast<uchar *>(data) + sizeof(SharedImageHeader);
83 memcpy(p, img.constBits(), img.sizeInBytes());
84}
85
86
88{
89 if (!data || size < int(sizeof(SharedImageHeader)))
90 return false;
91
92 const SharedImageHeader *h = static_cast<const SharedImageHeader *>(data);
93 if ((h->magic != 'Q')
94 || (h->version < 1)
95 || (h->offset < sizeof(SharedImageHeader))
96 || (h->width <= 0)
97 || (h->height <= 0)
98 || (h->bpl <= 0)
99 || (h->format <= QImage::Format_Invalid)
100 || (h->format >= QImage::NImageFormats)) {
101 return false;
102 }
103
104 int availSize = size - h->offset;
105 if (h->height * h->bpl > availSize)
106 return false;
107 if ((qt_depthForFormat(h->format) * h->width * h->height) > (8 * availSize))
108 return false;
109
110 return true;
111}
112
113
115{
116 const SharedImageHeader *h = static_cast<const SharedImageHeader *>(data);
117 const uchar *p = static_cast<const uchar *>(data) + h->offset;
118
119 QImage img(p, h->width, h->height, h->bpl, h->format, cleanupSharedImage, cleanupInfo);
120 return img;
121}
122
123
125{
126#if QT_CONFIG(sharedmemory)
128
129 QImage nil;
130 if (path.isEmpty())
131 return nil;
132
133 auto shm = std::make_unique<QSharedMemory>(QSharedMemory::legacyNativeKey(q->key(path, params)));
134 bool locked = false;
135
136 if (!shm->attach(QSharedMemory::ReadOnly)) {
137 QImage img = q->loadFile(path, params);
138 if (img.isNull())
139 return nil;
140 size_t size = sizeof(SharedImageHeader) + img.sizeInBytes();
141 if (size > size_t(std::numeric_limits<int>::max())) {
142 qCDebug(lcSharedImage) << "Image" << path << "to large to load";
143 return nil;
144 } else if (shm->create(int(size))) {
145 qCDebug(lcSharedImage) << "Created new shm segment of size" << size << "for image" << path;
146 if (!shm->lock()) {
147 qCDebug(lcSharedImage) << "Lock1 failed!?" << shm->errorString();
148 return nil;
149 }
150 locked = true;
151 storeImageToMem(shm->data(), img);
152 } else if (shm->error() == QSharedMemory::AlreadyExists) {
153 // race handling: other process may have created the share while
154 // we loaded the image, so try again to just attach
155 if (!shm->attach(QSharedMemory::ReadOnly)) {
156 qCDebug(lcSharedImage) << "Attach to existing failed?" << shm->errorString();
157 return nil;
158 }
159 } else {
160 qCDebug(lcSharedImage) << "Create failed?" << shm->errorString();
161 return nil;
162 }
163 }
164
165 Q_ASSERT(shm->isAttached());
166
167 if (!locked) {
168 if (!shm->lock()) {
169 qCDebug(lcSharedImage) << "Lock2 failed!?" << shm->errorString();
170 return nil;
171 }
172 locked = true;
173 }
174
175 if (!verifyMem(shm->constData(), shm->size())) {
176 qCDebug(lcSharedImage) << "Verifymem failed!?";
177 shm->unlock();
178 return nil;
179 }
180
181 QSharedMemory *shmp = shm.release();
182 SharedImageInfo *sii = new SharedImageInfo;
183 sii->path = path;
184 sii->shmp = shmp;
185 QImage shImg = createImageFromMem(shmp->constData(), sii);
186
187 if (!shmp->unlock()) {
188 qCDebug(lcSharedImage) << "UnLock failed!?";
189 }
190
191 return shImg;
192#else
193 Q_UNUSED(path);
195 return QImage();
196#endif
197}
198
199
202{
203}
204
206{
207}
208
210{
212
213 return d->load(path, params);
214}
215
217{
219
220 return QImage(path);
221}
222
224{
226
227 return path;
228}
229
230
232
233#include "moc_qsharedimageloader_p.cpp"
\inmodule QtGui
Definition qimage.h:37
qsizetype sizeInBytes() const
Definition qimage.cpp:1526
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_Invalid
Definition qimage.h:42
@ NImageFormats
Definition qimage.h:79
Definition qlist.h:74
\inmodule QtCore
Definition qobject.h:90
\inmodule QtCore
Definition qpointer.h:18
void storeImageToMem(void *data, const QImage &img)
bool verifyMem(const void *data, int size)
QImage createImageFromMem(const void *data, void *cleanupInfo)
QImage load(const QString &path, QSharedImageLoader::ImageParameters *params)
QSharedImageLoader(QObject *parent=nullptr)
virtual QString key(const QString &path, ImageParameters *params)
virtual QImage loadFile(const QString &path, ImageParameters *params)
QImage load(const QString &path, ImageParameters *params=nullptr)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
Combined button and popup list for selecting options.
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:105
int qt_depthForFormat(QImage::Format format)
Definition qimage_p.h:140
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat GLfloat GLfloat h
void ** params
GLint void * img
Definition qopenglext.h:233
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
void cleanupSharedImage(void *)
#define Q_UNUSED(x)
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
int qint32
Definition qtypes.h:44
unsigned char quint8
Definition qtypes.h:41
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent