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
qtgafile.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
4#include "qtgafile.h"
5
6#include <QtCore/QIODevice>
7#include <QtCore/QDebug>
8#include <QtCore/QDateTime>
9#include <QtGui/QImageIOHandler>
10
12{
13 Q_DISABLE_COPY(TgaReader)
14
15 TgaReader() = default;
16
17 virtual ~TgaReader() {}
18 virtual QRgb operator()(QIODevice *s) const = 0;
19};
20
21struct Tga16Reader : public TgaReader
22{
24 QRgb operator()(QIODevice *s) const override
25 {
26 char ch1, ch2;
27 if (s->getChar(&ch1) && s->getChar(&ch2)) {
28 quint16 d = (int(ch1) & 0xFF) | ((int(ch2) & 0xFF) << 8);
29 QRgb result = (d & 0x8000) ? 0xFF000000 : 0x00000000;
30 result |= ((d & 0x7C00) << 6) | ((d & 0x03E0) << 3) | (d & 0x001F);
31 return result;
32 } else {
33 return 0;
34 }
35 }
36};
37
38struct Tga24Reader : public TgaReader
39{
40 QRgb operator()(QIODevice *s) const override
41 {
42 char r, g, b;
43 if (s->getChar(&b) && s->getChar(&g) && s->getChar(&r))
44 return qRgb(uchar(r), uchar(g), uchar(b));
45 else
46 return 0;
47 }
48};
49
50struct Tga32Reader : public TgaReader
51{
52 QRgb operator()(QIODevice *s) const override
53 {
54 char r, g, b, a;
55 if (s->getChar(&b) && s->getChar(&g) && s->getChar(&r) && s->getChar(&a))
56 return qRgba(uchar(r), uchar(g), uchar(b), uchar(a));
57 else
58 return 0;
59 }
60};
61
98 : mDevice(device)
99{
100 ::memset(mHeader, 0, HeaderSize);
101 if (!mDevice->isReadable())
102 {
103 mErrorMessage = tr("Could not read image data");
104 return;
105 }
106 if (mDevice->isSequential())
107 {
108 mErrorMessage = tr("Sequential device (eg socket) for image read not supported");
109 return;
110 }
111 if (!mDevice->seek(0))
112 {
113 mErrorMessage = tr("Seek file/device for image read failed");
114 return;
115 }
116 if (device->read(reinterpret_cast<char*>(mHeader), HeaderSize) != HeaderSize) {
117 mErrorMessage = tr("Image header read failed");
118 return;
119 }
120 if (mHeader[ImageType] != 2)
121 {
122 // TODO: should support other image types
123 mErrorMessage = tr("Image type not supported");
124 return;
125 }
126 int bitsPerPixel = mHeader[PixelDepth];
127 bool validDepth = (bitsPerPixel == 16 || bitsPerPixel == 24 || bitsPerPixel == 32);
128 if (!validDepth)
129 {
130 mErrorMessage = tr("Image depth not valid");
131 return;
132 }
133 if (quint64(width()) * quint64(height()) > (8192 * 8192))
134 {
135 mErrorMessage = tr("Image size exceeds limit");
136 return;
137 }
138 int curPos = mDevice->pos();
139 int fileBytes = mDevice->size();
140 if (!mDevice->seek(fileBytes - FooterSize))
141 {
142 mErrorMessage = tr("Could not seek to image read footer");
143 return;
144 }
145 char footer[FooterSize];
146 if (mDevice->read(reinterpret_cast<char*>(footer), FooterSize) != FooterSize) {
147 mErrorMessage = tr("Could not read footer");
148 }
149 if (qstrncmp(&footer[SignatureOffset], "TRUEVISION-XFILE", 16) != 0)
150 {
151 mErrorMessage = tr("Image type (non-TrueVision 2.0) not supported");
152 }
153 if (!mDevice->seek(curPos))
154 {
155 mErrorMessage = tr("Could not reset to read data");
156 }
157}
158
166
182{
183 if (!isValid())
184 return QImage();
185
186 int offset = mHeader[IdLength]; // Mostly always zero
187
188 // Even in TrueColor files a color palette may be present so we have to check it here
189 // even we only support image type 2 (= uncompressed true-color image)
190 if (mHeader[ColorMapType] == 1) {
191 int cmapDepth = mHeader[CMapDepth];
192 if (cmapDepth == 15) // 15 bit is stored as 16 bit + ignoring the highest bit (no alpha)
193 cmapDepth = 16;
194 if (cmapDepth != 16 && cmapDepth != 24 && cmapDepth != 32) {
195 mErrorMessage = tr("Invalid color map depth (%1)").arg(cmapDepth);
196 return {};
197 }
198 offset += littleEndianInt(&mHeader[CMapLength]) * cmapDepth / 8;
199 }
200
201 mDevice->seek(HeaderSize + offset);
202
203 char dummy;
204 for (int i = 0; i < offset; ++i)
205 mDevice->getChar(&dummy);
206
207 int bitsPerPixel = mHeader[PixelDepth];
208 int imageWidth = width();
209 int imageHeight = height();
210
211 unsigned char desc = mHeader[ImageDescriptor];
212 //unsigned char xCorner = desc & 0x10; // 0 = left, 1 = right
213 unsigned char yCorner = desc & 0x20; // 0 = lower, 1 = upper
214
215 QImage im;
216 if (!QImageIOHandler::allocateImage(QSize(imageWidth, imageHeight), QImage::Format_ARGB32, &im))
217 return QImage();
218 TgaReader *reader = 0;
219 if (bitsPerPixel == 16)
220 reader = new Tga16Reader();
221 else if (bitsPerPixel == 24)
222 reader = new Tga24Reader();
223 else if (bitsPerPixel == 32)
224 reader = new Tga32Reader();
225 else
226 return QImage();
227 TgaReader &read = *reader;
228
229 // For now only deal with yCorner, since no one uses xCorner == 1
230 // Also this is upside down, since Qt has the origin flipped
231 if (yCorner)
232 {
233 for (int y = 0; y < imageHeight; ++y)
234 for (int x = 0; x < imageWidth; ++x)
235 im.setPixel(x, y, read(mDevice));
236 }
237 else
238 {
239 for (int y = imageHeight - 1; y >= 0; --y)
240 for (int x = 0; x < imageWidth; ++x)
241 im.setPixel(x, y, read(mDevice));
242 }
243
244 delete reader;
245
246 // TODO: add processing of TGA extension information - ie TGA 2.0 files
247 return im;
248}
IOBluetoothDevice * device
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from.
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
bool getChar(char *c)
Reads one character from the device and stores it in c.
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success,...
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
static bool allocateImage(QSize size, QImage::Format format, QImage *image)
\inmodule QtGui
Definition qimage.h:37
void setPixel(int x, int y, uint index_or_rgb)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qimage.cpp:2588
@ Format_ARGB32
Definition qimage.h:47
\inmodule QtCore
Definition qsize.h:25
bool isValid() const
Definition qtgafile.h:69
@ SignatureOffset
Definition qtgafile.h:44
@ FooterSize
Definition qtgafile.h:45
int width() const
Definition qtgafile.h:98
QTgaFile(QIODevice *)
Construct a new QTgaFile object getting data from device.
Definition qtgafile.cpp:97
int height() const
Definition qtgafile.h:103
@ ColorMapType
Definition qtgafile.h:27
@ CMapDepth
Definition qtgafile.h:31
@ IdLength
Definition qtgafile.h:26
@ CMapLength
Definition qtgafile.h:30
@ ImageDescriptor
Definition qtgafile.h:37
@ PixelDepth
Definition qtgafile.h:36
@ HeaderSize
Definition qtgafile.h:38
@ ImageType
Definition qtgafile.h:28
QImage readImage()
Definition qtgafile.cpp:181
int qstrncmp(const char *str1, const char *str2, size_t len)
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLenum GLuint GLintptr offset
GLboolean GLboolean g
GLint y
GLdouble s
[6]
Definition qopenglext.h:235
GLuint64EXT * result
[6]
constexpr QPixelLayout::BPP bitsPerPixel()
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr QRgb qRgb(int r, int g, int b)
Definition qrgb.h:30
constexpr QRgb qRgba(int r, int g, int b, int a)
Definition qrgb.h:33
#define tr(X)
unsigned char uchar
Definition qtypes.h:32
unsigned short quint16
Definition qtypes.h:48
unsigned long long quint64
Definition qtypes.h:61
ReturnedValue read(const char *data)
QRgb operator()(QIODevice *s) const override
Definition qtgafile.cpp:24
QRgb operator()(QIODevice *s) const override
Definition qtgafile.cpp:40
QRgb operator()(QIODevice *s) const override
Definition qtgafile.cpp:52
virtual QRgb operator()(QIODevice *s) const =0