47 char comment[81] = {};
52 const int bytesRead = s.
readRawData(header.id.data(), 4);
54 header.id.resize(bytesRead);
62 header.fields =
static_cast<PicFields
>(fields);
83 char comment[80] = {};
84 strncpy(comment, header.comment.constData(),
sizeof(comment));
88 strncpy(
id, header.id.constData(),
sizeof(
id));
94 s << quint16(header.fields);
115 const unsigned maxChannels = 8;
123 s >> channel.encoding;
150 Q_ASSERT(channels.
size() > 0);
151 for (
int i = 0; i < channels.
size() - 1; ++i) {
153 s << channels[i].
size;
154 s << quint8(channels[i].encoding);
155 s << channels[i].code;
158 s << channels.
last().size;
159 s << quint8(channels.
last().encoding);
160 s << channels.
last().code;
166 for (
const PicChannel &channel : channels) {
169 if (channel.code & RED) {
173 if (channel.code & GREEN) {
177 if (channel.code & BLUE) {
181 if (channel.code & ALPHA) {
184 return qRgba(red, green, blue, alpha);
186 auto updatePixel = [&](QRgb oldPixel, QRgb newPixel) -> QRgb {
187 return qRgba(qRed((channel.code & RED) ? newPixel : oldPixel),
188 qGreen((channel.code & GREEN) ? newPixel : oldPixel),
189 qBlue((channel.code & BLUE) ? newPixel : oldPixel),
190 qAlpha((channel.code & ALPHA) ? newPixel : oldPixel));
192 if (channel.encoding == MixedRLE) {
193 bool success = decodeRLEData(RLEVariant::PIC, stream, row, width, readPixel, updatePixel);
195 qDebug() <<
"decodeRLEData failed";
198 }
else if (channel.encoding == Uncompressed) {
199 for (quint16 i = 0; i < width; ++i) {
200 QRgb pixel = readPixel(stream);
201 row[i] = updatePixel(row[i], pixel);
205 qDebug() <<
"Unknown encoding";
210 qDebug() <<
"DataStream status was" << stream.
status();
215bool SoftimagePICHandler::canRead()
const
217 if (!SoftimagePICHandler::canRead(device())) {
224bool SoftimagePICHandler::read(
QImage *image)
226 if (!readChannels()) {
231 for (
const PicChannel &channel : std::as_const(m_channels)) {
232 if (channel.size != 8) {
234 qDebug() <<
"Channel size was" << channel.size;
238 if (channel.code & ALPHA) {
243 QImage img = imageAlloc(m_header.width, m_header.height, fmt);
245 qDebug() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(m_header.width, m_header.height) << fmt;
249 img.
fill(qRgb(0, 0, 0));
251 for (
int y = 0; y < m_header.height; y++) {
252 QRgb *row =
reinterpret_cast<QRgb *
>(img.
scanLine(y));
253 if (!readRow(m_dataStream, row, m_header.width, m_channels)) {
254 qDebug() <<
"readRow failed";
266bool SoftimagePICHandler::write(
const QImage &_image)
270#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
272 if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && _image.
format() == QImage::Format_CMYK8888) {
281 qDebug() <<
"Image size invalid:" << image.
width() << image.
height();
284 if (image.
width() > 65535 || image.
height() > 65535) {
285 qDebug() <<
"Image too big:" << image.
width() << image.
height();
292 stream << PicHeader(image.
width(), image.
height(), m_description);
294 PicChannelEncoding encoding = m_compression ? MixedRLE : Uncompressed;
296 channels << PicChannel(encoding, RED | GREEN | BLUE);
298 channels << PicChannel(encoding, ALPHA);
302 for (
int r = 0; r < image.
height(); r++) {
303 const QRgb *row =
reinterpret_cast<const QRgb *
>(image.
constScanLine(r));
306 auto rgbEqual = [](QRgb p1, QRgb p2) ->
bool {
307 return qRed(p1) == qRed(p2) && qGreen(p1) == qGreen(p2) && qBlue(p1) == qBlue(p2);
309 auto writeRgb = [](
QDataStream &str, QRgb pixel) ->
void {
310 str << quint8(qRed(pixel)) << quint8(qGreen(pixel)) << quint8(qBlue(pixel));
313 encodeRLEData(RLEVariant::PIC, stream, row, image.
width(), rgbEqual, writeRgb);
315 for (
int i = 0; i < image.
width(); ++i) {
316 writeRgb(stream, row[i]);
322 auto alphaEqual = [](QRgb p1, QRgb p2) ->
bool {
323 return qAlpha(p1) == qAlpha(p2);
325 auto writeAlpha = [](
QDataStream &str, QRgb pixel) ->
void {
326 str << quint8(qAlpha(pixel));
329 encodeRLEData(RLEVariant::PIC, stream, row, image.
width(), alphaEqual, writeAlpha);
331 for (
int i = 0; i < image.
width(); ++i) {
332 writeAlpha(stream, row[i]);
340bool SoftimagePICHandler::canRead(
QIODevice *device)
343 if (device->
peek(data, 4) != 4) {
346 return qFromBigEndian<qint32>(
reinterpret_cast<uchar *
>(data)) == PIC_MAGIC_NUMBER;
349bool SoftimagePICHandler::readHeader()
351 if (m_state == Ready) {
353 m_dataStream.setDevice(device());
354 m_dataStream >> m_header;
356 m_state = ReadHeader;
360 return m_state !=
Error;
363bool SoftimagePICHandler::readChannels()
366 if (m_state == ReadHeader) {
368 m_dataStream >> m_channels;
370 m_state = ReadChannels;
373 return m_state !=
Error;
376void SoftimagePICHandler::setOption(ImageOption option,
const QVariant &value)
379 case CompressionRatio:
380 m_compression = value.
toBool();
383 m_description.clear();
385 for (
const QString &entry : entries) {
386 if (entry.startsWith(QStringLiteral(
"Description: "))) {
387 m_description = entry.mid(13).simplified().toUtf8();
397QVariant SoftimagePICHandler::option(ImageOption option)
const
399 const_cast<SoftimagePICHandler *
>(
this)->readHeader();
402 if (
const_cast<SoftimagePICHandler *
>(
this)->readHeader()) {
403 return QSize(m_header.width, m_header.height);
407 case CompressionRatio:
408 return m_compression;
410 if (
const_cast<SoftimagePICHandler *
>(
this)->readHeader()) {
413 return QString(QStringLiteral(
"Description: ") + descStr + QStringLiteral(
"\n\n"));
418 if (
const_cast<SoftimagePICHandler *
>(
this)->readChannels()) {
419 for (
const PicChannel &channel : std::as_const(m_channels)) {
420 if (channel.code & ALPHA) {
432bool SoftimagePICHandler::supportsOption(ImageOption option)
const
434 return (option == CompressionRatio || option == Description || option == ImageFormat || option == Size);
439 if (format ==
"pic") {
450 if (device->
isReadable() && SoftimagePICHandler::canRead(device)) {
467#include "moc_pic_p.cpp"
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
QDebug operator<<(QDebug dbg, const DcrawInfoContainer &c)
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)
QColorSpace colorSpace() const const
const uchar * constScanLine(int i) const const
QImage convertedToColorSpace(const QColorSpace &colorSpace) const const
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