2020-11-10 00:58:19 +01:00
|
|
|
#include "huffmantext.h"
|
|
|
|
#include "rgnfile.h"
|
2019-05-10 18:56:19 +02:00
|
|
|
#include "lblfile.h"
|
|
|
|
|
2021-09-20 21:43:17 +02:00
|
|
|
using namespace Garmin;
|
2021-04-10 15:27:40 +02:00
|
|
|
using namespace IMG;
|
|
|
|
|
2019-05-10 18:56:19 +02:00
|
|
|
enum Charset {Normal, Symbol, Special};
|
|
|
|
|
|
|
|
static quint8 NORMAL_CHARS[] = {
|
|
|
|
' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
|
|
|
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
|
|
|
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
|
2019-06-30 20:39:22 +02:00
|
|
|
'X', 'Y', 'Z', '~', '~', '~', ' ', ' ',
|
2019-05-10 18:56:19 +02:00
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
|
|
'8', '9', '~', '~', '~', '~', '~', '~'
|
|
|
|
};
|
|
|
|
|
|
|
|
static quint8 SYMBOL_CHARS[] = {
|
|
|
|
'@', '!', '"', '#', '$', '%', '&', '\'',
|
|
|
|
'(', ')', '*', '+', ',', '-', '.', '/',
|
|
|
|
'~', '~', '~', '~', '~', '~', '~', '~',
|
|
|
|
'~', '~', ':', ';', '<', '=', '>', '?',
|
|
|
|
'~', '~', '~', '~', '~', '~', '~', '~',
|
|
|
|
'~', '~', '~', '[', '\\', ']', '^', '_'
|
|
|
|
};
|
|
|
|
|
|
|
|
static quint8 SPECIAL_CHARS[] = {
|
|
|
|
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
|
|
|
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
|
|
|
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
|
|
|
'x', 'y', 'z', '~', '~', '~', '~', '~',
|
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
|
|
|
'8', '9', '~', '~', '~', '~', '~', '~'
|
|
|
|
};
|
|
|
|
|
2020-02-16 12:57:40 +01:00
|
|
|
static bool isAllUpperCase(const QString &str)
|
2019-05-10 18:56:19 +02:00
|
|
|
{
|
|
|
|
if (str.isEmpty())
|
2020-02-16 12:57:40 +01:00
|
|
|
return false;
|
2019-05-10 18:56:19 +02:00
|
|
|
for (int i = 0; i < str.size(); i++)
|
2019-07-28 10:31:03 +02:00
|
|
|
if (str.at(i).isLetter() && !(str.at(i).isUpper()
|
|
|
|
|| str.at(i) == QChar(0x00DF)))
|
2020-02-16 12:57:40 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2020-02-16 12:57:40 +01:00
|
|
|
static QString capitalized(const QString &str)
|
|
|
|
{
|
2019-05-10 18:56:19 +02:00
|
|
|
QString ret(str);
|
|
|
|
for (int i = 0; i < str.size(); i++)
|
|
|
|
if (i && !str.at(i-1).isSpace())
|
|
|
|
ret[i] = str.at(i).toLower();
|
|
|
|
else
|
|
|
|
ret[i] = str.at(i);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-08-16 09:00:36 +02:00
|
|
|
static QByteArray ft2m(const QByteArray &str)
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
int number = str.toInt(&ok);
|
|
|
|
return ok ? QByteArray::number(qRound(number * 0.3048)) : str;
|
|
|
|
}
|
2019-06-30 20:39:22 +02:00
|
|
|
|
2020-11-10 00:58:19 +01:00
|
|
|
LBLFile::~LBLFile()
|
2019-05-10 18:56:19 +02:00
|
|
|
{
|
2020-11-10 00:58:19 +01:00
|
|
|
delete _huffmanText;
|
2021-02-01 20:06:05 +01:00
|
|
|
delete[] _table;
|
2021-02-10 21:26:26 +01:00
|
|
|
delete[] _rasters;
|
2020-11-10 00:58:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool LBLFile::load(Handle &hdl, const RGNFile *rgn, Handle &rgnHdl)
|
|
|
|
{
|
|
|
|
quint16 hdrLen, codepage;
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2020-11-10 00:58:19 +01:00
|
|
|
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
|
2022-03-25 19:28:32 +01:00
|
|
|
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _base.offset)
|
|
|
|
&& readUInt32(hdl, _base.size) && readByte(hdl, &_shift)
|
2021-02-01 20:06:05 +01:00
|
|
|
&& readByte(hdl, &_encoding) && seek(hdl, _gmpOffset + 0x57)
|
2022-03-25 19:28:32 +01:00
|
|
|
&& readUInt32(hdl, _poi.offset) && readUInt32(hdl, _poi.size)
|
|
|
|
&& readByte(hdl, &_poiShift) && seek(hdl, _gmpOffset + 0xAA)
|
2019-08-12 22:20:12 +02:00
|
|
|
&& readUInt16(hdl, codepage)))
|
2019-05-10 18:56:19 +02:00
|
|
|
return false;
|
|
|
|
|
2020-11-10 00:58:19 +01:00
|
|
|
if (hdrLen >= 0x132) {
|
|
|
|
quint32 offset, size;
|
|
|
|
quint16 recordSize;
|
|
|
|
if (!(seek(hdl, _gmpOffset + 0x124) && readUInt32(hdl, offset)
|
|
|
|
&& readUInt32(hdl, size) && readUInt16(hdl, recordSize)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (size && recordSize) {
|
|
|
|
_table = new quint32[size / recordSize];
|
|
|
|
if (!seek(hdl, offset))
|
|
|
|
return false;
|
|
|
|
for (quint32 i = 0; i < size / recordSize; i++) {
|
|
|
|
if (!readVUInt32(hdl, recordSize, _table[i]))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-25 21:37:07 +01:00
|
|
|
if (hdrLen >= 0x19A) {
|
2021-01-27 21:18:06 +01:00
|
|
|
quint32 offset, recordSize, size, flags;
|
|
|
|
if (!(seek(hdl, _gmpOffset + 0x184) && readUInt32(hdl, offset)
|
|
|
|
&& readUInt32(hdl, size) && readUInt16(hdl, recordSize)
|
2022-03-25 19:28:32 +01:00
|
|
|
&& readUInt32(hdl, flags) && readUInt32(hdl, _img.offset)
|
|
|
|
&& readUInt32(hdl, _img.size)))
|
2021-01-25 21:37:07 +01:00
|
|
|
return false;
|
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
if (size && recordSize)
|
|
|
|
if (!loadRasterTable(hdl, offset, size, recordSize))
|
2021-02-09 20:06:11 +01:00
|
|
|
return false;
|
2021-01-25 21:37:07 +01:00
|
|
|
}
|
|
|
|
|
2020-11-10 00:58:19 +01:00
|
|
|
if (_encoding == 11) {
|
|
|
|
_huffmanText = new HuffmanText();
|
|
|
|
if (!_huffmanText->load(rgn, rgnHdl))
|
|
|
|
return false;
|
|
|
|
}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2020-12-22 22:09:09 +01:00
|
|
|
_codec = TextCodec(codepage);
|
2019-05-10 18:56:19 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-11-10 00:58:19 +01:00
|
|
|
void LBLFile::clear()
|
|
|
|
{
|
|
|
|
delete _huffmanText;
|
2021-02-01 20:06:05 +01:00
|
|
|
delete[] _table;
|
2021-02-10 21:26:26 +01:00
|
|
|
delete[] _rasters;
|
2020-11-10 00:58:19 +01:00
|
|
|
_huffmanText = 0;
|
|
|
|
_table = 0;
|
2021-02-10 21:26:26 +01:00
|
|
|
_rasters = 0;
|
2020-11-10 00:58:19 +01:00
|
|
|
}
|
|
|
|
|
2022-02-06 02:42:37 +01:00
|
|
|
Label LBLFile::str2label(const QVector<quint8> &str, bool capitalize,
|
|
|
|
bool convert) const
|
|
|
|
{
|
|
|
|
Shield::Type shieldType = Shield::None;
|
|
|
|
QByteArray label, shieldLabel;
|
|
|
|
QByteArray *bap = &label;
|
|
|
|
int split = -1;
|
|
|
|
|
|
|
|
for (int i = 0; i < str.size(); i++) {
|
|
|
|
const quint8 &c = str.at(i);
|
|
|
|
|
|
|
|
if (c == 0 || c == 0x1d || c == 0x07)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c == 0x1c)
|
|
|
|
capitalize = false;
|
|
|
|
else if ((c >= 0x1e && c <= 0x1f)) {
|
|
|
|
if (bap == &shieldLabel)
|
|
|
|
bap = &label;
|
|
|
|
else {
|
|
|
|
if (!bap->isEmpty())
|
|
|
|
bap->append('\n');
|
|
|
|
if (c == 0x1f && split < 0)
|
|
|
|
split = bap->size();
|
|
|
|
}
|
|
|
|
} else if (c < 0x07) {
|
|
|
|
shieldType = static_cast<Shield::Type>(c);
|
|
|
|
bap = &shieldLabel;
|
|
|
|
} else if (bap == &shieldLabel && c == 0x20) {
|
|
|
|
bap = &label;
|
|
|
|
} else
|
|
|
|
bap->append(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (split >= 0)
|
|
|
|
label = label.left(split) + ft2m(label.mid(split));
|
|
|
|
else if (convert)
|
|
|
|
label = ft2m(label);
|
|
|
|
QString text(_codec.toString(label));
|
|
|
|
return Label(capitalize && isAllUpperCase(text) ? capitalized(text) : text,
|
|
|
|
Shield(shieldType, _codec.toString(shieldLabel)));
|
|
|
|
}
|
|
|
|
|
2022-02-06 11:53:43 +01:00
|
|
|
Label LBLFile::label6b(const SubFile *file, Handle &fileHdl, quint32 size,
|
|
|
|
bool capitalize, bool convert) const
|
2019-05-10 18:56:19 +02:00
|
|
|
{
|
2021-04-10 15:27:40 +02:00
|
|
|
Shield::Type shieldType = Shield::None;
|
2019-06-30 20:39:22 +02:00
|
|
|
QByteArray label, shieldLabel;
|
|
|
|
QByteArray *bap = &label;
|
2019-05-10 18:56:19 +02:00
|
|
|
Charset curCharSet = Normal;
|
|
|
|
quint8 b1, b2, b3;
|
2021-08-16 09:00:36 +02:00
|
|
|
int split = -1;
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2022-02-06 11:53:43 +01:00
|
|
|
for (quint32 i = 0; i < size; i = i + 3) {
|
2022-02-06 04:17:08 +01:00
|
|
|
if (!(file->readByte(fileHdl, &b1) && file->readByte(fileHdl, &b2)
|
|
|
|
&& file->readByte(fileHdl, &b3)))
|
2019-06-30 20:39:22 +02:00
|
|
|
return Label();
|
2019-05-10 18:56:19 +02:00
|
|
|
|
|
|
|
int c[]= {b1>>2, (b1&0x3)<<4|b2>>4, (b2&0xF)<<2|b3>>6, b3&0x3F};
|
|
|
|
|
|
|
|
for (int cpt = 0; cpt < 4; cpt++) {
|
2020-02-16 12:57:40 +01:00
|
|
|
if (c[cpt] > 0x2f || (curCharSet == Normal && c[cpt] == 0x1d)) {
|
2021-08-16 09:00:36 +02:00
|
|
|
if (split >= 0)
|
|
|
|
label = label.left(split) + ft2m(label.mid(split));
|
|
|
|
else if (convert)
|
|
|
|
label = ft2m(label);
|
2020-02-16 12:57:40 +01:00
|
|
|
QString text(QString::fromLatin1(label));
|
2020-02-16 13:59:19 +01:00
|
|
|
return Label(capitalize && isAllUpperCase(text)
|
2021-04-10 15:27:40 +02:00
|
|
|
? capitalized(text) : text, Shield(shieldType, shieldLabel));
|
2020-02-16 12:57:40 +01:00
|
|
|
}
|
2019-05-10 18:56:19 +02:00
|
|
|
switch (curCharSet) {
|
|
|
|
case Normal:
|
|
|
|
if (c[cpt] == 0x1c)
|
|
|
|
curCharSet = Symbol;
|
|
|
|
else if (c[cpt] == 0x1b)
|
|
|
|
curCharSet = Special;
|
2021-08-16 09:00:36 +02:00
|
|
|
else if (c[cpt] >= 0x1e && c[cpt] <= 0x1f) {
|
|
|
|
if (bap == &shieldLabel)
|
|
|
|
bap = &label;
|
|
|
|
else {
|
|
|
|
if (!bap->isEmpty())
|
|
|
|
bap->append('\n');
|
|
|
|
if (c[cpt] == 0x1f && split < 0)
|
|
|
|
split = bap->size();
|
|
|
|
}
|
|
|
|
} else if (c[cpt] >= 0x2a && c[cpt] <= 0x2f) {
|
2021-04-10 15:27:40 +02:00
|
|
|
shieldType = static_cast<Shield::Type>(c[cpt] - 0x29);
|
2019-06-30 20:39:22 +02:00
|
|
|
bap = &shieldLabel;
|
|
|
|
} else if (bap == &shieldLabel
|
|
|
|
&& NORMAL_CHARS[c[cpt]] == ' ')
|
|
|
|
bap = &label;
|
2019-05-10 18:56:19 +02:00
|
|
|
else
|
2019-06-30 20:39:22 +02:00
|
|
|
bap->append(NORMAL_CHARS[c[cpt]]);
|
2019-05-10 18:56:19 +02:00
|
|
|
break;
|
|
|
|
case Symbol:
|
2019-06-30 20:39:22 +02:00
|
|
|
bap->append(SYMBOL_CHARS[c[cpt]]);
|
2019-05-10 18:56:19 +02:00
|
|
|
curCharSet = Normal;
|
|
|
|
break;
|
|
|
|
case Special:
|
2019-06-30 20:39:22 +02:00
|
|
|
bap->append(SPECIAL_CHARS[c[cpt]]);
|
2019-05-10 18:56:19 +02:00
|
|
|
curCharSet = Normal;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-06 11:53:43 +01:00
|
|
|
|
|
|
|
return Label();
|
2019-05-10 18:56:19 +02:00
|
|
|
}
|
|
|
|
|
2022-02-06 11:53:43 +01:00
|
|
|
Label LBLFile::label8b(const SubFile *file, Handle &fileHdl, quint32 size,
|
|
|
|
bool capitalize, bool convert) const
|
2019-05-10 18:56:19 +02:00
|
|
|
{
|
2020-11-10 00:58:19 +01:00
|
|
|
QVector<quint8> str;
|
|
|
|
quint8 c;
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2022-02-06 11:53:43 +01:00
|
|
|
for (quint32 i = 0; i < size; i++) {
|
2022-02-06 04:17:08 +01:00
|
|
|
if (!file->readByte(fileHdl, &c))
|
2022-02-06 11:53:43 +01:00
|
|
|
break;
|
2020-11-10 00:58:19 +01:00
|
|
|
str.append(c);
|
2022-02-06 11:53:43 +01:00
|
|
|
if (!c)
|
|
|
|
return str2label(str, capitalize, convert);
|
|
|
|
}
|
2020-11-10 00:58:19 +01:00
|
|
|
|
2022-02-06 11:53:43 +01:00
|
|
|
return Label();
|
2020-11-10 00:58:19 +01:00
|
|
|
}
|
|
|
|
|
2022-02-06 04:17:08 +01:00
|
|
|
Label LBLFile::labelHuffman(Handle &hdl, const SubFile *file, Handle &fileHdl,
|
2022-02-06 11:53:43 +01:00
|
|
|
quint32 size, bool capitalize, bool convert) const
|
2020-11-10 00:58:19 +01:00
|
|
|
{
|
|
|
|
QVector<quint8> str;
|
|
|
|
|
2022-02-06 11:53:43 +01:00
|
|
|
if (!_huffmanText->decode(file, fileHdl, size, str))
|
2020-11-10 00:58:19 +01:00
|
|
|
return Label();
|
|
|
|
if (!_table)
|
2021-08-16 09:00:36 +02:00
|
|
|
return str2label(str, capitalize, convert);
|
2020-11-10 00:58:19 +01:00
|
|
|
|
|
|
|
|
|
|
|
QVector<quint8> str2;
|
|
|
|
for (int i = 0; i < str.size(); i++) {
|
|
|
|
quint32 val = _table[str.at(i)];
|
|
|
|
if (val) {
|
2022-03-25 19:28:32 +01:00
|
|
|
quint32 off = _base.offset + ((val & 0x7fffff) << _shift);
|
2021-11-02 21:15:22 +01:00
|
|
|
if (!seek(hdl, off))
|
2020-11-10 00:58:19 +01:00
|
|
|
return Label();
|
|
|
|
|
|
|
|
if (str2.size() && str2.back() == '\0')
|
|
|
|
str2[str2.size() - 1] = ' ';
|
|
|
|
else if (str2.size())
|
|
|
|
str2.append(' ');
|
2021-11-02 21:15:22 +01:00
|
|
|
|
2022-03-25 19:28:32 +01:00
|
|
|
if (!_huffmanText->decode(this, hdl, _base.offset + _base.size - off,
|
|
|
|
str2))
|
2020-11-10 00:58:19 +01:00
|
|
|
return Label();
|
|
|
|
} else {
|
|
|
|
if (str.at(i) == 7) {
|
|
|
|
str2.append(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (str2.size() && str2.back() == '\0')
|
|
|
|
str2[str2.size() - 1] = ' ';
|
|
|
|
str2.append(str.at(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-16 09:00:36 +02:00
|
|
|
return str2label(str2, capitalize, convert);
|
2020-11-10 00:58:19 +01:00
|
|
|
}
|
|
|
|
|
2021-08-16 09:00:36 +02:00
|
|
|
Label LBLFile::label(Handle &hdl, quint32 offset, bool poi, bool capitalize,
|
|
|
|
bool convert) const
|
2020-11-10 00:58:19 +01:00
|
|
|
{
|
2019-05-10 18:56:19 +02:00
|
|
|
quint32 labelOffset;
|
|
|
|
if (poi) {
|
|
|
|
quint32 poiOffset;
|
2022-03-25 19:28:32 +01:00
|
|
|
if (!(_poi.size >= (offset << _poiShift)
|
|
|
|
&& seek(hdl, _poi.offset + (offset << _poiShift))
|
2019-08-12 22:20:12 +02:00
|
|
|
&& readUInt24(hdl, poiOffset) && (poiOffset & 0x3FFFFF)))
|
2022-02-07 00:59:12 +01:00
|
|
|
return Label();
|
2022-03-25 19:28:32 +01:00
|
|
|
labelOffset = _base.offset + ((poiOffset & 0x3FFFFF) << _shift);
|
2019-05-10 18:56:19 +02:00
|
|
|
} else
|
2022-03-25 19:28:32 +01:00
|
|
|
labelOffset = _base.offset + (offset << _shift);
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2022-03-25 19:28:32 +01:00
|
|
|
if (labelOffset > _base.offset + _base.size)
|
2022-02-07 00:59:12 +01:00
|
|
|
return Label();
|
2022-02-06 02:42:37 +01:00
|
|
|
if (!seek(hdl, labelOffset))
|
|
|
|
return Label();
|
|
|
|
|
2022-03-25 19:28:32 +01:00
|
|
|
return label(hdl, this, hdl, _base.offset + _base.size - labelOffset,
|
|
|
|
capitalize, convert);
|
2022-02-06 02:42:37 +01:00
|
|
|
}
|
|
|
|
|
2022-02-06 04:17:08 +01:00
|
|
|
Label LBLFile::label(Handle &hdl, const SubFile *file, Handle &fileHdl,
|
2022-02-06 11:53:43 +01:00
|
|
|
quint32 size, bool capitalize, bool convert) const
|
2022-02-06 02:42:37 +01:00
|
|
|
{
|
2019-05-10 18:56:19 +02:00
|
|
|
switch (_encoding) {
|
|
|
|
case 6:
|
2022-02-06 11:53:43 +01:00
|
|
|
return label6b(file, fileHdl, size, capitalize, convert);
|
2019-05-10 18:56:19 +02:00
|
|
|
case 9:
|
|
|
|
case 10:
|
2022-02-06 11:53:43 +01:00
|
|
|
return label8b(file, fileHdl, size, capitalize, convert);
|
2020-11-10 00:58:19 +01:00
|
|
|
case 11:
|
2022-02-06 11:53:43 +01:00
|
|
|
return labelHuffman(hdl, file, fileHdl, size, capitalize, convert);
|
2019-05-10 18:56:19 +02:00
|
|
|
default:
|
2019-06-30 20:39:22 +02:00
|
|
|
return Label();
|
2019-05-10 18:56:19 +02:00
|
|
|
}
|
|
|
|
}
|
2021-01-25 21:37:07 +01:00
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
bool LBLFile::loadRasterTable(Handle &hdl, quint32 offset, quint32 size,
|
2021-01-27 21:18:06 +01:00
|
|
|
quint32 recordSize)
|
2021-01-25 21:37:07 +01:00
|
|
|
{
|
2021-02-10 21:26:26 +01:00
|
|
|
quint32 prev, cur;
|
|
|
|
|
|
|
|
_imgCount = size / recordSize;
|
2022-03-25 19:28:32 +01:00
|
|
|
_imgIdSize = byteSize(_imgCount - 1);
|
2021-02-10 21:26:26 +01:00
|
|
|
_rasters = new Image[_imgCount];
|
2021-01-27 21:18:06 +01:00
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
if (!(seek(hdl, offset) && readVUInt32(hdl, recordSize, prev)))
|
|
|
|
return false;
|
2021-01-27 21:18:06 +01:00
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
for (quint32 i = 1; i < _imgCount; i++) {
|
|
|
|
if (!readVUInt32(hdl, recordSize, cur))
|
2021-01-27 21:18:06 +01:00
|
|
|
return false;
|
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
_rasters[i-1].offset = prev;
|
|
|
|
_rasters[i-1].size = cur - prev;
|
|
|
|
|
|
|
|
prev = cur;
|
2021-01-25 21:37:07 +01:00
|
|
|
}
|
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
_rasters[_imgCount-1].offset = prev;
|
2022-03-25 19:28:32 +01:00
|
|
|
_rasters[_imgCount-1].size = _img.size - prev;
|
2021-02-10 21:26:26 +01:00
|
|
|
|
2021-01-27 21:18:06 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-03-19 08:42:20 +01:00
|
|
|
QPixmap LBLFile::image(Handle &hdl, quint32 id) const
|
2021-01-27 21:18:06 +01:00
|
|
|
{
|
2021-03-19 08:42:20 +01:00
|
|
|
QPixmap pm;
|
|
|
|
|
2021-02-10 21:26:26 +01:00
|
|
|
if (id >= _imgCount)
|
2021-03-19 08:42:20 +01:00
|
|
|
return pm;
|
2021-01-27 21:18:06 +01:00
|
|
|
|
2022-03-25 19:28:32 +01:00
|
|
|
if (!seek(hdl, _img.offset + _rasters[id].offset))
|
2021-03-19 08:42:20 +01:00
|
|
|
return pm;
|
2021-01-25 21:37:07 +01:00
|
|
|
QByteArray ba;
|
2021-02-10 21:26:26 +01:00
|
|
|
ba.resize(_rasters[id].size);
|
|
|
|
if (!read(hdl, ba.data(), _rasters[id].size))
|
2021-03-19 08:42:20 +01:00
|
|
|
return pm;
|
|
|
|
|
|
|
|
pm.loadFromData(ba, "jpeg");
|
2021-01-25 21:37:07 +01:00
|
|
|
|
2021-03-19 08:42:20 +01:00
|
|
|
return pm;
|
2021-01-25 21:37:07 +01:00
|
|
|
}
|