Qt 4.8
qtgafile.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQuick3D module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qtgafile.h"
43 
44 #include <QtCore/QIODevice>
45 #include <QtCore/QDebug>
46 #include <QtCore/QDateTime>
47 
48 struct TgaReader
49 {
50  virtual ~TgaReader() {}
51  virtual QRgb operator()(QIODevice *s) const = 0;
52 };
53 
54 struct Tga16Reader : public TgaReader
55 {
58  {
59  char ch1, ch2;
60  if (s->getChar(&ch1) && s->getChar(&ch2)) {
61  quint16 d = (int(ch1) & 0xFF) | ((int(ch2) & 0xFF) << 8);
62  QRgb result = (d & 0x8000) ? 0xFF000000 : 0x00000000;
63  result |= (d & 0x7C00 << 6) | (d & 0x03E0 << 3) | (d & 0x001F);
64  return result;
65  } else {
66  return 0;
67  }
68  }
69 };
70 
71 struct Tga24Reader : public TgaReader
72 {
74  {
75  char r, g, b;
76  if (s->getChar(&b) && s->getChar(&g) && s->getChar(&r))
77  return qRgb(uchar(r), uchar(g), uchar(b));
78  else
79  return 0;
80  }
81 };
82 
83 struct Tga32Reader : public TgaReader
84 {
86  {
87  char r, g, b, a;
88  if (s->getChar(&b) && s->getChar(&g) && s->getChar(&r) && s->getChar(&a))
89  return qRgba(uchar(r), uchar(g), uchar(b), uchar(a));
90  else
91  return 0;
92  }
93 };
94 
131  : mDevice(device)
132 {
133  ::memset(mHeader, 0, HeaderSize);
134  if (!mDevice->isReadable())
135  {
136  mErrorMessage = QObject::tr("Could not read image data");
137  return;
138  }
139  if (mDevice->isSequential())
140  {
141  mErrorMessage = QObject::tr("Sequential device (eg socket) for image read not supported");
142  return;
143  }
144  if (!mDevice->seek(0))
145  {
146  mErrorMessage = QObject::tr("Seek file/device for image read failed");
147  return;
148  }
149  int bytes = device->read((char*)mHeader, HeaderSize);
150  if (bytes != HeaderSize)
151  {
152  mErrorMessage = QObject::tr("Image mHeader read failed");
153  device->seek(0);
154  return;
155  }
156  if (mHeader[ImageType] != 2)
157  {
158  // TODO: should support other image types
159  mErrorMessage = QObject::tr("Image type not supported");
160  device->seek(0);
161  return;
162  }
163  int bitsPerPixel = mHeader[PixelDepth];
164  bool validDepth = (bitsPerPixel == 16 || bitsPerPixel == 24 || bitsPerPixel == 32);
165  if (!validDepth)
166  {
167  mErrorMessage = QObject::tr("Image depth not valid");
168  }
169  int fileBytes = mDevice->size();
170  if (!mDevice->seek(fileBytes - FooterSize))
171  {
172  mErrorMessage = QObject::tr("Could not seek to image read footer");
173  device->seek(0);
174  return;
175  }
176  char footer[FooterSize];
177  bytes = mDevice->read((char*)footer, FooterSize);
178  if (bytes != FooterSize)
179  {
180  mErrorMessage = QObject::tr("Could not read footer");
181  }
182  if (qstrncmp(&footer[SignatureOffset], "TRUEVISION-XFILE", 16) != 0)
183  {
184  mErrorMessage = QObject::tr("Image type (non-TrueVision 2.0) not supported");
185  }
186  if (!mDevice->seek(0))
187  {
188  mErrorMessage = QObject::tr("Could not reset to start position");
189  }
190 }
191 
200 {
201 }
202 
221 {
222  if (!isValid())
223  return QImage();
224 
225  int offset = mHeader[IdLength]; // Mostly always zero
226 
227  // Even in TrueColor files a color pallette may be present
228  if (mHeader[ColorMapType] == 1)
230 
231  mDevice->seek(HeaderSize + offset);
232 
233  char dummy;
234  for (int i = 0; i < offset; ++i)
235  mDevice->getChar(&dummy);
236 
237  int bitsPerPixel = mHeader[PixelDepth];
238  int imageWidth = width();
239  int imageHeight = height();
240 
241  unsigned char desc = mHeader[ImageDescriptor];
242  //unsigned char xCorner = desc & 0x10; // 0 = left, 1 = right
243  unsigned char yCorner = desc & 0x20; // 0 = lower, 1 = upper
244 
245  QImage im(imageWidth, imageHeight, QImage::Format_ARGB32);
246  TgaReader *reader = 0;
247  if (bitsPerPixel == 16)
248  reader = new Tga16Reader();
249  else if (bitsPerPixel == 24)
250  reader = new Tga24Reader();
251  else if (bitsPerPixel == 32)
252  reader = new Tga32Reader();
253  TgaReader &read = *reader;
254 
255  // For now only deal with yCorner, since no one uses xCorner == 1
256  // Also this is upside down, since Qt has the origin flipped
257  if (yCorner)
258  {
259  for (int y = 0; y < imageHeight; ++y)
260  for (int x = 0; x < imageWidth; ++x)
261  im.setPixel(x, y, read(mDevice));
262  }
263  else
264  {
265  for (int y = imageHeight - 1; y >= 0; --y)
266  for (int x = 0; x < imageWidth; ++x)
267  im.setPixel(x, y, read(mDevice));
268  }
269 
270  delete reader;
271 
272  // TODO: add processing of TGA extension information - ie TGA 2.0 files
273  return im;
274 }
double d
Definition: qnumeric_p.h:62
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
unsigned int QRgb
Definition: qrgb.h:53
QRgb operator()(QIODevice *s) const
Definition: qtgafile.cpp:73
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
Definition: qiodevice.cpp:544
virtual QRgb operator()(QIODevice *s) const =0
bool getChar(char *c)
Reads one character from the device and stores it in c.
Definition: qiodevice.cpp:1536
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QTgaFile(QIODevice *)
Construct a new QTgaFile object getting data from device.
Definition: qtgafile.cpp:130
long ASN1_INTEGER_get ASN1_INTEGER * a
QImage readImage()
Reads an image file from the QTgaFile&#39;s device, and returns it.
Definition: qtgafile.cpp:220
QString mErrorMessage
Definition: qtgafile.h:99
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
unsigned char uchar
Definition: qglobal.h:994
QRgb operator()(QIODevice *s) const
Definition: qtgafile.cpp:57
QIODevice * mDevice
Definition: qtgafile.h:101
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
Definition: qrgb.h:72
virtual ~TgaReader()
Definition: qtgafile.cpp:50
unsigned short quint16
Definition: qglobal.h:936
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition: qiodevice.cpp:454
void setPixel(int x, int y, uint index_or_rgb)
Sets the pixel index or color at (x, y) to index_or_rgb.
Definition: qimage.cpp:4311
unsigned char mHeader[HeaderSize]
Definition: qtgafile.h:100
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qbytearray.h:101
bool isValid() const
Definition: qtgafile.h:104
QRgb operator()(QIODevice *s) const
Definition: qtgafile.cpp:85
static quint16 littleEndianInt(const unsigned char *d)
Returns the integer encoded in the two little endian bytes at d.
Definition: qtgafile.h:121
~QTgaFile()
Destroy the device, recovering any resources.
Definition: qtgafile.cpp:199
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
int width() const
Definition: qtgafile.h:136
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
int height() const
Definition: qtgafile.h:141