简体   繁体   中英

TGA reading header with QDataStream

I am trying to read a TGA file header with Qt QDataStream. I have the following structure from the specs with fixed types:

#pragma pack(push, 1)
/* TGA header */
struct tga_header_t
{
    quint8   id_lenght;            /* size of image id */
    quint8   colormap_type;        /* 1 is has a colormap */
    quint8   image_type;           /* compression type */

    /* Color Map Specification */
    quint16  cm_origin;            /* colormap origin */
    quint16  cm_length;            /* colormap length */
    quint8   cm_size;              /* colormap size */

    /* Image Specification */
    quint16  x_origin;           /* bottom left x coord origin */
    quint16  y_origin;           /* bottom left y coord origin */
    quint16  width;              /* picture width (in pixels) */
    quint16  height;             /* picture height (in pixels) */
    quint8   pixel_depth;        /* bits per pixel: 8, 16, 24 or 32 */
    quint8   image_descriptor;   /* 24 bits = 0x00; 32 bits = 0x80 */
};
#pragma pack(pop)

I open a file with QFile then construct a QDataStream with it as such:

QFile file(path);
tga_header_t header;

file.open(QIODevice::ReadOnly);
QDataStream stream(&file);
stream >> header.id_lenght >>
          header.colormap_type >>
          header.image_type >>
          header.cm_origin >>
          header.cm_length >>
          header.cm_size >>
          header.x_origin >>
          header.y_origin >>
          header.width >>
          header.height >>
          header.pixel_depth >>
          header.image_descriptor;
qDebug() << header.id_lenght << "id_lenght" <<
            header.colormap_type << "colormap_type" <<
            header.image_type << "image_type" <<
            header.cm_origin << "cm_origin" <<
            header.cm_length << "cm_length" <<
            header.cm_size << "cm_size" <<
            header.x_origin << "x_origin" <<
            header.y_origin << "y_origin" <<
            header.width << "width" <<
            header.height << "height" <<
            header.pixel_depth << "pixel_depth" <<
            header.image_descriptor << "image_descriptor" <<
            "SIZE:" << sizeof(header);

The problem is with width and height I get :

0 id_lenght 0 colormap_type 2 image_type 0 cm_origin 0 cm_length 0 cm_size 0 x_origin 0 y_origin 22021 width 3 height 24 pixel_depth 0 image_descriptor SIZE: 18

And I should get 1366 and 768. If I hexdump the file I get :

0000000 0000 0002 0000 0000 0000 0000 0556 0300
0000010 0018 0000 0000 0000 0000 0000 0000 0000

Which is weird because it has an extra byte at the start and another missing somewhere between 0x0002 and 0x0556 .

Update:
Using fstream works, so correct me if I am wrong but I think the << operator does not work as I expect it to (read only the size necessary to fill the struct variable).

    stream.read((char*)&header.id_lenght, sizeof(header.id_lenght));
    stream.read((char*)&header.colormap_type, sizeof(header.colormap_type));
    stream.read((char*)&header.image_type, sizeof(header.image_type));
    stream.read((char*)&header.cm_origin, sizeof(header.cm_origin));
    stream.read((char*)&header.cm_length, sizeof(header.cm_length));
    stream.read((char*)&header.cm_size, sizeof(header.cm_size));
    stream.read((char*)&header.x_origin, sizeof(header.x_origin));
    stream.read((char*)&header.y_origin, sizeof(header.y_origin));
    stream.read((char*)&header.width, sizeof(header.width));
    stream.read((char*)&header.height, sizeof(header.height));
    stream.read((char*)&header.pixel_depth, sizeof(header.pixel_depth));
    stream.read((char*)&header.image_descriptor, sizeof(header.image_descriptor));

Using QDataStream::readRawData also works:

stream.readRawData((char*)&header.id_lenght, sizeof(header.id_lenght));
    stream.readRawData((char*)&header.colormap_type, sizeof(header.colormap_type));
    stream.readRawData((char*)&header.image_type, sizeof(header.image_type));
    stream.readRawData((char*)&header.cm_origin, sizeof(header.cm_origin));
    stream.readRawData((char*)&header.cm_length, sizeof(header.cm_length));
    stream.readRawData((char*)&header.cm_size, sizeof(header.cm_size));
    stream.readRawData((char*)&header.x_origin, sizeof(header.x_origin));
    stream.readRawData((char*)&header.y_origin, sizeof(header.y_origin));
    stream.readRawData((char*)&header.width, sizeof(header.width));
    stream.readRawData((char*)&header.height, sizeof(header.height));
    stream.readRawData((char*)&header.pixel_depth, sizeof(header.pixel_depth));
    stream.readRawData((char*)&header.image_descriptor, sizeof(header.image_descriptor));

The data is OK. Your PC interprets 16-bit words as little-endian. In the file they are stored as big endians.

For all 16-bit types you should swap low/high bytes. You also could use the helper functions from Qt: http://doc.qt.io/qt-4.8/qtendian.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM