1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-24 03:35:53 +01:00

Be more tolerant to broken TYP files

Where possible, only skip the point/line/polygon entry, not the whole TYP file.
This commit is contained in:
Martin Tůma 2022-04-24 17:19:26 +02:00
parent 208e31c6de
commit 8f9af0d973
2 changed files with 526 additions and 484 deletions

View File

@ -4,6 +4,153 @@
using namespace IMG;
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
{
quint8 b, g, r;
if (!(file->readByte(hdl, &b) && file->readByte(hdl, &g)
&& file->readByte(hdl, &r)))
return false;
color = qRgb(r, g, b);
return true;
}
static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
int colors, int bpp, bool transparent)
{
img.setColorCount(colors);
if (transparent) {
quint8 byte;
quint32 bits = 0, reg = 0, mask = 0x000000FF;
for (int i = 0; i < colors; i++) {
while (bits < 28) {
if (!file->readByte(hdl, &byte))
return false;
mask = 0x000000FF << bits;
reg = reg & (~mask);
reg = reg | (byte << bits);
bits += 8;
}
img.setColor(i, qRgba((reg >> 16) & 0x0FF, (reg >> 8) & 0x0FF,
reg & 0x0FF, ~((reg >> 24) & 0x0F) << 4));
reg = reg >> 28;
bits -= 28;
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
} else {
QColor color;
for (int i = 0; i < colors; i++) {
if (!readColor(file, hdl, color))
return false;
img.setColor(i, color.rgb());
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
}
return true;
}
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
int bpp)
{
if (!bpp)
return true;
for (int y = 0; y < img.height(); y++) {
for (int x = 0; x < img.width(); x += 8/bpp) {
quint8 color;
if (!file->readByte(hdl, &color))
return false;
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
int value = (i > 0) ? (color >>= bpp) : color;
if (bpp == 4)
value = value & 0xf;
else if (bpp == 2)
value = value & 0x3;
else if (bpp == 1)
value = value & 0x1;
img.setPixel(x + i, y, value);
}
}
}
return true;
}
static int colors2bpp(quint8 colors, quint8 flags)
{
switch (flags) {
case 0x00:
if (colors < 3)
return colors;
else if (colors == 3)
return 2;
else if (colors < 16)
return 4;
else
return 8;
case 0x10:
if (colors == 0)
return 1;
else if (colors < 3)
return 2;
else if (colors < 15)
return 4;
else
return 8;
case 0x20:
if (colors == 0)
return -1;
else if (colors < 3)
return colors;
else if (colors < 4)
return 2;
else if (colors < 16)
return 4;
else
return 8;
default:
return -1;
}
}
static bool skipLabel(SubFile *file, SubFile::Handle &hdl)
{
quint32 len;
if (!file->readVUInt32(hdl, len))
return false;
if (!file->seek(hdl, file->pos(hdl) + len))
return false;
return true;
}
static QImage railroad()
{
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
img.fill(QColor("#717171"));
QPainter p(&img);
p.setPen(QPen(Qt::white, 2));
p.drawLine(9, 2, 15, 2);
return img;
}
void Style::defaultPolygonStyle()
{
_polygons[TYPE(0x01)] = Polygon(QBrush("#dfd3b5"));
@ -151,17 +298,6 @@ void Style::defaultPolygonStyle()
<< TYPE(0x13) << 0x10900;
}
static QImage railroad()
{
QImage img(16, 4, QImage::Format_ARGB32_Premultiplied);
img.fill(QColor("#717171"));
QPainter p(&img);
p.setPen(QPen(Qt::white, 2));
p.drawLine(9, 2, 15, 2);
return img;
}
void Style::defaultLineStyle()
{
_lines[TYPE(0x01)] = Line(QPen(QColor("#9bd772"), 2, Qt::SolidLine),
@ -537,62 +673,6 @@ void Style::defaultPointStyle()
_points[0x10705] = Point(QImage(":/IMG/anchoring-prohibited.png"));
}
static bool readBitmap(SubFile *file, SubFile::Handle &hdl, QImage &img,
int bpp)
{
if (!bpp)
return true;
for (int y = 0; y < img.height(); y++) {
for (int x = 0; x < img.width(); x += 8/bpp) {
quint8 color;
if (!file->readByte(hdl, &color))
return false;
for (int i = 0; i < 8/bpp && x + i < img.width(); i++) {
int value = (i > 0) ? (color >>= bpp) : color;
if (bpp == 4)
value = value & 0xf;
else if (bpp == 2)
value = value & 0x3;
else if (bpp == 1)
value = value & 0x1;
img.setPixel(x + i, y, value);
}
}
}
return true;
}
static bool readColor(SubFile *file, SubFile::Handle &hdl, QColor &color)
{
quint8 b, g, r;
if (!(file->readByte(hdl, &b) && file->readByte(hdl, &g)
&& file->readByte(hdl, &r)))
return false;
color = qRgb(r, g, b);
return true;
}
static bool skipLabel(SubFile *file, SubFile::Handle &hdl)
{
quint32 len;
if (!file->readVUInt32(hdl, len))
return false;
if (!file->seek(hdl, file->pos(hdl) + len))
return false;
return true;
}
bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
const Section &section, ItemInfo &info)
{
@ -623,21 +703,9 @@ bool Style::itemInfo(SubFile *file, SubFile::Handle &hdl,
return true;
}
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
const Section &section)
bool Style::parsePolygon(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
quint8 t8, flags;
if (!(file->seek(hdl, section.offset + info.offset)
&& file->readByte(hdl, &t8)))
@ -734,26 +802,13 @@ bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
default:
return false;
}
}
return true;
}
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
const Section &section)
bool Style::parseLine(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
quint8 t8_1, t8_2, flags, rows;
if (!(file->seek(hdl, section.offset + info.offset)
&& file->readByte(hdl, &t8_1) && file->readByte(hdl, &t8_2)))
@ -938,108 +993,15 @@ bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
}
_lines[type].setTextFontSize((FontSize)(labelFlags & 0x07));
}
}
return true;
}
static int colors2bpp(quint8 colors, quint8 flags)
bool Style::parsePoint(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type)
{
switch (flags) {
case 0x00:
if (colors < 3)
return colors;
else if (colors == 3)
return 2;
else if (colors < 16)
return 4;
else
return 8;
case 0x10:
if (colors == 0)
return 1;
else if (colors < 3)
return 2;
else if (colors < 15)
return 4;
else
return 8;
case 0x20:
if (colors == 0)
return -1;
else if (colors < 3)
return colors;
else if (colors < 4)
return 2;
else if (colors < 16)
return 4;
else
return 8;
default:
return -1;
}
}
static bool readColorTable(SubFile *file, SubFile::Handle &hdl, QImage& img,
int colors, int bpp, bool transparent)
{
img.setColorCount(colors);
if (transparent) {
quint8 byte;
quint32 bits = 0, reg = 0, mask = 0x000000FF;
for (int i = 0; i < colors; i++) {
while (bits < 28) {
if (!file->readByte(hdl, &byte))
return false;
mask = 0x000000FF << bits;
reg = reg & (~mask);
reg = reg | (byte << bits);
bits += 8;
}
img.setColor(i, qRgba((reg >> 16) & 0x0FF, (reg >> 8) & 0x0FF,
reg & 0x0FF, ~((reg >> 24) & 0x0F) << 4));
reg = reg >> 28;
bits -= 28;
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
} else {
QColor color;
for (int i = 0; i < colors; i++) {
if (!readColor(file, hdl, color))
return false;
img.setColor(i, color.rgb());
}
for (int i = colors; i < 1<<bpp; i++)
img.setColor(i, qRgba(0, 0, 0, 0));
}
return true;
}
bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype
: (info.type << 8) | info.subtype;
quint8 t8_1, width, height, numColors, imgType;
if (!(file->seek(hdl, section.offset + info.offset)
&& file->readByte(hdl, &t8_1) && file->readByte(hdl, &width)
&& file->readByte(hdl, &height) && file->readByte(hdl, &numColors)
@ -1051,7 +1013,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
int bpp = colors2bpp(numColors, imgType);
if (bpp <= 0)
continue;
return true;
QImage img(width, height, QImage::Format_Indexed8);
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
return false;
@ -1064,7 +1026,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
&& file->readByte(hdl, &imgType)))
return false;
if ((bpp = colors2bpp(numColors, imgType)) < 0)
continue;
return true;
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
return false;
if (!readBitmap(file, hdl, img, bpp))
@ -1074,7 +1036,7 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
&& file->readByte(hdl, &imgType)))
return false;
if ((bpp = colors2bpp(numColors, imgType)) < 0)
continue;
return true;
if (!readColorTable(file, hdl, img, numColors, bpp, imgType == 0x20))
return false;
}
@ -1094,6 +1056,79 @@ bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
}
_points[type].setTextFontSize((FontSize)(labelFlags & 0x07));
}
return true;
}
bool Style::parsePolygons(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
if (!parsePolygon(file, hdl, section, info, type))
qWarning("%s: %x: broken polygon style",
qPrintable(file->fileName()), type);
}
return true;
}
bool Style::parseLines(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype : (info.type << 8);
if (!parseLine(file, hdl, section, info, type))
qWarning("%s: %x: broken line style", qPrintable(file->fileName()),
type);
}
return true;
}
bool Style::parsePoints(SubFile *file, SubFile::Handle &hdl,
const Section &section)
{
if (!section.arrayItemSize)
return section.arraySize ? false : true;
for (quint32 i = 0; i < section.arraySize / section.arrayItemSize; i++) {
if (!file->seek(hdl, section.arrayOffset + i * section.arrayItemSize))
return false;
ItemInfo info;
if (!itemInfo(file, hdl, section, info))
return false;
quint32 type = info.extended
? 0x10000 | (info.type << 8) | info.subtype
: (info.type << 8) | info.subtype;
if (!parsePoint(file, hdl, section, info, type))
qWarning("%s: %x: broken point style", qPrintable(file->fileName()),
type);
}
return true;

View File

@ -147,18 +147,25 @@ private:
bool parseTYPFile(SubFile *file);
bool parsePoints(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool parsePoint(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type);
bool parseLines(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool parseLine(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type);
bool parsePolygons(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool parsePolygon(SubFile *file, SubFile::Handle &hdl,
const Section &section, const ItemInfo &info, quint32 type);
bool parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
const Section &section);
bool itemInfo(SubFile *file, SubFile::Handle &hdl,
const Section &section, ItemInfo &info);
void defaultPolygonStyle();
void defaultLineStyle();
void defaultPointStyle();
static bool itemInfo(SubFile *file, SubFile::Handle &hdl,
const Section &section, ItemInfo &info);
QMap<quint32, Line> _lines;
QMap<quint32, Polygon> _polygons;
QMap<quint32, Point> _points;