25 static RGB from(
const QRgb color)
38 void setColor(
int i,
const QRgb color)
46 QRgb color(
int i)
const
48 return qRgb(rgb[i].r, rgb[i].g, rgb[i].b);
59 inline int width()
const
61 return (XMax - XMin) + 1;
63 inline int height()
const
65 return (YMax - YMin) + 1;
67 inline bool isCompressed()
const
69 return (Encoding == 1);
77 inline bool isValid()
const
79 return Manufacturer == 10 && BytesPerLine != 0;
85 inline bool isSupported()
const
92 if (Bpp == 1 && NPlanes == 1) {
94 }
else if (Bpp == 1 && NPlanes == 4) {
96 }
else if (Bpp == 1 && NPlanes == 3) {
98 }
else if (Bpp == 4 && NPlanes == 1) {
100 }
else if (Bpp == 2 && NPlanes == 1) {
102 }
else if (Bpp == 8 && NPlanes == 1) {
104 }
else if (Bpp == 8 && NPlanes == 3) {
106 }
else if (Bpp == 8 && NPlanes == 4) {
135 quint16 BytesPerLine;
166 for (
int i = 0; i < 16; ++i) {
179 s >> m >> ver >> enc >> bpp;
188 s >> xmin >> ymin >> xmax >> ymax;
201 s >> colorMap >> res >> np;
202 ph.ColorMap = colorMap;
205 quint16 bytesperline;
207 ph.BytesPerLine = bytesperline;
210 ph.PaletteInfo = paletteinfo;
214 ph.HScreenSize = hscreensize;
216 ph.VScreenSize = vscreensize;
219 for (
size_t i = 0, n =
sizeof(ph.unused); i < n; ++i) {
228 s << rgb.r << rgb.g << rgb.b;
235 for (
int i = 0; i < 16; ++i) {
244 s << ph.Manufacturer;
248 s << ph.XMin << ph.YMin << ph.XMax << ph.YMax;
249 s << ph.HDpi << ph.YDpi;
253 s << ph.BytesPerLine;
258 for (
size_t i = 0, n =
sizeof(ph.unused); i < n; ++i) {
265PCXHEADER::PCXHEADER()
274bool peekHeader(
QIODevice *d, PCXHEADER& h)
276 auto head = d->
peek(
sizeof(PCXHEADER));
277 if (
size_t(head.size()) <
sizeof(PCXHEADER)) {
291 quint32 size = buf.
size();
295 if (header.isCompressed()) {
304 while (count-- && i < size) {
323 img = imageAlloc(header.width(), header.height(), header.format());
327 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(header.width(), header.height());
331 for (
int y = 0; y < header.height(); ++y) {
336 if (!readLine(s, buf, header)) {
341 unsigned int bpl = qMin((quint16)((header.width() + 7) / 8), header.BytesPerLine);
342 for (
unsigned int x = 0; x < bpl; ++x) {
349 img.
setColor(1, qRgb(255, 255, 255));
356 QByteArray buf(header.BytesPerLine * header.NPlanes, 0);
359 img = imageAlloc(header.width(), header.height(), header.format());
362 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(header.width(), header.height());
366 if (header.BytesPerLine < (header.width() + 7) / 8) {
367 qWarning() <<
"PCX image has invalid BytesPerLine value";
371 for (
int y = 0; y < header.height(); ++y) {
377 if (!readLine(s, buf, header)) {
381 for (
int i = 0; i < header.NPlanes; i++) {
382 quint32 offset = i * header.BytesPerLine;
383 for (
int x = 0; x < header.width(); ++x) {
384 if (buf[offset + (x / 8)] & (128 >> (x % 8))) {
385 pixbuf[x] = (int)(pixbuf[x]) + (1 << i);
392 qWarning() <<
"Failed to get scanline for" << y <<
"might be out of bounds";
394 for (
int x = 0; x < header.width(); ++x) {
400 for (
int i = 0; i < 16; ++i) {
401 img.
setColor(i, header.ColorMap.color(i));
411 img = imageAlloc(header.width(), header.height(), header.format());
415 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(header.width(), header.height());
419 for (
int y = 0; y < header.height(); ++y) {
424 if (!readLine(s, buf, header)) {
433 const unsigned int bpl = std::min(header.BytesPerLine,
static_cast<quint16
>(header.width() / 4));
434 for (
unsigned int x = 0; x < bpl; ++x) {
435 p[x * 4] = (buf[x] >> 6) & 3;
436 p[x * 4 + 1] = (buf[x] >> 4) & 3;
437 p[x * 4 + 2] = (buf[x] >> 2) & 3;
438 p[x * 4 + 3] = buf[x] & 3;
443 for (
int i = 0; i < 4; ++i) {
444 img.
setColor(i, header.ColorMap.color(i));
454 img = imageAlloc(header.width(), header.height(), header.format());
458 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(header.width(), header.height());
462 for (
int y = 0; y < header.height(); ++y) {
467 if (!readLine(s, buf, header)) {
476 const unsigned int bpl = std::min(header.BytesPerLine,
static_cast<quint16
>(header.width() / 2));
477 for (
unsigned int x = 0; x < bpl; ++x) {
478 p[x * 2] = (buf[x] & 240) >> 4;
479 p[x * 2 + 1] = buf[x] & 15;
484 for (
int i = 0; i < 16; ++i) {
485 img.
setColor(i, header.ColorMap.color(i));
495 img = imageAlloc(header.width(), header.height(), header.format());
499 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(header.width(), header.height());
503 for (
int y = 0; y < header.height(); ++y) {
508 if (!readLine(s, buf, header)) {
517 unsigned int bpl = qMin(header.BytesPerLine, (quint16)header.width());
518 for (
unsigned int x = 0; x < bpl; ++x) {
525 if (
auto device = s.
device()) {
526 if (device->isSequential()) {
532 device->seek(device->size() - 769);
538 if (flag == 12 && (header.Version == 5 || header.Version == 2)) {
543 for (
int i = 0; i < 256; ++i) {
557 QByteArray a_buf(header.BytesPerLine,
char(0xFF));
559 img = imageAlloc(header.width(), header.height(), header.format());
562 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(header.width(), header.height());
566 const unsigned int bpl = std::min(header.BytesPerLine,
static_cast<quint16
>(header.width()));
568 for (
int y = 0; y < header.height(); ++y) {
573 if (!readLine(s, r_buf, header)) {
576 if (!readLine(s, g_buf, header)) {
579 if (!readLine(s, b_buf, header)) {
582 if (header.NPlanes == 4 && !readLine(s, a_buf, header)) {
586 auto p =
reinterpret_cast<QRgb *
>(img.
scanLine(y));
587 for (
unsigned int x = 0; x < bpl; ++x) {
588 p[x] = qRgba(r_buf[x], g_buf[x], b_buf[x], a_buf[x]);
598 quint32 size = buf.
size();
607 while ((i < size) && (
byte == buf[i]) && (count < 63)) {
614 if (count > 1 || data >= 0xc0) {
632 auto rgb = img.
color(0);
633 auto minIsBlack = (qRed(rgb) + qGreen(rgb) + qBlue(rgb)) / 3 < 127;
638 if (header.BytesPerLine == 0) {
646 for (
int y = 0; y < header.height(); ++y) {
650 for (
int i = 0; i < header.BytesPerLine; ++i) {
651 buf[i] = minIsBlack ? p[i] : ~p[i];
654 if (!writeLine(s, buf)) {
665 header.BytesPerLine = header.width() / 8;
666 if (header.BytesPerLine == 0) {
670 for (
int i = 0; i < 16; ++i) {
671 header.ColorMap.setColor(i, img.
color(i));
678 for (
int i = 0; i < 4; ++i) {
679 buf[i].
resize(header.BytesPerLine);
682 for (
int y = 0; y < header.height(); ++y) {
685 for (
int i = 0; i < 4; ++i) {
689 for (
int x = 0; x < header.width(); ++x) {
690 for (
int i = 0; i < 4; ++i) {
691 if (*(p + x) & (1 << i)) {
692 buf[i][x / 8] = (int)(buf[i][x / 8]) | 1 << (7 - x % 8);
697 for (
int i = 0; i < 4; ++i) {
698 if (!writeLine(s, buf[i])) {
718 if (header.BytesPerLine == 0) {
726 for (
int y = 0; y < header.height(); ++y) {
729 for (
int i = 0; i < header.BytesPerLine; ++i) {
733 if (!writeLine(s, buf)) {
743 for (
int i = 0; i < 256; ++i) {
745 s << RGB::from(qRgb(i, i, i));
747 s << RGB::from(img.
color(i));
757 header.NPlanes = hasAlpha ? 4 : 3;
758 header.BytesPerLine = header.width();
759 if (header.BytesPerLine == 0) {
777 for (
int y = 0; y < header.height(); ++y) {
778 auto p =
reinterpret_cast<const QRgb *
>(img.
constScanLine(y));
780 for (
int x = 0; x < header.width(); ++x) {
782 r_buf[x] = qRed(rgb);
783 g_buf[x] = qGreen(rgb);
784 b_buf[x] = qBlue(rgb);
785 a_buf[x] = qAlpha(rgb);
788 if (!writeLine(s, r_buf)) {
791 if (!writeLine(s, g_buf)) {
794 if (!writeLine(s, b_buf)) {
797 if (hasAlpha && !writeLine(s, a_buf)) {
805class PCXHandlerPrivate
808 PCXHandlerPrivate() {}
809 ~PCXHandlerPrivate() {}
814PCXHandler::PCXHandler()
816 , d(new PCXHandlerPrivate)
820bool PCXHandler::canRead()
const
822 if (canRead(device())) {
829bool PCXHandler::read(
QImage *outImage)
838 auto&& header = d->m_header;
845 if (!header.isSupported()) {
851 if (header.Bpp == 1 && header.NPlanes == 1) {
852 ok = readImage1(img, s, header);
853 }
else if (header.Bpp == 1 && (header.NPlanes == 4 || header.NPlanes == 3)) {
854 ok = readImage4(img, s, header);
855 }
else if (header.Bpp == 2 && header.NPlanes == 1) {
856 ok = readImage2(img, s, header);
857 }
else if (header.Bpp == 4 && header.NPlanes == 1) {
858 ok = readImage4v2(img, s, header);
859 }
else if (header.Bpp == 8 && header.NPlanes == 1) {
860 ok = readImage8(img, s, header);
861 }
else if (header.Bpp == 8 && (header.NPlanes == 3 || header.NPlanes == 4)) {
862 ok = readImage24(img, s, header);
865 if (img.
isNull() || !ok) {
875bool PCXHandler::write(
const QImage &image)
881#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
883 if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.
format() == QImage::Format_CMYK8888) {
888 const int w = img.
width();
889 const int h = img.
height();
891 if (w > 65536 || h > 65536) {
897 header.Manufacturer = 10;
907 header.PaletteInfo = 1;
910 if (img.
depth() == 1) {
911 ok = writeImage1(img, s, header);
913 ok = writeImage4(img, s, header);
915 ok = writeImage8(img, s, header);
916 }
else if (img.
depth() >= 16) {
917 ok = writeImage24(img, s, header);
923bool PCXHandler::supportsOption(ImageOption option)
const
934QVariant PCXHandler::option(ImageOption option)
const
939 auto&& header = d->m_header;
940 if (header.isSupported()) {
942 }
else if (
auto dev = device()) {
943 if (peekHeader(dev, header) && header.isSupported()) {
950 auto&& header = d->m_header;
951 if (header.isSupported()) {
953 }
else if (
auto dev = device()) {
954 if (peekHeader(dev, header) && header.isSupported()) {
963bool PCXHandler::canRead(
QIODevice *device)
966 qWarning(
"PCXHandler::canRead() called with no device");
971 if (!peekHeader(device, header)) {
974 return header.isSupported();
979 if (format ==
"pcx") {
990 if (device->
isReadable() && PCXHandler::canRead(device)) {
1007#include "moc_pcx_p.cpp"
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
QDebug operator<<(QDebug dbg, const DcrawInfoContainer &c)
QFlags< Capability > Capabilities
QByteArray & fill(char ch, qsizetype size)
bool isEmpty() const const
void resize(qsizetype newSize, char c)
qsizetype size() const const
QIODevice * device() const const
void setByteOrder(ByteOrder bo)
Status status() const const
qsizetype bytesPerLine() const const
QRgb color(int i) const const
int colorCount() const const
QColorSpace colorSpace() const const
const uchar * constScanLine(int i) const const
void convertTo(Format format, Qt::ImageConversionFlags flags)
QImage convertedToColorSpace(const QColorSpace &colorSpace) const const
int dotsPerMeterX() const const
int dotsPerMeterY() const const
bool hasAlphaChannel() const const
bool isNull() const const
void setColor(int index, QRgb colorValue)
void setColorCount(int colorCount)
void setDotsPerMeterX(int x)
void setDotsPerMeterY(int y)
void setDevice(QIODevice *device)
bool isOpen() const const
bool isReadable() const const
bool isWritable() const const
QByteArray peek(qint64 maxSize)
virtual qint64 size() const const
QVariant fromValue(T &&value)