Я пытаюсь написать простой TGA-загрузчик и обнаружил, что чтение некоторых изображений приводит к появлению большого количества нежелательных нулей после определенного момента.
Я тестирую шесть изображений: каждое из них имеет 32×32 пикселя с BGR-цветами.
Теперь четыре изображения читаются нормально, а остальные два читаются только до 17-го байта. С этого момента они состоят из нулей, которые выглядят так:
0: 220 164 55
1: 232 173 57
2: 241 177 51
…
16: 252 181 41
17: 249 180 41
18:00 0
19:00
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
является определенной структурой, содержащей поля uint8_t и uint16_t.
Я удалил обработку исключений для ясности, я никогда не распознавал никаких ошибок при чтении данных. IrfanView и Gimp смогли открыть проблемные изображения, и в двоичном средстве просмотра нули не были найдены. Я выбрал только изображения без Image-ID, без цветовой карты и эквивалентных заголовков, так что это тоже не должно быть проблемой.
Так почему же эти нули там?
Наконец, я обнаружил проблему: по причинам, которые я не вижу, позиция ifstream перешла к ок. 450. Оттуда заголовок может быть прочитан, даже если информация заголовка находится в первых 18 байтах.
Как следствие, после прочтения заголовка я просто установил позицию ifstream в точку, где начались данные цвета:
vector<uint8_t> * imRawData = new vector<uint8_t> (imSize);
myFile->seekg(ios_base::beg + 18);
myFile->read((char *) imRawData->data(), imSize);
Других решений пока нет …