Qt 4.8
Functions
qppmhandler.cpp File Reference
#include "private/qppmhandler_p.h"
#include <qimage.h>
#include <qvariant.h>
#include <qvector.h>
#include <ctype.h>

Go to the source code of this file.

Functions

static bool read_pbm_body (QIODevice *device, char type, int w, int h, int mcc, QImage *outImage)
 
static bool read_pbm_header (QIODevice *device, char &type, int &w, int &h, int &mcc)
 
static int read_pbm_int (QIODevice *d)
 
static bool write_pbm_image (QIODevice *out, const QImage &sourceImage, const QByteArray &sourceFormat)
 

Function Documentation

◆ read_pbm_body()

static bool read_pbm_body ( QIODevice device,
char  type,
int  w,
int  h,
int  mcc,
QImage outImage 
)
static

Definition at line 117 of file qppmhandler.cpp.

Referenced by QPpmHandler::read().

118 {
119  int nbits, y;
120  int pbm_bpl;
121  bool raw;
122 
124  switch (type) {
125  case '1': // ascii PBM
126  case '4': // raw PBM
127  nbits = 1;
128  format = QImage::Format_Mono;
129  break;
130  case '2': // ascii PGM
131  case '5': // raw PGM
132  nbits = 8;
133  format = QImage::Format_Indexed8;
134  break;
135  case '3': // ascii PPM
136  case '6': // raw PPM
137  nbits = 32;
138  format = QImage::Format_RGB32;
139  break;
140  default:
141  return false;
142  }
143  raw = type >= '4';
144 
145  int maxc = mcc;
146  if (maxc > 255)
147  maxc = 255;
148  if (outImage->size() != QSize(w, h) || outImage->format() != format) {
149  *outImage = QImage(w, h, format);
150  if (outImage->isNull())
151  return false;
152  }
153 
154  pbm_bpl = (nbits*w+7)/8; // bytes per scanline in PBM
155 
156  if (raw) { // read raw data
157  if (nbits == 32) { // type 6
158  pbm_bpl = mcc < 256 ? 3*w : 6*w;
159  uchar *buf24 = new uchar[pbm_bpl], *b;
160  QRgb *p;
161  QRgb *end;
162  for (y=0; y<h; y++) {
163  if (device->read((char *)buf24, pbm_bpl) != pbm_bpl) {
164  delete[] buf24;
165  return false;
166  }
167  p = (QRgb *)outImage->scanLine(y);
168  end = p + w;
169  b = buf24;
170  while (p < end) {
171  if (mcc < 256) {
172  *p++ = qRgb(b[0],b[1],b[2]);
173  b += 3;
174  } else {
175  *p++ = qRgb(((int(b[0]) * 256 + int(b[1]) + 1) * 256) / (mcc + 1) - 1,
176  ((int(b[2]) * 256 + int(b[3]) + 1) * 256) / (mcc + 1) - 1,
177  ((int(b[4]) * 256 + int(b[5]) + 1) * 256) / (mcc + 1) - 1);
178  b += 6;
179  }
180  }
181  }
182  delete[] buf24;
183  } else { // type 4,5
184  for (y=0; y<h; y++) {
185  if (device->read((char *)outImage->scanLine(y), pbm_bpl)
186  != pbm_bpl)
187  return false;
188  }
189  }
190  } else { // read ascii data
191  register uchar *p;
192  int n;
193  for (y=0; y<h; y++) {
194  p = outImage->scanLine(y);
195  n = pbm_bpl;
196  if (nbits == 1) {
197  int b;
198  int bitsLeft = w;
199  while (n--) {
200  b = 0;
201  for (int i=0; i<8; i++) {
202  if (i < bitsLeft)
203  b = (b << 1) | (read_pbm_int(device) & 1);
204  else
205  b = (b << 1) | (0 & 1); // pad it our self if we need to
206  }
207  bitsLeft -= 8;
208  *p++ = b;
209  }
210  } else if (nbits == 8) {
211  if (mcc == maxc) {
212  while (n--) {
213  *p++ = read_pbm_int(device);
214  }
215  } else {
216  while (n--) {
217  *p++ = read_pbm_int(device) * maxc / mcc;
218  }
219  }
220  } else { // 32 bits
221  n /= 4;
222  int r, g, b;
223  if (mcc == maxc) {
224  while (n--) {
225  r = read_pbm_int(device);
226  g = read_pbm_int(device);
227  b = read_pbm_int(device);
228  *((QRgb*)p) = qRgb(r, g, b);
229  p += 4;
230  }
231  } else {
232  while (n--) {
233  r = read_pbm_int(device) * maxc / mcc;
234  g = read_pbm_int(device) * maxc / mcc;
235  b = read_pbm_int(device) * maxc / mcc;
236  *((QRgb*)p) = qRgb(r, g, b);
237  p += 4;
238  }
239  }
240  }
241  }
242  }
243 
244  if (nbits == 1) { // bitmap
245  outImage->setColorCount(2);
246  outImage->setColor(0, qRgb(255,255,255)); // white
247  outImage->setColor(1, qRgb(0,0,0)); // black
248  } else if (nbits == 8) { // graymap
249  outImage->setColorCount(maxc+1);
250  for (int i=0; i<=maxc; i++)
251  outImage->setColor(i, qRgb(i*255/maxc,i*255/maxc,i*255/maxc));
252  }
253 
254  return true;
255 }
static int read_pbm_int(QIODevice *d)
Definition: qppmhandler.cpp:57
Format
The following image formats are available in Qt.
Definition: qimage.h:91
unsigned int QRgb
Definition: qrgb.h:53
int type
Definition: qmetatype.cpp:239
void setColor(int i, QRgb c)
Sets the color at the given index in the color table, to the given to colorValue. ...
Definition: qimage.cpp:1850
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
unsigned char uchar
Definition: qglobal.h:994
void setColorCount(int)
Resizes the color table to contain colorCount entries.
Definition: qimage.cpp:2275
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
QRgb qRgb(int r, int g, int b)
Returns the ARGB quadruplet (255, {r}, {g}, {b}).
Definition: qrgb.h:69
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
static const KeyPair *const end
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886

◆ read_pbm_header()

static bool read_pbm_header ( QIODevice device,
char &  type,
int &  w,
int &  h,
int &  mcc 
)
static

Definition at line 90 of file qppmhandler.cpp.

Referenced by QPpmHandler::readHeader().

91 {
92  char buf[3];
93  if (device->read(buf, 3) != 3) // read P[1-6]<white-space>
94  return false;
95 
96  if (!(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])))
97  return false;
98 
99  type = buf[1];
100  if (type < '1' || type > '6')
101  return false;
102 
103  w = read_pbm_int(device); // get image width
104  h = read_pbm_int(device); // get image height
105 
106  if (type == '1' || type == '4')
107  mcc = 1; // ignore max color component
108  else
109  mcc = read_pbm_int(device); // get max color component
110 
111  if (w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0)
112  return false; // weird P.M image
113 
114  return true;
115 }
static int read_pbm_int(QIODevice *d)
Definition: qppmhandler.cpp:57
int type
Definition: qmetatype.cpp:239
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
unsigned char uchar
Definition: qglobal.h:994

◆ read_pbm_int()

static int read_pbm_int ( QIODevice d)
static

Definition at line 57 of file qppmhandler.cpp.

Referenced by read_pbm_body(), and read_pbm_header().

58 {
59  char c;
60  int val = -1;
61  bool digit;
62  const int buflen = 100;
63  char buf[buflen];
64  for (;;) {
65  if (!d->getChar(&c)) // end of file
66  break;
67  digit = isdigit((uchar) c);
68  if (val != -1) {
69  if (digit) {
70  val = 10*val + c - '0';
71  continue;
72  } else {
73  if (c == '#') // comment
74  d->readLine(buf, buflen);
75  break;
76  }
77  }
78  if (digit) // first digit
79  val = c - '0';
80  else if (isspace((uchar) c))
81  continue;
82  else if (c == '#')
83  (void)d->readLine(buf, buflen);
84  else
85  break;
86  }
87  return val;
88 }
unsigned char c[8]
Definition: qnumeric_p.h:62
bool getChar(char *c)
Reads one character from the device and stores it in c.
Definition: qiodevice.cpp:1536
unsigned char uchar
Definition: qglobal.h:994
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes...
Definition: qiodevice.cpp:1110

◆ write_pbm_image()

static bool write_pbm_image ( QIODevice out,
const QImage sourceImage,
const QByteArray sourceFormat 
)
static

Definition at line 257 of file qppmhandler.cpp.

Referenced by QPpmHandler::write().

258 {
259  QByteArray str;
260  QImage image = sourceImage;
261  QByteArray format = sourceFormat;
262 
263  format = format.left(3); // ignore RAW part
264  bool gray = format == "pgm";
265 
266  if (format == "pbm") {
267  image = image.convertToFormat(QImage::Format_Mono);
268  } else if (image.depth() == 1) {
270  } else {
271  switch (image.format()) {
277  image = image.convertToFormat(QImage::Format_RGB32);
278  break;
283  image = image.convertToFormat(QImage::Format_ARGB32);
284  break;
285  default:
286  break;
287  }
288  }
289 
290  if (image.depth() == 1 && image.colorCount() == 2) {
291  if (qGray(image.color(0)) < qGray(image.color(1))) {
292  // 0=dark/black, 1=light/white - invert
293  image.detach();
294  for (int y=0; y<image.height(); y++) {
295  uchar *p = image.scanLine(y);
296  uchar *end = p + image.bytesPerLine();
297  while (p < end)
298  *p++ ^= 0xff;
299  }
300  }
301  }
302 
303  uint w = image.width();
304  uint h = image.height();
305 
306  str = "P\n";
307  str += QByteArray::number(w);
308  str += ' ';
309  str += QByteArray::number(h);
310  str += '\n';
311 
312  switch (image.depth()) {
313  case 1: {
314  str.insert(1, '4');
315  if (out->write(str, str.length()) != str.length())
316  return false;
317  w = (w+7)/8;
318  for (uint y=0; y<h; y++) {
319  uchar* line = image.scanLine(y);
320  if (w != (uint)out->write((char*)line, w))
321  return false;
322  }
323  }
324  break;
325 
326  case 8: {
327  str.insert(1, gray ? '5' : '6');
328  str.append("255\n");
329  if (out->write(str, str.length()) != str.length())
330  return false;
331  QVector<QRgb> color = image.colorTable();
332  uint bpl = w*(gray ? 1 : 3);
333  uchar *buf = new uchar[bpl];
334  for (uint y=0; y<h; y++) {
335  uchar *b = image.scanLine(y);
336  uchar *p = buf;
337  uchar *end = buf+bpl;
338  if (gray) {
339  while (p < end) {
340  uchar g = (uchar)qGray(color[*b++]);
341  *p++ = g;
342  }
343  } else {
344  while (p < end) {
345  QRgb rgb = color[*b++];
346  *p++ = qRed(rgb);
347  *p++ = qGreen(rgb);
348  *p++ = qBlue(rgb);
349  }
350  }
351  if (bpl != (uint)out->write((char*)buf, bpl))
352  return false;
353  }
354  delete [] buf;
355  }
356  break;
357 
358  case 32: {
359  str.insert(1, gray ? '5' : '6');
360  str.append("255\n");
361  if (out->write(str, str.length()) != str.length())
362  return false;
363  uint bpl = w*(gray ? 1 : 3);
364  uchar *buf = new uchar[bpl];
365  for (uint y=0; y<h; y++) {
366  QRgb *b = (QRgb*)image.scanLine(y);
367  uchar *p = buf;
368  uchar *end = buf+bpl;
369  if (gray) {
370  while (p < end) {
371  uchar g = (uchar)qGray(*b++);
372  *p++ = g;
373  }
374  } else {
375  while (p < end) {
376  QRgb rgb = *b++;
377  *p++ = qRed(rgb);
378  *p++ = qGreen(rgb);
379  *p++ = qBlue(rgb);
380  }
381  }
382  if (bpl != (uint)out->write((char*)buf, bpl))
383  return false;
384  }
385  delete [] buf;
386  }
387  break;
388 
389  default:
390  return false;
391  }
392 
393  return true;
394 }
unsigned int QRgb
Definition: qrgb.h:53
QByteArray & append(char c)
Appends the character ch to this byte array.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
int qRed(QRgb rgb)
Returns the red component of the ARGB quadruplet rgb.
Definition: qrgb.h:57
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
unsigned char uchar
Definition: qglobal.h:994
void detach()
If multiple images share common data, this image makes a copy of the data and detaches itself from th...
Definition: qimage.cpp:1359
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
unsigned int uint
Definition: qglobal.h:996
int qGray(int r, int g, int b)
Definition: qrgb.h:75
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
int length() const
Same as size().
Definition: qbytearray.h:356
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
int colorCount() const
Returns the size of the color table for the image.
Definition: qimage.cpp:1656
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
int qGreen(QRgb rgb)
Returns the green component of the ARGB quadruplet rgb.
Definition: qrgb.h:60
int qBlue(QRgb rgb)
Returns the blue component of the ARGB quadruplet rgb.
Definition: qrgb.h:63
static const KeyPair *const end
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
QVector< QRgb > colorTable() const
Returns a list of the colors contained in the image&#39;s color table, or an empty list if the image does...
Definition: qimage.cpp:1770
QRgb color(int i) const
Returns the color in the color table at index i.
Definition: qimage.cpp:1829
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
QByteArray & insert(int i, char c)
Inserts character ch at index position i in the byte array.