summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qppmhandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image/qppmhandler.cpp')
-rw-r--r--src/gui/image/qppmhandler.cpp69
1 files changed, 56 insertions, 13 deletions
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index a0a1dcdaca9..8a413ded95e 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -123,8 +123,8 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
break;
case '2': // ascii PGM
case '5': // raw PGM
- nbits = 8;
- format = QImage::Format_Grayscale8;
+ nbits = mcc <= std::numeric_limits<uint8_t>::max() ? 8 : 16;
+ format = mcc <= std::numeric_limits<uint8_t>::max() ? QImage::Format_Grayscale8 : QImage::Format_Grayscale16;
break;
case '3': // ascii PPM
case '6': // raw PPM
@@ -175,20 +175,20 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
}
}
delete[] buf24;
- } else if (nbits == 8 && mcc > 255) { // type 5 16bit
- pbm_bpl = 2*w;
+ } else if (nbits == 16) { // type 5 16bit
+ pbm_bpl = sizeof(uint16_t)*w;
uchar *buf16 = new uchar[pbm_bpl];
for (y=0; y<h; y++) {
if (device->read((char *)buf16, pbm_bpl) != pbm_bpl) {
delete[] buf16;
return false;
}
- uchar *p = outImage->scanLine(y);
- uchar *end = p + w;
- uchar *b = buf16;
+ uint16_t *p = reinterpret_cast<uint16_t *>(outImage->scanLine(y));
+ uint16_t *end = p + w;
+ uint16_t *b = reinterpret_cast<uint16_t *>(buf16);
while (p < end) {
- *p++ = (b[0] << 8 | b[1]) * 255 / mcc;
- b += 2;
+ *p++ = qFromBigEndian(*b) * std::numeric_limits<uint16_t>::max() / mcc;
+ b++;
}
}
delete[] buf16;
@@ -225,13 +225,25 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
*p++ = b;
}
} else if (nbits == 8) {
- if (mcc == 255) {
+ if (mcc == std::numeric_limits<uint8_t>::max()) {
while (n-- && ok) {
*p++ = read_pbm_int(device, &ok);
}
} else {
while (n-- && ok) {
- *p++ = (read_pbm_int(device, &ok) & 0xffff) * 255 / mcc;
+ *p++ = (read_pbm_int(device, &ok) & 0xffff) * std::numeric_limits<uint8_t>::max() / mcc;
+ }
+ }
+ } else if (nbits == 16) {
+ uint16_t* data = reinterpret_cast<uint16_t*>(p);
+ qsizetype numPixel = n/2;
+ if (mcc == std::numeric_limits<uint16_t>::max()) {
+ while (numPixel-- && ok) {
+ *data++ = read_pbm_int(device, &ok);
+ }
+ } else {
+ while (numPixel-- && ok) {
+ *data++ = (read_pbm_int(device, &ok) & 0xffff) * std::numeric_limits<uint16_t>::max() / mcc;
}
}
} else { // 32 bits
@@ -280,7 +292,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, QByteArra
if (format == "pbm") {
image = image.convertToFormat(QImage::Format_Mono);
} else if (gray) {
- image = image.convertToFormat(QImage::Format_Grayscale8);
+ image = image.depth() <= 8 ? image.convertToFormat(QImage::Format_Grayscale8) : image.convertToFormat(QImage::Format_Grayscale16);
} else {
switch (image.format()) {
case QImage::Format_Mono:
@@ -388,6 +400,34 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, QByteArra
delete [] buf;
break;
}
+ case 16: {
+ str.insert(1, gray ? '5' : '6');
+ str.append("65535\n");
+ if (out->write(str, str.size()) != str.size())
+ return false;
+ qsizetype bpl = sizeof(uint16_t) * qsizetype(w) * (gray ? 1 : 3);
+ uchar *buf = new uchar[bpl];
+ for (uint y=0; y<h; y++) {
+ const uint16_t *b = reinterpret_cast<const uint16_t *>(image.constScanLine(y));
+ uint16_t *p = reinterpret_cast<uint16_t *>(buf);
+ uint16_t *end = reinterpret_cast<uint16_t *>(buf + bpl);
+ if (gray) {
+ while (p < end)
+ *p++ = qToBigEndian(*b++);
+ } else {
+ while (p < end) {
+ uchar color = qToBigEndian(*b++);
+ *p++ = color;
+ *p++ = color;
+ *p++ = color;
+ }
+ }
+ if (bpl != (qsizetype)out->write((char*)buf, bpl))
+ return false;
+ }
+ delete [] buf;
+ break;
+ }
case 32: {
str.insert(1, '6');
@@ -530,7 +570,10 @@ QVariant QPpmHandler::option(ImageOption option) const
break;
case '2': // ascii PGM
case '5': // raw PGM
- format = QImage::Format_Grayscale8;
+ if (mcc <= std::numeric_limits<uint8_t>::max())
+ format = QImage::Format_Grayscale8;
+ else
+ format = QImage::Format_Grayscale16;
break;
case '3': // ascii PPM
case '6': // raw PPM