📄 tutorial_33.htm
字号:
else <font color="#ffffaa">// 如果不是24bit,则必是32bit</font>
{
texture->type = GL_RGBA; <font color="#ffffaa">//这样设置类型为GL_RGBA</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%">现在我们计算每像素的字节数和总共的图像数据。</td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
</font><pre><font color="#aaffaa" size="3"> tga.bytesPerPixel = (tga.Bpp / 8); <font color="#ffffaa">// 计算BPP</font>
<font color="#ffffaa">// 计算存储图像所需的内存</font>
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height);
</font></pre>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%"><p>我们需要一些空间去存储整个图像数据,因此我们将要使用malloc分配正确的内存数量</p>
<p>然后我们确认内存已经分配,并且它不是NULL。如果出现了错误,则运行错误处理代码。</p></td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> <font color="#ffffaa">// 分配内存</font>
texture->imageData = (GLubyte *)malloc(tga.imageSize);
if(texture->imageData == NULL) <font color="#ffffaa">// 确认已经分配成功</font>
{
...Error code here...
return false; <font color="#ffffaa">// 确认已经分配成功</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%">这里我们尝试读取所有的图像数据。如果不能,我们将再次触发错误处理代码。</td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> <font color="#ffffaa">// 尝试读取所有图像数据</font>
if(fread(texture->imageData, 1, tga.imageSize, fTGA) != tga.imageSize)
{
...Error code here...
return false; <font color="#ffffaa">// 如果不能,返回false</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%"><p>TGA文件用逆OpenGL需求顺序的方式存储图像,因此我们必须将格式从BGR到RGB。为了达到这一点,我们交换每个像素的第一个和第三个字节的内容。</p>
<p>Steve Thomas补充:我已经编写了能稍微更快速读取TGA文件的代码。它涉及到仅用3个二进制操作将BGR转换到RGB的方法。</p>
<p>然后我们关闭文件,并且成功退出函数。 </p></td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> <font color="#ffffaa">// 开始循环</font>
for(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel)
{
<font color="#ffffaa">// 第一字节 XOR第三字节XOR 第一字节 XOR 第三字节</font>
texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=
texture->imageData[cswap] ^= texture->imageData[cswap+2];
}
fclose(fTGA); <font color="#ffffaa">// 关闭文件</font>
return true; <font color="#ffffaa">// 返回成功</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%">以上是读取未压缩型TGA文件的方法。读取RLE压缩型文件的步骤稍微难一点。我们像平时一样读取文件头并且收集高度/宽度/色彩深度,这和读取未压缩版本是一致的。</td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3"><pre> bool LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA)
{
if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)
{
...Error code here...
}
texture->width = tga.header[1] * 256 + tga.header[0];
texture->height = tga.header[3] * 256 + tga.header[2];
texture->bpp = tga.header[4];
tga.Width = texture->width;
tga.Height = texture->height;
tga.Bpp = texture->bpp;
if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))
{
...Error code here...
} }
tga.bytesPerPixel = (tga.Bpp / 8);
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height);
</pre></font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%">现在我们需要分配存储图像所需的空间,这是为我们解压缩之后准备的,我们将使用malloc。如果内存分配失败,运行错误处理代码,并且返回false。</td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> <font color="#ffffaa">// 分配存储图像所需的内存空间</font>
texture->imageData = (GLubyte *)malloc(tga.imageSize);
if(texture->imageData == NULL) <font color="#ffffaa">// 如果不能分配内存</font>
{
...Error code here...
return false; <font color="#ffffaa">// 返回 False</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%"><p>下一步我们需要决定组成图像的像素数。我们将它存储在变量“pixelcount”中。</p>
<p>我们也需要存储当前所处的像素,以及我们正在写入的图像数据的字节,这样避免溢出写入过多的旧数据。<br>
</p>
<p>我们将要分配足够的内存来存储一个像素。 </p></td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> GLuint pixelcount = tga.Height * tga.Width; <font color="#ffffaa">// 图像中的像素数</font>
GLuint currentpixel = 0; <font color="#ffffaa">// 当前正在读取的像素</font>
GLuint currentbyte = 0; <font color="#ffffaa">// 当前正在向图像中写入的像素
// 一个像素的存储空间</font>
GLubyte * colorbuffer = (GLubyte *)malloc(tga.bytesPerPixel);
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%"><p>接下来我们将要进行一个大循环。</p>
<p>让我们将它分解为更多可管理的块。</p>
<p>首
先我们声明一个变量来存储“块”头。块头指示接下来的段是RLE还是RAW,它的长度是多少。如果一字节头小于等于127,则它是一个RAW头。头的值是
颜色数,是负数,在我们处理其它头字节之前,我们先读取它并且拷贝到内存中。这样我们将我们得到的值加1,然后读取大量像素并且将它们拷贝到
ImageData中,就像我们处理未压缩型图像一样。如果头大于127,那么它是下一个像素值随后将要重复的次数。要获取实际重复的数量,我们将它减去
127以除去1bit的的头标示符。然后我们读取下一个像素并且依照上述次数连续拷贝它到内存中。</p></td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> do <font color="#ffffaa">// 开始循环</font>
{
GLubyte chunkheader = 0; <font color="#ffffaa">// 存储Id块值的变量</font>
if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0) <font color="#ffffaa">// 尝试读取块的头</font>
{
...Error code...
return false; <font color="#ffffaa">// If It Fails, Return False</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_33_files/l.png"><img src="Tutorial_33_files/l.png"></td>
<td valign="top" width="100%">接下来我们将要看看它是否是RAW头。如果是,我们需要将此变量的值加1以获取紧随头之后的像素总数。</td>
<td background="Tutorial_33_files/r.png"><img src="Tutorial_33_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_33_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_33_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_33_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> if(chunkheader < 128) <font color="#ffffaa">// 如果是RAW块</font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -