1#define QT3_SUPPORT
2#include <QtGui/QApplication.h>
3#include <qlabel.h>
4#include <qpixmap.h>
5
6
7#pragma pack(push, 1)
8struct TgaHeader
9{
10 char identsize; // size of ID field that follows 18 byte header (0 usually)
11 char colourmaptype; // type of colour map 0=none, 1=has palette
12 char imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
13
14 short colourmapstart; // first colour map entry in palette
15 short colourmaplength; // number of colours in palette
16 char colourmapbits; // number of bits per palette entry 15,16,24,32
17
18 short xstart; // image x origin
19 short ystart; // image y origin
20
21 short width; // image width in pixels
22 short height; // image height in pixels
23
24 char bits; // image bits per pixel 8,16,24,32
25 char descriptor; // image descriptor bits (vh flip bits)
26
27};
28#pragma pack(pop)
29
30QPixmap loadTGA(const char *filename);
31
32int main(int argc, char *argv[])
33{
34 QApplication displayTGA(argc, argv);
35 QLabel *label =new QLabel("DisplayTGAFormatimage",0);
36 //QPixmap pm("rockbump.tga");
37 QPixmap pm(loadTGA("rockbump.tga"));
38
39 label->setPixmap(pm);
40 displayTGA.setMainWidget(label);
41 label->show();
42 return displayTGA.exec();
43}
44
45QPixmap loadTGA(const char *filename)
46{
47 // check if file has tga extension
48 bool isTga = false;
49 int len = strlen(filename);
50 if(len >= 3)
51 {
52 char ext[3];
53 ext[0] = tolower(filename[len - 3]);
54 ext[1] = tolower(filename[len - 2]);
55 ext[2] = tolower(filename[len - 1]);
56 if(ext[0] == 't' && ext[1] == 'g' && ext[2] == 'a')
57 isTga = true;
58 }
59
60 if(!isTga)
61 return QPixmap(filename);
62
63 // stupid Qt doesn't know how to load tga, so we'll load it by ourselves
64 QPixmap pixmap;
65
66 FILE *fp; // file streams would be more c++ oh well :D
67 fp = fopen(filename, "rb");
68
69 if(!fp)
70 return pixmap;
71
72 TgaHeader header;
73 fread(&header, sizeof(TgaHeader), 1, fp);
74
75 // we only deal with rgb images, unmapped and rle, and no additional header information
76 if(header.imagetype != 2 && header.imagetype != 10 && !header.identsize && !header.colourmaptype)
77 {
78 fclose(fp);
79 return pixmap;
80 }
81
82 int bytesPerPixel = header.bits/8;
83 int imageSize = header.width * header.height * bytesPerPixel;
84 uchar *imageData = new uchar[imageSize];
85 fread(imageData, imageSize, 1, fp);
86 fclose(fp);
87
88 // decode rle, if any
89 if(header.imagetype == 10)
90 {
91 uchar *rleData = new uchar[imageSize];
92 memcpy(rleData, imageData, imageSize);
93
94 int i = 0;
95 int r = 0;
96 while(i < imageSize && r < imageSize)
97 {
98 int num = (rleData[r]&0x7F) + 1;
99 if(rleData[r] > 127) // is rle
100 {
101 for(int k = 0; k < num; ++k)
102 {
103 if(r + 1 + bytesPerPixel >= imageSize || i >= imageSize)
104 return pixmap; // corrupt image data!
105
106 memcpy(&imageData[i], &rleData[r + 1], bytesPerPixel);
107 i += bytesPerPixel;
108 }
109 r += bytesPerPixel + 1;
110 }
111 else
112 {
113 if(r + num * bytesPerPixel + 1 >= imageSize)
114 return pixmap; // corrupt image data!
115
116 memcpy(&imageData[i], &rleData[r + 1], num * bytesPerPixel);
117 i += num * bytesPerPixel;
118 r += num * bytesPerPixel + 1;
119 }
120 }
121
122 delete[] rleData;
123 }
124
125 QImage::Format format;
126 switch(header.bits)
127 {
128 case 16 : format = QImage::Format_RGB16; break;
129 case 24 : format = QImage::Format_RGB32; break;
130 case 32 : format = QImage::Format_ARGB32; break;
131 default : delete[] imageData; return pixmap; // any other than 16, 24 or 32 would be a broken image
132 };
133 QImage image(imageData, header.width, header.height, format);
134
135 // deal with the TGA flipping of axis
136 // bit5 == 0 : flip
137 // bit5 == 1 : don't flip
138 image = image.mirrored(0, !(header.descriptor&16)); // copies the image. performance loss, but who cares ;-)
139
140 pixmap = QPixmap::fromImage(image);
141
142 delete[] imageData;
143
144 return pixmap;
ps:linux可能有问题
145}