TGA RLE : Something wrong ?

This topic is 1507 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hello,

I'm trying to parse TGA files and everything is working but the RLE.

First of all, this is how I thought RLE works : FFFFHJJJJJJ -> 4F1H6J

To know how to parse the file I went here for the specs : http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf

And it seemed pretty straightforward but I think there is something I don't get with RLE and maybe you will be able to help me.

I created a simple texture image with Photoshop CC :

And this is the start of the TGA :

<bh:00><bh:00>
<bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:00><bh:04><bh:00><bh:04><bh:18><bh:00><bh:01>**<bh:ff><bh:1b><bh:1b><bh:ff><bh:ff><bh:1d><bh:1d><bh:ff><bh:ff><bh:1d><bh:1d><bh:ff><bh:d0><bh:1d><bh:1d><bh:ff><bh:03><bh:1e><bh:1e>


For me the image data is displayed since the 18th byte :

<bh:01>**<bh:ff><bh:1b><bh:1b><bh:ff><bh:ff><bh:1d><bh:1d><bh:ff><bh:ff><bh:1d><bh:1d><bh:ff><bh:d0><bh:1d><bh:1d><bh:ff><bh:03><bh:1e><bh:1e>


And this is how I think I should read it :

• Take one byte and mask it with & 0x7FF (to set the MSB to 0) and store it as pixel count
• Take the 3 or 4 next (depending on the pixel depth) and store them as color components (BGR(A)) for the next [pixel count] number of pixels
• Repeat until w*h pixels are passed

So I am kinda lost because the 0x01 that should be the first pixel count doesn't even have 1 as MSB...

Where am I wrong ?

rXp

Edited by rXpSwiss

Share on other sites
The pixel data starts at offset 18, which is <bh:ff>, which is after the ** in your hex display (I haven't seen that syntax for hex dumps before, but whatever).

FF 1B 1B FF -> FF (1 = RLE, 7F = 0x7F+1 = 128 count), RLE mode, so read one color block: color(RGB24) = 1B 1B FF -> Blue 1B, Green 1B, Red FF (note, this is the bottom left corner of the image, not the top left).
FF 1D 1D FF -> RLE:128, 1D 1D FF
D0 1D 1D FF -> RLE:81, 1D 1D FF
03 1E 1E ?? -> RUN:4, 1E 1E ??, ?? ?? ??, ?? ?? ??, ?? ?? ??

etc....

RLE/RUN is the highest bit: RLE = ((rleCountByte & 0x80) == 0x80);
Count is the low 7 bits, then add 1: Count = (rleCountByte & 0x7F) + 1;

When in RLE mode, you read 1 color block and repeat it Count times. When in RUN mode, you read Count color blocks. The number of bytes in the color block depends on the color mode of the image. This particular one is 24-bit in BGR byte order.

TGA supports bottom-up and top-down vertical layout, so make sure you read that info from the header. In most cases programs use bottom-up to match the conventions of other image formats.

NOTE: The reason why there is a 4-pixel run between your colors is because the border between each color is smoothed slightly.

Loading TGA RLE is pretty easy. Writing them is a bit more complex but still nothing too difficult. Edited by Nypyren

Share on other sites

Sorry, my hex editor is nice but apparently the hex dump is really bad. The hex dump I gave is wrong, apparently the copy/past from the hex editor I am using is not working great...

So this is a screenshot :

So now you can see that the 18th is -> 0x01 0x2a 0x2a 0xff etc...

That is why I am lost. :(

Share on other sites
I fixed my issue : the raw packet were not handled. So if the msb was at 0 I was lost but I found what to do in this case :)

A side question : I draw it with opengl and the type I need to set to glTexImage2D is unsigned byte. Why? Shouldnt it be unsigned int 8 8 8 8 ?

Share on other sites

For a 4-component color on a little endian architecture, the UNSIGNED_INT_8_8_8_8 and the UNSIGNED_BYTE formats are equivalent. Former requires 4 bytes per pixel though, the latter is determined explicitly by the color format you select.

Edited by Brother Bob

Share on other sites

A side question : I draw it with opengl and the type I need to set to glTexImage2D is unsigned byte. Why? Shouldnt it be unsigned int 8 8 8 8 ?

GL_UNSIGNED_INT_8_8_8_8 denotes a 4 channel image with 8 bits per channel, while your source has only 3 channels (its RGB, has no Alpha). So, as long as you don't convert the source by inserting an alpha channel before overhanding to OpenGL, it is wrong to use GL_UNSIGNED_INT_8_8_8_8.

Moreover, GL_UNSIGNED_INT_8_8_8_8 denotes that the 4 channels are packed into an integer. This brings the necessity of considering the endianess with it. Due to this reason there exists also a GL_UNSIGNED_INT_8_8_8_8_REV for the "other" endianess.

Edited by haegarr

1. 1
Rutin
67
2. 2
3. 3
4. 4
5. 5

• 21
• 10
• 33
• 20
• 9
• Forum Statistics

• Total Topics
633417
• Total Posts
3011782
• Who's Online (See full list)

There are no registered users currently online

×