RagePhoto: G5E2P and G5E3P parser added
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
a798be0b53
commit
b70396f77e
2 changed files with 304 additions and 154 deletions
192
RagePhoto.cpp
192
RagePhoto.cpp
|
@ -23,18 +23,24 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
RagePhoto::RagePhoto(const QString &filePath) : p_filePath(filePath)
|
RagePhoto::RagePhoto(const QByteArray &data) : p_fileData(data)
|
||||||
{
|
{
|
||||||
p_inputMode = 0;
|
p_inputMode = 0;
|
||||||
p_isLoaded = false;
|
p_isLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RagePhoto::RagePhoto(QIODevice *ioDevice) : p_ioDevice(ioDevice)
|
RagePhoto::RagePhoto(const QString &filePath) : p_filePath(filePath)
|
||||||
{
|
{
|
||||||
p_inputMode = 1;
|
p_inputMode = 1;
|
||||||
p_isLoaded = false;
|
p_isLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RagePhoto::RagePhoto(QIODevice *ioDevice) : p_ioDevice(ioDevice)
|
||||||
|
{
|
||||||
|
p_inputMode = 2;
|
||||||
|
p_isLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool RagePhoto::isLoaded()
|
bool RagePhoto::isLoaded()
|
||||||
{
|
{
|
||||||
return p_isLoaded;
|
return p_isLoaded;
|
||||||
|
@ -45,36 +51,31 @@ bool RagePhoto::load()
|
||||||
if (p_isLoaded)
|
if (p_isLoaded)
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
QByteArray readData;
|
if (p_inputMode == 1) {
|
||||||
if (p_inputMode == 0) {
|
|
||||||
QFile pictureFile(p_filePath);
|
QFile pictureFile(p_filePath);
|
||||||
if (pictureFile.open(QIODevice::ReadOnly)) {
|
if (pictureFile.open(QIODevice::ReadOnly)) {
|
||||||
readData = pictureFile.readAll();
|
p_fileData = pictureFile.readAll();
|
||||||
}
|
}
|
||||||
pictureFile.close();
|
pictureFile.close();
|
||||||
}
|
}
|
||||||
else if (p_inputMode == 1) {
|
else if (p_inputMode == 2) {
|
||||||
if (!p_ioDevice->isOpen()) {
|
if (!p_ioDevice->isOpen()) {
|
||||||
if (!p_ioDevice->open(QIODevice::ReadOnly))
|
if (!p_ioDevice->open(QIODevice::ReadOnly))
|
||||||
return false;
|
return false;
|
||||||
readData = p_ioDevice->readAll();
|
|
||||||
}
|
}
|
||||||
}
|
p_fileData = p_ioDevice->readAll();
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QBuffer dataBuffer(&readData);
|
QBuffer dataBuffer(&p_fileData);
|
||||||
dataBuffer.open(QIODevice::ReadOnly);
|
dataBuffer.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
char formatHeader[4];
|
char formatHeader[4];
|
||||||
qint64 size = dataBuffer.read(formatHeader, 4);
|
qint64 size = dataBuffer.read(formatHeader, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
quint32 format = charToUInt32(formatHeader);
|
quint32 format = charToUInt32LE(formatHeader);
|
||||||
if (format != PhotoFormat::GTA5)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
if (format == PhotoFormat::GTA5) {
|
||||||
char photoHeader[256];
|
char photoHeader[256];
|
||||||
size = dataBuffer.read(photoHeader, 256);
|
size = dataBuffer.read(photoHeader, 256);
|
||||||
if (size != 256)
|
if (size != 256)
|
||||||
|
@ -89,31 +90,31 @@ bool RagePhoto::load()
|
||||||
size = dataBuffer.read(checksum, 4);
|
size = dataBuffer.read(checksum, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_headerCRC = charToUInt32(checksum);
|
p_headerSum = charToUInt32LE(checksum);
|
||||||
|
|
||||||
char endOfFile[4];
|
char endOfFile[4];
|
||||||
size = dataBuffer.read(endOfFile, 4);
|
size = dataBuffer.read(endOfFile, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_endOfFile = charToUInt32(endOfFile);
|
p_endOfFile = charToUInt32LE(endOfFile);
|
||||||
|
|
||||||
char jsonOffset[4];
|
char jsonOffset[4];
|
||||||
size = dataBuffer.read(jsonOffset, 4);
|
size = dataBuffer.read(jsonOffset, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_jsonOffset = charToUInt32(jsonOffset);
|
p_jsonOffset = charToUInt32LE(jsonOffset);
|
||||||
|
|
||||||
char titleOffset[4];
|
char titleOffset[4];
|
||||||
size = dataBuffer.read(titleOffset, 4);
|
size = dataBuffer.read(titleOffset, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_titlOffset = charToUInt32(titleOffset);
|
p_titlOffset = charToUInt32LE(titleOffset);
|
||||||
|
|
||||||
char descOffset[4];
|
char descOffset[4];
|
||||||
size = dataBuffer.read(descOffset, 4);
|
size = dataBuffer.read(descOffset, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_descOffset = charToUInt32(descOffset);
|
p_descOffset = charToUInt32LE(descOffset);
|
||||||
|
|
||||||
char jpegMarker[4];
|
char jpegMarker[4];
|
||||||
size = dataBuffer.read(jpegMarker, 4);
|
size = dataBuffer.read(jpegMarker, 4);
|
||||||
|
@ -126,13 +127,13 @@ bool RagePhoto::load()
|
||||||
size = dataBuffer.read(jpegBuffer, 4);
|
size = dataBuffer.read(jpegBuffer, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_jpegBuffer = charToUInt32(jpegBuffer);
|
p_jpegBuffer = charToUInt32LE(jpegBuffer);
|
||||||
|
|
||||||
char photoSize[4];
|
char photoSize[4];
|
||||||
size = dataBuffer.read(photoSize, 4);
|
size = dataBuffer.read(photoSize, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
p_photoSize = charToUInt32(photoSize);
|
p_photoSize = charToUInt32LE(photoSize);
|
||||||
|
|
||||||
char photoData[p_photoSize];
|
char photoData[p_photoSize];
|
||||||
size = dataBuffer.read(photoData, p_photoSize);
|
size = dataBuffer.read(photoData, p_photoSize);
|
||||||
|
@ -152,7 +153,7 @@ bool RagePhoto::load()
|
||||||
size = dataBuffer.read(jsonSize, 4);
|
size = dataBuffer.read(jsonSize, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
quint32 i_jsonSize = charToUInt32(jsonSize);
|
quint32 i_jsonSize = charToUInt32LE(jsonSize);
|
||||||
|
|
||||||
char jsonBytes[i_jsonSize];
|
char jsonBytes[i_jsonSize];
|
||||||
size = dataBuffer.read(jsonBytes, i_jsonSize);
|
size = dataBuffer.read(jsonBytes, i_jsonSize);
|
||||||
|
@ -181,7 +182,7 @@ bool RagePhoto::load()
|
||||||
size = dataBuffer.read(titlSize, 4);
|
size = dataBuffer.read(titlSize, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
quint32 i_titlSize = charToUInt32(titlSize);
|
quint32 i_titlSize = charToUInt32LE(titlSize);
|
||||||
|
|
||||||
char titlBytes[i_titlSize];
|
char titlBytes[i_titlSize];
|
||||||
size = dataBuffer.read(titlBytes, i_titlSize);
|
size = dataBuffer.read(titlBytes, i_titlSize);
|
||||||
|
@ -205,7 +206,7 @@ bool RagePhoto::load()
|
||||||
size = dataBuffer.read(descSize, 4);
|
size = dataBuffer.read(descSize, 4);
|
||||||
if (size != 4)
|
if (size != 4)
|
||||||
return false;
|
return false;
|
||||||
quint32 i_descSize = charToUInt32(descSize);
|
quint32 i_descSize = charToUInt32LE(descSize);
|
||||||
|
|
||||||
char descBytes[i_descSize];
|
char descBytes[i_descSize];
|
||||||
size = dataBuffer.read(descBytes, i_descSize);
|
size = dataBuffer.read(descBytes, i_descSize);
|
||||||
|
@ -225,9 +226,143 @@ bool RagePhoto::load()
|
||||||
if (strncmp(jendMarker, "JEND", 4) != 0)
|
if (strncmp(jendMarker, "JEND", 4) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
p_fileData.clear();
|
||||||
p_isLoaded = true;
|
p_isLoaded = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (format == PhotoFormat::G5EX) {
|
||||||
|
char formatHeader[4];
|
||||||
|
qint64 size = dataBuffer.read(formatHeader, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
quint32 format = charToUInt32LE(formatHeader);
|
||||||
|
if (format == ExportFormat::G5E3P) {
|
||||||
|
char photoHeaderSize[4];
|
||||||
|
size = dataBuffer.peek(photoHeaderSize, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
quint32 i_photoHeaderSize = charToUInt32BE(photoHeaderSize) + 4;
|
||||||
|
|
||||||
|
char compressedPhotoHeader[i_photoHeaderSize];
|
||||||
|
size = dataBuffer.read(compressedPhotoHeader, i_photoHeaderSize);
|
||||||
|
if (size != i_photoHeaderSize)
|
||||||
|
return false;
|
||||||
|
QByteArray t_photoHeaderBytes = QByteArray::fromRawData(compressedPhotoHeader, i_photoHeaderSize);
|
||||||
|
t_photoHeaderBytes = qUncompress(t_photoHeaderBytes);
|
||||||
|
p_photoString = QString::fromUtf8(t_photoHeaderBytes);
|
||||||
|
|
||||||
|
char checksum[4];
|
||||||
|
size = dataBuffer.read(checksum, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
p_headerSum = charToUInt32LE(checksum);
|
||||||
|
|
||||||
|
char jpegBuffer[4];
|
||||||
|
size = dataBuffer.read(jpegBuffer, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
p_jpegBuffer = charToUInt32LE(jpegBuffer);
|
||||||
|
|
||||||
|
char photoSize[4];
|
||||||
|
size = dataBuffer.peek(photoSize, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
quint32 i_photoSize = charToUInt32BE(photoSize) + 4;
|
||||||
|
|
||||||
|
char compressedPhoto[i_photoSize];
|
||||||
|
size = dataBuffer.read(compressedPhoto, i_photoSize);
|
||||||
|
if (size != i_photoSize)
|
||||||
|
return false;
|
||||||
|
QByteArray t_photoData = QByteArray::fromRawData(compressedPhoto, i_photoSize);
|
||||||
|
p_photoData = qUncompress(t_photoData);
|
||||||
|
p_photoSize = p_photoData.size();
|
||||||
|
|
||||||
|
char jsonOffset[4];
|
||||||
|
size = dataBuffer.read(jsonOffset, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
p_jsonOffset = charToUInt32LE(jsonOffset);
|
||||||
|
|
||||||
|
char jsonSize[4];
|
||||||
|
size = dataBuffer.peek(jsonSize, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
quint32 i_jsonSize = charToUInt32BE(jsonSize) + 4;
|
||||||
|
|
||||||
|
char compressedJson[i_jsonSize];
|
||||||
|
size = dataBuffer.read(compressedJson, i_jsonSize);
|
||||||
|
if (size != i_jsonSize)
|
||||||
|
return false;
|
||||||
|
QByteArray t_jsonBytes = QByteArray::fromRawData(compressedJson, i_jsonSize);
|
||||||
|
t_jsonBytes = qUncompress(t_jsonBytes);
|
||||||
|
QJsonDocument t_jsonDocument = QJsonDocument::fromJson(t_jsonBytes);
|
||||||
|
if (t_jsonDocument.isNull())
|
||||||
|
return false;
|
||||||
|
p_jsonObject = t_jsonDocument.object();
|
||||||
|
|
||||||
|
char titleOffset[4];
|
||||||
|
size = dataBuffer.read(titleOffset, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
p_titlOffset = charToUInt32LE(titleOffset);
|
||||||
|
|
||||||
|
char titlSize[4];
|
||||||
|
size = dataBuffer.peek(titlSize, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
quint32 i_titlSize = charToUInt32BE(titlSize) + 4;
|
||||||
|
|
||||||
|
char compressedTitl[i_titlSize];
|
||||||
|
size = dataBuffer.read(compressedTitl, i_titlSize);
|
||||||
|
if (size != i_titlSize)
|
||||||
|
return false;
|
||||||
|
QByteArray t_titlBytes = QByteArray::fromRawData(compressedTitl, i_titlSize);
|
||||||
|
t_titlBytes = qUncompress(t_titlBytes);
|
||||||
|
p_titleString = QString::fromUtf8(t_titlBytes);
|
||||||
|
|
||||||
|
char descOffset[4];
|
||||||
|
size = dataBuffer.read(descOffset, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
p_descOffset = charToUInt32LE(descOffset);
|
||||||
|
|
||||||
|
char descSize[4];
|
||||||
|
size = dataBuffer.peek(descSize, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
quint32 i_descSize = charToUInt32BE(descSize) + 4;
|
||||||
|
|
||||||
|
char compressedDesc[i_descSize];
|
||||||
|
size = dataBuffer.read(compressedDesc, i_descSize);
|
||||||
|
if (size != i_descSize)
|
||||||
|
return false;
|
||||||
|
QByteArray t_descBytes = QByteArray::fromRawData(compressedDesc, i_descSize);
|
||||||
|
t_descBytes = qUncompress(t_descBytes);
|
||||||
|
p_descriptionString = QString::fromUtf8(t_descBytes);
|
||||||
|
|
||||||
|
char endOfFile[4];
|
||||||
|
size = dataBuffer.read(endOfFile, 4);
|
||||||
|
if (size != 4)
|
||||||
|
return false;
|
||||||
|
p_endOfFile = charToUInt32LE(endOfFile);
|
||||||
|
|
||||||
|
p_fileData.clear();
|
||||||
|
p_isLoaded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (format == ExportFormat::G5E2P) {
|
||||||
|
p_fileData = dataBuffer.readAll();
|
||||||
|
p_inputMode = 0;
|
||||||
|
return load();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RagePhoto::clear()
|
void RagePhoto::clear()
|
||||||
{
|
{
|
||||||
|
@ -236,7 +371,7 @@ void RagePhoto::clear()
|
||||||
p_photoData.clear();
|
p_photoData.clear();
|
||||||
p_photoString.clear();
|
p_photoString.clear();
|
||||||
p_titleString.clear();
|
p_titleString.clear();
|
||||||
p_headerCRC = 0;
|
p_headerSum = 0;
|
||||||
p_isLoaded = false;
|
p_isLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +428,12 @@ RagePhoto* RagePhoto::loadFile(const QString &filePath)
|
||||||
return ragePhoto;
|
return ragePhoto;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 RagePhoto::charToUInt32(char *x)
|
quint32 RagePhoto::charToUInt32BE(char *x)
|
||||||
|
{
|
||||||
|
return (((unsigned char)x[0] << 24) | ((unsigned char)x[1] << 16) | ((unsigned char)x[2] << 8) | ((unsigned char)x[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 RagePhoto::charToUInt32LE(char *x)
|
||||||
{
|
{
|
||||||
return (((unsigned char)x[3] << 24) | ((unsigned char)x[2] << 16) | ((unsigned char)x[1] << 8) | ((unsigned char)x[0]));
|
return (((unsigned char)x[3] << 24) | ((unsigned char)x[2] << 16) | ((unsigned char)x[1] << 8) | ((unsigned char)x[0]));
|
||||||
}
|
}
|
||||||
|
|
14
RagePhoto.h
14
RagePhoto.h
|
@ -27,10 +27,18 @@ class RagePhoto : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
enum ExportFormat {
|
||||||
|
G5E2P = 0x01000032U,
|
||||||
|
G5E2S = 0x02000032U,
|
||||||
|
G5E3P = 0x01000033U,
|
||||||
|
G5E3S = 0x02000033U,
|
||||||
|
};
|
||||||
enum PhotoFormat {
|
enum PhotoFormat {
|
||||||
|
G5EX = 0x45354700U,
|
||||||
GTA5 = 0x01000000U,
|
GTA5 = 0x01000000U,
|
||||||
RDR2 = 0x04000000U,
|
RDR2 = 0x04000000U,
|
||||||
};
|
};
|
||||||
|
explicit RagePhoto(const QByteArray &data);
|
||||||
explicit RagePhoto(const QString &filePath = QString());
|
explicit RagePhoto(const QString &filePath = QString());
|
||||||
explicit RagePhoto(QIODevice *device);
|
explicit RagePhoto(QIODevice *device);
|
||||||
bool isLoaded();
|
bool isLoaded();
|
||||||
|
@ -48,8 +56,10 @@ public:
|
||||||
static RagePhoto* loadFile(const QString &filePath);
|
static RagePhoto* loadFile(const QString &filePath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline quint32 charToUInt32(char *x);
|
inline quint32 charToUInt32BE(char *x);
|
||||||
|
inline quint32 charToUInt32LE(char *x);
|
||||||
QJsonObject p_jsonObject;
|
QJsonObject p_jsonObject;
|
||||||
|
QByteArray p_fileData;
|
||||||
QByteArray p_photoData;
|
QByteArray p_photoData;
|
||||||
QIODevice *p_ioDevice;
|
QIODevice *p_ioDevice;
|
||||||
QString p_descriptionString;
|
QString p_descriptionString;
|
||||||
|
@ -58,7 +68,7 @@ private:
|
||||||
QString p_titleString;
|
QString p_titleString;
|
||||||
quint32 p_descOffset;
|
quint32 p_descOffset;
|
||||||
quint32 p_endOfFile;
|
quint32 p_endOfFile;
|
||||||
quint32 p_headerCRC;
|
quint32 p_headerSum;
|
||||||
quint32 p_jpegBuffer;
|
quint32 p_jpegBuffer;
|
||||||
quint32 p_jsonOffset;
|
quint32 p_jsonOffset;
|
||||||
quint32 p_photoSize;
|
quint32 p_photoSize;
|
||||||
|
|
Loading…
Reference in a new issue