Perceptual Color

iohandlerfactory.cpp
1// SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR MIT
3
4// Own headers
5// First the interface, which forces the header to be self-contained.
6#include "iohandlerfactory.h"
7
8#include "helpermath.h"
9#include <lcms2.h>
10#include <lcms2_plugin.h>
11#include <limits>
12#include <qdebug.h>
13#include <qfile.h>
14#include <qglobal.h>
15#include <qiodevice.h>
16#include <qstringliteral.h>
17
18#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
19#include <qiodevicebase.h>
20#endif
21
22namespace PerceptualColor
23{
24/** @internal
25 *
26 * @brief Read from file.
27 *
28 * @param iohandler The <tt>cmsIOHANDLER</tt> on which to operate
29 * @param Buffer Pointer to the buffer to which the data should be loaded
30 * @param size Size of the chucks that should be loaded
31 * @param count Number of elements that should be loaded
32 * @returns On success, <tt>count</tt> is returned. If failing (either
33 * because less elements have been read or because zero elements have
34 * been read), <tt>0</tt> is returned. */
35cmsUInt32Number IOHandlerFactory::read(cmsIOHANDLER *iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count)
36{
37 QFile *const myFile = static_cast<QFile *>(iohandler->stream);
38 const cmsUInt32Number numberOfBytesRequested = size * count;
39 const qint64 numberOfBytesRead = myFile->read( //
40 static_cast<char *>(Buffer),
41 size * count);
42 if (numberOfBytesRead != numberOfBytesRequested) {
43 return 0;
44 }
45 return count;
46}
47
48/** @internal
49 *
50 * @brief Sets the current position within the file.
51 *
52 * @param iohandler The <tt>cmsIOHANDLER</tt> on which to operate
53 * @param offset Set the current position to this position
54 * @returns <tt>true</tt> on success, or <tt>false</tt> if an error
55 * occurred. */
56cmsBool IOHandlerFactory::seek(cmsIOHANDLER *iohandler, cmsUInt32Number offset)
57{
58 QFile *const myFile = static_cast<QFile *>(iohandler->stream);
59 const bool seekSucceeded = myFile->seek(offset);
60 if (!seekSucceeded) {
61 qDebug() << QStringLiteral("Seek error; probably corrupted file");
62 return false;
63 }
64 return true;
65}
66
67/** @internal
68 *
69 * @brief The position that data is written to or read from.
70 * @param iohandler The <tt>cmsIOHANDLER</tt> on which to operate
71 * @returns The position that data is written to or read from. */
72cmsUInt32Number IOHandlerFactory::tell(cmsIOHANDLER *iohandler)
73{
74 const QFile *const myFile = static_cast<QFile *>(iohandler->stream);
75 return static_cast<cmsUInt32Number>(myFile->pos());
76}
77
78/** @internal
79 *
80 * @brief Writes data to stream.
81 *
82 * Also keeps used space for further reference.
83 *
84 * @param iohandler The <tt>cmsIOHANDLER</tt> on which to operate
85 * @param size The size of the buffer that should be written
86 * @param Buffer The buffer that should be written
87 * @returns Returns <tt>true</tt> on success, <tt>false</tt> on error.
88 *
89 * @note Because @ref IOHandlerFactory only provides support for read-only
90 * handlers, this function does nothing and returns always <tt>false</tt>. */
91cmsBool IOHandlerFactory::write(cmsIOHANDLER *iohandler, cmsUInt32Number size, const void *Buffer)
92{
93 Q_UNUSED(iohandler)
94 Q_UNUSED(size)
95 Q_UNUSED(Buffer)
96 return false;
97}
98
99/** @internal
100 *
101 * @brief Closes the file and deletes the file handler.
102 * @param iohandler The <tt>cmsIOHANDLER</tt> on which to operate
103 * @returns <tt>true</tt> on success. */
104cmsBool IOHandlerFactory::close(cmsIOHANDLER *iohandler)
105{
106 QFile *const myFile = static_cast<QFile *>(iohandler->stream);
107 delete myFile; // This will also close the file.
108 iohandler->stream = nullptr;
109 _cmsFree(iohandler->ContextID, iohandler);
110 return true;
111}
112
113/** @brief Create a read-only LittleCMS IO handler for a file.
114 *
115 * The handler has to be deleted with <tt>cmsCloseIOhandler</tt>
116 * to free memory once it is not used anymore.
117 *
118 * @param ContextID Handle to user-defined context, or <tt>nullptr</tt> for
119 * the global context
120 * @param fileName Name of the file. See QFile::setFileName() for
121 * the valid format. This format is portable, has standardized directory
122 * separators and supports Unicode file names on all platforms.
123 * @returns On success, a pointer to a new IO handler. On fail,
124 * <tt>nullptr</tt>. The function might fail when the file does not
125 * exist or cannot be opened for reading.
126 *
127 * @internal
128 *
129 * @note The type of the return value is not fully defined
130 * in <tt>lcms2.h</tt> but only in <tt>lcms2_plugin.h</tt>. This is
131 * the expected behaviour for an opaque handle. */
132cmsIOHANDLER *IOHandlerFactory::createReadOnly(cmsContext ContextID, const QString &fileName)
133{
134 cmsIOHANDLER *const result = static_cast<cmsIOHANDLER *>( //
135 _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)) //
136 );
137 if (result == nullptr) {
138 return nullptr;
139 }
140
141 QFile *const fileObject = new QFile(fileName);
142 if (fileObject == nullptr) {
143 return nullptr;
144 }
145
146 const bool openSucceeded = fileObject->open(QIODevice::ReadOnly);
147 const qint64 fileSize = fileObject->size();
148 // Check if the size is not negative (this might be an error indicator)
149 // neither too big for LittleCMS’s data types:
150 const bool isFileSizeOkay = PerceptualColor::isInRange<qint64>( //
151 0,
152 fileSize,
153 std::numeric_limits<cmsInt32Number>::max());
154 if ((!openSucceeded) || (!isFileSizeOkay)) {
155 delete fileObject;
156 _cmsFree(ContextID, result);
157 return nullptr;
158 }
159
160 // Initialize data members
161 result->ContextID = ContextID;
162 // static_cast loses integer precision: 'qint64' to 'cmsInt32Number'.
163 // This is okay because we have tested yet that the file is not that big.
164 result->ReportedSize = static_cast<cmsUInt32Number>(fileSize);
165 result->stream = static_cast<void *>(fileObject);
166 result->UsedSpace = 0;
167 result->PhysicalFile[0] = 0;
168
169 // Initialize function pointers
170 result->Read = read;
171 result->Seek = seek;
172 result->Close = close;
173 result->Tell = tell;
174 result->Write = write;
175
176 return result;
177}
178
179} // namespace PerceptualColor
The namespace of this library.
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
virtual qint64 size() const const override
virtual qint64 pos() const const override
virtual bool seek(qint64 pos) override
QByteArray read(qint64 maxSize)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:36 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.