PxCrypt v0.2.2
Encrypt data within an image
Loading...
Searching...
No Matches
artwork.h
1#ifndef ARTWORK_H
2#define ARTWORK_H
3
4// Qt Includes
5#include <QByteArray>
6
7// Qx Includes
8#include <qx/core/qx-error.h>
9
10// Project Includes
11#include "medium_io/canvas.h"
12#include "art_io/artwork_error.h"
13#include "art_io/measure.h"
14
15using namespace Qt::Literals::StringLiterals;
16
17namespace PxCryptPrivate
18{
19
20class IArtwork
21{
22//-Class Aliases--------------------------------------------------------------------------------------------------------
23public:
24 using rendition_id_t = quint16;
25
26//-Class Variables--------------------------------------------------------------------------------------------------------
27protected:
28 static constexpr QDataStream::Version STREAM_VER = QDataStream::Qt_6_0; // Shouldn't matter for this, but just in case
29 static inline const QByteArray MAGIC_NUM = "PXC"_ba;
30
31//-Constructor---------------------------------------------------------------------------------------------------------
32protected:
33 IArtwork();
34
35//-Class Functions----------------------------------------------------------------------------------------------
36public:
37 static quint64 size(quint64 renditionSize);
38
39//-Instance Functions----------------------------------------------------------------------------------------------
40protected:
41 virtual quint64 renditionSize() const = 0;
42
43public:
44 quint64 size() const;
45};
46
47template<typename DerivedT, IArtwork::rendition_id_t RenditionId>
48class Artwork : IArtwork
49{
50//-Class Variables----------------------------------------------------------------------------------------------------------
51public:
52 static constexpr quint16 RENDITION_ID = RenditionId;
53
54//-Constructor-------------------------------------------------------------------------------------------------------------
55protected:
56 Artwork()
57 {
58 // Check requirement here as workaround to delay evaluation of incomplete type DerivedT
59 static_assert(measureable<DerivedT>);
60 };
61
62//-Class Functions----------------------------------------------------------------------------------------------
63public:
64 static ArtworkError readFromCanvas(DerivedT& art, Canvas& canvas)
65 {
66 // Null out return buffer
67 art = DerivedT();
68
69 // Setup stream
70 QDataStream canvasStream(&canvas);
71 canvasStream.setVersion(STREAM_VER);
72
73 // Read magic
74 QByteArray magic(MAGIC_NUM.size(), Qt::Uninitialized);
75 canvasStream.readRawData(magic.data(), MAGIC_NUM.size());
76 if(magic != MAGIC_NUM)
77 return ArtworkError(ArtworkError::NotMagic);
78
79 // Read rendition ID
80 quint16 renditionId; canvasStream >> renditionId;
81 if(renditionId != RENDITION_ID)
82 return ArtworkError(ArtworkError::WrongCodec, u"0x%1 instead of 0x%2."_s.arg(renditionId, 2, 16, QChar(u'0'))
83 .arg(RENDITION_ID, 2, 16, QChar(u'0')));
84
85 // Setup new artwork
86 DerivedT readArt;
87 Artwork& readArtBase = static_cast<Artwork&>(readArt); // TODO: WTF is this cast for???
88
89 // Read rendition portion
90 ArtworkError renditionError = readArtBase.renditionRead(canvasStream);
91
92 // Check stream
93 QDataStream::Status ss = canvasStream.status();
94 if(ss != QDataStream::Ok)
95 return ArtworkError(ArtworkError::DataStreamError, ENUM_NAME(ss));
96
97 // Check for rendition error
98 if(renditionError)
99 return renditionError;
100
101 // Return art
102 art = readArt;
103 return ArtworkError();
104 }
105
106//-Instance Functions----------------------------------------------------------------------------------------------
107protected:
108 virtual ArtworkError renditionRead(QDataStream& stream) = 0;
109 virtual ArtworkError renditionWrite(QDataStream& stream) const = 0;
110
111public:
112 ArtworkError writeToCanvas(Canvas& canvas)
113 {
114 // Setup stream
115 QDataStream canvasStream(&canvas);
116 canvasStream.setVersion(STREAM_VER);
117
118 // Write magic and rendition ID
119 canvasStream.writeRawData(MAGIC_NUM.constData(), MAGIC_NUM.size());
120 canvasStream << RENDITION_ID;
121
122 // Write rendition portion
123 ArtworkError renditionError = renditionWrite(canvasStream);
124
125 // Check stream
126 QDataStream::Status ss = canvasStream.status();
127 if(ss != QDataStream::Ok)
128 return ArtworkError(ArtworkError::DataStreamError, ENUM_NAME(ss));
129
130 return renditionError;
131 }
132};
133
134}
135
136#endif // ARTWORK_H