Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmemrotate.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant reason:default
4
5#include "qmemrotate_p.h"
7
9
10static const int tileSize = 32;
11
12template<class T>
13static inline void qt_memrotate90_tiled(const T *src, int w, int h, int isstride, T *dest, int idstride)
14{
15 const qsizetype sstride = isstride / sizeof(T);
16 const qsizetype dstride = idstride / sizeof(T);
17
18 const int pack = sizeof(quint32) / sizeof(T);
19 const int unaligned =
20 qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h));
21 const int restX = w % tileSize;
22 const int restY = (h - unaligned) % tileSize;
23 const int unoptimizedY = restY % pack;
24 const int numTilesX = w / tileSize + (restX > 0);
25 const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
26
27 for (int tx = 0; tx < numTilesX; ++tx) {
28 const int startx = w - tx * tileSize - 1;
29 const int stopx = qMax(startx - tileSize, 0);
30
31 if (unaligned) {
32 for (int x = startx; x >= stopx; --x) {
33 T *d = dest + (w - x - 1) * dstride;
34 for (int y = 0; y < unaligned; ++y) {
35 *d++ = src[y * sstride + x];
36 }
37 }
38 }
39
40 for (int ty = 0; ty < numTilesY; ++ty) {
41 const int starty = ty * tileSize + unaligned;
42 const int stopy = qMin(starty + tileSize, h - unoptimizedY);
43
44 for (int x = startx; x >= stopx; --x) {
45 quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty);
46 for (int y = starty; y < stopy; y += pack) {
47 quint32 c = src[y * sstride + x];
48 for (int i = 1; i < pack; ++i) {
49 const int shift = (sizeof(T) * 8 * i);
50 const T color = src[(y + i) * sstride + x];
51 c |= color << shift;
52 }
53 *d++ = c;
54 }
55 }
56 }
57
58 if (unoptimizedY) {
59 const int starty = h - unoptimizedY;
60 for (int x = startx; x >= stopx; --x) {
61 T *d = dest + (w - x - 1) * dstride + starty;
62 for (int y = starty; y < h; ++y) {
63 *d++ = src[y * sstride + x];
64 }
65 }
66 }
67 }
68}
69
70template<class T>
71static inline void qt_memrotate90_tiled_unpacked(const T *src, int w, int h, int isstride, T *dest, int idstride)
72{
73 const qsizetype sstride = isstride;
74 const qsizetype dstride = idstride;
75 const int numTilesX = (w + tileSize - 1) / tileSize;
76 const int numTilesY = (h + tileSize - 1) / tileSize;
77
78 for (int tx = 0; tx < numTilesX; ++tx) {
79 const int startx = w - tx * tileSize - 1;
80 const int stopx = qMax(startx - tileSize, 0);
81
82 for (int ty = 0; ty < numTilesY; ++ty) {
83 const int starty = ty * tileSize;
84 const int stopy = qMin(starty + tileSize, h);
85
86 for (int x = startx; x >= stopx; --x) {
87 T *d = (T *)((char*)dest + (w - x - 1) * dstride) + starty;
88 const char *s = (const char*)(src + x) + starty * sstride;
89 for (int y = starty; y < stopy; ++y) {
90 *d++ = *(const T *)(s);
91 s += sstride;
92 }
93 }
94 }
95 }
96}
97
98template<class T>
99static inline void qt_memrotate270_tiled(const T *src, int w, int h, int isstride, T *dest, int idstride)
100{
101 const qsizetype sstride = isstride / sizeof(T);
102 const qsizetype dstride = idstride / sizeof(T);
103
104 const int pack = sizeof(quint32) / sizeof(T);
105 const int unaligned =
106 qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h));
107 const int restX = w % tileSize;
108 const int restY = (h - unaligned) % tileSize;
109 const int unoptimizedY = restY % pack;
110 const int numTilesX = w / tileSize + (restX > 0);
111 const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
112
113 for (int tx = 0; tx < numTilesX; ++tx) {
114 const int startx = tx * tileSize;
115 const int stopx = qMin(startx + tileSize, w);
116
117 if (unaligned) {
118 for (int x = startx; x < stopx; ++x) {
119 T *d = dest + x * dstride;
120 for (int y = h - 1; y >= h - unaligned; --y) {
121 *d++ = src[y * sstride + x];
122 }
123 }
124 }
125
126 for (int ty = 0; ty < numTilesY; ++ty) {
127 const int starty = h - 1 - unaligned - ty * tileSize;
128 const int stopy = qMax(starty - tileSize, unoptimizedY);
129
130 for (int x = startx; x < stopx; ++x) {
131 quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
132 + h - 1 - starty);
133 for (int y = starty; y >= stopy; y -= pack) {
134 quint32 c = src[y * sstride + x];
135 for (int i = 1; i < pack; ++i) {
136 const int shift = (sizeof(T) * 8 * i);
137 const T color = src[(y - i) * sstride + x];
138 c |= color << shift;
139 }
140 *d++ = c;
141 }
142 }
143 }
144 if (unoptimizedY) {
145 const int starty = unoptimizedY - 1;
146 for (int x = startx; x < stopx; ++x) {
147 T *d = dest + x * dstride + h - 1 - starty;
148 for (int y = starty; y >= 0; --y) {
149 *d++ = src[y * sstride + x];
150 }
151 }
152 }
153 }
154}
155
156template<class T>
157static inline void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int isstride, T *dest, int idstride)
158{
159 const qsizetype sstride = isstride;
160 const qsizetype dstride = idstride;
161 const int numTilesX = (w + tileSize - 1) / tileSize;
162 const int numTilesY = (h + tileSize - 1) / tileSize;
163
164 for (int tx = 0; tx < numTilesX; ++tx) {
165 const int startx = tx * tileSize;
166 const int stopx = qMin(startx + tileSize, w);
167
168 for (int ty = 0; ty < numTilesY; ++ty) {
169 const int starty = h - 1 - ty * tileSize;
170 const int stopy = qMax(starty - tileSize, 0);
171
172 for (int x = startx; x < stopx; ++x) {
173 T *d = (T*)((char*)dest + x * dstride) + h - 1 - starty;
174 const char *s = (const char*)(src + x) + starty * sstride;
175 for (int y = starty; y >= stopy; --y) {
176 *d++ = *(const T*)s;
177 s -= sstride;
178 }
179 }
180 }
181 }
182}
183
184
185template <class T>
186static
187inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, int srcStride,
188 T *dest, int dstStride)
189{
190#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
191 // packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
192 static_assert(sizeof(quint32) % sizeof(T) == 0);
193 qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
194#else
195 qt_memrotate90_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
196#endif
197}
198
199template<class T>
200static inline void qt_memrotate180_template(const T *src, int w, int h, int isstride, T *dest, int idstride)
201{
202 const qsizetype sstride = isstride;
203 const qsizetype dstride = idstride;
204
205 const char *s = (const char*)(src) + (h - 1) * sstride;
206 for (int dy = 0; dy < h; ++dy) {
207 T *d = reinterpret_cast<T*>((char *)(dest) + dy * dstride);
208 src = reinterpret_cast<const T*>(s);
209 for (int dx = 0; dx < w; ++dx) {
210 d[dx] = src[w - 1 - dx];
211 }
212 s -= sstride;
213 }
214}
215
216template <class T>
217static
218inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight, int srcStride,
219 T *dest, int dstStride)
220{
221#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
222 // packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
223 static_assert(sizeof(quint32) % sizeof(T) == 0);
224 qt_memrotate270_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
225#else
226 qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
227#endif
228}
229
230#define QT_IMPL_MEMROTATE(type) Q_GUI_EXPORT
231 void qt_memrotate90(const type *src, int w, int h, int sstride,
232 type *dest, int dstride) \
233{
234 qt_memrotate90_template(src, w, h, sstride, dest, dstride); \
235} Q_GUI_EXPORT
236 void qt_memrotate180(const type *src, int w, int h, int sstride,
237 type *dest, int dstride) \
238{
239 qt_memrotate180_template(src, w, h, sstride, dest, dstride); \
240} Q_GUI_EXPORT
241 void qt_memrotate270(const type *src, int w, int h, int sstride,
242 type *dest, int dstride) \
243{
244 qt_memrotate270_template(src, w, h, sstride, dest, dstride); \
245}
246
247#define QT_IMPL_SIMPLE_MEMROTATE(type) Q_GUI_EXPORT
248 void qt_memrotate90(const type *src, int w, int h, int sstride,
249 type *dest, int dstride) \
250{
251 qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride); \
252} Q_GUI_EXPORT
253 void qt_memrotate180(const type *src, int w, int h, int sstride,
254 type *dest, int dstride) \
255{
256 qt_memrotate180_template(src, w, h, sstride, dest, dstride); \
257} Q_GUI_EXPORT
258 void qt_memrotate270(const type *src, int w, int h, int sstride,
259 type *dest, int dstride) \
260{
261 qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride); \
262}
263
264QT_IMPL_SIMPLE_MEMROTATE(QRgbaFloat32)
268QT_IMPL_MEMROTATE(quint16)
269QT_IMPL_MEMROTATE(quint8)
270
271void qt_memrotate90_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
272{
273 qt_memrotate90(srcPixels, w, h, sbpl, destPixels, dbpl);
274}
275
276void qt_memrotate180_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
277{
278 qt_memrotate180(srcPixels, w, h, sbpl, destPixels, dbpl);
279}
280
281void qt_memrotate270_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
282{
283 qt_memrotate270(srcPixels, w, h, sbpl, destPixels, dbpl);
284}
285
286void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
287{
288 qt_memrotate90((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
289}
290
291void qt_memrotate180_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
292{
293 qt_memrotate180((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
294}
295
296void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
297{
298 qt_memrotate270((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
299}
300
301void qt_memrotate90_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
302{
303 qt_memrotate90((const quint24 *)srcPixels, w, h, sbpl, (quint24 *)destPixels, dbpl);
304}
305
306void qt_memrotate180_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
307{
308 qt_memrotate180((const quint24 *)srcPixels, w, h, sbpl, (quint24 *)destPixels, dbpl);
309}
310
311void qt_memrotate270_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
312{
313 qt_memrotate270((const quint24 *)srcPixels, w, h, sbpl, (quint24 *)destPixels, dbpl);
314}
315
316void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
317{
318 qt_memrotate90((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
319}
320
321void qt_memrotate180_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
322{
323 qt_memrotate180((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
324}
325
326void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
327{
328 qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
329}
330
331
332void qt_memrotate90_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
333{
334 qt_memrotate90((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
335}
336
337void qt_memrotate180_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
338{
339 qt_memrotate180((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
340}
341
342void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
343{
344 qt_memrotate270((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
345}
346
347void qt_memrotate90_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
348{
349 qt_memrotate90((const QRgbaFloat32 *)srcPixels, w, h, sbpl, (QRgbaFloat32 *)destPixels, dbpl);
350}
351
352void qt_memrotate180_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
353{
354 qt_memrotate180((const QRgbaFloat32 *)srcPixels, w, h, sbpl, (QRgbaFloat32 *)destPixels, dbpl);
355}
356
357void qt_memrotate270_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
358{
359 qt_memrotate270((const QRgbaFloat32 *)srcPixels, w, h, sbpl, (QRgbaFloat32 *)destPixels, dbpl);
360}
361
363// 90, 180, 270
364{
365 { nullptr, nullptr, nullptr }, // BPPNone,
366 { nullptr, nullptr, nullptr }, // BPP1MSB,
367 { nullptr, nullptr, nullptr }, // BPP1LSB,
368 { qt_memrotate90_8, qt_memrotate180_8, qt_memrotate270_8 }, // BPP8,
369 { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 }, // BPP16,
370 { qt_memrotate90_24, qt_memrotate180_24, qt_memrotate270_24 }, // BPP24
371 { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // BPP32
372 { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP64
373 { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP16FPx4
374 { qt_memrotate90_128, qt_memrotate180_128, qt_memrotate270_128 }, // BPP32FPx4
375};
376
377QT_END_NAMESPACE
Combined button and popup list for selecting options.
void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
static QT_BEGIN_NAMESPACE const int tileSize
void qt_memrotate90_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate270_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
static void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight, int srcStride, T *dest, int dstStride)
void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
static void qt_memrotate270_tiled(const T *src, int w, int h, int isstride, T *dest, int idstride)
void qt_memrotate180_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
#define QT_IMPL_SIMPLE_MEMROTATE(type)
static void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, int srcStride, T *dest, int dstStride)
void qt_memrotate90_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate180_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate270_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate180_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate270_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
static void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int isstride, T *dest, int idstride)
void qt_memrotate90_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate180_8(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
static void qt_memrotate180_template(const T *src, int w, int h, int isstride, T *dest, int idstride)
void qt_memrotate180_128(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
void qt_memrotate90_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
static void qt_memrotate90_tiled_unpacked(const T *src, int w, int h, int isstride, T *dest, int idstride)
void qt_memrotate180_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
#define QT_IMPL_MEMROTATE(type)
static void qt_memrotate90_tiled(const T *src, int w, int h, int isstride, T *dest, int idstride)
MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3]
void(* MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)