2017-10-10 2 views
0

Ich versuche, einen einfachen TGA-Loader zu schreiben, und ich fand, dass das Lesen einiger Bilder nach einem bestimmten Punkt viele unerwünschte Nullen erzeugte. Es gibt sechs Bilder, die ich teste: Jeder von ihnen hat 32x32 Pixel mit BGR-Farben. Jetzt werden vier Bilder gut gelesen, während die restlichen zwei nur bis zum 17. Byte gelesen werden. Von da an sie bestehen aus Nullen, die so aussehen:Lesen von TGA zeigt Nullen anstelle von Farbdaten

0: 220 164 55
1: 232 173 57
2: 241 177 51
...
16: 252 181 41
17: 249 180 41
18: 0 0 0
19: 0 0 0

ifstream myFile(filePath); 

// Read Header 

struct tgaHeader *header = new struct tgaHeader; 

myFile.read((char *) &header->imageIDlength, 1); 
myFile.read((char *) &header->colormapType, 1); 
myFile.read((char *) &header->imageType, 1); 

myFile.read((char *) &header->colormapBegin, 2); 
myFile.read((char *) &header->colormapLength, 2); 

myFile.read((char *) &header->sizeOfEntryInPallette, 1); 

myFile.read((char *) &header->xOrigin, 2); 
myFile.read((char *) &header->yOrigin, 2); 
myFile.read((char *) &header->width, 2); 
myFile.read((char *) &header->height, 2); 

myFile.read((char *) &header->bitsPerPoint, 1); 
myFile.read((char *) &header->attributeByte, 1); 

// Test if Format is supported 

if(header->imageIDlength != 0 || 
    header->colormapType != 0 || header->colormapBegin != 0 || header->colormapLength != 0 || 
    header->imageType != 2  || header->xOrigin != 0  || header->yOrigin != 0  || 
    !(header->bitsPerPoint == 24 || header->bitsPerPoint == 32)) 
{ 
    myFile.close(); 
    throw runtime_error("image format is not supported"); 
} 

// Since only TGA-files with no Image-ID and no Colormap are supported, 
// here immediatly the image data can be read. 

uint16_t bytesPerPoint = header->bitsPerPoint/8; 
unsigned long long imSize = static_cast<long long> (header->width) * header->height * bytesPerPoint; 

vector<uint8_t> * pixels = new vector<uint8_t> (imSize); 
myFile.read((char *) pixels->data(), imSize); 

unsigned long long i; 
for(i=0; i < imSize; i+=3) { 

    uint8_t t0 = pixels->at(i+0);  // swap from BGR to RGB 
    uint8_t t1 = pixels->at(i+1); 
    uint8_t t2 = pixels->at(i+2); 

    (*pixels)[i+0] = t2; 
    (*pixels)[i+1] = t1; 
    (*pixels)[i+2] = t0; 

} 

// Further Meta-Data following the image data are ignored. 

myFile.close(); 

return pixels; 

TgaHeader ist eine definierte Struktur, die enthält uint8_t und uint16_t Felder. Ich habe die Ausnahmebehandlung aus Gründen der Übersichtlichkeit entfernt. Ich habe niemals Fehler beim Lesen der Daten erkannt. IrfanView und Gimp konnten die problematischen Bilder öffnen und in einem binären Viewer wurden keine Nullen gefunden. Ich habe nur Bilder ohne Bild-ID und ohne Colormap und äquivalente Header ausgewählt, also sollte dies auch kein Problem sein.
Warum sind diese Nullen da?

+0

Vielleicht sind die Bilder nur schwarz von diesem Punkt an. Vielleicht sind die Dateien aus irgendeinem Grund abgeschnitten oder kaputt. Sie scheinen nicht zu überprüfen, ob eines der 'read() 's tatsächlich erfolgreich ist. – kolrabi

+0

Ich habe überprüft, ob die 'read()' s tatsächlich ihre Arbeit machen, und alles scheint gut gelesen zu werden. –

Antwort

0

Endlich fand ich das Problem: Aus Gründen kann ich nicht sehen, dass die ifstream-Position auf ca. 450. Von dort aus konnte der Header gelesen werden, obwohl sich die Kopfinformationen in den ersten 18 Bytes befinden. Als Folge nach dem Header-Lese ich einfach die ifstream Position auf den Punkt setzen die Farbdaten waren begann:

vector<uint8_t> * imRawData = new vector<uint8_t> (imSize); 

myFile->seekg(ios_base::beg + 18); 
myFile->read((char *) imRawData->data(), imSize); 
Verwandte Themen