107static bool read_pbm_body(QIODevice *device,
char type,
int w,
int h, quint16 mcc, QImage *outImage)
113 QImage::Format format;
118 format = QImage::Format_Mono;
122 nbits = mcc <=
std::numeric_limits<uint8_t>::max() ? 8 : 16;
123 format = mcc <= std::numeric_limits<uint8_t>::max() ? QImage::Format_Grayscale8 : QImage::Format_Grayscale16;
128 format = QImage::Format_RGB32;
135 if (!QImageIOHandler::allocateImage(QSize(w, h), format, outImage))
138 pbm_bpl = (qsizetype(w) * nbits + 7) / 8;
142 pbm_bpl = mcc < 256 ? 3*w : 6*w;
143 uchar *buf24 =
new uchar[pbm_bpl], *b;
146 for (y=0; y<h; y++) {
147 if (device->read((
char *)buf24, pbm_bpl) != pbm_bpl) {
151 p = (QRgb *)outImage->scanLine(y);
157 *p++ = qRgb(b[0],b[1],b[2]);
159 *p++ = scale_pbm_color(mcc, b[0], b[1], b[2]);
162 quint16 rv = b[0] << 8 | b[1];
163 quint16 gv = b[2] << 8 | b[3];
164 quint16 bv = b[4] << 8 | b[5];
166 *p++ = QRgba64::fromRgba64(rv, gv, bv, 0xffff).toArgb32();
168 *p++ = scale_pbm_color(mcc, rv, gv, bv);
174 }
else if (nbits == 16) {
175 pbm_bpl =
sizeof(uint16_t)*w;
176 uchar *buf16 =
new uchar[pbm_bpl];
177 for (y=0; y<h; y++) {
178 if (device->read((
char *)buf16, pbm_bpl) != pbm_bpl) {
182 uint16_t *p =
reinterpret_cast<uint16_t *>(outImage->scanLine(y));
183 uint16_t *end = p + w;
184 uint16_t *b =
reinterpret_cast<uint16_t *>(buf16);
186 *p++ = qFromBigEndian(*b) * 0xffffu / mcc;
192 for (y=0; y<h; y++) {
193 uchar *p = outImage->scanLine(y);
194 if (device->read((
char *)p, pbm_bpl) != pbm_bpl)
196 if (nbits == 8 && mcc < 255) {
197 for (qsizetype i = 0; i < pbm_bpl; i++)
198 p[i] = (p[i] * 0xffu) / mcc;
206 for (y = 0; y < h && ok; y++) {
207 p = outImage->scanLine(y);
214 for (
int i=0; i<8; i++) {
218 b = (b << 1) | (0 & 1);
223 }
else if (nbits == 8) {
224 if (mcc ==
std::numeric_limits<uint8_t>::max()) {
226 *p++ = read_pbm_int(device, &ok);
230 *p++ = read_pbm_int(device, &ok) * 0xffu / mcc;
233 }
else if (nbits == 16) {
234 uint16_t* data =
reinterpret_cast<uint16_t*>(p);
235 qsizetype numPixel = n/2;
236 if (mcc ==
std::numeric_limits<uint16_t>::max()) {
237 while (numPixel-- && ok) {
238 *data++ = read_pbm_int(device, &ok);
241 while (numPixel-- && ok) {
242 *data++ = read_pbm_int(device, &ok) * 0xffffu / mcc;
250 r = read_pbm_int(device, &ok);
251 g = read_pbm_int(device, &ok);
252 b = read_pbm_int(device, &ok);
253 *((QRgb*)p) = qRgb(r, g, b);
258 r = read_pbm_int(device, &ok);
259 g = read_pbm_int(device, &ok);
260 b = read_pbm_int(device, &ok);
261 *((QRgb*)p) = scale_pbm_color(mcc, r, g, b);
271 if (format == QImage::Format_Mono) {
272 outImage->setColorCount(2);
273 outImage->setColor(0, qRgb(255,255,255));
274 outImage->setColor(1, qRgb(0,0,0));
280static bool write_pbm_image(QIODevice *out,
const QImage &sourceImage, QByteArrayView sourceFormat)
283 QImage image = sourceImage;
284 const QByteArrayView format = sourceFormat.left(3);
286 bool gray = format ==
"pgm";
288 if (format ==
"pbm") {
289 image = image.convertToFormat(QImage::Format_Mono);
291 image = image.depth() <= 8 ? image.convertToFormat(QImage::Format_Grayscale8) : image.convertToFormat(QImage::Format_Grayscale16);
293 switch (image.format()) {
294 case QImage::Format_Mono:
295 case QImage::Format_MonoLSB:
296 image = image.convertToFormat(QImage::Format_Indexed8);
298 case QImage::Format_Indexed8:
299 case QImage::Format_RGB32:
300 case QImage::Format_ARGB32:
303 if (image.hasAlphaChannel())
304 image = image.convertToFormat(QImage::Format_ARGB32);
306 image = image.convertToFormat(QImage::Format_RGB32);
311 if (image.depth() == 1 && image.colorCount() == 2) {
312 if (qGray(image.color(0)) < qGray(image.color(1))) {
315 for (
int y=0; y<image.height(); y++) {
316 uchar *p = image.scanLine(y);
317 uchar *end = p + image.bytesPerLine();
324 uint w = image.width();
325 uint h = image.height();
328 str += QByteArray::number(w);
330 str += QByteArray::number(h);
333 switch (image.depth()) {
336 if (out->write(str, str.size()) != str.size())
339 for (uint y=0; y<h; y++) {
340 uchar* line = image.scanLine(y);
341 if (w != (uint)out->write((
char*)line, w))
348 str.insert(1, gray ?
'5' :
'6');
350 if (out->write(str, str.size()) != str.size())
352 qsizetype bpl = qsizetype(w) * (gray ? 1 : 3);
353 uchar *buf =
new uchar[bpl];
354 if (image.format() == QImage::Format_Indexed8) {
355 const QList<QRgb> color = image.colorTable();
356 for (uint y=0; y<h; y++) {
357 const uchar *b = image.constScanLine(y);
359 uchar *end = buf+bpl;
362 uchar g = (uchar)qGray(color[*b++]);
367 QRgb rgb = color[*b++];
373 if (bpl != (qsizetype)out->write((
char*)buf, bpl))
377 for (uint y=0; y<h; y++) {
378 const uchar *b = image.constScanLine(y);
380 uchar *end = buf + bpl;
392 if (bpl != (qsizetype)out->write((
char*)buf, bpl))
400 str.insert(1, gray ?
'5' :
'6');
401 str.append(
"65535\n");
402 if (out->write(str, str.size()) != str.size())
404 qsizetype bpl =
sizeof(uint16_t) * qsizetype(w) * (gray ? 1 : 3);
405 uchar *buf =
new uchar[bpl];
406 for (uint y=0; y<h; y++) {
407 const uint16_t *b =
reinterpret_cast<
const uint16_t *>(image.constScanLine(y));
408 uint16_t *p =
reinterpret_cast<uint16_t *>(buf);
409 uint16_t *end =
reinterpret_cast<uint16_t *>(buf + bpl);
412 *p++ = qToBigEndian(*b++);
415 uchar color = qToBigEndian(*b++);
421 if (bpl != (qsizetype)out->write((
char*)buf, bpl))
431 if (out->write(str, str.size()) != str.size())
433 qsizetype bpl = qsizetype(w) * 3;
434 uchar *buf =
new uchar[bpl];
435 for (uint y=0; y<h; y++) {
436 const QRgb *b =
reinterpret_cast<
const QRgb *>(image.constScanLine(y));
438 uchar *end = buf+bpl;
445 if (bpl != (qsizetype)out->write((
char*)buf, bpl))