38 lines
1.5 KiB
C++
38 lines
1.5 KiB
C++
#pragma once
|
|||
|
|
|
||
|
|
#include <QByteArray>
|
||
|
|
#include <QString>
|
||
|
|
|
||
|
|
// Turns a picked image into a file the gallery's upload API accepts.
|
||
|
|
//
|
||
|
|
// Three things must be true of the result: no EXIF (the gallery publishes the
|
||
|
|
// uploaded file verbatim as its full-size download, so embedded GPS would be
|
||
|
|
// public), a .jpg or .png extension (server.go rejects anything else, HEIC
|
||
|
|
// included), and under nginx's 20M body cap.
|
||
|
|
//
|
||
|
|
// JPEG and PNG take a lossless route — whole metadata segments are dropped
|
||
|
|
// without touching the compressed image data — so the published file keeps the
|
||
|
|
// original sensor pixels. Anything else, or a file whose EXIF orientation must
|
||
|
|
// be baked in, is decoded and re-encoded as JPEG (HEIC via Qt's qtimageformats
|
||
|
|
// plugin). The strippers are a direct port of the Android app's.
|
||
|
|
class ImagePrep
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
struct Prepared {
|
||
|
|
QString filePath;
|
||
|
|
QString note; // non-empty when the app departed from a byte-exact copy
|
||
|
|
QString error;
|
||
|
|
bool ok() const { return error.isEmpty(); }
|
||
|
|
};
|
||
|
|
|
||
|
|
// Writes the upload-ready file into cacheDir as baseName.(jpg|png).
|
||
|
|
static Prepared prepare(const QString &sourcePath, const QString &cacheDir,
|
||
|
|
const QString &baseName);
|
||
|
|
|
||
|
|
private:
|
||
|
|
static QByteArray stripJpegSegments(const QByteArray &src); // empty on parse failure
|
||
|
|
static QByteArray stripPngChunks(const QByteArray &src);
|
||
|
|
static bool isJpeg(const QByteArray &b);
|
||
|
|
static bool isPng(const QByteArray &b);
|
||
|
|
};
|