Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
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
8#include <QtCore/qpointer.h>
9#include <QSharedMemory>
10
11#include <memory>
12
14
15Q_LOGGING_CATEGORY(lcSharedImage, "qt.quick.sharedimage");
16
27
28#if QT_CONFIG(sharedmemory)
29struct SharedImageInfo {
31 QPointer<QSharedMemory> shmp;
32};
33
34void cleanupSharedImage(void *cleanupInfo)
35{
36 if (!cleanupInfo)
37 return;
38 SharedImageInfo *sii = static_cast<SharedImageInfo *>(cleanupInfo);
39 qCDebug(lcSharedImage) << "Cleanup called for" << sii->path;
40 if (sii->shmp.isNull()) {
41 qCDebug(lcSharedImage) << "shm is 0 for" << sii->path;
42 return;
43 }
44 QSharedMemory *shm = sii->shmp.data();
45 sii->shmp.clear();
46 delete shm; // destructor detaches
47 delete sii;
48}
49#else
50void cleanupSharedImage(void *) {}
51#endif
52
54{
55 Q_DECLARE_PUBLIC(QSharedImageLoader)
56
57public:
59
61
62 void storeImageToMem(void *data, const QImage &img);
63
64 bool verifyMem(const void *data, int size);
65
66 QImage createImageFromMem(const void *data, void *cleanupInfo);
67
68};
69
70
72{
73 Q_ASSERT(data && !img.isNull());
74
75 SharedImageHeader *h = static_cast<SharedImageHeader *>(data);
76 h->magic = 'Q';
77 h->version = 1;
78 h->offset = sizeof(SharedImageHeader);
79 h->width = img.width();
80 h->height = img.height();
81 h->bpl = img.bytesPerLine();
82 h->format = img.format();
83
84 uchar *p = static_cast<uchar *>(data) + sizeof(SharedImageHeader);
85 memcpy(p, img.constBits(), img.sizeInBytes());
86}
87
88
90{
91 if (!data || size < int(sizeof(SharedImageHeader)))
92 return false;
93
94 const SharedImageHeader *h = static_cast<const SharedImageHeader *>(data);
95 if ((h->magic != 'Q')
96 || (h->version < 1)
97 || (h->offset < sizeof(SharedImageHeader))
98 || (h->width <= 0)
99 || (h->height <= 0)
100 || (h->bpl <= 0)
101 || (h->format <= QImage::Format_Invalid)
102 || (h->format >= QImage::NImageFormats)) {
103 return false;
104 }
105
106 int availSize = size - h->offset;
107 if (h->height * h->bpl > availSize)
108 return false;
109 if ((qt_depthForFormat(h->format) * h->width * h->height) > (8 * availSize))
110 return false;
111
112 return true;
113}
114
115
117{
118 const SharedImageHeader *h = static_cast<const SharedImageHeader *>(data);
119 const uchar *p = static_cast<const uchar *>(data) + h->offset;
120
121 QImage img(p, h->width, h->height, h->bpl, h->format, cleanupSharedImage, cleanupInfo);
122 return img;
123}
124
125
127{
128#if QT_CONFIG(sharedmemory)
130
131 QImage nil;
132 if (path.isEmpty())
133 return nil;
134
135 auto shm = std::make_unique<QSharedMemory>(QSharedMemory::legacyNativeKey(q->key(path, params)));
136 bool locked = false;
137
138 if (!shm->attach(QSharedMemory::ReadOnly)) {
139 QImage img = q->loadFile(path, params);
140 if (img.isNull())
141 return nil;
142 size_t size = sizeof(SharedImageHeader) + img.sizeInBytes();
143 if (size > size_t(std::numeric_limits<int>::max())) {
144 qCDebug(lcSharedImage) << "Image" << path << "to large to load";
145 return nil;
146 } else if (shm->create(int(size))) {
147 qCDebug(lcSharedImage) << "Created new shm segment of size" << size << "for image" << path;
148 if (!shm->lock()) {
149 qCDebug(lcSharedImage) << "Lock1 failed!?" << shm->errorString();
150 return nil;
151 }
152 locked = true;
153 storeImageToMem(shm->data(), img);
154 } else if (shm->error() == QSharedMemory::AlreadyExists) {
155 // race handling: other process may have created the share while
156 // we loaded the image, so try again to just attach
157 if (!shm->attach(QSharedMemory::ReadOnly)) {
158 qCDebug(lcSharedImage) << "Attach to existing failed?" << shm->errorString();
159 return nil;
160 }
161 } else {
162 qCDebug(lcSharedImage) << "Create failed?" << shm->errorString();
163 return nil;
164 }
165 }
166
167 Q_ASSERT(shm->isAttached());
168
169 if (!locked) {
170 if (!shm->lock()) {
171 qCDebug(lcSharedImage) << "Lock2 failed!?" << shm->errorString();
172 return nil;
173 }
174 locked = true;
175 }
176
177 if (!verifyMem(shm->constData(), shm->size())) {
178 qCDebug(lcSharedImage) << "Verifymem failed!?";
179 shm->unlock();
180 return nil;
181 }
182
183 QSharedMemory *shmp = shm.release();
184 SharedImageInfo *sii = new SharedImageInfo;
185 sii->path = path;
186 sii->shmp = shmp;
187 QImage shImg = createImageFromMem(shmp->constData(), sii);
188
189 if (!shmp->unlock()) {
190 qCDebug(lcSharedImage) << "UnLock failed!?";
191 }
192
193 return shImg;
194#else
195 Q_UNUSED(path);
197 return QImage();
198#endif
199}
200
201
206
210
212{
214
215 return d->load(path, params);
216}
217
224
231
232
234
235#include "moc_qsharedimageloader_p.cpp"
\inmodule QtGui
Definition qimage.h:37
qsizetype sizeInBytes() const
Definition qimage.cpp:1548
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_Invalid
Definition qimage.h:42
@ NImageFormats
Definition qimage.h:80
Definition qlist.h:75
\inmodule QtCore
Definition qobject.h:103
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:129
Combined button and popup list for selecting options.
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:108
int qt_depthForFormat(QImage::Format format)
Definition qimage_p.h:142
#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:32
unsigned short quint16
Definition qtypes.h:48
int qint32
Definition qtypes.h:49
unsigned char quint8
Definition qtypes.h:46