45 char comment[81] = {};
50 const int bytesRead = s.
readRawData(header.id.data(), 4);
52 header.id.resize(bytesRead);
60 header.fields =
static_cast<PicFields
>(fields);
81 char comment[80] = {};
82 strncpy(comment, header.comment.constData(),
sizeof(comment));
86 strncpy(
id, header.id.constData(),
sizeof(
id));
92 s << quint16(header.fields);
113 const unsigned maxChannels = 8;
121 s >> channel.encoding;
148 Q_ASSERT(channels.
size() > 0);
149 for (
int i = 0; i < channels.
size() - 1; ++i) {
151 s << channels[i].
size;
152 s << quint8(channels[i].encoding);
153 s << channels[i].code;
156 s << channels.
last().size;
157 s << quint8(channels.
last().encoding);
158 s << channels.
last().code;
164 for (
const PicChannel &channel : channels) {
167 if (channel.code & RED) {
171 if (channel.code & GREEN) {
175 if (channel.code & BLUE) {
179 if (channel.code & ALPHA) {
182 return qRgba(red, green, blue, alpha);
184 auto updatePixel = [&](QRgb oldPixel, QRgb newPixel) -> QRgb {
185 return qRgba(qRed((channel.code & RED) ? newPixel : oldPixel),
186 qGreen((channel.code & GREEN) ? newPixel : oldPixel),
187 qBlue((channel.code & BLUE) ? newPixel : oldPixel),
188 qAlpha((channel.code & ALPHA) ? newPixel : oldPixel));
190 if (channel.encoding == MixedRLE) {
191 bool success = decodeRLEData(RLEVariant::PIC, stream, row, width, readPixel, updatePixel);
193 qDebug() <<
"decodeRLEData failed";
196 }
else if (channel.encoding == Uncompressed) {
197 for (quint16 i = 0; i < width; ++i) {
198 QRgb pixel = readPixel(stream);
199 row[i] = updatePixel(row[i], pixel);
203 qDebug() <<
"Unknown encoding";
208 qDebug() <<
"DataStream status was" << stream.
status();
213bool SoftimagePICHandler::canRead()
const
215 if (!SoftimagePICHandler::canRead(device())) {
222bool SoftimagePICHandler::read(
QImage *image)
224 if (!readChannels()) {
229 for (
const PicChannel &channel : std::as_const(m_channels)) {
230 if (channel.size != 8) {
232 qDebug() <<
"Channel size was" << channel.size;
236 if (channel.code & ALPHA) {
241 QImage img = imageAlloc(m_header.width, m_header.height, fmt);
243 qDebug() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(m_header.width, m_header.height) << fmt;
247 img.
fill(qRgb(0, 0, 0));
249 for (
int y = 0; y < m_header.height; y++) {
250 QRgb *row =
reinterpret_cast<QRgb *
>(img.
scanLine(y));
251 if (!readRow(m_dataStream, row, m_header.width, m_channels)) {
252 qDebug() <<
"readRow failed";
264bool SoftimagePICHandler::write(
const QImage &_image)
270 qDebug() <<
"Image size invalid:" << image.
width() << image.
height();
273 if (image.
width() > 65535 || image.
height() > 65535) {
274 qDebug() <<
"Image too big:" << image.
width() << image.
height();
281 stream << PicHeader(image.
width(), image.
height(), m_description);
283 PicChannelEncoding encoding = m_compression ? MixedRLE : Uncompressed;
285 channels << PicChannel(encoding, RED | GREEN | BLUE);
287 channels << PicChannel(encoding, ALPHA);
291 for (
int r = 0; r < image.
height(); r++) {
292 const QRgb *row =
reinterpret_cast<const QRgb *
>(image.
scanLine(r));
295 auto rgbEqual = [](QRgb p1, QRgb p2) ->
bool {
296 return qRed(p1) == qRed(p2) && qGreen(p1) == qGreen(p2) && qBlue(p1) == qBlue(p2);
298 auto writeRgb = [](
QDataStream &str, QRgb pixel) ->
void {
299 str << quint8(qRed(pixel)) << quint8(qGreen(pixel)) << quint8(qBlue(pixel));
302 encodeRLEData(RLEVariant::PIC, stream, row, image.
width(), rgbEqual, writeRgb);
304 for (
int i = 0; i < image.
width(); ++i) {
305 writeRgb(stream, row[i]);
311 auto alphaEqual = [](QRgb p1, QRgb p2) ->
bool {
312 return qAlpha(p1) == qAlpha(p2);
314 auto writeAlpha = [](
QDataStream &str, QRgb pixel) ->
void {
315 str << quint8(qAlpha(pixel));
318 encodeRLEData(RLEVariant::PIC, stream, row, image.
width(), alphaEqual, writeAlpha);
320 for (
int i = 0; i < image.
width(); ++i) {
321 writeAlpha(stream, row[i]);
329bool SoftimagePICHandler::canRead(
QIODevice *device)
332 if (device->
peek(data, 4) != 4) {
335 return qFromBigEndian<qint32>(
reinterpret_cast<uchar *
>(data)) == PIC_MAGIC_NUMBER;
338bool SoftimagePICHandler::readHeader()
340 if (m_state == Ready) {
342 m_dataStream.setDevice(device());
343 m_dataStream >> m_header;
345 m_state = ReadHeader;
349 return m_state !=
Error;
352bool SoftimagePICHandler::readChannels()
355 if (m_state == ReadHeader) {
357 m_dataStream >> m_channels;
359 m_state = ReadChannels;
362 return m_state !=
Error;
365void SoftimagePICHandler::setOption(ImageOption option,
const QVariant &value)
368 case CompressionRatio:
369 m_compression = value.
toBool();
372 m_description.clear();
374 for (
const QString &entry : entries) {
375 if (entry.startsWith(QStringLiteral(
"Description: "))) {
376 m_description = entry.mid(13).simplified().toUtf8();
386QVariant SoftimagePICHandler::option(ImageOption option)
const
388 const_cast<SoftimagePICHandler *
>(
this)->readHeader();
391 if (
const_cast<SoftimagePICHandler *
>(
this)->readHeader()) {
392 return QSize(m_header.width, m_header.height);
396 case CompressionRatio:
397 return m_compression;
399 if (
const_cast<SoftimagePICHandler *
>(
this)->readHeader()) {
402 return QString(QStringLiteral(
"Description: ") + descStr + QStringLiteral(
"\n\n"));
407 if (
const_cast<SoftimagePICHandler *
>(
this)->readChannels()) {
408 for (
const PicChannel &channel : std::as_const(m_channels)) {
409 if (channel.code & ALPHA) {
421bool SoftimagePICHandler::supportsOption(ImageOption option)
const
423 return (option == CompressionRatio || option == Description || option == ImageFormat || option == Size);
428 if (format ==
"pic") {
439 if (device->
isReadable() && SoftimagePICHandler::canRead(device)) {
456#include "moc_pic_p.cpp"
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
KCALENDARCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalendarCore::Alarm::Ptr &)
QFlags< Capability > Capabilities
bool isEmpty() const const
int readRawData(char *s, int len)
void setFloatingPointPrecision(FloatingPointPrecision precision)
void setStatus(Status status)
Status status() const const
int version() const const
int writeRawData(const char *s, int len)
void fill(Qt::GlobalColor color)
bool hasAlphaChannel() const const
bool isNull() const const
void setDevice(QIODevice *device)
bool isOpen() const const
bool isReadable() const const
bool isWritable() const const
QByteArray peek(qint64 maxSize)
qsizetype size() const const
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool toBool() const const
QString toString() const const