improve image load performance,
can be improved more, but scanline has wrong results
This commit is contained in:
parent
bc5bfc62bc
commit
1c5631a5e0
@ -2,137 +2,145 @@
|
||||
#include <fstream>
|
||||
#include <QImage>
|
||||
#include <QColor>
|
||||
#include <QVector>
|
||||
#include <QFile>
|
||||
|
||||
#include "Profiler.h"
|
||||
|
||||
QImage loadTga(QString filePath, bool &success)
|
||||
{
|
||||
TIC("start");
|
||||
QImage img;
|
||||
success = true;
|
||||
|
||||
// open the file
|
||||
std::fstream fsPicture(filePath.toStdString().c_str(), std::ios::in | std::ios::binary);
|
||||
QFile file(filePath);
|
||||
|
||||
if (!fsPicture.is_open())
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
img = QImage(1, 1, QImage::Format_RGB32);
|
||||
img.fill(Qt::red);
|
||||
success = false;
|
||||
return img;
|
||||
}
|
||||
|
||||
// read in the header
|
||||
std::uint8_t ui8x18Header[19] = { 0 };
|
||||
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
|
||||
|
||||
//get variables
|
||||
std::uint32_t ui32BpP;
|
||||
std::uint32_t ui32Width;
|
||||
std::uint32_t ui32Height;
|
||||
std::uint32_t ui32IDLength;
|
||||
std::uint32_t ui32PicType;
|
||||
std::uint32_t ui32PaletteLength;
|
||||
std::uint32_t ui32Size;
|
||||
|
||||
// extract all information from header
|
||||
ui32IDLength = ui8x18Header[0];
|
||||
ui32PicType = ui8x18Header[2];
|
||||
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
|
||||
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
|
||||
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
|
||||
ui32BpP = ui8x18Header[16];
|
||||
|
||||
// calculate some more information
|
||||
ui32Size = ui32Width * ui32Height * ui32BpP / 8;
|
||||
|
||||
// jump to the data block
|
||||
fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);
|
||||
|
||||
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
|
||||
|
||||
// uncompressed
|
||||
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
|
||||
{
|
||||
std::vector<std::uint8_t> vui8Pixels;
|
||||
vui8Pixels.resize(ui32Size);
|
||||
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
|
||||
|
||||
for (unsigned int y = 0; y < ui32Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < ui32Width; x++)
|
||||
{
|
||||
int valr = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 2);
|
||||
int valg = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 1);
|
||||
int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8);
|
||||
int vala = 255;
|
||||
if (ui32BpP == 32)
|
||||
vala = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 3);
|
||||
|
||||
QColor value(valr, valg, valb, vala);
|
||||
img.setPixel(x, ui32Width - 1 - y, value.rgba());
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if compressed 24 or 32 bit
|
||||
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
|
||||
{
|
||||
std::uint8_t tempChunkHeader;
|
||||
std::uint8_t tempData[5];
|
||||
unsigned int tmp_pixelIndex = 0;
|
||||
|
||||
do {
|
||||
fsPicture.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
|
||||
|
||||
if (tempChunkHeader >> 7) // repeat count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
|
||||
|
||||
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
else // data count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
} while (tmp_pixelIndex < (ui32Width * ui32Height));
|
||||
}
|
||||
// not useable format
|
||||
else
|
||||
{
|
||||
fsPicture.close();
|
||||
success = false;
|
||||
return img;
|
||||
|
||||
// read in the header
|
||||
quint8 ui8x18Header[19] = { 0 };
|
||||
file.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
|
||||
|
||||
//get variables
|
||||
quint32 ui32BpP;
|
||||
quint32 ui32Width;
|
||||
quint32 ui32Height;
|
||||
quint32 ui32IDLength;
|
||||
quint32 ui32PicType;
|
||||
quint32 ui32PaletteLength;
|
||||
quint32 ui32Size;
|
||||
|
||||
// extract all information from header
|
||||
ui32IDLength = ui8x18Header[0];
|
||||
ui32PicType = ui8x18Header[2];
|
||||
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
|
||||
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
|
||||
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
|
||||
ui32BpP = ui8x18Header[16];
|
||||
|
||||
// calculate some more information
|
||||
ui32Size = ui32Width * ui32Height * ui32BpP / 8;
|
||||
|
||||
// jump to the data block
|
||||
file.seek(ui32IDLength + ui32PaletteLength + 18);
|
||||
|
||||
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
|
||||
|
||||
// uncompressed
|
||||
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
|
||||
{
|
||||
QVector<quint8> vui8Pixels;
|
||||
vui8Pixels.resize(ui32Size);
|
||||
file.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
|
||||
|
||||
for (unsigned int y = 0; y < ui32Height; y++)
|
||||
{
|
||||
//QRgb* imgLine = (QRgb*)img.scanLine(y);
|
||||
for (unsigned int x = 0; x < ui32Width; x++)
|
||||
{
|
||||
int valr = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 2);
|
||||
int valg = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 1);
|
||||
int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8);
|
||||
int vala = 255;
|
||||
if (ui32BpP == 32)
|
||||
vala = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 3);
|
||||
|
||||
QColor value(valr, valg, valb, vala);
|
||||
|
||||
//imgLine[x] = value.rgba();
|
||||
img.setPixel(x, ui32Width - 1 - y, value.rgba());
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if compressed 24 or 32 bit
|
||||
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
|
||||
{
|
||||
quint8 tempChunkHeader;
|
||||
quint8 tempData[5];
|
||||
unsigned int tmp_pixelIndex = 0;
|
||||
|
||||
do {
|
||||
file.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
|
||||
|
||||
if (tempChunkHeader >> 7) // repeat count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (quint8(tempChunkHeader << 1) >> 1);
|
||||
|
||||
file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
else // data count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
} while (tmp_pixelIndex < (ui32Width * ui32Height));
|
||||
}
|
||||
// not useable format
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
fsPicture.close();
|
||||
success = true;
|
||||
TOC("end");
|
||||
|
||||
if (file.isOpen())
|
||||
file.close();
|
||||
return img;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user