之前遇到QT不支持TGA圖片顯示的缺陷,人家寫的一種彌補(bǔ)的辦法,借用一下,手動(dòng)寫一個(gè)函數(shù),加載TGA圖片,希望對遇到同樣問題的朋友有用。如果你有更好的方法也不妨告訴我,非常感謝!


1
#define QT3_SUPPORT
2
#include <QtGui/QApplication.h>
3
#include <qlabel.h>
4
#include <qpixmap.h>
5
6
7
#pragma pack(push, 1)
8
struct 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
30
QPixmap loadTGA(const char *filename);
31
32
int 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
45
QPixmap 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;
145
}
#define QT3_SUPPORT 2
#include <QtGui/QApplication.h>3
#include <qlabel.h>4
#include <qpixmap.h>5

6

7
#pragma pack(push, 1)8
struct TgaHeader9


{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 palette12
char imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed13

14
short colourmapstart; // first colour map entry in palette15
short colourmaplength; // number of colours in palette16
char colourmapbits; // number of bits per palette entry 15,16,24,3217

18
short xstart; // image x origin19
short ystart; // image y origin20

21
short width; // image width in pixels22
short height; // image height in pixels23

24
char bits; // image bits per pixel 8,16,24,3225
char descriptor; // image descriptor bits (vh flip bits)26

27
};28
#pragma pack(pop)29

30
QPixmap loadTGA(const char *filename);31

32
int 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

45
QPixmap loadTGA(const char *filename)46


{47
// check if file has tga extension48
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 ourselves64
QPixmap pixmap;65

66
FILE *fp; // file streams would be more c++
oh well :D67
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 information76
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 any89
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 rle100

{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
else112

{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 image132
};133
QImage image(imageData, header.width, header.height, format);134

135
// deal with the TGA flipping of axis136
// bit5 == 0 : flip137
// bit5 == 1 : don't flip138
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;145
}

