Note that there are some explanatory texts on larger screens.

plurals
  1. POProblems Displaying Targa/TGA
    primarykey
    data
    text
    <p>Very very slight problem with my Targa Reader. One pixel is off and 2 extra pixels are black :S</p> <p>The 24-bit targa file I'm loading looks like: <img src="https://i.stack.imgur.com/2S9hh.png" alt="enter image description here"></p> <p>Notice the White pixel in the very top left corner. The very first pixel at the top left is white.</p> <p>But when I save the file pixels back as a 24-bit bitmap, it looks like: <img src="https://i.stack.imgur.com/6IGQx.png" alt="enter image description here"></p> <p>Notice that the white pixel is somehow in the top right as well as 2 black pixels above it.</p> <p>I cannot for the life of me figure out why everything else is correct except for that.. It's bothering me because I'm so close to being able to load TGA's.</p> <p>Any idea what is wrong with my code below? I'm writing the TGA reader for 16, 24 and 32 bit TGA files created with Photoshop.</p> <pre><code>typedef union RGB //Struct which will hold all pixels. { uint32_t Color; struct { unsigned char B, G, R, A; } RGBA; } *PRGB; class Tga //My Targa class that will load the TGA file. { private: std::vector&lt;RGB&gt; Pixels; uint32_t width, height, size, BitsPerPixel; public: Tga(const char* FilePath); }; Tga::Tga(const char* FilePath) { //Open the file for reading.. std::fstream hFile(FilePath, std::ios::in | std::ios::binary); if (!hFile.is_open()){throw std::invalid_argument("File Not Found.");} //The header is 12 bytes. By reading it, I can tell if the TGA is compressed or not. byte Header[12] = {0}; byte DeCompressed[12] = {0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; byte IsCompressed[12] = {0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; hFile.read(reinterpret_cast&lt;char*&gt;(&amp;Header), sizeof(Header)); //Read the header. if (memcmp(DeCompressed, &amp;Header, sizeof(Header)) == 0) //If it is not compressed. { hFile.read(reinterpret_cast&lt;char*&gt;(&amp;Header), sizeof(Header)); BitsPerPixel = Header[4]; //Displays correctly. width = Header[1] * 256 + Header[0]; //Displays correctly. height = Header[3] * 256 + Header[2]; //Displays correctly. size = ((width * BitsPerPixel + 31) / 32) * 4 * height; //Same algorithm for bitmaps. width * height * 3 OR width * height * 4. Taken from MSDN. if ((BitsPerPixel != 24) &amp;&amp; (BitsPerPixel != 32) &amp;&amp; ((width &lt; 1) || (height &lt; 1))) { hFile.close(); throw std::logic_error("Error: Invalid TGA File. Width And Height cannot be less than 0. BitsPerPixel must be 24 or 32 bits."); } std::vector&lt;unsigned char&gt; ImageData(size); //An array for holding the image data. hFile.read(reinterpret_cast&lt;char*&gt;(ImageData.data()), size); unsigned char* BuffPos = ImageData.data(); Pixels.resize(width * height); //A vector holding my structs that will hold the pxiels. //The following is supposed to flip the Image and copy it into my struct vector. for (int I = 0; I &lt; height; I++) { for (int J = 0; J &lt; width; J++) { Pixels[(height - 1 - I) * width + J].RGBA.B = *(BuffPos++); Pixels[(height - 1 - I) * width + J].RGBA.G = *(BuffPos++); Pixels[(height - 1 - I) * width + J].RGBA.R = *(BuffPos++); Pixels[(height - 1 - I) * width + J].RGBA.A = (BitsPerPixel &gt; 24 ? *(BuffPos++) : 0xFF); } if(BitsPerPixel == 24) //Has padding? BuffPos += (4 - ((width * 3) % 4)) % 4; } } else if (memcmp(IsCompressed, &amp;Header, sizeof(Header)) == 0) //The TGA is compressed.. { hFile.read(reinterpret_cast&lt;char*&gt;(&amp;Header), sizeof(Header)); BitsPerPixel = Header[4]; height = Header[1] * 256 + Header[0]; width = Header[3] * 256 + Header[2]; size = ((width * BitsPerPixel + 31) / 32) * 4 * height; if ((BitsPerPixel != 24) &amp;&amp; (BitsPerPixel != 32) &amp;&amp; ((width &lt; 1) || (height &lt; 1))) { hFile.close(); throw std::logic_error("Error: Invalid TGA File. Width And Height cannot be less than 0. BitsPerPixel must be 24 or 32 bits."); } RGB Pixel = {0}; char* BuffPos = reinterpret_cast&lt;char*&gt;(&amp;Pixel); int CurrentByte = 0, CurrentPixel = 0; int BytesPerPixel = (BitsPerPixel / 8); Pixels.resize(width * height * sizeof(RGB)); do { byte ChunkHeader = 0; hFile.read(reinterpret_cast&lt;char*&gt;(&amp;ChunkHeader), sizeof(byte)); if (ChunkHeader &lt; 128) { ++ChunkHeader; for (int I = 0; I &lt; ChunkHeader; ++I) { hFile.read(BuffPos, BytesPerPixel); Pixels[CurrentByte].RGBA.B = Pixel.RGBA.B; Pixels[CurrentByte].RGBA.G = Pixel.RGBA.G; Pixels[CurrentByte].RGBA.R = Pixel.RGBA.R; Pixels[CurrentByte].RGBA.A = (BitsPerPixel &gt; 24) ? Pixel.RGBA.A : 0xFF; CurrentByte += BytesPerPixel; ++CurrentPixel; } } else { ChunkHeader -= 127; hFile.read(BuffPos, BytesPerPixel); for (int I = 0; I &lt; ChunkHeader; ++I) { Pixels[CurrentByte].RGBA.B = Pixel.RGBA.B; Pixels[CurrentByte].RGBA.G = Pixel.RGBA.G; Pixels[CurrentByte].RGBA.R = Pixel.RGBA.R; Pixels[CurrentByte].RGBA.A = (BitsPerPixel &gt; 24) ? Pixel.RGBA.A : 0xFF; CurrentByte += BytesPerPixel; ++CurrentPixel; } } } while(CurrentPixel &lt; (width * height)); } hFile.close(); //I can guarantee nothing is wrong with the bitmap creator. Bitmap BMP(width, height, 24); //Take the pixels structure and create a 24 bit bitmap. This works 100% of the time for PNG and Bitmap using the same structure. BMP.Set(Pixels); BMP.Save("C:/Foo.bmp"); } int main() { Tga F("C:/Foo.tga"); } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload