1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Do not cache the raster data

This commit is contained in:
Martin Tůma 2021-01-27 21:18:06 +01:00
parent 02c3682758
commit 33f2002a52
12 changed files with 154 additions and 114 deletions

View File

@ -12,7 +12,7 @@ public:
GMAP(const QString &fileName); GMAP(const QString &fileName);
~GMAP(); ~GMAP();
QString fileName() const {return _fileName;} const QString &fileName() const {return _fileName;}
static bool isGMAP(const QString &path); static bool isGMAP(const QString &path);

View File

@ -1,5 +1,6 @@
#include <QMap> #include <QMap>
#include <QtEndian> #include <QtEndian>
#include <QFile>
#include "vectortile.h" #include "vectortile.h"
#include "img.h" #include "img.h"
@ -24,7 +25,7 @@ static SubFile::Type tileType(const char str[3])
return SubFile::Unknown; return SubFile::Unknown;
} }
IMG::IMG(const QString &fileName) : _file(fileName) IMG::IMG(const QString &fileName) : _fileName(fileName)
{ {
#define CHECK(condition) \ #define CHECK(condition) \
if (!(condition)) { \ if (!(condition)) { \
@ -33,19 +34,20 @@ IMG::IMG(const QString &fileName) : _file(fileName)
return; \ return; \
} }
QFile file(fileName);
TileMap tileMap; TileMap tileMap;
QByteArray typFile; QByteArray typFile;
if (!_file.open(QFile::ReadOnly)) { if (!file.open(QFile::ReadOnly)) {
_errorString = _file.errorString(); _errorString = file.errorString();
return; return;
} }
// Read IMG header // Read IMG header
char signature[7], identifier[7]; char signature[7], identifier[7];
_file.read((char*)&_key, 1) && _file.seek(0x10) file.read((char*)&_key, 1) && file.seek(0x10)
&& read(signature, sizeof(signature)) && _file.seek(0x41) && read(file, signature, sizeof(signature)) && file.seek(0x41)
&& read(identifier, sizeof(identifier)); && read(file, identifier, sizeof(identifier));
if (memcmp(signature, "DSKIMG", sizeof(signature)) if (memcmp(signature, "DSKIMG", sizeof(signature))
|| memcmp(identifier, "GARMIN", sizeof(identifier))) { || memcmp(identifier, "GARMIN", sizeof(identifier))) {
_errorString = "Not a Garmin IMG file"; _errorString = "Not a Garmin IMG file";
@ -53,9 +55,9 @@ IMG::IMG(const QString &fileName) : _file(fileName)
} }
char d1[20], d2[31]; char d1[20], d2[31];
quint8 e1, e2; quint8 e1, e2;
CHECK(_file.seek(0x49) && read(d1, sizeof(d1)) && _file.seek(0x61) CHECK(file.seek(0x49) && read(file, d1, sizeof(d1)) && file.seek(0x61)
&& readValue(e1) && readValue(e2) && _file.seek(0x65) && readValue(file, e1) && readValue(file, e2) && file.seek(0x65)
&& read(d2, sizeof(d2))); && read(file, d2, sizeof(d2)));
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2))); QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed(); _name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
@ -66,7 +68,7 @@ IMG::IMG(const QString &fileName) : _file(fileName)
quint64 offset = 0x200; quint64 offset = 0x200;
// Skip unused FAT blocks if any // Skip unused FAT blocks if any
while (true) { while (true) {
CHECK(_file.seek(offset) && readValue(flag)); CHECK(file.seek(offset) && readValue(file, flag));
if (flag) if (flag)
break; break;
offset += 512; offset += 512;
@ -76,15 +78,17 @@ IMG::IMG(const QString &fileName) : _file(fileName)
char name[8], type[3]; char name[8], type[3];
quint32 size; quint32 size;
quint16 part; quint16 part;
CHECK(_file.seek(offset + 12) && readValue(size)); CHECK(file.seek(offset + 12) && readValue(file, size));
offset += 512; offset += 512;
int cnt = (size - offset) / 512; int cnt = (size - offset) / 512;
// Read FAT blocks describing the IMG sub-files // Read FAT blocks describing the IMG sub-files
for (int i = 0; i < cnt; i++) { for (int i = 0; i < cnt; i++) {
quint16 block; quint16 block;
CHECK(_file.seek(offset) && readValue(flag) && read(name, sizeof(name)) CHECK(file.seek(offset) && readValue(file, flag)
&& read(type, sizeof(type)) && readValue(size) && readValue(part)); && read(file, name, sizeof(name))
&& read(file, type, sizeof(type)) && readValue(file, size)
&& readValue(file, part));
SubFile::Type tt = tileType(type); SubFile::Type tt = tileType(type);
QByteArray fn(name, sizeof(name)); QByteArray fn(name, sizeof(name));
@ -97,16 +101,16 @@ IMG::IMG(const QString &fileName) : _file(fileName)
} else } else
tile = *it; tile = *it;
SubFile *file = part ? tile->file(tt) SubFile *subFile = part ? tile->file(tt)
: tile->addFile(this, tt); : tile->addFile(this, tt);
CHECK(file); CHECK(subFile);
_file.seek(offset + 0x20); file.seek(offset + 0x20);
for (int i = 0; i < 240; i++) { for (int i = 0; i < 240; i++) {
CHECK(readValue(block)); CHECK(readValue(file, block));
if (block == 0xFFFF) if (block == 0xFFFF)
break; break;
file->addBlock(block); subFile->addBlock(block);
} }
} else if (tt == SubFile::TYP) { } else if (tt == SubFile::TYP) {
SubFile *typ = 0; SubFile *typ = 0;
@ -118,9 +122,9 @@ IMG::IMG(const QString &fileName) : _file(fileName)
typ = _typ; typ = _typ;
if (typ) { if (typ) {
_file.seek(offset + 0x20); file.seek(offset + 0x20);
for (int i = 0; i < 240; i++) { for (int i = 0; i < 240; i++) {
CHECK(readValue(block)); CHECK(readValue(file, block));
if (block == 0xFFFF) if (block == 0xFFFF)
break; break;
typ->addBlock(block); typ->addBlock(block);
@ -138,7 +142,7 @@ IMG::IMG(const QString &fileName) : _file(fileName)
VectorTile *tile = it.value(); VectorTile *tile = it.value();
if (!tile->init()) { if (!tile->init()) {
qWarning("%s: %s: Invalid map tile", qPrintable(_file.fileName()), qWarning("%s: %s: Invalid map tile", qPrintable(file.fileName()),
qPrintable(it.key())); qPrintable(it.key()));
delete tile; delete tile;
continue; continue;
@ -178,20 +182,20 @@ IMG::IMG(const QString &fileName) : _file(fileName)
_valid = true; _valid = true;
} }
qint64 IMG::read(char *data, qint64 maxSize) qint64 IMG::read(QFile &file, char *data, qint64 maxSize)
{ {
qint64 ret = _file.read(data, maxSize); qint64 ret = file.read(data, maxSize);
if (_key) if (_key)
for (int i = 0; i < ret; i++) for (int i = 0; i < ret; i++)
data[i] ^= _key; data[i] ^= _key;
return ret; return ret;
} }
template<class T> bool IMG::readValue(T &val) template<class T> bool IMG::readValue(QFile &file, T &val)
{ {
T data; T data;
if (read((char*)&data, sizeof(T)) < (qint64)sizeof(T)) if (read(file, (char*)&data, sizeof(T)) < (qint64)sizeof(T))
return false; return false;
val = qFromLittleEndian(data); val = qFromLittleEndian(data);
@ -199,11 +203,11 @@ template<class T> bool IMG::readValue(T &val)
return true; return true;
} }
bool IMG::readBlock(int blockNum, char *data) bool IMG::readBlock(QFile &file, int blockNum, char *data)
{ {
if (!_file.seek((quint64)blockNum << _blockBits)) if (!file.seek((quint64)blockNum << _blockBits))
return false; return false;
if (read(data, 1ULL<<_blockBits) < (qint64)(1ULL<<_blockBits)) if (read(file, data, 1ULL<<_blockBits) < (qint64)(1ULL<<_blockBits))
return false; return false;
return true; return true;

View File

@ -1,25 +1,26 @@
#ifndef IMG_H #ifndef IMG_H
#define IMG_H #define IMG_H
#include <QFile>
#include "mapdata.h" #include "mapdata.h"
class QFile;
class IMG : public MapData class IMG : public MapData
{ {
public: public:
IMG(const QString &fileName); IMG(const QString &fileName);
QString fileName() const {return _file.fileName();} const QString &fileName() const {return _fileName;}
private: private:
friend class SubFile; friend class SubFile;
unsigned blockBits() const {return _blockBits;} unsigned blockBits() const {return _blockBits;}
bool readBlock(int blockNum, char *data); bool readBlock(QFile &file, int blockNum, char *data);
qint64 read(char *data, qint64 maxSize); qint64 read(QFile &file, char *data, qint64 maxSize);
template<class T> bool readValue(T &val); template<class T> bool readValue(QFile &file, T &val);
QFile _file; QString _fileName;
quint8 _key; quint8 _key;
unsigned _blockBits; unsigned _blockBits;
}; };

View File

@ -94,20 +94,23 @@ bool LBLFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
} }
if (hdrLen >= 0x19A) { if (hdrLen >= 0x19A) {
quint32 size, flags; quint32 offset, recordSize, size, flags;
if (!(seek(hdl, _gmpOffset + 0x184) && readUInt32(hdl, _imgOffsetsOffset) if (!(seek(hdl, _gmpOffset + 0x184) && readUInt32(hdl, offset)
&& readUInt32(hdl, size) && readUInt16(hdl, _imgOffsetsRecordSize) && readUInt32(hdl, size) && readUInt16(hdl, recordSize)
&& readUInt32(hdl, flags) && readUInt32(hdl, _imgOffset) && readUInt32(hdl, flags) && readUInt32(hdl, _imgOffset)
&& readUInt32(hdl, _imgSize))) && readUInt32(hdl, _imgSize)))
return false; return false;
_imgOffsetsCount = size ? size / _imgOffsetsRecordSize : 0; quint32 count = size ? size / recordSize : 0;
quint32 maxId = _imgOffsetsCount - 1; quint32 maxId = count - 1;
_imgOffsetIdSize = 0; _imgOffsetIdSize = 0;
do { do {
_imgOffsetIdSize++; _imgOffsetIdSize++;
maxId = maxId >> 8; maxId = maxId >> 8;
} while (maxId != 0); } while (maxId != 0);
if (!loadFiles(hdl, count, offset, recordSize))
return false;
} }
if (_encoding == 11) { if (_encoding == 11) {
@ -301,31 +304,43 @@ Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize) con
} }
} }
QByteArray LBLFile::readImage(Handle &hdl, quint32 id) const bool LBLFile::loadFiles(Handle &hdl, quint32 count, quint32 offset,
quint32 recordSize)
{ {
quint32 offset, nextOffset, size; _rasters.resize(count);
if (id >= _imgOffsetsCount) for (quint32 i = 0; i < count; i++) {
return QByteArray(); quint32 currentOffset, nextOffset, size;
if (!(seek(hdl, _imgOffsetsOffset + id * _imgOffsetsRecordSize) if (!(seek(hdl, offset + i * recordSize)
&& readVUInt32(hdl, _imgOffsetsRecordSize, offset))) && readVUInt32(hdl, recordSize, currentOffset)))
return QByteArray(); return false;
if (id == _imgOffsetsCount - 1) if (i == count - 1)
nextOffset = _imgSize; nextOffset = _imgSize;
else { else {
if (!readVUInt32(hdl, _imgOffsetsRecordSize, nextOffset)) if (!readVUInt32(hdl, recordSize, nextOffset))
return QByteArray(); return false;
} }
size = nextOffset - offset; size = nextOffset - currentOffset;
if (!seek(hdl, _imgOffset + offset)) _rasters[i] = File(currentOffset, size);
return QByteArray(); }
QByteArray ba;
ba.resize(size);
for (quint32 i = 0; i < size; i++)
if (!readUInt8(hdl, *(ba.data() + i)))
return QByteArray();
return ba; return true;
}
QImage LBLFile::readImage(Handle &hdl, quint32 id) const
{
if (id >= (quint32)_rasters.size())
return QImage();
if (!seek(hdl, _imgOffset + _rasters.at(id).offset))
return QImage();
QByteArray ba;
ba.resize(_rasters.at(id).size);
for (int i = 0; i < ba.size(); i++)
if (!readUInt8(hdl, *(ba.data() + i)))
return QImage();
return QImage::fromData(ba);
} }

View File

@ -1,6 +1,7 @@
#ifndef LBLFILE_H #ifndef LBLFILE_H
#define LBLFILE_H #define LBLFILE_H
#include <QImage>
#include "common/textcodec.h" #include "common/textcodec.h"
#include "subfile.h" #include "subfile.h"
#include "label.h" #include "label.h"
@ -13,16 +14,16 @@ class LBLFile : public SubFile
public: public:
LBLFile(IMG *img) LBLFile(IMG *img)
: SubFile(img), _huffmanText(0), _table(0), _offset(0), _size(0), : SubFile(img), _huffmanText(0), _table(0), _offset(0), _size(0),
_poiOffset(0), _poiSize(0), _imgOffsetsCount(0), _imgOffsetIdSize(0), _poiOffset(0), _poiSize(0), _imgOffsetIdSize(0), _poiMultiplier(0),
_poiMultiplier(0), _multiplier(0), _encoding(0) {} _multiplier(0), _encoding(0) {}
LBLFile(const QString *path) LBLFile(const QString *path)
: SubFile(path), _huffmanText(0), _table(0), _offset(0), _size(0), : SubFile(path), _huffmanText(0), _table(0), _offset(0), _size(0),
_poiOffset(0), _poiSize(0), _imgOffsetsCount(0), _imgOffsetIdSize(0), _poiOffset(0), _poiSize(0), _imgOffsetIdSize(0), _poiMultiplier(0),
_poiMultiplier(0), _multiplier(0), _encoding(0) {} _multiplier(0), _encoding(0) {}
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_huffmanText(0), _table(0), _offset(0), _size(0), _poiOffset(0), _huffmanText(0), _table(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _imgOffsetsCount(0), _imgOffsetIdSize(0), _poiMultiplier(0), _poiSize(0), _imgOffsetIdSize(0), _poiMultiplier(0), _multiplier(0),
_multiplier(0), _encoding(0) {} _encoding(0) {}
~LBLFile(); ~LBLFile();
bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl); bool load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl);
@ -32,13 +33,23 @@ public:
bool capitalize = true) const; bool capitalize = true) const;
quint8 imageIdSize() const {return _imgOffsetIdSize;} quint8 imageIdSize() const {return _imgOffsetIdSize;}
QByteArray readImage(Handle &hdl, quint32 id) const; QImage readImage(Handle &hdl, quint32 id) const;
private: private:
struct File {
File() : offset(0), size(0) {}
File(quint32 offset, quint32 size) : offset(offset), size(size) {}
quint32 offset;
quint32 size;
};
Label str2label(const QVector<quint8> &str, bool capitalize) const; Label str2label(const QVector<quint8> &str, bool capitalize) const;
Label label6b(Handle &hdl, quint32 offset, bool capitalize) const; Label label6b(Handle &hdl, quint32 offset, bool capitalize) const;
Label label8b(Handle &hdl, quint32 offset, bool capitalize) const; Label label8b(Handle &hdl, quint32 offset, bool capitalize) const;
Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const; Label labelHuffman(Handle &hdl, quint32 offset, bool capitalize) const;
bool loadFiles(Handle &hdl, quint32 count, quint32 offset,
quint32 recordSize);
HuffmanText *_huffmanText; HuffmanText *_huffmanText;
quint32 *_table; quint32 *_table;
@ -47,15 +58,14 @@ private:
quint32 _size; quint32 _size;
quint32 _poiOffset; quint32 _poiOffset;
quint32 _poiSize; quint32 _poiSize;
quint32 _imgOffsetsOffset;
quint32 _imgOffsetsCount;
quint32 _imgOffsetsRecordSize;
quint32 _imgOffset; quint32 _imgOffset;
quint32 _imgSize; quint32 _imgSize;
quint8 _imgOffsetIdSize; quint8 _imgOffsetIdSize;
quint8 _poiMultiplier; quint8 _poiMultiplier;
quint8 _multiplier; quint8 _multiplier;
quint8 _encoding; quint8 _encoding;
QVector<File> _rasters;
}; };
#endif // LBLFILE_H #endif // LBLFILE_H

View File

@ -60,7 +60,7 @@ public:
void load(); void load();
void clear(); void clear();
virtual QString fileName() const = 0; virtual const QString &fileName() const = 0;
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}

View File

@ -2,34 +2,37 @@
#define RASTER_H #define RASTER_H
#include <QRect> #include <QRect>
#include <QByteArray>
#include <QDebug> #include <QDebug>
#include "common/rectc.h" #include "common/rectc.h"
#include "common/garmin.h" #include "common/garmin.h"
class LBLFile;
class Raster { class Raster {
public: public:
Raster() {} Raster() : _lbl(0) {}
Raster(const QByteArray &img, const QRect &rect) : _img(img), _rect(rect) {} Raster(const LBLFile *lbl, quint32 id, const QRect &rect)
: _lbl(lbl), _id(id), _rect(rect) {}
const QByteArray &img() const {return _img;} const LBLFile *lbl() const {return _lbl;}
quint32 id() const {return _id;}
const RectC rect() const const RectC rect() const
{ {
return RectC(Coordinates(toWGS32(_rect.left()), toWGS32(_rect.top())), return RectC(Coordinates(toWGS32(_rect.left()), toWGS32(_rect.top())),
Coordinates(toWGS32(_rect.right()), toWGS32(_rect.bottom()))); Coordinates(toWGS32(_rect.right()), toWGS32(_rect.bottom())));
} }
bool isValid() const {return !_img.isNull();} bool isValid() const {return (_lbl != 0);}
private: private:
QByteArray _img; const LBLFile *_lbl;
quint32 _id;
QRect _rect; QRect _rect;
}; };
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
inline QDebug operator<<(QDebug dbg, const Raster &raster) inline QDebug operator<<(QDebug dbg, const Raster &raster)
{ {
dbg.nospace() << "Raster(" << raster.img().size() << ", " << raster.rect() dbg.nospace() << "Raster(" << raster.rect() << ")";
<< ")";
return dbg.space(); return dbg.space();
} }
#endif // QT_NO_DEBUG #endif // QT_NO_DEBUG

View File

@ -5,6 +5,7 @@
#include "textpointitem.h" #include "textpointitem.h"
#include "bitmapline.h" #include "bitmapline.h"
#include "style.h" #include "style.h"
#include "lblfile.h"
#include "rastertile.h" #include "rastertile.h"
@ -224,8 +225,11 @@ void RasterTile::drawPolygons(QPainter *painter)
QPointF br(_map->ll2xy(r.bottomRight())); QPointF br(_map->ll2xy(r.bottomRight()));
QSize size(QRectF(tl, br).toRect().size()); QSize size(QRectF(tl, br).toRect().size());
painter->drawImage(tl, QImage::fromData(poly.raster.img()). SubFile::Handle hdl(poly.raster.lbl());
scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); QImage img(poly.raster.lbl()->readImage(hdl, poly.raster.id()));
painter->drawImage(tl, img.scaled(size, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
//painter->setPen(Qt::blue); //painter->setPen(Qt::blue);
//painter->setBrush(Qt::NoBrush); //painter->setBrush(Qt::NoBrush);

View File

@ -30,7 +30,7 @@ RGNFile::~RGNFile()
} }
bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType,
MapData::Poly *poly, const LBLFile *lbl, Handle *lblHdl) const MapData::Poly *poly, const LBLFile *lbl) const
{ {
quint8 flags; quint8 flags;
quint32 rs; quint32 rs;
@ -67,8 +67,8 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType,
&& readUInt32(hdl, bottom) && readUInt32(hdl, left))) && readUInt32(hdl, bottom) && readUInt32(hdl, left)))
return false; return false;
poly->raster = Raster(lbl->readImage(*lblHdl, id), poly->raster = Raster(lbl, id, QRect(QPoint(left, top), QPoint(right,
QRect(QPoint(left, top), QPoint(right, bottom))); bottom)));
rs -= lbl->imageIdSize() + 16; rs -= lbl->imageIdSize() + 16;
} }
@ -336,8 +336,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
if (subtype & 0x20 && !readUInt24(hdl, labelPtr)) if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
return false; return false;
if (subtype & 0x80 && !readClassFields(hdl, segmentType, &poly, lbl, if (subtype & 0x80 && !readClassFields(hdl, segmentType, &poly, lbl))
&lblHdl))
return false; return false;
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
? _linesLclFlags : _polygonsLclFlags)) ? _linesLclFlags : _polygonsLclFlags))

View File

@ -61,7 +61,7 @@ private:
QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv) QMap<SegmentType, SubDiv::Segment> segments(Handle &hdl, SubDiv *subdiv)
const; const;
bool readClassFields(Handle &hdl, SegmentType segmentType, bool readClassFields(Handle &hdl, SegmentType segmentType,
MapData::Poly *poly = 0, const LBLFile *lbl = 0, Handle *lblHdl = 0) const; MapData::Poly *poly = 0, const LBLFile *lbl = 0) const;
bool skipLclFields(Handle &hdl, const quint32 flags[3]) const; bool skipLclFields(Handle &hdl, const quint32 flags[3]) const;
bool skipGblFields(Handle &hdl, quint32 flags) const; bool skipGblFields(Handle &hdl, quint32 flags) const;

View File

@ -7,38 +7,37 @@
bool SubFile::seek(Handle &handle, quint32 pos) const bool SubFile::seek(Handle &handle, quint32 pos) const
{ {
if (handle._file) { if (_img) {
int blockNum = pos >> BLOCK_BITS;
if (handle._blockNum != blockNum) {
if (!handle._file->seek((quint64)blockNum << BLOCK_BITS))
return false;
if (handle._file->read(handle._data.data(), (1<<BLOCK_BITS)) < 0)
return false;
handle._blockNum = blockNum;
}
handle._blockPos = mod2n(pos, 1U<<BLOCK_BITS);
handle._pos = pos;
return true;
} else {
quint32 blockBits = _img->blockBits(); quint32 blockBits = _img->blockBits();
int blockNum = pos >> blockBits; int blockNum = pos >> blockBits;
if (handle._blockNum != blockNum) { if (handle._blockNum != blockNum) {
if (blockNum >= _blocks->size()) if (blockNum >= _blocks->size())
return false; return false;
if (!_img->readBlock(_blocks->at(blockNum), handle._data.data())) if (!_img->readBlock(handle._file, _blocks->at(blockNum),
handle._data.data()))
return false; return false;
handle._blockNum = blockNum; handle._blockNum = blockNum;
} }
handle._blockPos = mod2n(pos, 1U<<blockBits); handle._blockPos = mod2n(pos, 1U<<blockBits);
handle._pos = pos; handle._pos = pos;
} else {
int blockNum = pos >> BLOCK_BITS;
if (handle._blockNum != blockNum) {
if (!handle._file.seek((quint64)blockNum << BLOCK_BITS))
return false;
if (handle._file.read(handle._data.data(), (1<<BLOCK_BITS)) < 0)
return false;
handle._blockNum = blockNum;
}
handle._blockPos = mod2n(pos, 1U<<BLOCK_BITS);
handle._pos = pos;
}
return true; return true;
}
} }
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const

View File

@ -17,21 +17,26 @@ public:
{ {
public: public:
Handle(const SubFile *subFile) Handle(const SubFile *subFile)
: _file(0), _blockNum(-1), _blockPos(-1), _pos(-1) : _blockNum(-1), _blockPos(-1), _pos(-1)
{ {
if (subFile && subFile->_path) { if (!subFile)
_file = new QFile(*(subFile->_path)); return;
_file->open(QIODevice::ReadOnly);
if (subFile->_path) {
_file.setFileName(*(subFile->_path));
_data.resize(1U<<BLOCK_BITS); _data.resize(1U<<BLOCK_BITS);
} else if (subFile) } else {
_file.setFileName(subFile->_img->fileName());
_data.resize(1U<<subFile->_img->blockBits()); _data.resize(1U<<subFile->_img->blockBits());
} }
~Handle() {delete _file;}
_file.open(QIODevice::ReadOnly);
}
private: private:
friend class SubFile; friend class SubFile;
QFile *_file; QFile _file;
QByteArray _data; QByteArray _data;
int _blockNum; int _blockNum;
int _blockPos; int _blockPos;