not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / ksplash / ksplashx / qimage.cpp
blob7e9196bcec120d6869f53b1ac2f8c7c2db855606
1 /****************************************************************************
2 **
3 ** This file is based on sources of the Qt GUI Toolkit, used under the terms
4 ** of the GNU General Public License version 2 (see the original copyright
5 ** notice below).
6 ** All further contributions to this file are (and are required to be)
7 ** licensed under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
11 ** The original Qt license header follows:
12 **
14 ** Implementation of QImage and QImageIO classes
16 ** Created : 950207
18 ** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
20 ** This file is part of the kernel module of the Qt GUI Toolkit.
22 ** This file may be distributed under the terms of the Q Public License
23 ** as defined by Trolltech AS of Norway and appearing in the file
24 ** LICENSE.QPL included in the packaging of this file.
26 ** This file may be distributed and/or modified under the terms of the
27 ** GNU General Public License version 2 as published by the Free Software
28 ** Foundation and appearing in the file LICENSE.GPL included in the
29 ** packaging of this file.
31 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
32 ** licenses may use this file in accordance with the Qt Commercial License
33 ** Agreement provided with the Software.
35 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
36 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
38 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
39 ** information about Qt Commercial License Agreements.
40 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
41 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
43 ** Contact info@trolltech.com if any conditions of this licensing are
44 ** not clear to you.
46 **********************************************************************/
48 #include "qimage.h"
49 #include "qcolor.h"
50 //#include "qregexp.h"
51 //#include "qfile.h"
52 //#include "qdatastream.h"
53 //#include "qtextstream.h"
54 //#include "qbuffer.h"
55 //#include "qptrlist.h"
56 //#include "qasyncimageio.h"
57 //#include "qpngio.h"
58 //#include "qmngio.h"
59 //#include "qjpegio.h"
60 //#include "qmap.h"
61 //#include <private/qpluginmanager_p.h>
62 //#include "qimageformatinterface_p.h"
63 //#include "qwmatrix.h"
64 //#include "qapplication.h"
65 //#include "qmime.h"
66 //#include "qdragobject.h"
67 #include <ctype.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <limits.h>
71 #include "qnamespace.h"
72 #include "x11_defs.h"
74 #ifdef Q_WS_QWS
75 #include "qgfx_qws.h"
76 #endif
78 // 16bpp images on supported on Qt/Embedded
79 #if !defined( Q_WS_QWS ) && !defined(QT_NO_IMAGE_16_BIT)
80 #define QT_NO_IMAGE_16_BIT
81 #endif
84 /*!
85 \class QImage
86 \brief The QImage class provides a hardware-independent pixmap
87 representation with direct access to the pixel data.
89 \ingroup images
90 \ingroup graphics
91 \ingroup shared
92 \mainclass
94 It is one of the two classes Qt provides for dealing with images,
95 the other being QPixmap. QImage is designed and optimized for I/O
96 and for direct pixel access/manipulation. QPixmap is designed and
97 optimized for drawing. There are (slow) functions to convert
98 between QImage and QPixmap: QPixmap::convertToImage() and
99 QPixmap::convertFromImage().
101 An image has the parameters \link width() width\endlink, \link
102 height() height\endlink and \link depth() depth\endlink (bits per
103 pixel, bpp), a color table and the actual \link bits()
104 pixels\endlink. QImage supports 1-bpp, 8-bpp and 32-bpp image
105 data. 1-bpp and 8-bpp images use a color lookup table; the pixel
106 value is a color table index.
108 32-bpp images encode an RGB value in 24 bits and ignore the color
109 table. The most significant byte is used for the \link
110 setAlphaBuffer() alpha buffer\endlink.
112 An entry in the color table is an RGB triplet encoded as a \c
113 uint. Use the \link ::qRed() qRed()\endlink, \link ::qGreen()
114 qGreen()\endlink and \link ::qBlue() qBlue()\endlink functions (\c
115 qcolor.h) to access the components, and \link ::qRgb()
116 qRgb\endlink to make an RGB triplet (see the QColor class
117 documentation).
119 1-bpp (monochrome) images have a color table with a most two
120 colors. There are two different formats: big endian (MSB first) or
121 little endian (LSB first) bit order. To access a single bit you
122 will must do some bit shifts:
124 \code
125 QImage image;
126 // sets bit at (x,y) to 1
127 if ( image.bitOrder() == QImage::LittleEndian )
128 *(image.scanLine(y) + (x >> 3)) |= 1 << (x & 7);
129 else
130 *(image.scanLine(y) + (x >> 3)) |= 1 << (7 - (x & 7));
131 \endcode
133 If this looks complicated, it might be a good idea to convert the
134 1-bpp image to an 8-bpp image using convertDepth().
136 8-bpp images are much easier to work with than 1-bpp images
137 because they have a single byte per pixel:
139 \code
140 QImage image;
141 // set entry 19 in the color table to yellow
142 image.setColor( 19, qRgb(255,255,0) );
143 // set 8 bit pixel at (x,y) to value yellow (in color table)
144 *(image.scanLine(y) + x) = 19;
145 \endcode
147 32-bpp images ignore the color table; instead, each pixel contains
148 the RGB triplet. 24 bits contain the RGB value; the most
149 significant byte is reserved for the alpha buffer.
151 \code
152 QImage image;
153 // sets 32 bit pixel at (x,y) to yellow.
154 uint *p = (uint *)image.scanLine(y) + x;
155 *p = qRgb(255,255,0);
156 \endcode
158 On Qt/Embedded, scanlines are aligned to the pixel depth and may
159 be padded to any degree, while on all other platforms, the
160 scanlines are 32-bit aligned for all depths. The constructor
161 taking a \c{uchar*} argument always expects 32-bit aligned data.
162 On Qt/Embedded, an additional constructor allows the number of
163 bytes-per-line to be specified.
165 QImage supports a variety of methods for getting information about
166 the image, for example, colorTable(), allGray(), isGrayscale(),
167 bitOrder(), bytesPerLine(), depth(), dotsPerMeterX() and
168 dotsPerMeterY(), hasAlphaBuffer(), numBytes(), numColors(), and
169 width() and height().
171 Pixel colors are retrieved with pixel() and set with setPixel().
173 QImage also supports a number of functions for creating a new
174 image that is a transformed version of the original. For example,
175 copy(), convertBitOrder(), convertDepth(), createAlphaMask(),
176 createHeuristicMask(), mirror(), scale(), smoothScale(), swapRGB()
177 and xForm(). There are also functions for changing attributes of
178 an image in-place, for example, setAlphaBuffer(), setColor(),
179 setDotsPerMeterX() and setDotsPerMeterY() and setNumColors().
181 Images can be loaded and saved in the supported formats. Images
182 are saved to a file with save(). Images are loaded from a file
183 with load() (or in the constructor) or from an array of data with
184 loadFromData(). The lists of supported formats are available from
185 inputFormatList() and outputFormatList().
187 Strings of text may be added to images using setText().
189 The QImage class uses explicit \link shclass.html sharing\endlink,
190 similar to that used by QMemArray.
192 New image formats can be added as \link plugins-howto.html
193 plugins\endlink.
195 \sa QImageIO QPixmap \link shclass.html Shared Classes\endlink
200 \enum QImage::Endian
202 This enum type is used to describe the endianness of the CPU and
203 graphics hardware.
205 \value IgnoreEndian Endianness does not matter. Useful for some
206 operations that are independent of endianness.
207 \value BigEndian Network byte order, as on SPARC and Motorola CPUs.
208 \value LittleEndian PC/Alpha byte order.
212 \enum Qt::ImageConversionFlags
214 The conversion flag is a bitwise-OR of the following values. The
215 options marked "(default)" are set if no other values from the
216 list are included (since the defaults are zero):
218 Color/Mono preference (ignored for QBitmap)
219 \value AutoColor (default) - If the image has \link
220 QImage::depth() depth\endlink 1 and contains only
221 black and white pixels, the pixmap becomes monochrome.
222 \value ColorOnly The pixmap is dithered/converted to the
223 \link QPixmap::defaultDepth() native display depth\endlink.
224 \value MonoOnly The pixmap becomes monochrome. If necessary,
225 it is dithered using the chosen dithering algorithm.
227 Dithering mode preference for RGB channels
228 \value DiffuseDither (default) - A high-quality dither.
229 \value OrderedDither A faster, more ordered dither.
230 \value ThresholdDither No dithering; closest color is used.
232 Dithering mode preference for alpha channel
233 \value ThresholdAlphaDither (default) - No dithering.
234 \value OrderedAlphaDither A faster, more ordered dither.
235 \value DiffuseAlphaDither A high-quality dither.
236 \value NoAlpha Not supported.
238 Color matching versus dithering preference
239 \value PreferDither (default when converting to a pixmap) - Always dither
240 32-bit images when the image is converted to 8 bits.
241 \value AvoidDither (default when converting for the purpose of saving to
242 file) - Dither 32-bit images only if the image has more than 256
243 colors and it is being converted to 8 bits.
244 \value AutoDither Not supported.
246 The following are not values that are used directly, but masks for
247 the above classes:
248 \value ColorMode_Mask Mask for the color mode.
249 \value Dither_Mask Mask for the dithering mode for RGB channels.
250 \value AlphaDither_Mask Mask for the dithering mode for the alpha channel.
251 \value DitherMode_Mask Mask for the mode that determines the preference of
252 color matching versus dithering.
254 Using 0 as the conversion flag sets all the default options.
257 #if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
258 #pragma message disable narrowptr
259 #endif
261 #ifndef QT_NO_IMAGE_TEXT
262 class QImageDataMisc {
263 public:
264 QImageDataMisc() { }
265 QImageDataMisc( const QImageDataMisc& o ) :
266 text_lang(o.text_lang) { }
268 QImageDataMisc& operator=(const QImageDataMisc& o)
270 text_lang = o.text_lang;
271 return *this;
273 QValueList<QImageTextKeyLang> list()
275 return text_lang.keys();
278 QStringList languages()
280 QStringList r;
281 QMap<QImageTextKeyLang,QString>::Iterator it = text_lang.begin();
282 for ( ; it != text_lang.end(); ++it ) {
283 r.remove( it.key().lang );
284 r.append( it.key().lang );
286 return r;
288 QStringList keys()
290 QStringList r;
291 QMap<QImageTextKeyLang,QString>::Iterator it = text_lang.begin();
292 for ( ; it != text_lang.end(); ++it ) {
293 r.remove( it.key().key );
294 r.append( it.key().key );
296 return r;
299 QMap<QImageTextKeyLang,QString> text_lang;
301 #endif // QT_NO_IMAGE_TEXT
305 /*****************************************************************************
306 QImage member functions
307 *****************************************************************************/
309 // table to flip bits
310 static const uchar bitflip[256] = {
312 open OUT, "| fmt";
313 for $i (0..255) {
314 print OUT (($i >> 7) & 0x01) | (($i >> 5) & 0x02) |
315 (($i >> 3) & 0x04) | (($i >> 1) & 0x08) |
316 (($i << 7) & 0x80) | (($i << 5) & 0x40) |
317 (($i << 3) & 0x20) | (($i << 1) & 0x10), ", ";
319 close OUT;
321 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
322 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
323 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
324 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
325 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
326 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
327 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
328 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
329 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
330 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
331 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
332 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
333 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
334 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
335 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
336 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
339 const uchar *qt_get_bitflip_array() // called from QPixmap code
341 return bitflip;
346 Constructs a null image.
348 \sa isNull()
351 QImage::QImage()
353 init();
357 Constructs an image with \a w width, \a h height, \a depth bits
358 per pixel, \a numColors colors and bit order \a bitOrder.
360 Using this constructor is the same as first constructing a null
361 image and then calling the create() function.
363 \sa create()
366 QImage::QImage( int w, int h, int depth, int numColors, Endian bitOrder )
368 init();
369 create( w, h, depth, numColors, bitOrder );
373 Constructs an image with size \a size pixels, depth \a depth bits,
374 \a numColors and \a bitOrder endianness.
376 Using this constructor is the same as first constructing a null
377 image and then calling the create() function.
379 \sa create()
381 QImage::QImage( const QSize& size, int depth, int numColors, Endian bitOrder )
383 init();
384 create( size, depth, numColors, bitOrder );
387 #ifndef QT_NO_IMAGEIO
389 Constructs an image and tries to load the image from the file \a
390 fileName.
392 If \a format is specified, the loader attempts to read the image
393 using the specified format. If \a format is not specified (which
394 is the default), the loader reads a few bytes from the header to
395 guess the file format.
397 If the loading of the image failed, this object is a \link
398 isNull() null\endlink image.
400 The QImageIO documentation lists the supported image formats and
401 explains how to add extra formats.
403 \sa load() isNull() QImageIO
406 QImage::QImage( const QString &fileName, const char* format )
408 init();
409 load( fileName, format );
412 #ifndef QT_NO_IMAGEIO_XPM
413 // helper
414 static void read_xpm_image_or_array( QImageIO *, const char * const *, QImage & );
415 #endif
417 Constructs an image from \a xpm, which must be a valid XPM image.
419 Errors are silently ignored.
421 Note that it's possible to squeeze the XPM variable a little bit
422 by using an unusual declaration:
424 \code
425 static const char * const start_xpm[]={
426 "16 15 8 1",
427 "a c #cec6bd",
428 ....
429 \endcode
431 The extra \c const makes the entire definition read-only, which is
432 slightly more efficient (e.g. when the code is in a shared
433 library) and ROMable when the application is to be stored in ROM.
436 QImage::QImage( const char * const xpm[] )
438 init();
439 #ifndef QT_NO_IMAGEIO_XPM
440 read_xpm_image_or_array( 0, xpm, *this );
441 #else
442 // We use a qFatal rather than disabling the whole function, as this
443 // constructor may be ambiguous.
444 qFatal("XPM not supported");
445 #endif
449 Constructs an image from the binary data \a array. It tries to
450 guess the file format.
452 If the loading of the image failed, this object is a \link
453 isNull() null\endlink image.
455 \sa loadFromData() isNull() imageFormat()
457 QImage::QImage( const QByteArray &array )
459 init();
460 loadFromData(array);
462 #endif //QT_NO_IMAGEIO
466 Constructs a \link shclass.html shallow copy\endlink of \a image.
469 QImage::QImage( const QImage &image )
471 data = image.data;
472 data->ref();
476 Constructs an image \a w pixels wide, \a h pixels high with a
477 color depth of \a depth, that uses an existing memory buffer, \a
478 yourdata. The buffer must remain valid throughout the life of the
479 QImage. The image does not delete the buffer at destruction.
481 If \a colortable is 0, a color table sufficient for \a numColors
482 will be allocated (and destructed later).
484 Note that \a yourdata must be 32-bit aligned.
486 The endianness is given in \a bitOrder.
488 QImage::QImage( uchar* yourdata, int w, int h, int depth,
489 QRgb* colortable, int numColors,
490 Endian bitOrder )
492 init();
493 if ( w <= 0 || h <= 0 || depth <= 0 || numColors < 0 )
494 return; // invalid parameter(s)
495 data->w = w;
496 data->h = h;
497 data->d = depth;
498 data->ncols = depth != 32 ? numColors : 0;
499 if ( !yourdata )
500 return; // Image header info can be saved without needing to allocate memory.
501 int bpl = ((w*depth+31)/32)*4; // bytes per scanline
502 data->nbytes = bpl*h;
503 if ( colortable || !data->ncols ) {
504 data->ctbl = colortable;
505 data->ctbl_mine = false;
506 } else {
507 // calloc since we realloc, etc. later (ick)
508 data->ctbl = (QRgb*)calloc( data->ncols*sizeof(QRgb), data->ncols );
509 data->ctbl_mine = true;
511 uchar** jt = (uchar**)malloc(h*sizeof(uchar*));
512 for (int j=0; j<h; j++) {
513 jt[j] = yourdata+j*bpl;
515 data->bits = jt;
516 data->bitordr = bitOrder;
519 #ifdef Q_WS_QWS
522 Constructs an image that uses an existing memory buffer. The
523 buffer must remain valid for the life of the QImage. The image
524 does not delete the buffer at destruction. The buffer is passed as
525 \a yourdata. The image's width is \a w and its height is \a h. The
526 color depth is \a depth. \a bpl specifies the number of bytes per
527 line.
529 If \a colortable is 0, a color table sufficient for \a numColors
530 will be allocated (and destructed later).
532 The endianness is specified by \a bitOrder.
534 \warning This constructor is only available on Qt/Embedded.
536 QImage::QImage( uchar* yourdata, int w, int h, int depth,
537 int bpl, QRgb* colortable, int numColors,
538 Endian bitOrder )
540 init();
541 if ( !yourdata || w <= 0 || h <= 0 || depth <= 0 || numColors < 0 )
542 return; // invalid parameter(s)
543 data->w = w;
544 data->h = h;
545 data->d = depth;
546 data->ncols = numColors;
547 data->nbytes = bpl * h;
548 if ( colortable || !numColors ) {
549 data->ctbl = colortable;
550 data->ctbl_mine = false;
551 } else {
552 // calloc since we realloc, etc. later (ick)
553 data->ctbl = (QRgb*)calloc( numColors*sizeof(QRgb), numColors );
554 data->ctbl_mine = true;
556 uchar** jt = (uchar**)malloc(h*sizeof(uchar*));
557 for (int j=0; j<h; j++) {
558 jt[j] = yourdata+j*bpl;
560 data->bits = jt;
561 data->bitordr = bitOrder;
563 #endif // Q_WS_QWS
566 Destroys the image and cleans up.
569 QImage::~QImage()
571 if ( data && data->deref() ) {
572 reset();
573 delete data;
580 /*! Convenience function. Gets the data associated with the absolute
581 name \a abs_name from the default mime source factory and decodes it
582 to an image.
584 \sa QMimeSourceFactory, QImage::fromMimeSource(), QImageDrag::decode()
586 #ifndef QT_NO_MIME
587 QImage QImage::fromMimeSource( const QString &abs_name )
589 const QMimeSource *m = QMimeSourceFactory::defaultFactory()->data( abs_name );
590 if ( !m ) {
591 #if defined(QT_CHECK_STATE)
592 qWarning("QImage::fromMimeSource: Cannot find image \"%s\" in the mime source factory", abs_name.latin1() );
593 #endif
594 return QImage();
596 QImage img;
597 QImageDrag::decode( m, img );
598 return img;
600 #endif
604 Assigns a \link shclass.html shallow copy\endlink of \a image to
605 this image and returns a reference to this image.
607 \sa copy()
610 QImage &QImage::operator=( const QImage &image )
612 image.data->ref(); // avoid 'x = x'
613 if ( data->deref() ) {
614 reset();
615 delete data;
617 data = image.data;
618 return *this;
622 \overload
624 Sets the image bits to the \a pixmap contents and returns a
625 reference to the image.
627 If the image shares data with other images, it will first
628 dereference the shared data.
630 Makes a call to QPixmap::convertToImage().
633 #if 0
634 QImage &QImage::operator=( const QPixmap &pixmap )
636 *this = pixmap.convertToImage();
637 return *this;
639 #endif
642 Detaches from shared image data and makes sure that this image is
643 the only one referring to the data.
645 If multiple images share common data, this image makes a copy of
646 the data and detaches itself from the sharing mechanism.
647 Nothing is done if there is just a single reference.
649 \sa copy()
652 void QImage::detach()
654 if ( data->count != 1 )
655 *this = copy();
659 Returns a \link shclass.html deep copy\endlink of the image.
661 \sa detach()
664 QImage QImage::copy() const
666 if ( isNull() ) {
667 // maintain the fields of invalid QImages when copied
668 return QImage( 0, width(), height(), depth(), colorTable(), numColors(), bitOrder() );
669 } else {
670 QImage image;
671 image.create( width(), height(), depth(), numColors(), bitOrder() );
672 #ifdef Q_WS_QWS
673 // Qt/Embedded can create images with non-default bpl
674 // make sure we don't crash.
675 if ( image.numBytes() != numBytes() )
676 for ( int i = 0; i < height(); i++ )
677 memcpy( image.scanLine(i), scanLine(i), image.bytesPerLine() );
678 else
679 #endif
680 memcpy( image.bits(), bits(), numBytes() );
681 memcpy( image.colorTable(), colorTable(), numColors() * sizeof(QRgb) );
682 image.setAlphaBuffer( hasAlphaBuffer() );
683 image.data->dpmx = dotsPerMeterX();
684 image.data->dpmy = dotsPerMeterY();
685 image.data->offset = offset();
686 #ifndef QT_NO_IMAGE_TEXT
687 if ( data->misc ) {
688 image.data->misc = new QImageDataMisc;
689 *image.data->misc = misc();
691 #endif
692 return image;
697 \overload
699 Returns a \link shclass.html deep copy\endlink of a sub-area of
700 the image.
702 The returned image is always \a w by \a h pixels in size, and is
703 copied from position \a x, \a y in this image. In areas beyond
704 this image pixels are filled with pixel 0.
706 If the image needs to be modified to fit in a lower-resolution
707 result (e.g. converting from 32-bit to 8-bit), use the \a
708 conversion_flags to specify how you'd prefer this to happen.
710 \sa bitBlt() Qt::ImageConversionFlags
713 QImage QImage::copy(int x, int y, int w, int h, int conversion_flags) const
715 int dx = 0;
716 int dy = 0;
717 if ( w <= 0 || h <= 0 ) return QImage(); // Nothing to copy
719 QImage image( w, h, depth(), numColors(), bitOrder() );
721 if ( x < 0 || y < 0 || x + w > width() || y + h > height() ) {
722 // bitBlt will not cover entire image - clear it.
723 // ### should deal with each side separately for efficiency
724 image.fill(0);
725 if ( x < 0 ) {
726 dx = -x;
727 x = 0;
729 if ( y < 0 ) {
730 dy = -y;
731 y = 0;
735 bool has_alpha = hasAlphaBuffer();
736 if ( has_alpha ) {
737 // alpha channel should be only copied, not used by bitBlt(), and
738 // this is mutable, we will restore the image state before returning
739 QImage *that = (QImage *) this;
740 that->setAlphaBuffer( false );
742 memcpy( image.colorTable(), colorTable(), numColors()*sizeof(QRgb) );
743 bitBlt( &image, dx, dy, this, x, y, -1, -1, conversion_flags );
744 if ( has_alpha ) {
745 // restore image state
746 QImage *that = (QImage *) this;
747 that->setAlphaBuffer( true );
749 image.setAlphaBuffer(hasAlphaBuffer());
750 image.data->dpmx = dotsPerMeterX();
751 image.data->dpmy = dotsPerMeterY();
752 image.data->offset = offset();
753 #ifndef QT_NO_IMAGE_TEXT
754 if ( data->misc ) {
755 image.data->misc = new QImageDataMisc;
756 *image.data->misc = misc();
758 #endif
759 return image;
763 \overload QImage QImage::copy(const QRect& r) const
765 Returns a \link shclass.html deep copy\endlink of a sub-area of
766 the image.
768 The returned image always has the size of the rectangle \a r. In
769 areas beyond this image pixels are filled with pixel 0.
773 \fn bool QImage::isNull() const
775 Returns true if it is a null image; otherwise returns FALSE.
777 A null image has all parameters set to zero and no allocated data.
782 \fn int QImage::width() const
784 Returns the width of the image.
786 \sa height() size() rect()
790 \fn int QImage::height() const
792 Returns the height of the image.
794 \sa width() size() rect()
798 \fn QSize QImage::size() const
800 Returns the size of the image, i.e. its width and height.
802 \sa width() height() rect()
806 \fn QRect QImage::rect() const
808 Returns the enclosing rectangle (0, 0, width(), height()) of the
809 image.
811 \sa width() height() size()
815 \fn int QImage::depth() const
817 Returns the depth of the image.
819 The image depth is the number of bits used to encode a single
820 pixel, also called bits per pixel (bpp) or bit planes of an image.
822 The supported depths are 1, 8, 16 (Qt/Embedded only) and 32.
824 \sa convertDepth()
828 \fn int QImage::numColors() const
830 Returns the size of the color table for the image.
832 Notice that numColors() returns 0 for 16-bpp (Qt/Embedded only)
833 and 32-bpp images because these images do not use color tables,
834 but instead encode pixel values as RGB triplets.
836 \sa setNumColors() colorTable()
840 \fn QImage::Endian QImage::bitOrder() const
842 Returns the bit order for the image.
844 If it is a 1-bpp image, this function returns either
845 QImage::BigEndian or QImage::LittleEndian.
847 If it is not a 1-bpp image, this function returns
848 QImage::IgnoreEndian.
850 \sa depth()
854 \fn uchar **QImage::jumpTable() const
856 Returns a pointer to the scanline pointer table.
858 This is the beginning of the data block for the image.
860 \sa bits() scanLine()
864 \fn QRgb *QImage::colorTable() const
866 Returns a pointer to the color table.
868 \sa numColors()
872 \fn int QImage::numBytes() const
874 Returns the number of bytes occupied by the image data.
876 \sa bytesPerLine() bits()
880 \fn int QImage::bytesPerLine() const
882 Returns the number of bytes per image scanline. This is equivalent
883 to numBytes()/height().
885 \sa numBytes() scanLine()
889 \fn QRgb QImage::color( int i ) const
891 Returns the color in the color table at index \a i. The first
892 color is at index 0.
894 A color value is an RGB triplet. Use the \link ::qRed()
895 qRed()\endlink, \link ::qGreen() qGreen()\endlink and \link
896 ::qBlue() qBlue()\endlink functions (defined in \c qcolor.h) to
897 get the color value components.
899 \sa setColor() numColors() QColor
903 \fn void QImage::setColor( int i, QRgb c )
905 Sets a color in the color table at index \a i to \a c.
907 A color value is an RGB triplet. Use the \link ::qRgb()
908 qRgb()\endlink function (defined in \c qcolor.h) to make RGB
909 triplets.
911 \sa color() setNumColors() numColors()
915 \fn uchar *QImage::scanLine( int i ) const
917 Returns a pointer to the pixel data at the scanline with index \a
918 i. The first scanline is at index 0.
920 The scanline data is aligned on a 32-bit boundary.
922 \warning If you are accessing 32-bpp image data, cast the returned
923 pointer to \c{QRgb*} (QRgb has a 32-bit size) and use it to
924 read/write the pixel value. You cannot use the \c{uchar*} pointer
925 directly, because the pixel format depends on the byte order on
926 the underlying platform. Hint: use \link ::qRed() qRed()\endlink,
927 \link ::qGreen() qGreen()\endlink and \link ::qBlue()
928 qBlue()\endlink, etc. (qcolor.h) to access the pixels.
930 \warning If you are accessing 16-bpp image data, you must handle
931 endianness yourself. (Qt/Embedded only)
933 \sa bytesPerLine() bits() jumpTable()
937 \fn uchar *QImage::bits() const
939 Returns a pointer to the first pixel data. This is equivalent to
940 scanLine(0).
942 \sa numBytes() scanLine() jumpTable()
947 void QImage::warningIndexRange( const char *func, int i )
949 #if defined(QT_CHECK_RANGE)
950 qWarning( "QImage::%s: Index %d out of range", func, i );
951 #else
952 Q_UNUSED( func )
953 Q_UNUSED( i )
954 #endif
959 Resets all image parameters and deallocates the image data.
962 void QImage::reset()
964 freeBits();
965 setNumColors( 0 );
966 #ifndef QT_NO_IMAGE_TEXT
967 delete data->misc;
968 #endif
969 reinit();
974 Fills the entire image with the pixel value \a pixel.
976 If the \link depth() depth\endlink of this image is 1, only the
977 lowest bit is used. If you say fill(0), fill(2), etc., the image
978 is filled with 0s. If you say fill(1), fill(3), etc., the image is
979 filled with 1s. If the depth is 8, the lowest 8 bits are used.
981 If the depth is 32 and the image has no alpha buffer, the \a pixel
982 value is written to each pixel in the image. If the image has an
983 alpha buffer, only the 24 RGB bits are set and the upper 8 bits
984 (alpha value) are left unchanged.
986 Note: QImage::pixel() returns the color of the pixel at the given
987 coordinates; QColor::pixel() returns the pixel value of the
988 underlying window system (essentially an index value), so normally
989 you will want to use QImage::pixel() to use a color from an
990 existing image or QColor::rgb() to use a specific color.
992 \sa invertPixels() depth() hasAlphaBuffer() create()
995 void QImage::fill( uint pixel )
997 if ( depth() == 1 || depth() == 8 ) {
998 if ( depth() == 1 ) {
999 if ( pixel & 1 )
1000 pixel = 0xffffffff;
1001 else
1002 pixel = 0;
1003 } else {
1004 uint c = pixel & 0xff;
1005 pixel = c | ((c << 8) & 0xff00) | ((c << 16) & 0xff0000) |
1006 ((c << 24) & 0xff000000);
1008 int bpl = bytesPerLine();
1009 for ( int i=0; i<height(); i++ )
1010 memset( scanLine(i), pixel, bpl );
1011 #ifndef QT_NO_IMAGE_16_BIT
1012 } else if ( depth() == 16 ) {
1013 for ( int i=0; i<height(); i++ ) {
1014 //optimize with 32-bit writes, since image is always aligned
1015 uint *p = (uint *)scanLine(i);
1016 uint *end = (uint*)(((ushort*)p) + width());
1017 uint fill;
1018 ushort *f = (ushort*)&fill;
1019 f[0]=pixel;
1020 f[1]=pixel;
1021 while ( p < end )
1022 *p++ = fill;
1024 #endif // QT_NO_IMAGE_16_BIT
1025 #ifndef QT_NO_IMAGE_TRUECOLOR
1026 } else if ( depth() == 32 ) {
1027 if ( hasAlphaBuffer() ) {
1028 pixel &= 0x00ffffff;
1029 for ( int i=0; i<height(); i++ ) {
1030 uint *p = (uint *)scanLine(i);
1031 uint *end = p + width();
1032 while ( p < end ) {
1033 *p = (*p & 0xff000000) | pixel;
1034 p++;
1037 } else {
1038 for ( int i=0; i<height(); i++ ) {
1039 uint *p = (uint *)scanLine(i);
1040 uint *end = p + width();
1041 while ( p < end )
1042 *p++ = pixel;
1045 #endif // QT_NO_IMAGE_TRUECOLOR
1051 Inverts all pixel values in the image.
1053 If the depth is 32: if \a invertAlpha is true, the alpha bits are
1054 also inverted, otherwise they are left unchanged.
1056 If the depth is not 32, the argument \a invertAlpha has no
1057 meaning.
1059 Note that inverting an 8-bit image means to replace all pixels
1060 using color index \e i with a pixel using color index 255 minus \e
1061 i. Similarly for a 1-bit image. The color table is not changed.
1063 \sa fill() depth() hasAlphaBuffer()
1066 void QImage::invertPixels( bool invertAlpha )
1068 quint32 n = numBytes();
1069 if ( n % 4 ) {
1070 Q_UINT8 *p = (Q_UINT8*)bits();
1071 Q_UINT8 *end = p + n;
1072 while ( p < end )
1073 *p++ ^= 0xff;
1074 } else {
1075 quint32 *p = (quint32*)bits();
1076 quint32 *end = p + n/4;
1077 uint xorbits = invertAlpha && depth() == 32 ? 0x00ffffff : 0xffffffff;
1078 while ( p < end )
1079 *p++ ^= xorbits;
1085 Determines the host computer byte order. Returns
1086 QImage::LittleEndian (LSB first) or QImage::BigEndian (MSB first).
1088 \sa systemBitOrder()
1091 QImage::Endian QImage::systemByteOrder()
1093 static Endian sbo = IgnoreEndian;
1094 if ( sbo == IgnoreEndian ) { // initialize
1095 int ws;
1096 bool be;
1097 qSysInfo( &ws, &be );
1098 sbo = be ? BigEndian : LittleEndian;
1100 return sbo;
1104 #if defined(Q_WS_X11)
1105 #include <X11/Xlib.h> // needed for systemBitOrder
1106 #include <X11/Xutil.h>
1107 #include <X11/Xos.h>
1108 #if defined(Q_OS_WIN32)
1109 #undef open
1110 #undef close
1111 #undef read
1112 #undef write
1113 #endif
1114 #endif
1116 // POSIX Large File Support redefines open -> open64
1117 #if defined(open)
1118 # undef open
1119 #endif
1121 // POSIX Large File Support redefines truncate -> truncate64
1122 #if defined(truncate)
1123 # undef truncate
1124 #endif
1127 Determines the bit order of the display hardware. Returns
1128 QImage::LittleEndian (LSB first) or QImage::BigEndian (MSB first).
1130 \sa systemByteOrder()
1133 QImage::Endian QImage::systemBitOrder()
1135 #if defined(Q_WS_X11)
1136 return BitmapBitOrder(qt_xdisplay()) == MSBFirst ? BigEndian :LittleEndian;
1137 #else
1138 return BigEndian;
1139 #endif
1144 Resizes the color table to \a numColors colors.
1146 If the color table is expanded all the extra colors will be set to
1147 black (RGB 0,0,0).
1149 \sa numColors() color() setColor() colorTable()
1152 void QImage::setNumColors( int numColors )
1154 if ( numColors == data->ncols )
1155 return;
1156 if ( numColors == 0 ) { // use no color table
1157 if ( data->ctbl ) {
1158 if ( data->ctbl_mine )
1159 free( data->ctbl );
1160 else
1161 data->ctbl_mine = true;
1162 data->ctbl = 0;
1164 data->ncols = 0;
1165 return;
1167 if ( data->ctbl && data->ctbl_mine ) { // already has color table
1168 data->ctbl = (QRgb*)realloc( data->ctbl, numColors*sizeof(QRgb) );
1169 if ( data->ctbl && numColors > data->ncols )
1170 memset( (char *)&data->ctbl[data->ncols], 0,
1171 (numColors-data->ncols)*sizeof(QRgb) );
1172 } else { // create new color table
1173 data->ctbl = (QRgb*)calloc( numColors*sizeof(QRgb), 1 );
1174 data->ctbl_mine = true;
1176 data->ncols = data->ctbl == 0 ? 0 : numColors;
1181 \fn bool QImage::hasAlphaBuffer() const
1183 Returns true if alpha buffer mode is enabled; otherwise returns
1184 FALSE.
1186 \sa setAlphaBuffer()
1190 Enables alpha buffer mode if \a enable is true, otherwise disables
1191 it. The default setting is disabled.
1193 An 8-bpp image has 8-bit pixels. A pixel is an index into the
1194 \link color() color table\endlink, which contains 32-bit color
1195 values. In a 32-bpp image, the 32-bit pixels are the color values.
1197 This 32-bit value is encoded as follows: The lower 24 bits are
1198 used for the red, green, and blue components. The upper 8 bits
1199 contain the alpha component.
1201 The alpha component specifies the transparency of a pixel. 0 means
1202 completely transparent and 255 means opaque. The alpha component
1203 is ignored if you do not enable alpha buffer mode.
1205 The alpha buffer is used to set a mask when a QImage is translated
1206 to a QPixmap.
1208 \sa hasAlphaBuffer() createAlphaMask()
1211 void QImage::setAlphaBuffer( bool enable )
1213 data->alpha = enable;
1218 Sets the image \a width, \a height, \a depth, its number of colors
1219 (in \a numColors), and bit order. Returns true if successful, or
1220 FALSE if the parameters are incorrect or if memory cannot be
1221 allocated.
1223 The \a width and \a height is limited to 32767. \a depth must be
1224 1, 8, or 32. If \a depth is 1, \a bitOrder must be set to
1225 either QImage::LittleEndian or QImage::BigEndian. For other depths
1226 \a bitOrder must be QImage::IgnoreEndian.
1228 This function allocates a color table and a buffer for the image
1229 data. The image data is not initialized.
1231 The image buffer is allocated as a single block that consists of a
1232 table of \link scanLine() scanline\endlink pointers (jumpTable())
1233 and the image data (bits()).
1235 \sa fill() width() height() depth() numColors() bitOrder()
1236 jumpTable() scanLine() bits() bytesPerLine() numBytes()
1239 bool QImage::create( int width, int height, int depth, int numColors,
1240 Endian bitOrder )
1242 reset(); // reset old data
1243 if ( width <= 0 || height <= 0 || depth <= 0 || numColors < 0 )
1244 return false; // invalid parameter(s)
1245 if ( depth == 1 && bitOrder == IgnoreEndian ) {
1246 #if defined(QT_CHECK_RANGE)
1247 qWarning( "QImage::create: Bit order is required for 1 bpp images" );
1248 #endif
1249 return false;
1251 if ( depth != 1 )
1252 bitOrder = IgnoreEndian;
1254 #if defined(QT_CHECK_RANGE)
1255 if ( depth == 24 )
1256 qWarning( "QImage::create: 24-bpp images no longer supported, "
1257 "use 32-bpp instead" );
1258 #endif
1259 switch ( depth ) {
1260 case 1:
1261 case 8:
1262 #ifndef QT_NO_IMAGE_16_BIT
1263 case 16:
1264 #endif
1265 #ifndef QT_NO_IMAGE_TRUECOLOR
1266 case 32:
1267 #endif
1268 break;
1269 default: // invalid depth
1270 return false;
1273 if ( depth == 32 )
1274 numColors = 0;
1275 setNumColors( numColors );
1276 if ( data->ncols != numColors ) // could not alloc color table
1277 return false;
1279 if ( INT_MAX / depth < width) { // sanity check for potential overflow
1280 setNumColors( 0 );
1281 return false;
1283 // Qt/Embedded doesn't waste memory on unnecessary padding.
1284 #ifdef Q_WS_QWS
1285 const int bpl = (width*depth+7)/8; // bytes per scanline
1286 const int pad = 0;
1287 #else
1288 const int bpl = ((width*depth+31)/32)*4; // bytes per scanline
1289 // #### WWA: shouldn't this be (width*depth+7)/8:
1290 const int pad = bpl - (width*depth)/8; // pad with zeros
1291 #endif
1292 if (INT_MAX / bpl < height) { // sanity check for potential overflow
1293 setNumColors( 0 );
1294 return false;
1296 int nbytes = bpl*height; // image size
1297 int ptbl = height*sizeof(uchar*); // pointer table size
1298 int size = nbytes + ptbl; // total size of data block
1299 uchar **p = (uchar **)malloc( size ); // alloc image bits
1300 Q_CHECK_PTR(p);
1301 if ( !p ) { // no memory
1302 setNumColors( 0 );
1303 return false;
1305 data->w = width;
1306 data->h = height;
1307 data->d = depth;
1308 data->nbytes = nbytes;
1309 data->bitordr = bitOrder;
1310 data->bits = p; // set image pointer
1311 //uchar *d = (uchar*)p + ptbl; // setup scanline pointers
1312 uchar *d = (uchar*)(p + height); // setup scanline pointers
1313 while ( height-- ) {
1314 *p++ = d;
1315 if ( pad )
1316 memset( d+bpl-pad, 0, pad );
1317 d += bpl;
1319 return true;
1323 \overload bool QImage::create( const QSize&, int depth, int numColors, Endian bitOrder )
1325 bool QImage::create( const QSize& size, int depth, int numColors,
1326 QImage::Endian bitOrder )
1328 return create(size.width(), size.height(), depth, numColors, bitOrder);
1332 \internal
1333 Initializes the image data structure.
1336 void QImage::init()
1338 data = new QImageData;
1339 Q_CHECK_PTR( data );
1340 reinit();
1343 void QImage::reinit()
1345 data->w = data->h = data->d = data->ncols = 0;
1346 data->nbytes = 0;
1347 data->ctbl = 0;
1348 data->bits = 0;
1349 data->bitordr = QImage::IgnoreEndian;
1350 data->alpha = false;
1351 #ifndef QT_NO_IMAGE_TEXT
1352 data->misc = 0;
1353 #endif
1354 data->dpmx = 0;
1355 data->dpmy = 0;
1356 data->offset = QPoint(0,0);
1360 \internal
1361 Deallocates the image data and sets the bits pointer to 0.
1364 void QImage::freeBits()
1366 if ( data->bits ) { // dealloc image bits
1367 free( data->bits );
1368 data->bits = 0;
1373 /*****************************************************************************
1374 Internal routines for converting image depth.
1375 *****************************************************************************/
1378 // convert_32_to_8: Converts a 32 bits depth (true color) to an 8 bit
1379 // image with a colormap. If the 32 bit image has more than 256 colors,
1380 // we convert the red,green and blue bytes into a single byte encoded
1381 // as 6 shades of each of red, green and blue.
1383 // if dithering is needed, only 1 color at most is available for alpha.
1385 #ifndef QT_NO_IMAGE_TRUECOLOR
1386 struct QRgbMap {
1387 QRgbMap() : rgb(0xffffffff) { }
1388 bool used() const { return rgb!=0xffffffff; }
1389 uchar pix;
1390 QRgb rgb;
1393 static bool convert_32_to_8( const QImage *src, QImage *dst, int conversion_flags, QRgb* palette=0, int palette_count=0 )
1395 register QRgb *p;
1396 uchar *b;
1397 bool do_quant = false;
1398 int y, x;
1400 if ( !dst->create(src->width(), src->height(), 8, 256) )
1401 return false;
1403 const int tablesize = 997; // prime
1404 QRgbMap table[tablesize];
1405 int pix=0;
1406 QRgb amask = src->hasAlphaBuffer() ? 0xffffffff : 0x00ffffff;
1407 if ( src->hasAlphaBuffer() )
1408 dst->setAlphaBuffer(true);
1410 if ( palette ) {
1411 // Preload palette into table.
1413 p = palette;
1414 // Almost same code as pixel insertion below
1415 while ( palette_count-- > 0 ) {
1416 // Find in table...
1417 int hash = (*p & amask) % tablesize;
1418 for (;;) {
1419 if ( table[hash].used() ) {
1420 if ( table[hash].rgb == (*p & amask) ) {
1421 // Found previous insertion - use it
1422 break;
1423 } else {
1424 // Keep searching...
1425 if (++hash == tablesize) hash = 0;
1427 } else {
1428 // Cannot be in table
1429 Q_ASSERT ( pix != 256 ); // too many colors
1430 // Insert into table at this unused position
1431 dst->setColor( pix, (*p & amask) );
1432 table[hash].pix = pix++;
1433 table[hash].rgb = *p & amask;
1434 break;
1437 p++;
1441 if ( (conversion_flags & Qt::DitherMode_Mask) == Qt::PreferDither ) {
1442 do_quant = true;
1443 } else {
1444 for ( y=0; y<src->height(); y++ ) { // check if <= 256 colors
1445 p = (QRgb *)src->scanLine(y);
1446 b = dst->scanLine(y);
1447 x = src->width();
1448 while ( x-- ) {
1449 // Find in table...
1450 int hash = (*p & amask) % tablesize;
1451 for (;;) {
1452 if ( table[hash].used() ) {
1453 if ( table[hash].rgb == (*p & amask) ) {
1454 // Found previous insertion - use it
1455 break;
1456 } else {
1457 // Keep searching...
1458 if (++hash == tablesize) hash = 0;
1460 } else {
1461 // Cannot be in table
1462 if ( pix == 256 ) { // too many colors
1463 do_quant = true;
1464 // Break right out
1465 x = 0;
1466 y = src->height();
1467 } else {
1468 // Insert into table at this unused position
1469 dst->setColor( pix, (*p & amask) );
1470 table[hash].pix = pix++;
1471 table[hash].rgb = (*p & amask);
1473 break;
1476 *b++ = table[hash].pix; // May occur once incorrectly
1477 p++;
1481 int ncols = do_quant ? 256 : pix;
1483 static uint bm[16][16];
1484 static int init=0;
1485 if (!init) {
1486 // Build a Bayer Matrix for dithering
1488 init = 1;
1489 int n, i, j;
1491 bm[0][0]=0;
1493 for (n=1; n<16; n*=2) {
1494 for (i=0; i<n; i++) {
1495 for (j=0; j<n; j++) {
1496 bm[i][j]*=4;
1497 bm[i+n][j]=bm[i][j]+2;
1498 bm[i][j+n]=bm[i][j]+3;
1499 bm[i+n][j+n]=bm[i][j]+1;
1504 for (i=0; i<16; i++)
1505 for (j=0; j<16; j++)
1506 bm[i][j]<<=8;
1509 dst->setNumColors( ncols );
1511 if ( do_quant ) { // quantization needed
1513 #define MAX_R 5
1514 #define MAX_G 5
1515 #define MAX_B 5
1516 #define INDEXOF(r,g,b) (((r)*(MAX_G+1)+(g))*(MAX_B+1)+(b))
1518 int rc, gc, bc;
1520 for ( rc=0; rc<=MAX_R; rc++ ) // build 6x6x6 color cube
1521 for ( gc=0; gc<=MAX_G; gc++ )
1522 for ( bc=0; bc<=MAX_B; bc++ ) {
1523 dst->setColor( INDEXOF(rc,gc,bc),
1524 (amask&0xff000000)
1525 | qRgb( rc*255/MAX_R, gc*255/MAX_G, bc*255/MAX_B ) );
1528 int sw = src->width();
1530 int* line1[3];
1531 int* line2[3];
1532 int* pv[3];
1533 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::DiffuseDither ) {
1534 line1[0] = new int[src->width()];
1535 line2[0] = new int[src->width()];
1536 line1[1] = new int[src->width()];
1537 line2[1] = new int[src->width()];
1538 line1[2] = new int[src->width()];
1539 line2[2] = new int[src->width()];
1540 pv[0] = new int[sw];
1541 pv[1] = new int[sw];
1542 pv[2] = new int[sw];
1545 for ( y=0; y < src->height(); y++ ) {
1546 p = (QRgb *)src->scanLine(y);
1547 b = dst->scanLine(y);
1548 QRgb *end = p + sw;
1550 // perform quantization
1551 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::ThresholdDither ) {
1552 #define DITHER(p,m) ((uchar) ((p * (m) + 127) / 255))
1553 while ( p < end ) {
1554 rc = qRed( *p );
1555 gc = qGreen( *p );
1556 bc = qBlue( *p );
1558 *b++ =
1559 INDEXOF(
1560 DITHER(rc, MAX_R),
1561 DITHER(gc, MAX_G),
1562 DITHER(bc, MAX_B)
1565 p++;
1567 #undef DITHER
1568 } else if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::OrderedDither ) {
1569 #define DITHER(p,d,m) ((uchar) ((((256 * (m) + (m) + 1)) * (p) + (d)) / 65536 ))
1571 int x = 0;
1572 while ( p < end ) {
1573 uint d = bm[y&15][x&15];
1575 rc = qRed( *p );
1576 gc = qGreen( *p );
1577 bc = qBlue( *p );
1579 *b++ =
1580 INDEXOF(
1581 DITHER(rc, d, MAX_R),
1582 DITHER(gc, d, MAX_G),
1583 DITHER(bc, d, MAX_B)
1586 p++;
1587 x++;
1589 #undef DITHER
1590 } else { // Diffuse
1591 int endian = (QImage::systemByteOrder() == QImage::BigEndian);
1592 int x;
1593 uchar* q = src->scanLine(y);
1594 uchar* q2 = src->scanLine(y+1 < src->height() ? y + 1 : 0);
1595 for (int chan = 0; chan < 3; chan++) {
1596 b = dst->scanLine(y);
1597 int *l1 = (y&1) ? line2[chan] : line1[chan];
1598 int *l2 = (y&1) ? line1[chan] : line2[chan];
1599 if ( y == 0 ) {
1600 for (int i=0; i<sw; i++)
1601 l1[i] = q[i*4+chan+endian];
1603 if ( y+1 < src->height() ) {
1604 for (int i=0; i<sw; i++)
1605 l2[i] = q2[i*4+chan+endian];
1607 // Bi-directional error diffusion
1608 if ( y&1 ) {
1609 for (x=0; x<sw; x++) {
1610 int pix = qMax(qMin(5, (l1[x] * 5 + 128)/ 255), 0);
1611 int err = l1[x] - pix * 255 / 5;
1612 pv[chan][x] = pix;
1614 // Spread the error around...
1615 if ( x+1<sw ) {
1616 l1[x+1] += (err*7)>>4;
1617 l2[x+1] += err>>4;
1619 l2[x]+=(err*5)>>4;
1620 if (x>1)
1621 l2[x-1]+=(err*3)>>4;
1623 } else {
1624 for (x=sw; x-->0; ) {
1625 int pix = qMax(qMin(5, (l1[x] * 5 + 128)/ 255), 0);
1626 int err = l1[x] - pix * 255 / 5;
1627 pv[chan][x] = pix;
1629 // Spread the error around...
1630 if ( x > 0 ) {
1631 l1[x-1] += (err*7)>>4;
1632 l2[x-1] += err>>4;
1634 l2[x]+=(err*5)>>4;
1635 if (x+1 < sw)
1636 l2[x+1]+=(err*3)>>4;
1640 if (endian) {
1641 for (x=0; x<sw; x++) {
1642 *b++ = INDEXOF(pv[0][x],pv[1][x],pv[2][x]);
1644 } else {
1645 for (x=0; x<sw; x++) {
1646 *b++ = INDEXOF(pv[2][x],pv[1][x],pv[0][x]);
1652 #ifndef QT_NO_IMAGE_DITHER_TO_1
1653 if ( src->hasAlphaBuffer() ) {
1654 const int trans = 216;
1655 dst->setColor(trans, 0x00000000); // transparent
1656 QImage mask = src->createAlphaMask(conversion_flags);
1657 uchar* m;
1658 for ( y=0; y < src->height(); y++ ) {
1659 uchar bit = 0x80;
1660 m = mask.scanLine(y);
1661 b = dst->scanLine(y);
1662 int w = src->width();
1663 for ( x = 0; x<w; x++ ) {
1664 if ( !(*m&bit) )
1665 b[x] = trans;
1666 if (!(bit >>= 1)) {
1667 bit = 0x80;
1668 while ( x<w-1 && *++m == 0xff ) // skip chunks
1669 x+=8;
1674 #endif
1676 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::DiffuseDither ) {
1677 delete [] line1[0];
1678 delete [] line2[0];
1679 delete [] line1[1];
1680 delete [] line2[1];
1681 delete [] line1[2];
1682 delete [] line2[2];
1683 delete [] pv[0];
1684 delete [] pv[1];
1685 delete [] pv[2];
1688 #undef MAX_R
1689 #undef MAX_G
1690 #undef MAX_B
1691 #undef INDEXOF
1695 return true;
1699 static bool convert_8_to_32( const QImage *src, QImage *dst )
1701 if ( !dst->create(src->width(), src->height(), 32) )
1702 return false; // create failed
1703 dst->setAlphaBuffer( src->hasAlphaBuffer() );
1704 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
1705 register uint *p = (uint *)dst->scanLine(y);
1706 uchar *b = src->scanLine(y);
1707 uint *end = p + dst->width();
1708 while ( p < end )
1709 *p++ = src->color(*b++);
1711 return true;
1715 static bool convert_1_to_32( const QImage *src, QImage *dst )
1717 if ( !dst->create(src->width(), src->height(), 32) )
1718 return false; // could not create
1719 dst->setAlphaBuffer( src->hasAlphaBuffer() );
1720 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
1721 register uint *p = (uint *)dst->scanLine(y);
1722 uchar *b = src->scanLine(y);
1723 int x;
1724 if ( src->bitOrder() == QImage::BigEndian ) {
1725 for ( x=0; x<dst->width(); x++ ) {
1726 *p++ = src->color( (*b >> (7 - (x & 7))) & 1 );
1727 if ( (x & 7) == 7 )
1728 b++;
1730 } else {
1731 for ( x=0; x<dst->width(); x++ ) {
1732 *p++ = src->color( (*b >> (x & 7)) & 1 );
1733 if ( (x & 7) == 7 )
1734 b++;
1738 return true;
1740 #endif // QT_NO_IMAGE_TRUECOLOR
1742 static bool convert_1_to_8( const QImage *src, QImage *dst )
1744 if ( !dst->create(src->width(), src->height(), 8, 2) )
1745 return false; // something failed
1746 dst->setAlphaBuffer( src->hasAlphaBuffer() );
1747 if (src->numColors() >= 2) {
1748 dst->setColor( 0, src->color(0) ); // copy color table
1749 dst->setColor( 1, src->color(1) );
1750 } else {
1751 // Unlikely, but they do exist
1752 if (src->numColors() >= 1)
1753 dst->setColor( 0, src->color(0) );
1754 else
1755 dst->setColor( 0, 0xffffffff );
1756 dst->setColor( 1, 0xff000000 );
1758 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
1759 register uchar *p = dst->scanLine(y);
1760 uchar *b = src->scanLine(y);
1761 int x;
1762 if ( src->bitOrder() == QImage::BigEndian ) {
1763 for ( x=0; x<dst->width(); x++ ) {
1764 *p++ = (*b >> (7 - (x & 7))) & 1;
1765 if ( (x & 7) == 7 )
1766 b++;
1768 } else {
1769 for ( x=0; x<dst->width(); x++ ) {
1770 *p++ = (*b >> (x & 7)) & 1;
1771 if ( (x & 7) == 7 )
1772 b++;
1776 return true;
1779 #ifndef QT_NO_IMAGE_DITHER_TO_1
1781 // dither_to_1: Uses selected dithering algorithm.
1784 static bool dither_to_1( const QImage *src, QImage *dst,
1785 int conversion_flags, bool fromalpha )
1787 if ( !dst->create(src->width(), src->height(), 1, 2, QImage::BigEndian) )
1788 return false; // something failed
1790 enum { Threshold, Ordered, Diffuse } dithermode;
1792 if ( fromalpha ) {
1793 if ( ( conversion_flags & Qt::AlphaDither_Mask ) == Qt::DiffuseAlphaDither )
1794 dithermode = Diffuse;
1795 else if ( ( conversion_flags & Qt::AlphaDither_Mask ) == Qt::OrderedAlphaDither )
1796 dithermode = Ordered;
1797 else
1798 dithermode = Threshold;
1799 } else {
1800 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::ThresholdDither )
1801 dithermode = Threshold;
1802 else if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::OrderedDither )
1803 dithermode = Ordered;
1804 else
1805 dithermode = Diffuse;
1808 dst->setColor( 0, qRgb(255, 255, 255) );
1809 dst->setColor( 1, qRgb( 0, 0, 0) );
1810 int w = src->width();
1811 int h = src->height();
1812 int d = src->depth();
1813 uchar gray[256]; // gray map for 8 bit images
1814 bool use_gray = d == 8;
1815 if ( use_gray ) { // make gray map
1816 if ( fromalpha ) {
1817 // Alpha 0x00 -> 0 pixels (white)
1818 // Alpha 0xFF -> 1 pixels (black)
1819 for ( int i=0; i<src->numColors(); i++ )
1820 gray[i] = (255 - (src->color(i) >> 24));
1821 } else {
1822 // Pixel 0x00 -> 1 pixels (black)
1823 // Pixel 0xFF -> 0 pixels (white)
1824 for ( int i=0; i<src->numColors(); i++ )
1825 gray[i] = qGray( src->color(i) & 0x00ffffff );
1829 switch ( dithermode ) {
1830 case Diffuse: {
1831 int *line1 = new int[w];
1832 int *line2 = new int[w];
1833 int bmwidth = (w+7)/8;
1834 if ( !(line1 && line2) )
1835 return false;
1836 register uchar *p;
1837 uchar *end;
1838 int *b1, *b2;
1839 int wbytes = w * (d/8);
1840 p = src->bits();
1841 end = p + wbytes;
1842 b2 = line2;
1843 if ( use_gray ) { // 8 bit image
1844 while ( p < end )
1845 *b2++ = gray[*p++];
1846 #ifndef QT_NO_IMAGE_TRUECOLOR
1847 } else { // 32 bit image
1848 if ( fromalpha ) {
1849 while ( p < end ) {
1850 *b2++ = 255 - (*(uint*)p >> 24);
1851 p += 4;
1853 } else {
1854 while ( p < end ) {
1855 *b2++ = qGray(*(uint*)p);
1856 p += 4;
1859 #endif
1861 int x, y;
1862 for ( y=0; y<h; y++ ) { // for each scan line...
1863 int *tmp = line1; line1 = line2; line2 = tmp;
1864 bool not_last_line = y < h - 1;
1865 if ( not_last_line ) { // calc. grayvals for next line
1866 p = src->scanLine(y+1);
1867 end = p + wbytes;
1868 b2 = line2;
1869 if ( use_gray ) { // 8 bit image
1870 while ( p < end )
1871 *b2++ = gray[*p++];
1872 #ifndef QT_NO_IMAGE_TRUECOLOR
1873 } else { // 24 bit image
1874 if ( fromalpha ) {
1875 while ( p < end ) {
1876 *b2++ = 255 - (*(uint*)p >> 24);
1877 p += 4;
1879 } else {
1880 while ( p < end ) {
1881 *b2++ = qGray(*(uint*)p);
1882 p += 4;
1885 #endif
1889 int err;
1890 p = dst->scanLine( y );
1891 memset( p, 0, bmwidth );
1892 b1 = line1;
1893 b2 = line2;
1894 int bit = 7;
1895 for ( x=1; x<=w; x++ ) {
1896 if ( *b1 < 128 ) { // black pixel
1897 err = *b1++;
1898 *p |= 1 << bit;
1899 } else { // white pixel
1900 err = *b1++ - 255;
1902 if ( bit == 0 ) {
1903 p++;
1904 bit = 7;
1905 } else {
1906 bit--;
1908 if ( x < w )
1909 *b1 += (err*7)>>4; // spread error to right pixel
1910 if ( not_last_line ) {
1911 b2[0] += (err*5)>>4; // pixel below
1912 if ( x > 1 )
1913 b2[-1] += (err*3)>>4; // pixel below left
1914 if ( x < w )
1915 b2[1] += err>>4; // pixel below right
1917 b2++;
1920 delete [] line1;
1921 delete [] line2;
1922 } break;
1923 case Ordered: {
1924 static uint bm[16][16];
1925 static int init=0;
1926 if (!init) {
1927 // Build a Bayer Matrix for dithering
1929 init = 1;
1930 int n, i, j;
1932 bm[0][0]=0;
1934 for (n=1; n<16; n*=2) {
1935 for (i=0; i<n; i++) {
1936 for (j=0; j<n; j++) {
1937 bm[i][j]*=4;
1938 bm[i+n][j]=bm[i][j]+2;
1939 bm[i][j+n]=bm[i][j]+3;
1940 bm[i+n][j+n]=bm[i][j]+1;
1945 // Force black to black
1946 bm[0][0]=1;
1949 dst->fill( 0 );
1950 uchar** mline = dst->jumpTable();
1951 #ifndef QT_NO_IMAGE_TRUECOLOR
1952 if ( d == 32 ) {
1953 uint** line = (uint**)src->jumpTable();
1954 for ( int i=0; i<h; i++ ) {
1955 uint *p = line[i];
1956 uint *end = p + w;
1957 uchar *m = mline[i];
1958 int bit = 7;
1959 int j = 0;
1960 if ( fromalpha ) {
1961 while ( p < end ) {
1962 if ( (*p++ >> 24) >= bm[j++&15][i&15] )
1963 *m |= 1 << bit;
1964 if ( bit == 0 ) {
1965 m++;
1966 bit = 7;
1967 } else {
1968 bit--;
1971 } else {
1972 while ( p < end ) {
1973 if ( (uint)qGray(*p++) < bm[j++&15][i&15] )
1974 *m |= 1 << bit;
1975 if ( bit == 0 ) {
1976 m++;
1977 bit = 7;
1978 } else {
1979 bit--;
1984 } else
1985 #endif // QT_NO_IMAGE_TRUECOLOR
1986 /* ( d == 8 ) */ {
1987 uchar** line = src->jumpTable();
1988 for ( int i=0; i<h; i++ ) {
1989 uchar *p = line[i];
1990 uchar *end = p + w;
1991 uchar *m = mline[i];
1992 int bit = 7;
1993 int j = 0;
1994 while ( p < end ) {
1995 if ( (uint)gray[*p++] < bm[j++&15][i&15] )
1996 *m |= 1 << bit;
1997 if ( bit == 0 ) {
1998 m++;
1999 bit = 7;
2000 } else {
2001 bit--;
2006 } break;
2007 default: { // Threshold:
2008 dst->fill( 0 );
2009 uchar** mline = dst->jumpTable();
2010 #ifndef QT_NO_IMAGE_TRUECOLOR
2011 if ( d == 32 ) {
2012 uint** line = (uint**)src->jumpTable();
2013 for ( int i=0; i<h; i++ ) {
2014 uint *p = line[i];
2015 uint *end = p + w;
2016 uchar *m = mline[i];
2017 int bit = 7;
2018 if ( fromalpha ) {
2019 while ( p < end ) {
2020 if ( (*p++ >> 24) >= 128 )
2021 *m |= 1 << bit; // Set mask "on"
2022 if ( bit == 0 ) {
2023 m++;
2024 bit = 7;
2025 } else {
2026 bit--;
2029 } else {
2030 while ( p < end ) {
2031 if ( qGray(*p++) < 128 )
2032 *m |= 1 << bit; // Set pixel "black"
2033 if ( bit == 0 ) {
2034 m++;
2035 bit = 7;
2036 } else {
2037 bit--;
2042 } else
2043 #endif //QT_NO_IMAGE_TRUECOLOR
2044 if ( d == 8 ) {
2045 uchar** line = src->jumpTable();
2046 for ( int i=0; i<h; i++ ) {
2047 uchar *p = line[i];
2048 uchar *end = p + w;
2049 uchar *m = mline[i];
2050 int bit = 7;
2051 while ( p < end ) {
2052 if ( gray[*p++] < 128 )
2053 *m |= 1 << bit; // Set mask "on"/ pixel "black"
2054 if ( bit == 0 ) {
2055 m++;
2056 bit = 7;
2057 } else {
2058 bit--;
2065 return true;
2067 #endif
2069 #ifndef QT_NO_IMAGE_16_BIT
2070 //###### Endianness issues!
2071 static inline bool is16BitGray( ushort c )
2073 int r=(c & 0xf800) >> 11;
2074 int g=(c & 0x07e0) >> 6; //green/2
2075 int b=(c & 0x001f);
2076 return r == g && g == b;
2080 static bool convert_16_to_32( const QImage *src, QImage *dst )
2082 if ( !dst->create(src->width(), src->height(), 32) )
2083 return false; // create failed
2084 dst->setAlphaBuffer( src->hasAlphaBuffer() );
2085 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
2086 register uint *p = (uint *)dst->scanLine(y);
2087 ushort *s = (ushort*)src->scanLine(y);
2088 uint *end = p + dst->width();
2089 while ( p < end )
2090 *p++ = qt_conv16ToRgb( *s++ );
2092 return true;
2096 static bool convert_32_to_16( const QImage *src, QImage *dst )
2098 if ( !dst->create(src->width(), src->height(), 16) )
2099 return false; // create failed
2100 dst->setAlphaBuffer( src->hasAlphaBuffer() );
2101 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
2102 register ushort *p = (ushort *)dst->scanLine(y);
2103 uint *s = (uint*)src->scanLine(y);
2104 ushort *end = p + dst->width();
2105 while ( p < end )
2106 *p++ = qt_convRgbTo16( *s++ );
2108 return true;
2112 #endif
2115 Converts the depth (bpp) of the image to \a depth and returns the
2116 converted image. The original image is not changed.
2118 The \a depth argument must be 1, 8, 16 (Qt/Embedded only) or 32.
2120 Returns \c *this if \a depth is equal to the image depth, or a
2121 \link isNull() null\endlink image if this image cannot be
2122 converted.
2124 If the image needs to be modified to fit in a lower-resolution
2125 result (e.g. converting from 32-bit to 8-bit), use the \a
2126 conversion_flags to specify how you'd prefer this to happen.
2128 \sa Qt::ImageConversionFlags depth() isNull()
2131 QImage QImage::convertDepth( int depth, int conversion_flags ) const
2133 QImage image;
2134 if ( data->d == depth )
2135 image = *this; // no conversion
2136 #ifndef QT_NO_IMAGE_DITHER_TO_1
2137 else if ( (data->d == 8 || data->d == 32) && depth == 1 ) // dither
2138 dither_to_1( this, &image, conversion_flags, false );
2139 #endif
2140 #ifndef QT_NO_IMAGE_TRUECOLOR
2141 else if ( data->d == 32 && depth == 8 ) // 32 -> 8
2142 convert_32_to_8( this, &image, conversion_flags );
2143 else if ( data->d == 8 && depth == 32 ) // 8 -> 32
2144 convert_8_to_32( this, &image );
2145 #endif
2146 else if ( data->d == 1 && depth == 8 ) // 1 -> 8
2147 convert_1_to_8( this, &image );
2148 #ifndef QT_NO_IMAGE_TRUECOLOR
2149 else if ( data->d == 1 && depth == 32 ) // 1 -> 32
2150 convert_1_to_32( this, &image );
2151 #endif
2152 #ifndef QT_NO_IMAGE_16_BIT
2153 else if ( data->d == 16 && depth != 16 ) {
2154 QImage tmp;
2155 convert_16_to_32( this, &tmp );
2156 image = tmp.convertDepth( depth, conversion_flags );
2157 } else if ( data->d != 16 && depth == 16 ) {
2158 QImage tmp = convertDepth( 32, conversion_flags );
2159 convert_32_to_16( &tmp, &image );
2161 #endif
2162 else {
2163 #if defined(QT_CHECK_RANGE)
2164 if ( isNull() )
2165 qWarning( "QImage::convertDepth: Image is a null image" );
2166 else
2167 qWarning( "QImage::convertDepth: Depth %d not supported", depth );
2168 #endif
2170 return image;
2174 \overload
2177 QImage QImage::convertDepth( int depth ) const
2179 return convertDepth( depth, 0 );
2183 Returns TRUE if ( \a x, \a y ) is a valid coordinate in the image;
2184 otherwise returns FALSE.
2186 \sa width() height() pixelIndex()
2189 bool QImage::valid( int x, int y ) const
2191 return x >= 0 && x < width()
2192 && y >= 0 && y < height();
2196 Returns the pixel index at the given coordinates.
2198 If (\a x, \a y) is not \link valid() valid\endlink, or if the
2199 image is not a paletted image (depth() \> 8), the results are
2200 undefined.
2202 \sa valid() depth()
2205 int QImage::pixelIndex( int x, int y ) const
2207 #if defined(QT_CHECK_RANGE)
2208 if ( x < 0 || x >= width() ) {
2209 qWarning( "QImage::pixel: x=%d out of range", x );
2210 return -12345;
2212 #endif
2213 uchar * s = scanLine( y );
2214 switch( depth() ) {
2215 case 1:
2216 if ( bitOrder() == QImage::LittleEndian )
2217 return (*(s + (x >> 3)) >> (x & 7)) & 1;
2218 else
2219 return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
2220 case 8:
2221 return (int)s[x];
2222 #ifndef QT_NO_IMAGE_TRUECOLOR
2223 #ifndef QT_NO_IMAGE_16_BIT
2224 case 16:
2225 #endif
2226 case 32:
2227 #if defined(QT_CHECK_RANGE)
2228 qWarning( "QImage::pixelIndex: Not applicable for %d-bpp images "
2229 "(no palette)", depth() );
2230 #endif
2231 return 0;
2232 #endif //QT_NO_IMAGE_TRUECOLOR
2234 return 0;
2239 Returns the color of the pixel at the coordinates (\a x, \a y).
2241 If (\a x, \a y) is not \link valid() on the image\endlink, the
2242 results are undefined.
2244 \sa setPixel() qRed() qGreen() qBlue() valid()
2247 QRgb QImage::pixel( int x, int y ) const
2249 #if defined(QT_CHECK_RANGE)
2250 if ( x < 0 || x >= width() ) {
2251 qWarning( "QImage::pixel: x=%d out of range", x );
2252 return 12345;
2254 #endif
2255 uchar * s = scanLine( y );
2256 switch( depth() ) {
2257 case 1:
2258 if ( bitOrder() == QImage::LittleEndian )
2259 return color( (*(s + (x >> 3)) >> (x & 7)) & 1 );
2260 else
2261 return color( (*(s + (x >> 3)) >> (7- (x & 7))) & 1 );
2262 case 8:
2263 return color( (int)s[x] );
2264 #ifndef QT_NO_IMAGE_16_BIT
2265 case 16:
2266 return qt_conv16ToRgb(((ushort*)s)[x]);
2267 #endif
2268 #ifndef QT_NO_IMAGE_TRUECOLOR
2269 case 32:
2270 return ((QRgb*)s)[x];
2271 #endif
2272 default:
2273 return 100367;
2279 Sets the pixel index or color at the coordinates (\a x, \a y) to
2280 \a index_or_rgb.
2282 If (\a x, \a y) is not \link valid() valid\endlink, the result is
2283 undefined.
2285 If the image is a paletted image (depth() \<= 8) and \a
2286 index_or_rgb \>= numColors(), the result is undefined.
2288 \sa pixelIndex() pixel() qRgb() qRgba() valid()
2291 void QImage::setPixel( int x, int y, uint index_or_rgb )
2293 if ( x < 0 || x >= width() ) {
2294 #if defined(QT_CHECK_RANGE)
2295 qWarning( "QImage::setPixel: x=%d out of range", x );
2296 #endif
2297 return;
2299 if ( depth() == 1 ) {
2300 uchar * s = scanLine( y );
2301 if ( index_or_rgb > 1) {
2302 #if defined(QT_CHECK_RANGE)
2303 qWarning( "QImage::setPixel: index=%d out of range",
2304 index_or_rgb );
2305 #endif
2306 } else if ( bitOrder() == QImage::LittleEndian ) {
2307 if (index_or_rgb==0)
2308 *(s + (x >> 3)) &= ~(1 << (x & 7));
2309 else
2310 *(s + (x >> 3)) |= (1 << (x & 7));
2311 } else {
2312 if (index_or_rgb==0)
2313 *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
2314 else
2315 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
2317 } else if ( depth() == 8 ) {
2318 if (index_or_rgb > (uint)numColors()) {
2319 #if defined(QT_CHECK_RANGE)
2320 qWarning( "QImage::setPixel: index=%d out of range",
2321 index_or_rgb );
2322 #endif
2323 return;
2325 uchar * s = scanLine( y );
2326 s[x] = index_or_rgb;
2327 #ifndef QT_NO_IMAGE_16_BIT
2328 } else if ( depth() == 16 ) {
2329 ushort * s = (ushort*)scanLine( y );
2330 s[x] = qt_convRgbTo16(index_or_rgb);
2331 #endif
2332 #ifndef QT_NO_IMAGE_TRUECOLOR
2333 } else if ( depth() == 32 ) {
2334 QRgb * s = (QRgb*)scanLine( y );
2335 s[x] = index_or_rgb;
2336 #endif
2342 Converts the bit order of the image to \a bitOrder and returns the
2343 converted image. The original image is not changed.
2345 Returns \c *this if the \a bitOrder is equal to the image bit
2346 order, or a \link isNull() null\endlink image if this image cannot
2347 be converted.
2349 \sa bitOrder() systemBitOrder() isNull()
2352 QImage QImage::convertBitOrder( Endian bitOrder ) const
2354 if ( isNull() || data->d != 1 || // invalid argument(s)
2355 !(bitOrder == BigEndian || bitOrder == LittleEndian) ) {
2356 QImage nullImage;
2357 return nullImage;
2359 if ( data->bitordr == bitOrder ) // nothing to do
2360 return copy();
2362 QImage image( data->w, data->h, 1, data->ncols, bitOrder );
2364 int bpl = (width() + 7) / 8;
2365 for ( int y = 0; y < data->h; y++ ) {
2366 register uchar *p = jumpTable()[y];
2367 uchar *end = p + bpl;
2368 uchar *b = image.jumpTable()[y];
2369 while ( p < end )
2370 *b++ = bitflip[*p++];
2372 memcpy( image.colorTable(), colorTable(), numColors()*sizeof(QRgb) );
2373 return image;
2376 // ### Candidate (renamed) for qcolor.h
2377 static
2378 bool isGray(QRgb c)
2380 return qRed(c) == qGreen(c)
2381 && qRed(c) == qBlue(c);
2385 Returns TRUE if all the colors in the image are shades of gray
2386 (i.e. their red, green and blue components are equal); otherwise
2387 returns FALSE.
2389 This function is slow for large 16-bit (Qt/Embedded only) and 32-bit images.
2391 \sa isGrayscale()
2393 bool QImage::allGray() const
2395 #ifndef QT_NO_IMAGE_TRUECOLOR
2396 if (depth()==32) {
2397 int p = width()*height();
2398 QRgb* b = (QRgb*)bits();
2399 while (p--)
2400 if (!isGray(*b++))
2401 return false;
2402 #ifndef QT_NO_IMAGE_16_BIT
2403 } else if (depth()==16) {
2404 int p = width()*height();
2405 ushort* b = (ushort*)bits();
2406 while (p--)
2407 if (!is16BitGray(*b++))
2408 return false;
2409 #endif
2410 } else
2411 #endif //QT_NO_IMAGE_TRUECOLOR
2413 if (!data->ctbl) return true;
2414 for (int i=0; i<numColors(); i++)
2415 if (!isGray(data->ctbl[i]))
2416 return false;
2418 return false;
2422 For 16-bit (Qt/Embedded only) and 32-bit images, this function is
2423 equivalent to allGray().
2425 For 8-bpp images, this function returns TRUE if color(i) is
2426 QRgb(i,i,i) for all indices of the color table; otherwise returns
2427 FALSE.
2429 \sa allGray() depth()
2431 bool QImage::isGrayscale() const
2433 switch (depth()) {
2434 #ifndef QT_NO_IMAGE_TRUECOLOR
2435 case 32:
2436 #ifndef QT_NO_IMAGE_16_BIT
2437 case 16:
2438 #endif
2439 return allGray();
2440 #endif //QT_NO_IMAGE_TRUECOLOR
2441 case 8: {
2442 for (int i=0; i<numColors(); i++)
2443 if (data->ctbl[i] != qRgb(i,i,i))
2444 return false;
2445 return true;
2448 return false;
2451 #ifndef QT_NO_IMAGE_SMOOTHSCALE
2452 static
2453 void pnmscale(const QImage& src, QImage& dst)
2455 QRgb* xelrow = 0;
2456 QRgb* tempxelrow = 0;
2457 register QRgb* xP;
2458 register QRgb* nxP;
2459 int rows, cols, rowsread, newrows, newcols;
2460 register int row, col, needtoreadrow;
2461 const uchar maxval = 255;
2462 double xscale, yscale;
2463 long sxscale, syscale;
2464 register long fracrowtofill, fracrowleft;
2465 long* as;
2466 long* rs;
2467 long* gs;
2468 long* bs;
2469 int rowswritten = 0;
2471 cols = src.width();
2472 rows = src.height();
2473 newcols = dst.width();
2474 newrows = dst.height();
2476 long SCALE;
2477 long HALFSCALE;
2479 if (cols > 4096)
2481 SCALE = 4096;
2482 HALFSCALE = 2048;
2484 else
2486 int fac = 4096;
2488 while (cols * fac > 4096)
2490 fac /= 2;
2493 SCALE = fac * cols;
2494 HALFSCALE = fac * cols / 2;
2497 xscale = (double) newcols / (double) cols;
2498 yscale = (double) newrows / (double) rows;
2500 sxscale = (long)(xscale * SCALE);
2501 syscale = (long)(yscale * SCALE);
2503 if ( newrows != rows ) /* shortcut Y scaling if possible */
2504 tempxelrow = new QRgb[cols];
2506 if ( src.hasAlphaBuffer() ) {
2507 dst.setAlphaBuffer(true);
2508 as = new long[cols];
2509 for ( col = 0; col < cols; ++col )
2510 as[col] = HALFSCALE;
2511 } else {
2512 as = 0;
2514 rs = new long[cols];
2515 gs = new long[cols];
2516 bs = new long[cols];
2517 rowsread = 0;
2518 fracrowleft = syscale;
2519 needtoreadrow = 1;
2520 for ( col = 0; col < cols; ++col )
2521 rs[col] = gs[col] = bs[col] = HALFSCALE;
2522 fracrowtofill = SCALE;
2524 for ( row = 0; row < newrows; ++row ) {
2525 /* First scale Y from xelrow into tempxelrow. */
2526 if ( newrows == rows ) {
2527 /* shortcut Y scaling if possible */
2528 tempxelrow = xelrow = (QRgb*)src.scanLine(rowsread++);
2529 } else {
2530 while ( fracrowleft < fracrowtofill ) {
2531 if ( needtoreadrow && rowsread < rows )
2532 xelrow = (QRgb*)src.scanLine(rowsread++);
2533 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) {
2534 if (as) {
2535 as[col] += fracrowleft * qAlpha( *xP );
2536 rs[col] += fracrowleft * qRed( *xP ) * qAlpha( *xP ) / 255;
2537 gs[col] += fracrowleft * qGreen( *xP ) * qAlpha( *xP ) / 255;
2538 bs[col] += fracrowleft * qBlue( *xP ) * qAlpha( *xP ) / 255;
2539 } else {
2540 rs[col] += fracrowleft * qRed( *xP );
2541 gs[col] += fracrowleft * qGreen( *xP );
2542 bs[col] += fracrowleft * qBlue( *xP );
2545 fracrowtofill -= fracrowleft;
2546 fracrowleft = syscale;
2547 needtoreadrow = 1;
2549 /* Now fracrowleft is >= fracrowtofill, so we can produce a row. */
2550 if ( needtoreadrow && rowsread < rows ) {
2551 xelrow = (QRgb*)src.scanLine(rowsread++);
2552 needtoreadrow = 0;
2554 register long a=0;
2555 for ( col = 0, xP = xelrow, nxP = tempxelrow;
2556 col < cols; ++col, ++xP, ++nxP )
2558 register long r, g, b;
2560 if ( as ) {
2561 r = rs[col] + fracrowtofill * qRed( *xP ) * qAlpha( *xP ) / 255;
2562 g = gs[col] + fracrowtofill * qGreen( *xP ) * qAlpha( *xP ) / 255;
2563 b = bs[col] + fracrowtofill * qBlue( *xP ) * qAlpha( *xP ) / 255;
2564 a = as[col] + fracrowtofill * qAlpha( *xP );
2565 if ( a ) {
2566 r = r * 255 / a * SCALE;
2567 g = g * 255 / a * SCALE;
2568 b = b * 255 / a * SCALE;
2570 } else {
2571 r = rs[col] + fracrowtofill * qRed( *xP );
2572 g = gs[col] + fracrowtofill * qGreen( *xP );
2573 b = bs[col] + fracrowtofill * qBlue( *xP );
2575 r /= SCALE;
2576 if ( r > maxval ) r = maxval;
2577 g /= SCALE;
2578 if ( g > maxval ) g = maxval;
2579 b /= SCALE;
2580 if ( b > maxval ) b = maxval;
2581 if ( as ) {
2582 a /= SCALE;
2583 if ( a > maxval ) a = maxval;
2584 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
2585 as[col] = HALFSCALE;
2586 } else {
2587 *nxP = qRgb( (int)r, (int)g, (int)b );
2589 rs[col] = gs[col] = bs[col] = HALFSCALE;
2591 fracrowleft -= fracrowtofill;
2592 if ( fracrowleft == 0 ) {
2593 fracrowleft = syscale;
2594 needtoreadrow = 1;
2596 fracrowtofill = SCALE;
2599 /* Now scale X from tempxelrow into dst and write it out. */
2600 if ( newcols == cols ) {
2601 /* shortcut X scaling if possible */
2602 memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols*4);
2603 } else {
2604 register long a, r, g, b;
2605 register long fraccoltofill, fraccolleft = 0;
2606 register int needcol;
2608 nxP = (QRgb*)dst.scanLine(rowswritten++);
2609 fraccoltofill = SCALE;
2610 a = r = g = b = HALFSCALE;
2611 needcol = 0;
2612 for ( col = 0, xP = tempxelrow; col < cols; ++col, ++xP ) {
2613 fraccolleft = sxscale;
2614 while ( fraccolleft >= fraccoltofill ) {
2615 if ( needcol ) {
2616 ++nxP;
2617 a = r = g = b = HALFSCALE;
2619 if ( as ) {
2620 r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255;
2621 g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255;
2622 b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255;
2623 a += fraccoltofill * qAlpha( *xP );
2624 if ( a ) {
2625 r = r * 255 / a * SCALE;
2626 g = g * 255 / a * SCALE;
2627 b = b * 255 / a * SCALE;
2629 } else {
2630 r += fraccoltofill * qRed( *xP );
2631 g += fraccoltofill * qGreen( *xP );
2632 b += fraccoltofill * qBlue( *xP );
2634 r /= SCALE;
2635 if ( r > maxval ) r = maxval;
2636 g /= SCALE;
2637 if ( g > maxval ) g = maxval;
2638 b /= SCALE;
2639 if ( b > maxval ) b = maxval;
2640 if (as) {
2641 a /= SCALE;
2642 if ( a > maxval ) a = maxval;
2643 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
2644 } else {
2645 *nxP = qRgb( (int)r, (int)g, (int)b );
2647 fraccolleft -= fraccoltofill;
2648 fraccoltofill = SCALE;
2649 needcol = 1;
2651 if ( fraccolleft > 0 ) {
2652 if ( needcol ) {
2653 ++nxP;
2654 a = r = g = b = HALFSCALE;
2655 needcol = 0;
2657 if (as) {
2658 a += fraccolleft * qAlpha( *xP );
2659 r += fraccolleft * qRed( *xP ) * qAlpha( *xP ) / 255;
2660 g += fraccolleft * qGreen( *xP ) * qAlpha( *xP ) / 255;
2661 b += fraccolleft * qBlue( *xP ) * qAlpha( *xP ) / 255;
2662 } else {
2663 r += fraccolleft * qRed( *xP );
2664 g += fraccolleft * qGreen( *xP );
2665 b += fraccolleft * qBlue( *xP );
2667 fraccoltofill -= fraccolleft;
2670 if ( fraccoltofill > 0 ) {
2671 --xP;
2672 if (as) {
2673 a += fraccolleft * qAlpha( *xP );
2674 r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255;
2675 g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255;
2676 b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255;
2677 if ( a ) {
2678 r = r * 255 / a * SCALE;
2679 g = g * 255 / a * SCALE;
2680 b = b * 255 / a * SCALE;
2682 } else {
2683 r += fraccoltofill * qRed( *xP );
2684 g += fraccoltofill * qGreen( *xP );
2685 b += fraccoltofill * qBlue( *xP );
2688 if ( ! needcol ) {
2689 r /= SCALE;
2690 if ( r > maxval ) r = maxval;
2691 g /= SCALE;
2692 if ( g > maxval ) g = maxval;
2693 b /= SCALE;
2694 if ( b > maxval ) b = maxval;
2695 if (as) {
2696 a /= SCALE;
2697 if ( a > maxval ) a = maxval;
2698 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
2699 } else {
2700 *nxP = qRgb( (int)r, (int)g, (int)b );
2706 if ( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 1 day
2707 delete [] tempxelrow;
2708 if ( as ) // Avoid purify complaint
2709 delete [] as;
2710 if ( rs ) // Robust, rs might be 0 one day
2711 delete [] rs;
2712 if ( gs ) // Robust, gs might be 0 one day
2713 delete [] gs;
2714 if ( bs ) // Robust, bs might be 0 one day
2715 delete [] bs;
2717 #endif
2720 \enum QImage::ScaleMode
2722 The functions scale() and smoothScale() use different modes for
2723 scaling the image. The purpose of these modes is to retain the
2724 ratio of the image if this is required.
2726 \img scaling.png
2728 \value ScaleFree The image is scaled freely: the resulting image
2729 fits exactly into the specified size; the ratio will not
2730 necessarily be preserved.
2731 \value ScaleMin The ratio of the image is preserved and the
2732 resulting image is guaranteed to fit into the specified size
2733 (it is as large as possible within these constraints) - the
2734 image might be smaller than the requested size.
2735 \value ScaleMax The ratio of the image is preserved and the
2736 resulting image fills the whole specified rectangle (it is as
2737 small as possible within these constraints) - the image might
2738 be larger than the requested size.
2741 #ifndef QT_NO_IMAGE_SMOOTHSCALE
2743 Returns a smoothly scaled copy of the image. The returned image
2744 has a size of width \a w by height \a h pixels if \a mode is \c
2745 ScaleFree. The modes \c ScaleMin and \c ScaleMax may be used to
2746 preserve the ratio of the image: if \a mode is \c ScaleMin, the
2747 returned image is guaranteed to fit into the rectangle specified
2748 by \a w and \a h (it is as large as possible within the
2749 constraints); if \a mode is \c ScaleMax, the returned image fits
2750 at least into the specified rectangle (it is a small as possible
2751 within the constraints).
2753 For 32-bpp images and 1-bpp/8-bpp color images the result will be
2754 32-bpp, whereas \link allGray() all-gray \endlink images
2755 (including black-and-white 1-bpp) will produce 8-bit \link
2756 isGrayscale() grayscale \endlink images with the palette spanning
2757 256 grays from black to white.
2759 This function uses code based on pnmscale.c by Jef Poskanzer.
2761 pnmscale.c - read a portable anymap and scale it
2763 \legalese
2765 Copyright (C) 1989, 1991 by Jef Poskanzer.
2767 Permission to use, copy, modify, and distribute this software and
2768 its documentation for any purpose and without fee is hereby
2769 granted, provided that the above copyright notice appear in all
2770 copies and that both that copyright notice and this permission
2771 notice appear in supporting documentation. This software is
2772 provided "as is" without express or implied warranty.
2774 \sa scale() mirror()
2776 QImage QImage::smoothScale( int w, int h, ScaleMode mode ) const
2778 return smoothScale( QSize( w, h ), mode );
2780 #endif
2782 #ifndef QT_NO_IMAGE_SMOOTHSCALE
2784 \overload
2786 The requested size of the image is \a s.
2788 QImage QImage::smoothScale( const QSize& s, ScaleMode mode ) const
2790 if ( isNull() ) {
2791 #if defined(QT_CHECK_RANGE)
2792 qWarning( "QImage::smoothScale: Image is a null image" );
2793 #endif
2794 return copy();
2797 QSize newSize = size();
2798 newSize.scale( s, (QSize::ScaleMode)mode ); // ### remove cast in Qt 4.0
2799 if ( newSize == size() )
2800 return copy();
2802 if ( depth() == 32 ) {
2803 QImage img( newSize, 32 );
2804 // 32-bpp to 32-bpp
2805 pnmscale( *this, img );
2806 return img;
2807 } else if ( depth() != 16 && allGray() && !hasAlphaBuffer() ) {
2808 // Inefficient
2809 return convertDepth(32).smoothScale(newSize, mode).convertDepth(8);
2810 } else {
2811 // Inefficient
2812 return convertDepth(32).smoothScale(newSize, mode);
2815 #endif
2818 Returns a copy of the image scaled to a rectangle of width \a w
2819 and height \a h according to the ScaleMode \a mode.
2821 \list
2822 \i If \a mode is \c ScaleFree, the image is scaled to (\a w,
2823 \a h).
2824 \i If \a mode is \c ScaleMin, the image is scaled to a rectangle
2825 as large as possible inside (\a w, \a h), preserving the aspect
2826 ratio.
2827 \i If \a mode is \c ScaleMax, the image is scaled to a rectangle
2828 as small as possible outside (\a w, \a h), preserving the aspect
2829 ratio.
2830 \endlist
2832 If either the width \a w or the height \a h is 0 or negative, this
2833 function returns a \link isNull() null\endlink image.
2835 This function uses a simple, fast algorithm. If you need better
2836 quality, use smoothScale() instead.
2838 \sa scaleWidth() scaleHeight() smoothScale() xForm()
2840 #ifndef QT_NO_IMAGE_TRANSFORMATION
2841 QImage QImage::scale( int w, int h, ScaleMode mode ) const
2843 return scale( QSize( w, h ), mode );
2845 #endif
2848 \overload
2850 The requested size of the image is \a s.
2852 #ifndef QT_NO_IMAGE_TRANSFORMATION
2853 QImage QImage::scale( const QSize& s, ScaleMode mode ) const
2855 if ( isNull() ) {
2856 #if defined(QT_CHECK_RANGE)
2857 qWarning( "QImage::scale: Image is a null image" );
2858 #endif
2859 return copy();
2861 if ( s.isEmpty() )
2862 return QImage();
2864 QSize newSize = size();
2865 newSize.scale( s, (QSize::ScaleMode)mode ); // ### remove cast in Qt 4.0
2866 if ( newSize == size() )
2867 return copy();
2869 QImage img;
2870 QWMatrix wm;
2871 wm.scale( (double)newSize.width() / width(), (double)newSize.height() / height() );
2872 img = xForm( wm );
2873 // ### I should test and resize the image if it has not the right size
2874 // if ( img.width() != newSize.width() || img.height() != newSize.height() )
2875 // img.resize( newSize.width(), newSize.height() );
2876 return img;
2878 #endif
2881 Returns a scaled copy of the image. The returned image has a width
2882 of \a w pixels. This function automatically calculates the height
2883 of the image so that the ratio of the image is preserved.
2885 If \a w is 0 or negative a \link isNull() null\endlink image is
2886 returned.
2888 \sa scale() scaleHeight() smoothScale() xForm()
2890 #ifndef QT_NO_IMAGE_TRANSFORMATION
2891 QImage QImage::scaleWidth( int w ) const
2893 if ( isNull() ) {
2894 #if defined(QT_CHECK_RANGE)
2895 qWarning( "QImage::scaleWidth: Image is a null image" );
2896 #endif
2897 return copy();
2899 if ( w <= 0 )
2900 return QImage();
2902 QWMatrix wm;
2903 double factor = (double) w / width();
2904 wm.scale( factor, factor );
2905 return xForm( wm );
2907 #endif
2910 Returns a scaled copy of the image. The returned image has a
2911 height of \a h pixels. This function automatically calculates the
2912 width of the image so that the ratio of the image is preserved.
2914 If \a h is 0 or negative a \link isNull() null\endlink image is
2915 returned.
2917 \sa scale() scaleWidth() smoothScale() xForm()
2919 #ifndef QT_NO_IMAGE_TRANSFORMATION
2920 QImage QImage::scaleHeight( int h ) const
2922 if ( isNull() ) {
2923 #if defined(QT_CHECK_RANGE)
2924 qWarning( "QImage::scaleHeight: Image is a null image" );
2925 #endif
2926 return copy();
2928 if ( h <= 0 )
2929 return QImage();
2931 QWMatrix wm;
2932 double factor = (double) h / height();
2933 wm.scale( factor, factor );
2934 return xForm( wm );
2936 #endif
2940 Returns a copy of the image that is transformed using the
2941 transformation matrix, \a matrix.
2943 The transformation \a matrix is internally adjusted to compensate
2944 for unwanted translation, i.e. xForm() returns the smallest image
2945 that contains all the transformed points of the original image.
2947 \sa scale() QPixmap::xForm() QPixmap::trueMatrix() QWMatrix
2949 #ifndef QT_NO_IMAGE_TRANSFORMATION
2950 QImage QImage::xForm( const QWMatrix &matrix ) const
2952 // This function uses the same algorithm as (and steals quite some
2953 // code from) QPixmap::xForm().
2955 if ( isNull() )
2956 return copy();
2958 if ( depth() == 16 ) {
2959 // inefficient
2960 return convertDepth( 32 ).xForm( matrix );
2963 // source image data
2964 int ws = width();
2965 int hs = height();
2966 int sbpl = bytesPerLine();
2967 uchar *sptr = bits();
2969 // target image data
2970 int wd;
2971 int hd;
2973 int bpp = depth();
2975 // compute size of target image
2976 QWMatrix mat = QPixmap::trueMatrix( matrix, ws, hs );
2977 if ( mat.m12() == 0.0F && mat.m21() == 0.0F ) {
2978 if ( mat.m11() == 1.0F && mat.m22() == 1.0F ) // identity matrix
2979 return copy();
2980 hd = qRound( mat.m22() * hs );
2981 wd = qRound( mat.m11() * ws );
2982 hd = qAbs( hd );
2983 wd = qAbs( wd );
2984 } else { // rotation or shearing
2985 QPointArray a( QRect(0, 0, ws, hs) );
2986 a = mat.map( a );
2987 QRect r = a.boundingRect().normalize();
2988 wd = r.width();
2989 hd = r.height();
2992 bool invertible;
2993 mat = mat.invert( &invertible ); // invert matrix
2994 if ( hd == 0 || wd == 0 || !invertible ) // error, return null image
2995 return QImage();
2997 // create target image (some of the code is from QImage::copy())
2998 QImage dImage( wd, hd, depth(), numColors(), bitOrder() );
2999 memcpy( dImage.colorTable(), colorTable(), numColors()*sizeof(QRgb) );
3000 dImage.setAlphaBuffer( hasAlphaBuffer() );
3001 dImage.data->dpmx = dotsPerMeterX();
3002 dImage.data->dpmy = dotsPerMeterY();
3004 switch ( bpp ) {
3005 // initizialize the data
3006 case 1:
3007 memset( dImage.bits(), 0, dImage.numBytes() );
3008 break;
3009 case 8:
3010 if ( dImage.data->ncols < 256 ) {
3011 // colors are left in the color table, so pick that one as transparent
3012 dImage.setNumColors( dImage.data->ncols+1 );
3013 dImage.setColor( dImage.data->ncols-1, 0x00 );
3014 memset( dImage.bits(), dImage.data->ncols-1, dImage.numBytes() );
3015 } else {
3016 memset( dImage.bits(), 0, dImage.numBytes() );
3018 break;
3019 case 16:
3020 memset( dImage.bits(), 0xff, dImage.numBytes() );
3021 break;
3022 case 32:
3023 memset( dImage.bits(), 0x00, dImage.numBytes() );
3024 break;
3027 int type;
3028 if ( bitOrder() == BigEndian )
3029 type = QT_XFORM_TYPE_MSBFIRST;
3030 else
3031 type = QT_XFORM_TYPE_LSBFIRST;
3032 int dbpl = dImage.bytesPerLine();
3033 qt_xForm_helper( mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl,
3034 ws, hs );
3035 return dImage;
3037 #endif
3040 Builds and returns a 1-bpp mask from the alpha buffer in this
3041 image. Returns a \link isNull() null\endlink image if \link
3042 setAlphaBuffer() alpha buffer mode\endlink is disabled.
3044 See QPixmap::convertFromImage() for a description of the \a
3045 conversion_flags argument.
3047 The returned image has little-endian bit order, which you can
3048 convert to big-endianness using convertBitOrder().
3050 \sa createHeuristicMask() hasAlphaBuffer() setAlphaBuffer()
3052 #ifndef QT_NO_IMAGE_DITHER_TO_1
3053 QImage QImage::createAlphaMask( int conversion_flags ) const
3055 if ( conversion_flags == 1 ) {
3056 // Old code is passing "TRUE".
3057 conversion_flags = Qt::DiffuseAlphaDither;
3060 if ( isNull() || !hasAlphaBuffer() )
3061 return QImage();
3063 if ( depth() == 1 ) {
3064 // A monochrome pixmap, with alpha channels on those two colors.
3065 // Pretty unlikely, so use less efficient solution.
3066 return convertDepth(8, conversion_flags)
3067 .createAlphaMask( conversion_flags );
3070 QImage mask1;
3071 dither_to_1( this, &mask1, conversion_flags, true );
3072 return mask1;
3074 #endif
3076 #ifndef QT_NO_IMAGE_HEURISTIC_MASK
3078 Creates and returns a 1-bpp heuristic mask for this image. It
3079 works by selecting a color from one of the corners, then chipping
3080 away pixels of that color starting at all the edges.
3082 The four corners vote for which color is to be masked away. In
3083 case of a draw (this generally means that this function is not
3084 applicable to the image), the result is arbitrary.
3086 The returned image has little-endian bit order, which you can
3087 convert to big-endianness using convertBitOrder().
3089 If \a clipTight is TRUE the mask is just large enough to cover the
3090 pixels; otherwise, the mask is larger than the data pixels.
3092 This function disregards the \link hasAlphaBuffer() alpha buffer
3093 \endlink.
3095 \sa createAlphaMask()
3098 QImage QImage::createHeuristicMask( bool clipTight ) const
3100 if ( isNull() ) {
3101 QImage nullImage;
3102 return nullImage;
3104 if ( depth() != 32 ) {
3105 QImage img32 = convertDepth(32);
3106 return img32.createHeuristicMask(clipTight);
3109 #define PIX(x,y) (*((QRgb*)scanLine(y)+x) & 0x00ffffff)
3111 int w = width();
3112 int h = height();
3113 QImage m(w, h, 1, 2, QImage::LittleEndian);
3114 m.setColor( 0, 0xffffff );
3115 m.setColor( 1, 0 );
3116 m.fill( 0xff );
3118 QRgb background = PIX(0,0);
3119 if ( background != PIX(w-1,0) &&
3120 background != PIX(0,h-1) &&
3121 background != PIX(w-1,h-1) ) {
3122 background = PIX(w-1,0);
3123 if ( background != PIX(w-1,h-1) &&
3124 background != PIX(0,h-1) &&
3125 PIX(0,h-1) == PIX(w-1,h-1) ) {
3126 background = PIX(w-1,h-1);
3130 int x,y;
3131 bool done = false;
3132 uchar *ypp, *ypc, *ypn;
3133 while( !done ) {
3134 done = true;
3135 ypn = m.scanLine(0);
3136 ypc = 0;
3137 for ( y = 0; y < h; y++ ) {
3138 ypp = ypc;
3139 ypc = ypn;
3140 ypn = (y == h-1) ? 0 : m.scanLine(y+1);
3141 QRgb *p = (QRgb *)scanLine(y);
3142 for ( x = 0; x < w; x++ ) {
3143 // slowness here - it's possible to do six of these tests
3144 // together in one go. oh well.
3145 if ( ( x == 0 || y == 0 || x == w-1 || y == h-1 ||
3146 !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
3147 !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
3148 !(*(ypp + (x >> 3)) & (1 << (x & 7))) ||
3149 !(*(ypn + (x >> 3)) & (1 << (x & 7))) ) &&
3150 ( (*(ypc + (x >> 3)) & (1 << (x & 7))) ) &&
3151 ( (*p & 0x00ffffff) == background ) ) {
3152 done = true;
3153 *(ypc + (x >> 3)) &= ~(1 << (x & 7));
3155 p++;
3160 if ( !clipTight ) {
3161 ypn = m.scanLine(0);
3162 ypc = 0;
3163 for ( y = 0; y < h; y++ ) {
3164 ypp = ypc;
3165 ypc = ypn;
3166 ypn = (y == h-1) ? 0 : m.scanLine(y+1);
3167 QRgb *p = (QRgb *)scanLine(y);
3168 for ( x = 0; x < w; x++ ) {
3169 if ( (*p & 0x00ffffff) != background ) {
3170 if ( x > 0 )
3171 *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
3172 if ( x < w-1 )
3173 *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
3174 if ( y > 0 )
3175 *(ypp + (x >> 3)) |= (1 << (x & 7));
3176 if ( y < h-1 )
3177 *(ypn + (x >> 3)) |= (1 << (x & 7));
3179 p++;
3184 #undef PIX
3186 return m;
3188 #endif //QT_NO_IMAGE_HEURISTIC_MASK
3190 #ifndef QT_NO_IMAGE_MIRROR
3192 This code is contributed by Philipp Lang,
3193 GeneriCom Software Germany (www.generi.com)
3194 under the terms of the QPL, Version 1.0
3198 \overload
3200 Returns a mirror of the image, mirrored in the horizontal and/or
3201 the vertical direction depending on whether \a horizontal and \a
3202 vertical are set to TRUE or FALSE. The original image is not
3203 changed.
3205 \sa smoothScale()
3207 QImage QImage::mirror(bool horizontal, bool vertical) const
3209 int w = width();
3210 int h = height();
3211 if ( (w <= 1 && h <= 1) || (!horizontal && !vertical) )
3212 return copy();
3214 // Create result image, copy colormap
3215 QImage result(w, h, depth(), numColors(), bitOrder());
3216 memcpy(result.colorTable(), colorTable(), numColors()*sizeof(QRgb));
3217 result.setAlphaBuffer(hasAlphaBuffer());
3219 if (depth() == 1)
3220 w = (w+7)/8;
3221 int dxi = horizontal ? -1 : 1;
3222 int dxs = horizontal ? w-1 : 0;
3223 int dyi = vertical ? -1 : 1;
3224 int dy = vertical ? h-1: 0;
3226 // 1 bit, 8 bit
3227 if (depth() == 1 || depth() == 8) {
3228 for (int sy = 0; sy < h; sy++, dy += dyi) {
3229 Q_UINT8* ssl = (Q_UINT8*)(data->bits[sy]);
3230 Q_UINT8* dsl = (Q_UINT8*)(result.data->bits[dy]);
3231 int dx = dxs;
3232 for (int sx = 0; sx < w; sx++, dx += dxi)
3233 dsl[dx] = ssl[sx];
3236 #ifndef QT_NO_IMAGE_TRUECOLOR
3237 #ifndef QT_NO_IMAGE_16_BIT
3238 // 16 bit
3239 else if (depth() == 16) {
3240 for (int sy = 0; sy < h; sy++, dy += dyi) {
3241 Q_UINT16* ssl = (Q_UINT16*)(data->bits[sy]);
3242 Q_UINT16* dsl = (Q_UINT16*)(result.data->bits[dy]);
3243 int dx = dxs;
3244 for (int sx = 0; sx < w; sx++, dx += dxi)
3245 dsl[dx] = ssl[sx];
3248 #endif
3249 // 32 bit
3250 else if (depth() == 32) {
3251 for (int sy = 0; sy < h; sy++, dy += dyi) {
3252 quint32* ssl = (quint32*)(data->bits[sy]);
3253 quint32* dsl = (quint32*)(result.data->bits[dy]);
3254 int dx = dxs;
3255 for (int sx = 0; sx < w; sx++, dx += dxi)
3256 dsl[dx] = ssl[sx];
3259 #endif
3261 // special handling of 1 bit images for horizontal mirroring
3262 if (horizontal && depth() == 1) {
3263 int shift = width() % 8;
3264 for (int y = h-1; y >= 0; y--) {
3265 Q_UINT8* a0 = (Q_UINT8*)(result.data->bits[y]);
3266 // Swap bytes
3267 Q_UINT8* a = a0+dxs;
3268 while (a >= a0) {
3269 *a = bitflip[*a];
3270 a--;
3272 // Shift bits if unaligned
3273 if (shift != 0) {
3274 a = a0+dxs;
3275 Q_UINT8 c = 0;
3276 if (bitOrder() == QImage::LittleEndian) {
3277 while (a >= a0) {
3278 Q_UINT8 nc = *a << shift;
3279 *a = (*a >> (8-shift)) | c;
3280 --a;
3281 c = nc;
3283 } else {
3284 while (a >= a0) {
3285 Q_UINT8 nc = *a >> shift;
3286 *a = (*a << (8-shift)) | c;
3287 --a;
3288 c = nc;
3295 return result;
3299 Returns a QImage which is a vertically mirrored copy of this
3300 image. The original QImage is not changed.
3303 QImage QImage::mirror() const
3305 return mirror(false,true);
3307 #endif //QT_NO_IMAGE_MIRROR
3310 Returns a QImage in which the values of the red and blue
3311 components of all pixels have been swapped, effectively converting
3312 an RGB image to a BGR image. The original QImage is not changed.
3315 QImage QImage::swapRGB() const
3317 QImage res = copy();
3318 if ( !isNull() ) {
3319 #ifndef QT_NO_IMAGE_TRUECOLOR
3320 if ( depth() == 32 ) {
3321 for ( int i=0; i < height(); i++ ) {
3322 uint *p = (uint*)scanLine( i );
3323 uint *q = (uint*)res.scanLine( i );
3324 uint *end = p + width();
3325 while ( p < end ) {
3326 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) |
3327 (*p & 0xff00ff00);
3328 p++;
3329 q++;
3332 #ifndef QT_NO_IMAGE_16_BIT
3333 } else if ( depth() == 16 ) {
3334 qWarning( "QImage::swapRGB not implemented for 16bpp" );
3335 #endif
3336 } else
3337 #endif //QT_NO_IMAGE_TRUECOLOR
3339 uint* p = (uint*)colorTable();
3340 uint* q = (uint*)res.colorTable();
3341 if ( p && q ) {
3342 for ( int i=0; i < numColors(); i++ ) {
3343 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) |
3344 (*p & 0xff00ff00);
3345 p++;
3346 q++;
3351 return res;
3354 #ifndef QT_NO_IMAGEIO
3356 Returns a string that specifies the image format of the file \a
3357 fileName, or 0 if the file cannot be read or if the format is not
3358 recognized.
3360 The QImageIO documentation lists the guaranteed supported image
3361 formats, or use QImage::inputFormats() and QImage::outputFormats()
3362 to get lists that include the installed formats.
3364 \sa load() save()
3367 const char* QImage::imageFormat( const QString &fileName )
3369 return QImageIO::imageFormat( fileName );
3373 Returns a list of image formats that are supported for image
3374 input.
3376 \sa outputFormats() inputFormatList() QImageIO
3378 QStrList QImage::inputFormats()
3380 return QImageIO::inputFormats();
3382 #ifndef QT_NO_STRINGLIST
3384 Returns a list of image formats that are supported for image
3385 input.
3387 Note that if you want to iterate over the list, you should iterate
3388 over a copy, e.g.
3389 \code
3390 QStringList list = myImage.inputFormatList();
3391 QStringList::const_iterator it = list.begin();
3392 while( it != list.end() ) {
3393 myProcessing( *it );
3394 ++it;
3396 \endcode
3398 \sa outputFormatList() inputFormats() QImageIO
3400 QStringList QImage::inputFormatList()
3402 return QStringList::fromStrList(QImageIO::inputFormats());
3407 Returns a list of image formats that are supported for image
3408 output.
3410 Note that if you want to iterate over the list, you should iterate
3411 over a copy, e.g.
3412 \code
3413 QStringList list = myImage.outputFormatList();
3414 QStringList::const_iterator it = list.begin();
3415 while( it != list.end() ) {
3416 myProcessing( *it );
3417 ++it;
3419 \endcode
3421 \sa inputFormatList() outputFormats() QImageIO
3423 QStringList QImage::outputFormatList()
3425 return QStringList::fromStrList(QImageIO::outputFormats());
3427 #endif //QT_NO_STRINGLIST
3430 Returns a list of image formats that are supported for image
3431 output.
3433 \sa inputFormats() outputFormatList() QImageIO
3435 QStrList QImage::outputFormats()
3437 return QImageIO::outputFormats();
3442 Loads an image from the file \a fileName. Returns TRUE if the
3443 image was successfully loaded; otherwise returns FALSE.
3445 If \a format is specified, the loader attempts to read the image
3446 using the specified format. If \a format is not specified (which
3447 is the default), the loader reads a few bytes from the header to
3448 guess the file format.
3450 The QImageIO documentation lists the supported image formats and
3451 explains how to add extra formats.
3453 \sa loadFromData() save() imageFormat() QPixmap::load() QImageIO
3456 bool QImage::load( const QString &fileName, const char* format )
3458 QImageIO io( fileName, format );
3459 bool result = io.read();
3460 if ( result )
3461 operator=( io.image() );
3462 return result;
3466 Loads an image from the first \a len bytes of binary data in \a
3467 buf. Returns TRUE if the image was successfully loaded; otherwise
3468 returns FALSE.
3470 If \a format is specified, the loader attempts to read the image
3471 using the specified format. If \a format is not specified (which
3472 is the default), the loader reads a few bytes from the header to
3473 guess the file format.
3475 The QImageIO documentation lists the supported image formats and
3476 explains how to add extra formats.
3478 \sa load() save() imageFormat() QPixmap::loadFromData() QImageIO
3481 bool QImage::loadFromData( const uchar *buf, uint len, const char *format )
3483 QByteArray a;
3484 a.setRawData( (char *)buf, len );
3485 QBuffer b( a );
3486 b.open( IO_ReadOnly );
3487 QImageIO io( &b, format );
3488 bool result = io.read();
3489 b.close();
3490 a.resetRawData( (char *)buf, len );
3491 if ( result )
3492 operator=( io.image() );
3493 return result;
3497 \overload
3499 Loads an image from the QByteArray \a buf.
3501 bool QImage::loadFromData( QByteArray buf, const char *format )
3503 return loadFromData( (const uchar *)(buf.data()), buf.size(), format );
3507 Saves the image to the file \a fileName, using the image file
3508 format \a format and a quality factor of \a quality. \a quality
3509 must be in the range 0..100 or -1. Specify 0 to obtain small
3510 compressed files, 100 for large uncompressed files, and -1 (the
3511 default) to use the default settings.
3513 Returns TRUE if the image was successfully saved; otherwise
3514 returns FALSE.
3516 \sa load() loadFromData() imageFormat() QPixmap::save() QImageIO
3519 bool QImage::save( const QString &fileName, const char* format, int quality ) const
3521 if ( isNull() )
3522 return false; // nothing to save
3523 QImageIO io( fileName, format );
3524 return doImageIO( &io, quality );
3528 \overload
3530 This function writes a QImage to the QIODevice, \a device. This
3531 can be used, for example, to save an image directly into a
3532 QByteArray:
3533 \code
3534 QImage image;
3535 QByteArray ba;
3536 QBuffer buffer( ba );
3537 buffer.open( IO_WriteOnly );
3538 image.save( &buffer, "PNG" ); // writes image into ba in PNG format
3539 \endcode
3542 bool QImage::save( QIODevice* device, const char* format, int quality ) const
3544 if ( isNull() )
3545 return false; // nothing to save
3546 QImageIO io( device, format );
3547 return doImageIO( &io, quality );
3550 /* \internal
3553 bool QImage::doImageIO( QImageIO* io, int quality ) const
3555 if ( !io )
3556 return false;
3557 io->setImage( *this );
3558 #if defined(QT_CHECK_RANGE)
3559 if ( quality > 100 || quality < -1 )
3560 qWarning( "QPixmap::save: quality out of range [-1,100]" );
3561 #endif
3562 if ( quality >= 0 )
3563 io->setQuality( qMin(quality,100) );
3564 return io->write();
3566 #endif //QT_NO_IMAGEIO
3568 /*****************************************************************************
3569 QImage stream functions
3570 *****************************************************************************/
3571 #if !defined(QT_NO_DATASTREAM) && !defined(QT_NO_IMAGEIO)
3573 \relates QImage
3575 Writes the image \a image to the stream \a s as a PNG image, or as a
3576 BMP image if the stream's version is 1.
3578 Note that writing the stream to a file will not produce a valid image file.
3580 \sa QImage::save()
3581 \link datastreamformat.html Format of the QDataStream operators \endlink
3584 QDataStream &operator<<( QDataStream &s, const QImage &image )
3586 if ( s.version() >= 5 ) {
3587 if ( image.isNull() ) {
3588 s << (Q_INT32) 0; // null image marker
3589 return s;
3590 } else {
3591 s << (Q_INT32) 1;
3592 // continue ...
3595 QImageIO io;
3596 io.setIODevice( s.device() );
3597 if ( s.version() == 1 )
3598 io.setFormat( "BMP" );
3599 else
3600 io.setFormat( "PNG" );
3602 io.setImage( image );
3603 io.write();
3604 return s;
3608 \relates QImage
3610 Reads an image from the stream \a s and stores it in \a image.
3612 \sa QImage::load()
3613 \link datastreamformat.html Format of the QDataStream operators \endlink
3616 QDataStream &operator>>( QDataStream &s, QImage &image )
3618 if ( s.version() >= 5 ) {
3619 Q_INT32 nullMarker;
3620 s >> nullMarker;
3621 if ( !nullMarker ) {
3622 image = QImage(); // null image
3623 return s;
3626 QImageIO io( s.device(), 0 );
3627 if ( io.read() )
3628 image = io.image();
3629 return s;
3631 #endif
3633 /*****************************************************************************
3634 Standard image io handlers (defined below)
3635 *****************************************************************************/
3637 // standard image io handlers (defined below)
3638 #ifndef QT_NO_IMAGEIO_BMP
3639 static void read_bmp_image( QImageIO * );
3640 static void write_bmp_image( QImageIO * );
3641 #endif
3642 #ifndef QT_NO_IMAGEIO_PPM
3643 static void read_pbm_image( QImageIO * );
3644 static void write_pbm_image( QImageIO * );
3645 #endif
3646 #ifndef QT_NO_IMAGEIO_XBM
3647 static void read_xbm_image( QImageIO * );
3648 static void write_xbm_image( QImageIO * );
3649 #endif
3650 #ifndef QT_NO_IMAGEIO_XPM
3651 static void read_xpm_image( QImageIO * );
3652 static void write_xpm_image( QImageIO * );
3653 #endif
3655 #ifndef QT_NO_ASYNC_IMAGE_IO
3656 static void read_async_image( QImageIO * ); // Not in table of handlers
3657 #endif
3659 /*****************************************************************************
3660 Misc. utility functions
3661 *****************************************************************************/
3662 #if !defined(QT_NO_IMAGEIO_XPM) || !defined(QT_NO_IMAGEIO_XBM)
3663 static QString fbname( const QString &fileName ) // get file basename (sort of)
3665 QString s = fileName;
3666 if ( !s.isEmpty() ) {
3667 int i;
3668 if ( (i = s.findRev('/')) >= 0 )
3669 s = s.mid( i );
3670 if ( (i = s.findRev('\\')) >= 0 )
3671 s = s.mid( i );
3672 QRegExp r( QString::fromLatin1("[a-zA-Z][a-zA-Z0-9_]*") );
3673 int p = r.search( s );
3674 if ( p == -1 )
3675 s.truncate( 0 );
3676 else
3677 s = s.mid( p, r.matchedLength() );
3679 if ( s.isEmpty() )
3680 s = QString::fromLatin1( "dummy" );
3681 return s;
3683 #endif
3685 #ifndef QT_NO_IMAGEIO_BMP
3686 static void swapPixel01( QImage *image ) // 1-bpp: swap 0 and 1 pixels
3688 int i;
3689 if ( image->depth() == 1 && image->numColors() == 2 ) {
3690 register uint *p = (uint *)image->bits();
3691 int nbytes = image->numBytes();
3692 for ( i=0; i<nbytes/4; i++ ) {
3693 *p = ~*p;
3694 p++;
3696 uchar *p2 = (uchar *)p;
3697 for ( i=0; i<(nbytes&3); i++ ) {
3698 *p2 = ~*p2;
3699 p2++;
3701 QRgb t = image->color(0); // swap color 0 and 1
3702 image->setColor( 0, image->color(1) );
3703 image->setColor( 1, t );
3706 #endif
3709 /*****************************************************************************
3710 QImageIO member functions
3711 *****************************************************************************/
3714 \class QImageIO qimage.h
3716 \brief The QImageIO class contains parameters for loading and
3717 saving images.
3719 \ingroup images
3720 \ingroup graphics
3721 \ingroup io
3723 QImageIO contains a QIODevice object that is used for image data
3724 I/O. The programmer can install new image file formats in addition
3725 to those that Qt provides.
3727 Qt currently supports the following image file formats: PNG, BMP,
3728 XBM, XPM and PNM. It may also support JPEG, MNG and GIF, if
3729 specially configured during compilation. The different PNM formats
3730 are: PBM (P1 or P4), PGM (P2 or P5), and PPM (P3 or P6).
3732 You don't normally need to use this class; QPixmap::load(),
3733 QPixmap::save(), and QImage contain sufficient functionality.
3735 For image files that contain sequences of images, only the first
3736 is read. See QMovie for loading multiple images.
3738 PBM, PGM, and PPM format \e output is always in the more condensed
3739 raw format. PPM and PGM files with more than 256 levels of
3740 intensity are scaled down when reading.
3742 \warning If you are in a country which recognizes software patents
3743 and in which Unisys holds a patent on LZW compression and/or
3744 decompression and you want to use GIF, Unisys may require you to
3745 license the technology. Such countries include Canada, Japan, the
3746 USA, France, Germany, Italy and the UK.
3748 GIF support may be removed completely in a future version of Qt.
3749 We recommend using the PNG format.
3751 \sa QImage QPixmap QFile QMovie
3754 #ifndef QT_NO_IMAGEIO
3755 struct QImageIOData
3757 const char *parameters;
3758 int quality;
3759 float gamma;
3763 Constructs a QImageIO object with all parameters set to zero.
3766 QImageIO::QImageIO()
3768 init();
3772 Constructs a QImageIO object with the I/O device \a ioDevice and a
3773 \a format tag.
3776 QImageIO::QImageIO( QIODevice *ioDevice, const char *format )
3777 : frmt(format)
3779 init();
3780 iodev = ioDevice;
3784 Constructs a QImageIO object with the file name \a fileName and a
3785 \a format tag.
3788 QImageIO::QImageIO( const QString &fileName, const char* format )
3789 : frmt(format), fname(fileName)
3791 init();
3795 Contains initialization common to all QImageIO constructors.
3798 void QImageIO::init()
3800 d = new QImageIOData();
3801 d->parameters = 0;
3802 d->quality = -1; // default quality of the current format
3803 d->gamma=0.0f;
3804 iostat = 0;
3805 iodev = 0;
3809 Destroys the object and all related data.
3812 QImageIO::~QImageIO()
3814 if ( d->parameters )
3815 delete [] (char*)d->parameters;
3816 delete d;
3820 /*****************************************************************************
3821 QImageIO image handler functions
3822 *****************************************************************************/
3824 class QImageHandler
3826 public:
3827 QImageHandler( const char *f, const char *h, const QCString& fl,
3828 image_io_handler r, image_io_handler w );
3829 QCString format; // image format
3830 QRegExp header; // image header pattern
3831 enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;
3832 image_io_handler read_image; // image read function
3833 image_io_handler write_image; // image write function
3834 bool obsolete; // support not "published"
3837 QImageHandler::QImageHandler( const char *f, const char *h, const QCString& fl,
3838 image_io_handler r, image_io_handler w )
3839 : format(f), header(QString::fromLatin1(h))
3841 text_mode = Untranslated;
3842 if ( fl.contains('t') )
3843 text_mode = TranslateIn;
3844 else if ( fl.contains('T') )
3845 text_mode = TranslateInOut;
3846 obsolete = fl.contains('O');
3847 read_image = r;
3848 write_image = w;
3851 typedef QPtrList<QImageHandler> QIHList;// list of image handlers
3852 static QIHList *imageHandlers = 0;
3853 #ifndef QT_NO_COMPONENT
3854 static QPluginManager<QImageFormatInterface> *plugin_manager = 0;
3855 #else
3856 static void *plugin_manager = 0;
3857 #endif
3859 void qt_init_image_plugins()
3861 #ifndef QT_NO_COMPONENT
3862 if ( plugin_manager )
3863 return;
3865 plugin_manager = new QPluginManager<QImageFormatInterface>( IID_QImageFormat, QApplication::libraryPaths(), "/imageformats" );
3867 QStringList features = plugin_manager->featureList();
3868 QStringList::const_iterator it = features.begin();
3869 while ( it != features.end() ) {
3870 QString str = *it;
3871 ++it;
3872 QInterfacePtr<QImageFormatInterface> iface;
3873 plugin_manager->queryInterface( str, &iface );
3874 if ( iface )
3875 iface->installIOHandler( str );
3877 #endif
3880 static void cleanup()
3882 // make sure that image handlers are delete before plugin manager
3883 delete imageHandlers;
3884 imageHandlers = 0;
3885 #ifndef QT_NO_COMPONENT
3886 delete plugin_manager;
3887 plugin_manager = 0;
3888 #endif
3891 void qt_init_image_handlers() // initialize image handlers
3893 if ( !imageHandlers ) {
3894 imageHandlers = new QIHList;
3895 Q_CHECK_PTR( imageHandlers );
3896 imageHandlers->setAutoDelete( true );
3897 qAddPostRoutine( cleanup );
3898 #ifndef QT_NO_IMAGEIO_BMP
3899 QImageIO::defineIOHandler( "BMP", "^BM", 0,
3900 read_bmp_image, write_bmp_image );
3901 #endif
3902 #ifndef QT_NO_IMAGEIO_PPM
3903 QImageIO::defineIOHandler( "PBM", "^P1", "t",
3904 read_pbm_image, write_pbm_image );
3905 QImageIO::defineIOHandler( "PBMRAW", "^P4", "O",
3906 read_pbm_image, write_pbm_image );
3907 QImageIO::defineIOHandler( "PGM", "^P2", "t",
3908 read_pbm_image, write_pbm_image );
3909 QImageIO::defineIOHandler( "PGMRAW", "^P5", "O",
3910 read_pbm_image, write_pbm_image );
3911 QImageIO::defineIOHandler( "PPM", "^P3", "t",
3912 read_pbm_image, write_pbm_image );
3913 QImageIO::defineIOHandler( "PPMRAW", "^P6", "O",
3914 read_pbm_image, write_pbm_image );
3915 #endif
3916 #ifndef QT_NO_IMAGEIO_XBM
3917 QImageIO::defineIOHandler( "XBM", "^#define", "T",
3918 read_xbm_image, write_xbm_image );
3919 #endif
3920 #ifndef QT_NO_IMAGEIO_XPM
3921 QImageIO::defineIOHandler( "XPM", "/\\*.XPM.\\*/", "T",
3922 read_xpm_image, write_xpm_image );
3923 #endif
3924 #ifndef QT_NO_IMAGEIO_MNG
3925 qInitMngIO();
3926 #endif
3927 #ifndef QT_NO_IMAGEIO_PNG
3928 qInitPngIO();
3929 #endif
3930 #ifndef QT_NO_IMAGEIO_JPEG
3931 qInitJpegIO();
3932 #endif
3936 static QImageHandler *get_image_handler( const char *format )
3937 { // get pointer to handler
3938 qt_init_image_handlers();
3939 qt_init_image_plugins();
3940 register QImageHandler *p = imageHandlers->first();
3941 while ( p ) { // traverse list
3942 if ( p->format == format )
3943 return p;
3944 p = imageHandlers->next();
3946 return 0; // no such handler
3951 Defines an image I/O handler for the image format called \a
3952 format, which is recognized using the \link qregexp.html#details
3953 regular expression\endlink \a header, read using \a readImage and
3954 written using \a writeImage.
3956 \a flags is a string of single-character flags for this format.
3957 The only flag defined currently is T (upper case), so the only
3958 legal value for \a flags are "T" and the empty string. The "T"
3959 flag means that the image file is a text file, and Qt should treat
3960 all newline conventions as equivalent. (XPM files and some PPM
3961 files are text files for example.)
3963 \a format is used to select a handler to write a QImage; \a header
3964 is used to select a handler to read an image file.
3966 If \a readImage is a null pointer, the QImageIO will not be able
3967 to read images in \a format. If \a writeImage is a null pointer,
3968 the QImageIO will not be able to write images in \a format. If
3969 both are null, the QImageIO object is valid but useless.
3971 Example:
3972 \code
3973 void readGIF( QImageIO *image )
3975 // read the image using the image->ioDevice()
3978 void writeGIF( QImageIO *image )
3980 // write the image using the image->ioDevice()
3983 // add the GIF image handler
3985 QImageIO::defineIOHandler( "GIF",
3986 "^GIF[0-9][0-9][a-z]",
3988 readGIF,
3989 writeGIF );
3990 \endcode
3992 Before the regex test, all the 0 bytes in the file header are
3993 converted to 1 bytes. This is done because when Qt was
3994 ASCII-based, QRegExp could not handle 0 bytes in strings.
3996 The regexp is only applied on the first 14 bytes of the file.
3998 (Note that if one handlerIO supports writing a format and another
3999 supports reading it, Qt supports both reading and writing. If two
4000 handlers support the same operation, Qt chooses one arbitrarily.)
4003 void QImageIO::defineIOHandler( const char *format,
4004 const char *header,
4005 const char *flags,
4006 image_io_handler readImage,
4007 image_io_handler writeImage )
4009 qt_init_image_handlers();
4010 QImageHandler *p;
4011 p = new QImageHandler( format, header, flags,
4012 readImage, writeImage );
4013 Q_CHECK_PTR( p );
4014 imageHandlers->insert( 0, p );
4018 /*****************************************************************************
4019 QImageIO normal member functions
4020 *****************************************************************************/
4023 \fn const QImage &QImageIO::image() const
4025 Returns the image currently set.
4027 \sa setImage()
4031 \fn int QImageIO::status() const
4033 Returns the image's IO status. A non-zero value indicates an
4034 error, whereas 0 means that the IO operation was successful.
4036 \sa setStatus()
4040 \fn const char *QImageIO::format() const
4042 Returns the image format string or 0 if no format has been
4043 explicitly set.
4047 \fn QIODevice *QImageIO::ioDevice() const
4049 Returns the IO device currently set.
4051 \sa setIODevice()
4055 \fn QString QImageIO::fileName() const
4057 Returns the file name currently set.
4059 \sa setFileName()
4063 \fn QString QImageIO::description() const
4065 Returns the image description string.
4067 \sa setDescription()
4072 Sets the image to \a image.
4074 \sa image()
4077 void QImageIO::setImage( const QImage &image )
4079 im = image;
4083 Sets the image IO status to \a status. A non-zero value indicates
4084 an error, whereas 0 means that the IO operation was successful.
4086 \sa status()
4089 void QImageIO::setStatus( int status )
4091 iostat = status;
4095 Sets the image format to \a format for the image to be read or
4096 written.
4098 It is necessary to specify a format before writing an image, but
4099 it is not necessary to specify a format before reading an image.
4101 If no format has been set, Qt guesses the image format before
4102 reading it. If a format is set the image will only be read if it
4103 has that format.
4105 \sa read() write() format()
4108 void QImageIO::setFormat( const char *format )
4110 frmt = format;
4114 Sets the IO device to be used for reading or writing an image.
4116 Setting the IO device allows images to be read/written to any
4117 block-oriented QIODevice.
4119 If \a ioDevice is not null, this IO device will override file name
4120 settings.
4122 \sa setFileName()
4125 void QImageIO::setIODevice( QIODevice *ioDevice )
4127 iodev = ioDevice;
4131 Sets the name of the file to read or write an image from to \a
4132 fileName.
4134 \sa setIODevice()
4137 void QImageIO::setFileName( const QString &fileName )
4139 fname = fileName;
4143 Returns the quality of the written image, related to the
4144 compression ratio.
4146 \sa setQuality() QImage::save()
4149 int QImageIO::quality() const
4151 return d->quality;
4155 Sets the quality of the written image to \a q, related to the
4156 compression ratio.
4158 \a q must be in the range -1..100. Specify 0 to obtain small
4159 compressed files, 100 for large uncompressed files. (-1 signifies
4160 the default compression.)
4162 \sa quality() QImage::save()
4165 void QImageIO::setQuality( int q )
4167 d->quality = q;
4171 Returns the image's parameters string.
4173 \sa setParameters()
4176 const char *QImageIO::parameters() const
4178 return d->parameters;
4182 Sets the image's parameter string to \a parameters. This is for
4183 image handlers that require special parameters.
4185 Although the current image formats supported by Qt ignore the
4186 parameters string, it may be used in future extensions or by
4187 contributions (for example, JPEG).
4189 \sa parameters()
4192 void QImageIO::setParameters( const char *parameters )
4194 if ( d && d->parameters )
4195 delete [] (char*)d->parameters;
4196 d->parameters = qstrdup( parameters );
4200 Sets the gamma value at which the image will be viewed to \a
4201 gamma. If the image format stores a gamma value for which the
4202 image is intended to be used, then this setting will be used to
4203 modify the image. Setting to 0.0 will disable gamma correction
4204 (i.e. any specification in the file will be ignored).
4206 The default value is 0.0.
4208 \sa gamma()
4210 void QImageIO::setGamma( float gamma )
4212 d->gamma=gamma;
4216 Returns the gamma value at which the image will be viewed.
4218 \sa setGamma()
4220 float QImageIO::gamma() const
4222 return d->gamma;
4226 Sets the image description string for image handlers that support
4227 image descriptions to \a description.
4229 Currently, no image format supported by Qt uses the description
4230 string.
4233 void QImageIO::setDescription( const QString &description )
4235 descr = description;
4240 Returns a string that specifies the image format of the file \a
4241 fileName, or null if the file cannot be read or if the format is
4242 not recognized.
4245 const char* QImageIO::imageFormat( const QString &fileName )
4247 QFile file( fileName );
4248 if ( !file.open(IO_ReadOnly) )
4249 return 0;
4250 const char* format = imageFormat( &file );
4251 file.close();
4252 return format;
4256 \overload
4258 Returns a string that specifies the image format of the image read
4259 from IO device \a d, or 0 if the device cannot be read or if the
4260 format is not recognized.
4262 Make sure that \a d is at the right position in the device (for
4263 example, at the beginning of the file).
4265 \sa QIODevice::at()
4268 const char *QImageIO::imageFormat( QIODevice *d )
4270 // if you change this change the documentation for defineIOHandler()
4271 const int buflen = 14;
4273 char buf[buflen];
4274 char buf2[buflen];
4275 qt_init_image_handlers();
4276 qt_init_image_plugins();
4277 int pos = d->at(); // save position
4278 int rdlen = d->readBlock( buf, buflen ); // read a few bytes
4280 if ( rdlen != buflen )
4281 return 0;
4283 memcpy( buf2, buf, buflen );
4285 const char* format = 0;
4286 for ( int n = 0; n < rdlen; n++ )
4287 if ( buf[n] == '\0' )
4288 buf[n] = '\001';
4289 if ( d->status() == IO_Ok && rdlen > 0 ) {
4290 buf[rdlen - 1] = '\0';
4291 QString bufStr = QString::fromLatin1(buf);
4292 QImageHandler *p = imageHandlers->first();
4293 int bestMatch = -1;
4294 while ( p ) {
4295 if ( p->read_image && p->header.search(bufStr) != -1 ) {
4296 // try match with header if a read function is available
4297 if (p->header.matchedLength() > bestMatch) {
4298 // keep looking for best match
4299 format = p->format;
4300 bestMatch = p->header.matchedLength();
4303 p = imageHandlers->next();
4306 d->at( pos ); // restore position
4307 #ifndef QT_NO_ASYNC_IMAGE_IO
4308 if ( !format )
4309 format = QImageDecoder::formatName( (uchar*)buf2, rdlen );
4310 #endif
4312 return format;
4316 Returns a sorted list of image formats that are supported for
4317 image input.
4319 QStrList QImageIO::inputFormats()
4321 QStrList result;
4323 qt_init_image_handlers();
4324 qt_init_image_plugins();
4326 #ifndef QT_NO_ASYNC_IMAGE_IO
4327 // Include asynchronous loaders first.
4328 result = QImageDecoder::inputFormats();
4329 #endif
4331 QImageHandler *p = imageHandlers->first();
4332 while ( p ) {
4333 if ( p->read_image
4334 && !p->obsolete
4335 && !result.contains(p->format) )
4337 result.inSort(p->format);
4339 p = imageHandlers->next();
4342 return result;
4346 Returns a sorted list of image formats that are supported for
4347 image output.
4349 QStrList QImageIO::outputFormats()
4351 QStrList result;
4353 qt_init_image_handlers();
4354 qt_init_image_plugins();
4356 // Include asynchronous writers (!) first.
4357 // (None)
4359 QImageHandler *p = imageHandlers->first();
4360 while ( p ) {
4361 if ( p->write_image
4362 && !p->obsolete
4363 && !result.contains(p->format) )
4365 result.inSort(p->format);
4367 p = imageHandlers->next();
4370 return result;
4376 Reads an image into memory and returns TRUE if the image was
4377 successfully read; otherwise returns FALSE.
4379 Before reading an image you must set an IO device or a file name.
4380 If both an IO device and a file name have been set, the IO device
4381 will be used.
4383 Setting the image file format string is optional.
4385 Note that this function does \e not set the \link format()
4386 format\endlink used to read the image. If you need that
4387 information, use the imageFormat() static functions.
4389 Example:
4391 \code
4392 QImageIO iio;
4393 QPixmap pixmap;
4394 iio.setFileName( "vegeburger.bmp" );
4395 if ( image.read() ) // ok
4396 pixmap = iio.image(); // convert to pixmap
4397 \endcode
4399 \sa setIODevice() setFileName() setFormat() write() QPixmap::load()
4402 bool QImageIO::read()
4404 QFile file;
4405 const char *image_format;
4406 QImageHandler *h;
4408 if ( iodev ) { // read from io device
4409 // ok, already open
4410 } else if ( !fname.isEmpty() ) { // read from file
4411 file.setName( fname );
4412 if ( !file.open(IO_ReadOnly) )
4413 return false; // cannot open file
4414 iodev = &file;
4415 } else { // no file name or io device
4416 return false;
4418 if (frmt.isEmpty()) {
4419 // Try to guess format
4420 image_format = imageFormat( iodev ); // get image format
4421 if ( !image_format ) {
4422 if ( file.isOpen() ) { // unknown format
4423 file.close();
4424 iodev = 0;
4426 return false;
4428 } else {
4429 image_format = frmt;
4432 h = get_image_handler( image_format );
4433 if ( file.isOpen() ) {
4434 #if !defined(Q_OS_UNIX)
4435 if ( h && h->text_mode ) { // reopen in translated mode
4436 file.close();
4437 file.open( IO_ReadOnly | IO_Translate );
4439 else
4440 #endif
4441 file.at( 0 ); // position to start
4443 iostat = 1; // assume error
4445 if ( h && h->read_image ) {
4446 (*h->read_image)( this );
4448 #ifndef QT_NO_ASYNC_IMAGE_IO
4449 else {
4450 // Format name, but no handler - must be an asychronous reader
4451 read_async_image( this );
4453 #endif
4455 if ( file.isOpen() ) { // image was read using file
4456 file.close();
4457 iodev = 0;
4459 return iostat == 0; // image successfully read?
4464 Writes an image to an IO device and returns TRUE if the image was
4465 successfully written; otherwise returns FALSE.
4467 Before writing an image you must set an IO device or a file name.
4468 If both an IO device and a file name have been set, the IO device
4469 will be used.
4471 The image will be written using the specified image format.
4473 Example:
4474 \code
4475 QImageIO iio;
4476 QImage im;
4477 im = pixmap; // convert to image
4478 iio.setImage( im );
4479 iio.setFileName( "vegeburger.bmp" );
4480 iio.setFormat( "BMP" );
4481 if ( iio.write() )
4482 // returned TRUE if written successfully
4483 \endcode
4485 \sa setIODevice() setFileName() setFormat() read() QPixmap::save()
4488 bool QImageIO::write()
4490 if ( frmt.isEmpty() )
4491 return false;
4492 QImageHandler *h = get_image_handler( frmt );
4493 if ( !h && !plugin_manager) {
4494 qt_init_image_plugins();
4495 h = get_image_handler( frmt );
4497 if ( !h || !h->write_image ) {
4498 #if defined(QT_CHECK_RANGE)
4499 qWarning( "QImageIO::write: No such image format handler: %s",
4500 format() );
4501 #endif
4502 return false;
4504 QFile file;
4505 if ( !iodev && !fname.isEmpty() ) {
4506 file.setName( fname );
4507 bool translate = h->text_mode==QImageHandler::TranslateInOut;
4508 int fmode = translate ? IO_WriteOnly|IO_Translate : IO_WriteOnly;
4509 if ( !file.open(fmode) ) // couldn't create file
4510 return false;
4511 iodev = &file;
4513 iostat = 1;
4514 (*h->write_image)( this );
4515 if ( file.isOpen() ) { // image was written using file
4516 file.close();
4517 iodev = 0;
4519 return iostat == 0; // image successfully written?
4521 #endif //QT_NO_IMAGEIO
4523 #ifndef QT_NO_IMAGEIO_BMP
4525 /*****************************************************************************
4526 BMP (DIB) image read/write functions
4527 *****************************************************************************/
4529 const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data
4531 struct BMP_FILEHDR { // BMP file header
4532 char bfType[2]; // "BM"
4533 Q_INT32 bfSize; // size of file
4534 Q_INT16 bfReserved1;
4535 Q_INT16 bfReserved2;
4536 Q_INT32 bfOffBits; // pointer to the pixmap bits
4539 QDataStream &operator>>( QDataStream &s, BMP_FILEHDR &bf )
4540 { // read file header
4541 s.readRawBytes( bf.bfType, 2 );
4542 s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits;
4543 return s;
4546 QDataStream &operator<<( QDataStream &s, const BMP_FILEHDR &bf )
4547 { // write file header
4548 s.writeRawBytes( bf.bfType, 2 );
4549 s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits;
4550 return s;
4554 const int BMP_OLD = 12; // old Windows/OS2 BMP size
4555 const int BMP_WIN = 40; // new Windows BMP size
4556 const int BMP_OS2 = 64; // new OS/2 BMP size
4558 const int BMP_RGB = 0; // no compression
4559 const int BMP_RLE8 = 1; // run-length encoded, 8 bits
4560 const int BMP_RLE4 = 2; // run-length encoded, 4 bits
4561 const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields
4563 struct BMP_INFOHDR { // BMP information header
4564 Q_INT32 biSize; // size of this struct
4565 Q_INT32 biWidth; // pixmap width
4566 Q_INT32 biHeight; // pixmap height
4567 Q_INT16 biPlanes; // should be 1
4568 Q_INT16 biBitCount; // number of bits per pixel
4569 Q_INT32 biCompression; // compression method
4570 Q_INT32 biSizeImage; // size of image
4571 Q_INT32 biXPelsPerMeter; // horizontal resolution
4572 Q_INT32 biYPelsPerMeter; // vertical resolution
4573 Q_INT32 biClrUsed; // number of colors used
4574 Q_INT32 biClrImportant; // number of important colors
4578 QDataStream &operator>>( QDataStream &s, BMP_INFOHDR &bi )
4580 s >> bi.biSize;
4581 if ( bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 ) {
4582 s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
4583 s >> bi.biCompression >> bi.biSizeImage;
4584 s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
4585 s >> bi.biClrUsed >> bi.biClrImportant;
4587 else { // probably old Windows format
4588 Q_INT16 w, h;
4589 s >> w >> h >> bi.biPlanes >> bi.biBitCount;
4590 bi.biWidth = w;
4591 bi.biHeight = h;
4592 bi.biCompression = BMP_RGB; // no compression
4593 bi.biSizeImage = 0;
4594 bi.biXPelsPerMeter = bi.biYPelsPerMeter = 0;
4595 bi.biClrUsed = bi.biClrImportant = 0;
4597 return s;
4600 QDataStream &operator<<( QDataStream &s, const BMP_INFOHDR &bi )
4602 s << bi.biSize;
4603 s << bi.biWidth << bi.biHeight;
4604 s << bi.biPlanes;
4605 s << bi.biBitCount;
4606 s << bi.biCompression;
4607 s << bi.biSizeImage;
4608 s << bi.biXPelsPerMeter << bi.biYPelsPerMeter;
4609 s << bi.biClrUsed << bi.biClrImportant;
4610 return s;
4613 static
4614 int calc_shift(int mask)
4616 int result = 0;
4617 while (!(mask & 1)) {
4618 result++;
4619 mask >>= 1;
4621 return result;
4624 static
4625 bool read_dib( QDataStream& s, int offset, int startpos, QImage& image )
4627 BMP_INFOHDR bi;
4628 QIODevice* d = s.device();
4630 s >> bi; // read BMP info header
4631 if ( d->atEnd() ) // end of stream/file
4632 return false;
4633 #if 0
4634 qDebug( "offset...........%d", offset );
4635 qDebug( "startpos.........%d", startpos );
4636 qDebug( "biSize...........%d", bi.biSize );
4637 qDebug( "biWidth..........%d", bi.biWidth );
4638 qDebug( "biHeight.........%d", bi.biHeight );
4639 qDebug( "biPlanes.........%d", bi.biPlanes );
4640 qDebug( "biBitCount.......%d", bi.biBitCount );
4641 qDebug( "biCompression....%d", bi.biCompression );
4642 qDebug( "biSizeImage......%d", bi.biSizeImage );
4643 qDebug( "biXPelsPerMeter..%d", bi.biXPelsPerMeter );
4644 qDebug( "biYPelsPerMeter..%d", bi.biYPelsPerMeter );
4645 qDebug( "biClrUsed........%d", bi.biClrUsed );
4646 qDebug( "biClrImportant...%d", bi.biClrImportant );
4647 #endif
4648 int w = bi.biWidth, h = bi.biHeight, nbits = bi.biBitCount;
4649 int t = bi.biSize, comp = bi.biCompression;
4650 int red_mask, green_mask, blue_mask;
4651 int red_shift = 0;
4652 int green_shift = 0;
4653 int blue_shift = 0;
4654 int red_scale = 0;
4655 int green_scale = 0;
4656 int blue_scale = 0;
4658 if ( !(nbits == 1 || nbits == 4 || nbits == 8 || nbits == 16 || nbits == 24 || nbits == 32) ||
4659 bi.biPlanes != 1 || comp > BMP_BITFIELDS )
4660 return false; // weird BMP image
4661 if ( !(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) ||
4662 (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)) )
4663 return false; // weird compression type
4665 int ncols;
4666 int depth;
4667 switch ( nbits ) {
4668 case 32:
4669 case 24:
4670 case 16:
4671 depth = 32;
4672 break;
4673 case 8:
4674 case 4:
4675 depth = 8;
4676 break;
4677 default:
4678 depth = 1;
4680 if ( depth == 32 ) // there's no colormap
4681 ncols = 0;
4682 else // # colors used
4683 ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
4685 image.create( w, h, depth, ncols, nbits == 1 ?
4686 QImage::BigEndian : QImage::IgnoreEndian );
4687 if ( image.isNull() ) // could not create image
4688 return false;
4690 image.setDotsPerMeterX( bi.biXPelsPerMeter );
4691 image.setDotsPerMeterY( bi.biYPelsPerMeter );
4693 d->at( startpos + BMP_FILEHDR_SIZE + bi.biSize ); // goto start of colormap
4695 if ( ncols > 0 ) { // read color table
4696 uchar rgb[4];
4697 int rgb_len = t == BMP_OLD ? 3 : 4;
4698 for ( int i=0; i<ncols; i++ ) {
4699 if ( d->readBlock( (char *)rgb, rgb_len ) != rgb_len )
4700 return false;
4701 image.setColor( i, qRgb(rgb[2],rgb[1],rgb[0]) );
4702 if ( d->atEnd() ) // truncated file
4703 return false;
4705 } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
4706 if ( (Q_ULONG)d->readBlock( (char *)&red_mask, sizeof(red_mask) ) != sizeof(red_mask) )
4707 return false;
4708 if ( (Q_ULONG)d->readBlock( (char *)&green_mask, sizeof(green_mask) ) != sizeof(green_mask) )
4709 return false;
4710 if ( (Q_ULONG)d->readBlock( (char *)&blue_mask, sizeof(blue_mask) ) != sizeof(blue_mask) )
4711 return false;
4712 red_shift = calc_shift(red_mask);
4713 red_scale = 256 / ((red_mask >> red_shift) + 1);
4714 green_shift = calc_shift(green_mask);
4715 green_scale = 256 / ((green_mask >> green_shift) + 1);
4716 blue_shift = calc_shift(blue_mask);
4717 blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
4718 } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
4719 blue_mask = 0x000000ff;
4720 green_mask = 0x0000ff00;
4721 red_mask = 0x00ff0000;
4722 blue_shift = 0;
4723 green_shift = 8;
4724 red_shift = 16;
4725 blue_scale = green_scale = red_scale = 1;
4726 } else if (comp == BMP_RGB && nbits == 16) // don't support RGB values for 15/16 bpp
4727 return false;
4729 // offset can be bogus, be careful
4730 if (offset>=0 && startpos + offset > (Q_LONG)d->at() )
4731 d->at( startpos + offset ); // start of image data
4733 int bpl = image.bytesPerLine();
4734 #ifdef Q_WS_QWS
4736 // Guess the number of bytes-per-line if we don't know how much
4737 // image data is in the file (bogus image ?).
4739 int bmpbpl = bi.biSizeImage > 0 ?
4740 bi.biSizeImage / bi.biHeight :
4741 (d->size() - offset) / bi.biHeight;
4742 int pad = bmpbpl-bpl;
4743 #endif
4744 uchar **line = image.jumpTable();
4746 if ( nbits == 1 ) { // 1 bit BMP image
4747 while ( --h >= 0 ) {
4748 if ( d->readBlock((char*)line[h],bpl) != bpl )
4749 break;
4750 #ifdef Q_WS_QWS
4751 if ( pad > 0 )
4752 d->at(d->at()+pad);
4753 #endif
4755 if ( ncols == 2 && qGray(image.color(0)) < qGray(image.color(1)) )
4756 swapPixel01( &image ); // pixel 0 is white!
4759 else if ( nbits == 4 ) { // 4 bit BMP image
4760 int buflen = ((w+7)/8)*4;
4761 uchar *buf = new uchar[buflen];
4762 Q_CHECK_PTR( buf );
4763 if ( comp == BMP_RLE4 ) { // run length compression
4764 int x=0, y=0, b, c, i;
4765 register uchar *p = line[h-1];
4766 uchar *endp = line[h-1]+w;
4767 while ( y < h ) {
4768 if ( (b=d->getch()) == EOF )
4769 break;
4770 if ( b == 0 ) { // escape code
4771 switch ( (b=d->getch()) ) {
4772 case 0: // end of line
4773 x = 0;
4774 y++;
4775 p = line[h-y-1];
4776 break;
4777 case 1: // end of image
4778 case EOF: // end of file
4779 y = h; // exit loop
4780 break;
4781 case 2: // delta (jump)
4782 x += d->getch();
4783 y += d->getch();
4785 // Protection
4786 if ( (uint)x >= (uint)w )
4787 x = w-1;
4788 if ( (uint)y >= (uint)h )
4789 y = h-1;
4791 p = line[h-y-1] + x;
4792 break;
4793 default: // absolute mode
4794 // Protection
4795 if ( p + b > endp )
4796 b = endp-p;
4798 i = (c = b)/2;
4799 while ( i-- ) {
4800 b = d->getch();
4801 *p++ = b >> 4;
4802 *p++ = b & 0x0f;
4804 if ( c & 1 )
4805 *p++ = d->getch() >> 4;
4806 if ( (((c & 3) + 1) & 2) == 2 )
4807 d->getch(); // align on word boundary
4808 x += c;
4810 } else { // encoded mode
4811 // Protection
4812 if ( p + b > endp )
4813 b = endp-p;
4815 i = (c = b)/2;
4816 b = d->getch(); // 2 pixels to be repeated
4817 while ( i-- ) {
4818 *p++ = b >> 4;
4819 *p++ = b & 0x0f;
4821 if ( c & 1 )
4822 *p++ = b >> 4;
4823 x += c;
4826 } else if ( comp == BMP_RGB ) { // no compression
4827 while ( --h >= 0 ) {
4828 if ( d->readBlock((char*)buf,buflen) != buflen )
4829 break;
4830 register uchar *p = line[h];
4831 uchar *b = buf;
4832 for ( int i=0; i<w/2; i++ ) { // convert nibbles to bytes
4833 *p++ = *b >> 4;
4834 *p++ = *b++ & 0x0f;
4836 if ( w & 1 ) // the last nibble
4837 *p = *b >> 4;
4840 delete [] buf;
4843 else if ( nbits == 8 ) { // 8 bit BMP image
4844 if ( comp == BMP_RLE8 ) { // run length compression
4845 int x=0, y=0, b;
4846 register uchar *p = line[h-1];
4847 const uchar *endp = line[h-1]+w;
4848 while ( y < h ) {
4849 if ( (b=d->getch()) == EOF )
4850 break;
4851 if ( b == 0 ) { // escape code
4852 switch ( (b=d->getch()) ) {
4853 case 0: // end of line
4854 x = 0;
4855 y++;
4856 p = line[h-y-1];
4857 break;
4858 case 1: // end of image
4859 case EOF: // end of file
4860 y = h; // exit loop
4861 break;
4862 case 2: // delta (jump)
4863 x += d->getch();
4864 y += d->getch();
4866 // Protection
4867 if ( (uint)x >= (uint)w )
4868 x = w-1;
4869 if ( (uint)y >= (uint)h )
4870 y = h-1;
4872 p = line[h-y-1] + x;
4873 break;
4874 default: // absolute mode
4875 // Protection
4876 if ( p + b > endp )
4877 b = endp-p;
4879 if ( d->readBlock( (char *)p, b ) != b )
4880 return false;
4881 if ( (b & 1) == 1 )
4882 d->getch(); // align on word boundary
4883 x += b;
4884 p += b;
4886 } else { // encoded mode
4887 // Protection
4888 if ( p + b > endp )
4889 b = endp-p;
4891 memset( p, d->getch(), b ); // repeat pixel
4892 x += b;
4893 p += b;
4896 } else if ( comp == BMP_RGB ) { // uncompressed
4897 while ( --h >= 0 ) {
4898 if ( d->readBlock((char *)line[h],bpl) != bpl )
4899 break;
4900 #ifdef Q_WS_QWS
4901 if ( pad > 0 )
4902 d->at(d->at()+pad);
4903 #endif
4908 else if ( nbits == 16 || nbits == 24 || nbits == 32 ) { // 16,24,32 bit BMP image
4909 register QRgb *p;
4910 QRgb *end;
4911 uchar *buf24 = new uchar[bpl];
4912 int bpl24 = ((w*nbits+31)/32)*4;
4913 uchar *b;
4914 int c;
4916 while ( --h >= 0 ) {
4917 p = (QRgb *)line[h];
4918 end = p + w;
4919 if ( d->readBlock( (char *)buf24,bpl24) != bpl24 )
4920 break;
4921 b = buf24;
4922 while ( p < end ) {
4923 c = *(uchar*)b | (*(uchar*)(b+1)<<8);
4924 if (nbits != 16)
4925 c |= *(uchar*)(b+2)<<16;
4926 *p++ = qRgb(((c & red_mask) >> red_shift) * red_scale,
4927 ((c & green_mask) >> green_shift) * green_scale,
4928 ((c & blue_mask) >> blue_shift) * blue_scale);
4929 b += nbits/8;
4932 delete[] buf24;
4935 return true;
4938 bool qt_read_dib( QDataStream& s, QImage& image )
4940 return read_dib(s,-1,-BMP_FILEHDR_SIZE,image);
4944 static void read_bmp_image( QImageIO *iio )
4946 QIODevice *d = iio->ioDevice();
4947 QDataStream s( d );
4948 BMP_FILEHDR bf;
4949 int startpos = d->at();
4951 s.setByteOrder( QDataStream::LittleEndian );// Intel byte order
4952 s >> bf; // read BMP file header
4954 if ( qstrncmp(bf.bfType,"BM",2) != 0 ) // not a BMP image
4955 return;
4957 QImage image;
4958 if (read_dib( s, bf.bfOffBits, startpos, image )) {
4959 iio->setImage( image );
4960 iio->setStatus( 0 ); // image ok
4964 bool qt_write_dib( QDataStream& s, QImage image )
4966 int nbits;
4967 int bpl_bmp;
4968 int bpl = image.bytesPerLine();
4970 QIODevice* d = s.device();
4972 if ( image.depth() == 8 && image.numColors() <= 16 ) {
4973 bpl_bmp = (((bpl+1)/2+3)/4)*4;
4974 nbits = 4;
4975 } else if ( image.depth() == 32 ) {
4976 bpl_bmp = ((image.width()*24+31)/32)*4;
4977 nbits = 24;
4978 #ifdef Q_WS_QWS
4979 } else if ( image.depth() == 1 || image.depth() == 8 ) {
4980 // Qt/E doesn't word align.
4981 bpl_bmp = ((image.width()*image.depth()+31)/32)*4;
4982 nbits = image.depth();
4983 #endif
4984 } else {
4985 bpl_bmp = bpl;
4986 nbits = image.depth();
4989 BMP_INFOHDR bi;
4990 bi.biSize = BMP_WIN; // build info header
4991 bi.biWidth = image.width();
4992 bi.biHeight = image.height();
4993 bi.biPlanes = 1;
4994 bi.biBitCount = nbits;
4995 bi.biCompression = BMP_RGB;
4996 bi.biSizeImage = bpl_bmp*image.height();
4997 bi.biXPelsPerMeter = image.dotsPerMeterX() ? image.dotsPerMeterX()
4998 : 2834; // 72 dpi default
4999 bi.biYPelsPerMeter = image.dotsPerMeterY() ? image.dotsPerMeterY() : 2834;
5000 bi.biClrUsed = image.numColors();
5001 bi.biClrImportant = image.numColors();
5002 s << bi; // write info header
5004 if ( image.depth() != 32 ) { // write color table
5005 uchar *color_table = new uchar[4*image.numColors()];
5006 uchar *rgb = color_table;
5007 QRgb *c = image.colorTable();
5008 for ( int i=0; i<image.numColors(); i++ ) {
5009 *rgb++ = qBlue ( c[i] );
5010 *rgb++ = qGreen( c[i] );
5011 *rgb++ = qRed ( c[i] );
5012 *rgb++ = 0;
5014 d->writeBlock( (char *)color_table, 4*image.numColors() );
5015 delete [] color_table;
5018 if ( image.depth() == 1 && image.bitOrder() != QImage::BigEndian )
5019 image = image.convertBitOrder( QImage::BigEndian );
5021 int y;
5023 if ( nbits == 1 || nbits == 8 ) { // direct output
5024 #ifdef Q_WS_QWS
5025 // Qt/E doesn't word align.
5026 int pad = bpl_bmp - bpl;
5027 char padding[4];
5028 #endif
5029 for ( y=image.height()-1; y>=0; y-- ) {
5030 d->writeBlock( (char*)image.scanLine(y), bpl );
5031 #ifdef Q_WS_QWS
5032 d->writeBlock( padding, pad );
5033 #endif
5035 return true;
5038 uchar *buf = new uchar[bpl_bmp];
5039 uchar *b, *end;
5040 register uchar *p;
5042 memset( buf, 0, bpl_bmp );
5043 for ( y=image.height()-1; y>=0; y-- ) { // write the image bits
5044 if ( nbits == 4 ) { // convert 8 -> 4 bits
5045 p = image.scanLine(y);
5046 b = buf;
5047 end = b + image.width()/2;
5048 while ( b < end ) {
5049 *b++ = (*p << 4) | (*(p+1) & 0x0f);
5050 p += 2;
5052 if ( image.width() & 1 )
5053 *b = *p << 4;
5054 } else { // 32 bits
5055 QRgb *p = (QRgb *)image.scanLine( y );
5056 QRgb *end = p + image.width();
5057 b = buf;
5058 while ( p < end ) {
5059 *b++ = qBlue(*p);
5060 *b++ = qGreen(*p);
5061 *b++ = qRed(*p);
5062 p++;
5065 if ( bpl_bmp != d->writeBlock( (char*)buf, bpl_bmp ) ) {
5066 delete[] buf;
5067 return false;
5070 delete[] buf;
5071 return true;
5075 static void write_bmp_image( QImageIO *iio )
5077 QIODevice *d = iio->ioDevice();
5078 QImage image = iio->image();
5079 QDataStream s( d );
5080 BMP_FILEHDR bf;
5081 int bpl_bmp;
5082 int bpl = image.bytesPerLine();
5084 // Code partially repeated in qt_write_dib
5085 if ( image.depth() == 8 && image.numColors() <= 16 ) {
5086 bpl_bmp = (((bpl+1)/2+3)/4)*4;
5087 } else if ( image.depth() == 32 ) {
5088 bpl_bmp = ((image.width()*24+31)/32)*4;
5089 } else {
5090 bpl_bmp = bpl;
5093 iio->setStatus( 0 );
5094 s.setByteOrder( QDataStream::LittleEndian );// Intel byte order
5095 strncpy( bf.bfType, "BM", 2 ); // build file header
5096 bf.bfReserved1 = bf.bfReserved2 = 0; // reserved, should be zero
5097 bf.bfOffBits = BMP_FILEHDR_SIZE + BMP_WIN + image.numColors()*4;
5098 bf.bfSize = bf.bfOffBits + bpl_bmp*image.height();
5099 s << bf; // write file header
5101 if ( !qt_write_dib( s, image ) )
5102 iio->setStatus( 1 );
5106 #endif // QT_NO_IMAGEIO_BMP
5108 #ifndef QT_NO_IMAGEIO_PPM
5110 /*****************************************************************************
5111 PBM/PGM/PPM (ASCII and RAW) image read/write functions
5112 *****************************************************************************/
5114 static int read_pbm_int( QIODevice *d )
5116 int c;
5117 int val = -1;
5118 bool digit;
5119 const int buflen = 100;
5120 char buf[buflen];
5121 for ( ;; ) {
5122 if ( (c=d->getch()) == EOF ) // end of file
5123 break;
5124 digit = isdigit( (uchar) c );
5125 if ( val != -1 ) {
5126 if ( digit ) {
5127 val = 10*val + c - '0';
5128 continue;
5129 } else {
5130 if ( c == '#' ) // comment
5131 d->readLine( buf, buflen );
5132 break;
5135 if ( digit ) // first digit
5136 val = c - '0';
5137 else if ( isspace((uchar) c) )
5138 continue;
5139 else if ( c == '#' )
5140 d->readLine( buf, buflen );
5141 else
5142 break;
5144 return val;
5147 static void read_pbm_image( QImageIO *iio ) // read PBM image data
5149 const int buflen = 300;
5150 char buf[buflen];
5151 QIODevice *d = iio->ioDevice();
5152 int w, h, nbits, mcc, y;
5153 int pbm_bpl;
5154 char type;
5155 bool raw;
5156 QImage image;
5158 if ( d->readBlock( buf, 3 ) != 3 ) // read P[1-6]<white-space>
5159 return;
5160 if ( !(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])) )
5161 return;
5162 switch ( (type=buf[1]) ) {
5163 case '1': // ascii PBM
5164 case '4': // raw PBM
5165 nbits = 1;
5166 break;
5167 case '2': // ascii PGM
5168 case '5': // raw PGM
5169 nbits = 8;
5170 break;
5171 case '3': // ascii PPM
5172 case '6': // raw PPM
5173 nbits = 32;
5174 break;
5175 default:
5176 return;
5178 raw = type >= '4';
5179 w = read_pbm_int( d ); // get image width
5180 h = read_pbm_int( d ); // get image height
5181 if ( nbits == 1 )
5182 mcc = 1; // ignore max color component
5183 else
5184 mcc = read_pbm_int( d ); // get max color component
5185 if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 )
5186 return; // weird P.M image
5188 int maxc = mcc;
5189 if ( maxc > 255 )
5190 maxc = 255;
5191 image.create( w, h, nbits, 0,
5192 nbits == 1 ? QImage::BigEndian : QImage::IgnoreEndian );
5193 if ( image.isNull() )
5194 return;
5196 pbm_bpl = (nbits*w+7)/8; // bytes per scanline in PBM
5198 if ( raw ) { // read raw data
5199 if ( nbits == 32 ) { // type 6
5200 pbm_bpl = 3*w;
5201 uchar *buf24 = new uchar[pbm_bpl], *b;
5202 QRgb *p;
5203 QRgb *end;
5204 for ( y=0; y<h; y++ ) {
5205 if ( d->readBlock( (char *)buf24, pbm_bpl ) != pbm_bpl ) {
5206 delete[] buf24;
5207 return;
5209 p = (QRgb *)image.scanLine( y );
5210 end = p + w;
5211 b = buf24;
5212 while ( p < end ) {
5213 *p++ = qRgb(b[0],b[1],b[2]);
5214 b += 3;
5217 delete[] buf24;
5218 } else { // type 4,5
5219 for ( y=0; y<h; y++ ) {
5220 if ( d->readBlock( (char *)image.scanLine(y), pbm_bpl )
5221 != pbm_bpl )
5222 return;
5225 } else { // read ascii data
5226 register uchar *p;
5227 int n;
5228 for ( y=0; y<h; y++ ) {
5229 p = image.scanLine( y );
5230 n = pbm_bpl;
5231 if ( nbits == 1 ) {
5232 int b;
5233 while ( n-- ) {
5234 b = 0;
5235 for ( int i=0; i<8; i++ )
5236 b = (b << 1) | (read_pbm_int(d) & 1);
5237 *p++ = b;
5239 } else if ( nbits == 8 ) {
5240 if ( mcc == maxc ) {
5241 while ( n-- ) {
5242 *p++ = read_pbm_int( d );
5244 } else {
5245 while ( n-- ) {
5246 *p++ = read_pbm_int( d ) * maxc / mcc;
5249 } else { // 32 bits
5250 n /= 4;
5251 int r, g, b;
5252 if ( mcc == maxc ) {
5253 while ( n-- ) {
5254 r = read_pbm_int( d );
5255 g = read_pbm_int( d );
5256 b = read_pbm_int( d );
5257 *((QRgb*)p) = qRgb( r, g, b );
5258 p += 4;
5260 } else {
5261 while ( n-- ) {
5262 r = read_pbm_int( d ) * maxc / mcc;
5263 g = read_pbm_int( d ) * maxc / mcc;
5264 b = read_pbm_int( d ) * maxc / mcc;
5265 *((QRgb*)p) = qRgb( r, g, b );
5266 p += 4;
5273 if ( nbits == 1 ) { // bitmap
5274 image.setNumColors( 2 );
5275 image.setColor( 0, qRgb(255,255,255) ); // white
5276 image.setColor( 1, qRgb(0,0,0) ); // black
5277 } else if ( nbits == 8 ) { // graymap
5278 image.setNumColors( maxc+1 );
5279 for ( int i=0; i<=maxc; i++ )
5280 image.setColor( i, qRgb(i*255/maxc,i*255/maxc,i*255/maxc) );
5283 iio->setImage( image );
5284 iio->setStatus( 0 ); // image ok
5288 static void write_pbm_image( QImageIO *iio )
5290 QIODevice* out = iio->ioDevice();
5291 QCString str;
5293 QImage image = iio->image();
5294 QCString format = iio->format();
5295 format = format.left(3); // ignore RAW part
5296 bool gray = format == "PGM";
5298 if ( format == "PBM" ) {
5299 image = image.convertDepth(1);
5300 } else if ( image.depth() == 1 ) {
5301 image = image.convertDepth(8);
5304 if ( image.depth() == 1 && image.numColors() == 2 ) {
5305 if ( qGray(image.color(0)) < qGray(image.color(1)) ) {
5306 // 0=dark/black, 1=light/white - invert
5307 image.detach();
5308 for ( int y=0; y<image.height(); y++ ) {
5309 uchar *p = image.scanLine(y);
5310 uchar *end = p + image.bytesPerLine();
5311 while ( p < end )
5312 *p++ ^= 0xff;
5317 uint w = image.width();
5318 uint h = image.height();
5320 str.sprintf("P\n%d %d\n", w, h);
5322 switch (image.depth()) {
5323 case 1: {
5324 str.insert(1, '4');
5325 if ((uint)out->writeBlock(str, str.length()) != str.length()) {
5326 iio->setStatus(1);
5327 return;
5329 w = (w+7)/8;
5330 for (uint y=0; y<h; y++) {
5331 uchar* line = image.scanLine(y);
5332 if ( w != (uint)out->writeBlock((char*)line, w) ) {
5333 iio->setStatus(1);
5334 return;
5338 break;
5340 case 8: {
5341 str.insert(1, gray ? '5' : '6');
5342 str.append("255\n");
5343 if ((uint)out->writeBlock(str, str.length()) != str.length()) {
5344 iio->setStatus(1);
5345 return;
5347 QRgb *color = image.colorTable();
5348 uint bpl = w*(gray ? 1 : 3);
5349 uchar *buf = new uchar[bpl];
5350 for (uint y=0; y<h; y++) {
5351 uchar *b = image.scanLine(y);
5352 uchar *p = buf;
5353 uchar *end = buf+bpl;
5354 if ( gray ) {
5355 while ( p < end ) {
5356 uchar g = (uchar)qGray(color[*b++]);
5357 *p++ = g;
5359 } else {
5360 while ( p < end ) {
5361 QRgb rgb = color[*b++];
5362 *p++ = qRed(rgb);
5363 *p++ = qGreen(rgb);
5364 *p++ = qBlue(rgb);
5367 if ( bpl != (uint)out->writeBlock((char*)buf, bpl) ) {
5368 iio->setStatus(1);
5369 return;
5372 delete [] buf;
5374 break;
5376 case 32: {
5377 str.insert(1, gray ? '5' : '6');
5378 str.append("255\n");
5379 if ((uint)out->writeBlock(str, str.length()) != str.length()) {
5380 iio->setStatus(1);
5381 return;
5383 uint bpl = w*(gray ? 1 : 3);
5384 uchar *buf = new uchar[bpl];
5385 for (uint y=0; y<h; y++) {
5386 QRgb *b = (QRgb*)image.scanLine(y);
5387 uchar *p = buf;
5388 uchar *end = buf+bpl;
5389 if ( gray ) {
5390 while ( p < end ) {
5391 uchar g = (uchar)qGray(*b++);
5392 *p++ = g;
5394 } else {
5395 while ( p < end ) {
5396 QRgb rgb = *b++;
5397 *p++ = qRed(rgb);
5398 *p++ = qGreen(rgb);
5399 *p++ = qBlue(rgb);
5402 if ( bpl != (uint)out->writeBlock((char*)buf, bpl) ) {
5403 iio->setStatus(1);
5404 return;
5407 delete [] buf;
5411 iio->setStatus(0);
5414 #endif // QT_NO_IMAGEIO_PPM
5416 #ifndef QT_NO_ASYNC_IMAGE_IO
5418 class QImageIOFrameGrabber : public QImageConsumer {
5419 public:
5420 QImageIOFrameGrabber() : framecount(0) { }
5422 QImageDecoder *decoder;
5423 int framecount;
5425 void changed(const QRect&) { }
5426 void end() { }
5427 void frameDone(const QPoint&, const QRect&) { framecount++; }
5428 void frameDone() { framecount++; }
5429 void setLooping(int) { }
5430 void setFramePeriod(int) { }
5431 void setSize(int, int) { }
5434 static void read_async_image( QImageIO *iio )
5436 const int buf_len = 2048;
5437 uchar buffer[buf_len];
5438 QIODevice *d = iio->ioDevice();
5439 QImageIOFrameGrabber* consumer = new QImageIOFrameGrabber();
5440 QImageDecoder *decoder = new QImageDecoder(consumer);
5441 consumer->decoder = decoder;
5442 int startAt = d->at();
5443 int totLen = 0;
5445 for (;;) {
5446 int length = d->readBlock((char*)buffer, buf_len);
5447 if ( length <= 0 ) {
5448 iio->setStatus(length);
5449 break;
5451 uchar* b = buffer;
5452 int r = -1;
5453 while (length > 0 && consumer->framecount==0) {
5454 r = decoder->decode(b, length);
5455 if ( r <= 0 ) break;
5456 b += r;
5457 totLen += r;
5458 length -= r;
5460 if ( consumer->framecount ) {
5461 // Stopped after first frame
5462 if ( d->isDirectAccess() )
5463 d->at( startAt + totLen );
5464 else {
5465 // ### We have (probably) read too much from the stream into
5466 // the buffer, and there is no way to put it back!
5468 iio->setImage(decoder->image());
5469 iio->setStatus(0);
5470 break;
5472 if ( r <= 0 ) {
5473 iio->setStatus(r);
5474 break;
5478 consumer->decoder = 0;
5479 delete decoder;
5480 delete consumer;
5483 #endif // QT_NO_ASYNC_IMAGE_IO
5485 #ifndef QT_NO_IMAGEIO_XBM
5487 /*****************************************************************************
5488 X bitmap image read/write functions
5489 *****************************************************************************/
5491 static inline int hex2byte( register char *p )
5493 return ( (isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4 ) |
5494 ( isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10 );
5497 static void read_xbm_image( QImageIO *iio )
5499 const int buflen = 300;
5500 char buf[buflen];
5501 QRegExp r1, r2;
5502 QIODevice *d = iio->ioDevice();
5503 int w=-1, h=-1;
5504 QImage image;
5506 r1 = QString::fromLatin1("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+");
5507 r2 = QString::fromLatin1("[0-9]+");
5508 d->readLine( buf, buflen ); // "#define .._width <num>"
5509 QString sbuf;
5510 sbuf = QString::fromLatin1(buf);
5512 if ( r1.search(sbuf) == 0 &&
5513 r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() )
5514 w = atoi( &buf[r1.matchedLength()] );
5516 d->readLine( buf, buflen ); // "#define .._height <num>"
5517 sbuf = QString::fromLatin1(buf);
5519 if ( r1.search(sbuf) == 0 &&
5520 r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() )
5521 h = atoi( &buf[r1.matchedLength()] );
5523 if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 )
5524 return; // format error
5526 for ( ;; ) { // scan for data
5527 if ( d->readLine(buf, buflen) <= 0 ) // end of file
5528 return;
5529 if ( strstr(buf,"0x") != 0 ) // does line contain data?
5530 break;
5533 image.create( w, h, 1, 2, QImage::LittleEndian );
5534 if ( image.isNull() )
5535 return;
5537 image.setColor( 0, qRgb(255,255,255) ); // white
5538 image.setColor( 1, qRgb(0,0,0) ); // black
5540 int x = 0, y = 0;
5541 uchar *b = image.scanLine(0);
5542 char *p = strstr( buf, "0x" );
5543 w = (w+7)/8; // byte width
5545 while ( y < h ) { // for all encoded bytes...
5546 if ( p ) { // p = "0x.."
5547 *b++ = hex2byte(p+2);
5548 p += 2;
5549 if ( ++x == w && ++y < h ) {
5550 b = image.scanLine(y);
5551 x = 0;
5553 p = strstr( p, "0x" );
5554 } else { // read another line
5555 if ( d->readLine(buf,buflen) <= 0 ) // EOF ==> truncated image
5556 break;
5557 p = strstr( buf, "0x" );
5561 iio->setImage( image );
5562 iio->setStatus( 0 ); // image ok
5566 static void write_xbm_image( QImageIO *iio )
5568 QIODevice *d = iio->ioDevice();
5569 QImage image = iio->image();
5570 int w = image.width();
5571 int h = image.height();
5572 int i;
5573 QString s = fbname(iio->fileName()); // get file base name
5574 char buf[100];
5576 sprintf( buf, "#define %s_width %d\n", s.ascii(), w );
5577 d->writeBlock( buf, qstrlen(buf) );
5578 sprintf( buf, "#define %s_height %d\n", s.ascii(), h );
5579 d->writeBlock( buf, qstrlen(buf) );
5580 sprintf( buf, "static char %s_bits[] = {\n ", s.ascii() );
5581 d->writeBlock( buf, qstrlen(buf) );
5583 iio->setStatus( 0 );
5585 if ( image.depth() != 1 )
5586 image = image.convertDepth( 1 ); // dither
5587 if ( image.bitOrder() != QImage::LittleEndian )
5588 image = image.convertBitOrder( QImage::LittleEndian );
5590 bool invert = qGray(image.color(0)) < qGray(image.color(1));
5591 char hexrep[16];
5592 for ( i=0; i<10; i++ )
5593 hexrep[i] = '0' + i;
5594 for ( i=10; i<16; i++ )
5595 hexrep[i] = 'a' -10 + i;
5596 if ( invert ) {
5597 char t;
5598 for ( i=0; i<8; i++ ) {
5599 t = hexrep[15-i];
5600 hexrep[15-i] = hexrep[i];
5601 hexrep[i] = t;
5604 int bcnt = 0;
5605 register char *p = buf;
5606 uchar *b = image.scanLine(0);
5607 int x=0, y=0;
5608 int nbytes = image.numBytes();
5609 w = (w+7)/8;
5610 while ( nbytes-- ) { // write all bytes
5611 *p++ = '0'; *p++ = 'x';
5612 *p++ = hexrep[*b >> 4];
5613 *p++ = hexrep[*b++ & 0xf];
5614 if ( ++x == w && y < h-1 ) {
5615 b = image.scanLine(++y);
5616 x = 0;
5618 if ( nbytes > 0 ) {
5619 *p++ = ',';
5620 if ( ++bcnt > 14 ) {
5621 *p++ = '\n';
5622 *p++ = ' ';
5623 *p = '\0';
5624 if ( (int)qstrlen(buf) != d->writeBlock( buf, qstrlen(buf) ) ) {
5625 iio->setStatus( 1 );
5626 return;
5628 p = buf;
5629 bcnt = 0;
5633 strcpy( p, " };\n" );
5634 if ( (int)qstrlen(buf) != d->writeBlock( buf, qstrlen(buf) ) )
5635 iio->setStatus( 1 );
5638 #endif // QT_NO_IMAGEIO_XBM
5641 #ifndef QT_NO_IMAGEIO_XPM
5643 /*****************************************************************************
5644 XPM image read/write functions
5645 *****************************************************************************/
5648 // Skip until ", read until the next ", return the rest in *buf
5649 // Returns FALSE on error, TRUE on success
5651 static bool read_xpm_string( QCString &buf, QIODevice *d,
5652 const char * const *source, int &index )
5654 if ( source ) {
5655 buf = source[index++];
5656 return true;
5659 if ( buf.size() < 69 ) //# just an approximation
5660 buf.resize( 123 );
5662 buf[0] = '\0';
5663 int c;
5664 int i;
5665 while ( (c=d->getch()) != EOF && c != '"' ) { }
5666 if ( c == EOF ) {
5667 return false;
5669 i = 0;
5670 while ( (c=d->getch()) != EOF && c != '"' ) {
5671 if ( i == (int)buf.size() )
5672 buf.resize( i*2+42 );
5673 buf[i++] = c;
5675 if ( c == EOF ) {
5676 return false;
5679 if ( i == (int)buf.size() ) // always use a 0 terminator
5680 buf.resize( i+1 );
5681 buf[i] = '\0';
5682 return true;
5687 static int nextColorSpec(const QCString & buf)
5689 int i = buf.find(" c ");
5690 if (i < 0)
5691 i = buf.find(" g ");
5692 if (i < 0)
5693 i = buf.find(" g4 ");
5694 if (i < 0)
5695 i = buf.find(" m ");
5696 if (i < 0)
5697 i = buf.find(" s ");
5698 return i;
5702 // INTERNAL
5704 // Reads an .xpm from either the QImageIO or from the QString *.
5705 // One of the two HAS to be 0, the other one is used.
5708 static void read_xpm_image_or_array( QImageIO * iio, const char * const * source,
5709 QImage & image)
5711 QCString buf;
5712 QIODevice *d = 0;
5713 buf.resize( 200 );
5715 int i, cpp, ncols, w, h, index = 0;
5717 if ( iio ) {
5718 iio->setStatus( 1 );
5719 d = iio ? iio->ioDevice() : 0;
5720 d->readLine( buf.data(), buf.size() ); // "/* XPM */"
5721 QRegExp r( QString::fromLatin1("/\\*.XPM.\\*/") );
5722 if ( buf.find(r) == -1 )
5723 return; // bad magic
5724 } else if ( !source ) {
5725 return;
5728 if ( !read_xpm_string( buf, d, source, index ) )
5729 return;
5731 if ( sscanf( buf, "%d %d %d %d", &w, &h, &ncols, &cpp ) < 4 )
5732 return; // < 4 numbers parsed
5734 if ( cpp > 15 )
5735 return;
5737 if ( ncols > 256 ) {
5738 image.create( w, h, 32 );
5739 } else {
5740 image.create( w, h, 8, ncols );
5743 QMap<QString, int> colorMap;
5744 int currentColor;
5746 for( currentColor=0; currentColor < ncols; ++currentColor ) {
5747 if ( !read_xpm_string( buf, d, source, index ) ) {
5748 #if defined(QT_CHECK_RANGE)
5749 qWarning( "QImage: XPM color specification missing");
5750 #endif
5751 return;
5753 QString index;
5754 index = buf.left( cpp );
5755 buf = buf.mid( cpp ).simplifyWhiteSpace().lower();
5756 buf.prepend( " " );
5757 i = nextColorSpec(buf);
5758 if ( i < 0 ) {
5759 #if defined(QT_CHECK_RANGE)
5760 qWarning( "QImage: XPM color specification is missing: %s", buf.data());
5761 #endif
5762 return; // no c/g/g4/m/s specification at all
5764 buf = buf.mid( i+3 );
5765 // Strip any other colorspec
5766 int end = nextColorSpec(buf);
5767 if (end != -1)
5768 buf.truncate(end);
5769 buf = buf.stripWhiteSpace();
5770 if ( buf == "none" ) {
5771 image.setAlphaBuffer( true );
5772 int transparentColor = currentColor;
5773 if ( image.depth() == 8 ) {
5774 image.setColor( transparentColor,
5775 RGB_MASK & qRgb(198,198,198) );
5776 colorMap.insert( index, transparentColor );
5777 } else {
5778 QRgb rgb = RGB_MASK & qRgb(198,198,198);
5779 colorMap.insert( index, rgb );
5781 } else {
5782 if ( ((buf.length()-1) % 3) && (buf[0] == '#') ) {
5783 buf.truncate (((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
5785 QColor c( buf.data() );
5786 if ( image.depth() == 8 ) {
5787 image.setColor( currentColor, 0xff000000 | c.rgb() );
5788 colorMap.insert( index, currentColor );
5789 } else {
5790 QRgb rgb = 0xff000000 | c.rgb();
5791 colorMap.insert( index, rgb );
5796 // Read pixels
5797 for( int y=0; y<h; y++ ) {
5798 if ( !read_xpm_string( buf, d, source, index ) ) {
5799 #if defined(QT_CHECK_RANGE)
5800 qWarning( "QImage: XPM pixels missing on image line %d", y);
5801 #endif
5802 return;
5804 if ( image.depth() == 8 ) {
5805 uchar *p = image.scanLine(y);
5806 uchar *d = (uchar *)buf.data();
5807 uchar *end = d + buf.length();
5808 int x;
5809 if ( cpp == 1 ) {
5810 char b[2];
5811 b[1] = '\0';
5812 for ( x=0; x<w && d<end; x++ ) {
5813 b[0] = *d++;
5814 *p++ = (uchar)colorMap[b];
5816 } else {
5817 char b[16];
5818 b[cpp] = '\0';
5819 for ( x=0; x<w && d<end; x++ ) {
5820 strncpy( b, (char *)d, cpp );
5821 *p++ = (uchar)colorMap[b];
5822 d += cpp;
5825 } else {
5826 QRgb *p = (QRgb*)image.scanLine(y);
5827 uchar *d = (uchar *)buf.data();
5828 uchar *end = d + buf.length();
5829 int x;
5830 char b[16];
5831 b[cpp] = '\0';
5832 for ( x=0; x<w && d<end; x++ ) {
5833 strncpy( b, (char *)d, cpp );
5834 *p++ = (QRgb)colorMap[b];
5835 d += cpp;
5839 if ( iio ) {
5840 iio->setImage( image );
5841 iio->setStatus( 0 ); // image ok
5846 static void read_xpm_image( QImageIO * iio )
5848 QImage i;
5849 (void)read_xpm_image_or_array( iio, 0, i );
5850 return;
5854 static const char* xpm_color_name( int cpp, int index )
5856 static char returnable[5];
5857 static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD"
5858 "EFGHIJKLMNOPQRSTUVWXYZ0123456789";
5859 // cpp is limited to 4 and index is limited to 64^cpp
5860 if ( cpp > 1 ) {
5861 if ( cpp > 2 ) {
5862 if ( cpp > 3 ) {
5863 returnable[3] = code[index % 64];
5864 index /= 64;
5865 } else
5866 returnable[3] = '\0';
5867 returnable[2] = code[index % 64];
5868 index /= 64;
5869 } else
5870 returnable[2] = '\0';
5871 // the following 4 lines are a joke!
5872 if ( index == 0 )
5873 index = 64*44+21;
5874 else if ( index == 64*44+21 )
5875 index = 0;
5876 returnable[1] = code[index % 64];
5877 index /= 64;
5878 } else
5879 returnable[1] = '\0';
5880 returnable[0] = code[index];
5882 return returnable;
5886 // write XPM image data
5887 static void write_xpm_image( QImageIO * iio )
5889 if ( iio )
5890 iio->setStatus( 1 );
5891 else
5892 return;
5894 // ### 8-bit case could be made faster
5895 QImage image;
5896 if ( iio->image().depth() != 32 )
5897 image = iio->image().convertDepth( 32 );
5898 else
5899 image = iio->image();
5901 QMap<QRgb, int> colorMap;
5903 int w = image.width(), h = image.height(), ncolors = 0;
5904 int x, y;
5906 // build color table
5907 for( y=0; y<h; y++ ) {
5908 QRgb * yp = (QRgb *)image.scanLine( y );
5909 for( x=0; x<w; x++ ) {
5910 QRgb color = *(yp + x);
5911 if ( !colorMap.contains(color) )
5912 colorMap.insert( color, ncolors++ );
5916 // number of 64-bit characters per pixel needed to encode all colors
5917 int cpp = 1;
5918 for ( int k = 64; ncolors > k; k *= 64 ) {
5919 ++cpp;
5920 // limit to 4 characters per pixel
5921 // 64^4 colors is enough for a 4096x4096 image
5922 if ( cpp > 4)
5923 break;
5926 QString line;
5928 // write header
5929 QTextStream s( iio->ioDevice() );
5930 s << "/* XPM */" << endl
5931 << "static char *" << fbname(iio->fileName()) << "[]={" << endl
5932 << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\"";
5934 // write palette
5935 QMap<QRgb, int>::Iterator c = colorMap.begin();
5936 while ( c != colorMap.end() ) {
5937 QRgb color = c.key();
5938 if ( image.hasAlphaBuffer() && color == (color & RGB_MASK) )
5939 line.sprintf( "\"%s c None\"",
5940 xpm_color_name(cpp, *c) );
5941 else
5942 line.sprintf( "\"%s c #%02x%02x%02x\"",
5943 xpm_color_name(cpp, *c),
5944 qRed(color),
5945 qGreen(color),
5946 qBlue(color) );
5947 ++c;
5948 s << "," << endl << line;
5951 // write pixels, limit to 4 characters per pixel
5952 line.truncate( cpp*w );
5953 for( y=0; y<h; y++ ) {
5954 QRgb * yp = (QRgb *) image.scanLine( y );
5955 int cc = 0;
5956 for( x=0; x<w; x++ ) {
5957 int color = (int)(*(yp + x));
5958 QCString chars = xpm_color_name( cpp, colorMap[color] );
5959 line[cc++] = chars[0];
5960 if ( cpp > 1 ) {
5961 line[cc++] = chars[1];
5962 if ( cpp > 2 ) {
5963 line[cc++] = chars[2];
5964 if ( cpp > 3 ) {
5965 line[cc++] = chars[3];
5970 s << "," << endl << "\"" << line << "\"";
5972 s << "};" << endl;
5974 iio->setStatus( 0 );
5977 #endif // QT_NO_IMAGEIO_XPM
5980 Returns an image with depth \a d, using the \a palette_count
5981 colors pointed to by \a palette. If \a d is 1 or 8, the returned
5982 image will have its color table ordered the same as \a palette.
5984 If the image needs to be modified to fit in a lower-resolution
5985 result (e.g. converting from 32-bit to 8-bit), use the \a
5986 conversion_flags to specify how you'd prefer this to happen.
5988 Note: currently no closest-color search is made. If colors are
5989 found that are not in the palette, the palette may not be used at
5990 all. This result should not be considered valid because it may
5991 change in future implementations.
5993 Currently inefficient for non-32-bit images.
5995 \sa Qt::ImageConversionFlags
5997 #ifndef QT_NO_IMAGE_TRUECOLOR
5998 QImage QImage::convertDepthWithPalette( int d, QRgb* palette, int palette_count, int conversion_flags ) const
6000 if ( depth() == 1 ) {
6001 return convertDepth( 8, conversion_flags )
6002 .convertDepthWithPalette( d, palette, palette_count, conversion_flags );
6003 } else if ( depth() == 8 ) {
6004 // ### this could be easily made more efficient
6005 return convertDepth( 32, conversion_flags )
6006 .convertDepthWithPalette( d, palette, palette_count, conversion_flags );
6007 } else {
6008 QImage result;
6009 convert_32_to_8( this, &result,
6010 (conversion_flags&~Qt::DitherMode_Mask) | Qt::AvoidDither,
6011 palette, palette_count );
6012 return result.convertDepth( d );
6015 #endif
6016 static
6017 bool
6018 haveSamePalette(const QImage& a, const QImage& b)
6020 if (a.depth() != b.depth()) return false;
6021 if (a.numColors() != b.numColors()) return false;
6022 QRgb* ca = a.colorTable();
6023 QRgb* cb = b.colorTable();
6024 for (int i=a.numColors(); i--; ) {
6025 if (*ca++ != *cb++) return false;
6027 return true;
6031 \relates QImage
6033 Copies a block of pixels from \a src to \a dst. The pixels
6034 copied from source (src) are converted according to
6035 \a conversion_flags if it is incompatible with the destination
6036 (\a dst).
6038 \a sx, \a sy is the top-left pixel in \a src, \a dx, \a dy
6039 is the top-left position in \a dst and \a sw, \sh is the
6040 size of the copied block.
6042 The copying is clipped if areas outside \a src or \a dst are
6043 specified.
6045 If \a sw is -1, it is adjusted to src->width(). Similarly, if \a
6046 sh is -1, it is adjusted to src->height().
6048 Currently inefficient for non 32-bit images.
6050 void bitBlt( QImage* dst, int dx, int dy, const QImage* src,
6051 int sx, int sy, int sw, int sh, int conversion_flags )
6053 // Parameter correction
6054 if ( sw < 0 ) sw = src->width();
6055 if ( sh < 0 ) sh = src->height();
6056 if ( sx < 0 ) { dx -= sx; sw += sx; sx = 0; }
6057 if ( sy < 0 ) { dy -= sy; sh += sy; sy = 0; }
6058 if ( dx < 0 ) { sx -= dx; sw += dx; dx = 0; }
6059 if ( dy < 0 ) { sy -= dy; sh += dy; dy = 0; }
6060 if ( sx + sw > src->width() ) sw = src->width() - sx;
6061 if ( sy + sh > src->height() ) sh = src->height() - sy;
6062 if ( dx + sw > dst->width() ) sw = dst->width() - dx;
6063 if ( dy + sh > dst->height() ) sh = dst->height() - dy;
6064 if ( sw <= 0 || sh <= 0 ) return; // Nothing left to copy
6065 if ( (dst->data == src->data) && dx==sx && dy==sy ) return; // Same pixels
6067 // "Easy" to copy if both same depth and one of:
6068 // - 32 bit
6069 // - 8 bit, identical palette
6070 // - 1 bit, identical palette and byte-aligned area
6072 if ( haveSamePalette(*dst,*src)
6073 && ( dst->depth() != 1 ||
6074 !( (dx&7) || (sx&7) ||
6075 ((sw&7) && (sx+sw < src->width()) ||
6076 (dx+sw < dst->width()) ) ) ) )
6078 // easy to copy
6079 } else if ( dst->depth() != 32 ) {
6080 #ifndef QT_NO_IMAGE_TRUECOLOR
6082 QImage dstconv = dst->convertDepth( 32 );
6083 bitBlt( &dstconv, dx, dy, src, sx, sy, sw, sh,
6084 (conversion_flags&~Qt::DitherMode_Mask) | Qt::AvoidDither );
6085 *dst = dstconv.convertDepthWithPalette( dst->depth(),
6086 dst->colorTable(), dst->numColors() );
6087 #endif
6088 return;
6091 // Now assume palette can be ignored
6093 if ( dst->depth() != src->depth() ) {
6094 if ( sw == src->width() && sh == src->height() || dst->depth()==32 ) {
6095 QImage srcconv = src->convertDepth( dst->depth(), conversion_flags );
6096 bitBlt( dst, dx, dy, &srcconv, sx, sy, sw, sh, conversion_flags );
6097 } else {
6098 QImage srcconv = src->copy( sx, sy, sw, sh ); // ie. bitBlt
6099 bitBlt( dst, dx, dy, &srcconv, 0, 0, sw, sh, conversion_flags );
6101 return;
6104 // Now assume both are the same depth.
6106 // Now assume both are 32-bit or 8-bit with compatible palettes.
6108 // "Easy"
6110 switch ( dst->depth() ) {
6111 case 1:
6113 uchar* d = dst->scanLine(dy) + dx/8;
6114 uchar* s = src->scanLine(sy) + sx/8;
6115 const int bw = (sw+7)/8;
6116 if ( bw < 64 ) {
6117 // Trust ourselves
6118 const int dd = dst->bytesPerLine() - bw;
6119 const int ds = src->bytesPerLine() - bw;
6120 while ( sh-- ) {
6121 for ( int t=bw; t--; )
6122 *d++ = *s++;
6123 d += dd;
6124 s += ds;
6126 } else {
6127 // Trust libc
6128 const int dd = dst->bytesPerLine();
6129 const int ds = src->bytesPerLine();
6130 while ( sh-- ) {
6131 memcpy( d, s, bw );
6132 d += dd;
6133 s += ds;
6137 break;
6138 case 8:
6140 uchar* d = dst->scanLine(dy) + dx;
6141 uchar* s = src->scanLine(sy) + sx;
6142 if ( sw < 64 ) {
6143 // Trust ourselves
6144 const int dd = dst->bytesPerLine() - sw;
6145 const int ds = src->bytesPerLine() - sw;
6146 while ( sh-- ) {
6147 for ( int t=sw; t--; )
6148 *d++ = *s++;
6149 d += dd;
6150 s += ds;
6152 } else {
6153 // Trust libc
6154 const int dd = dst->bytesPerLine();
6155 const int ds = src->bytesPerLine();
6156 while ( sh-- ) {
6157 memcpy( d, s, sw );
6158 d += dd;
6159 s += ds;
6163 break;
6164 #ifndef QT_NO_IMAGE_TRUECOLOR
6165 case 32:
6166 if ( src->hasAlphaBuffer() ) {
6167 QRgb* d = (QRgb*)dst->scanLine(dy) + dx;
6168 QRgb* s = (QRgb*)src->scanLine(sy) + sx;
6169 const int dd = dst->width() - sw;
6170 const int ds = src->width() - sw;
6171 while ( sh-- ) {
6172 for ( int t=sw; t--; ) {
6173 unsigned char a = qAlpha(*s);
6174 if ( a == 255 )
6175 *d++ = *s++;
6176 else if ( a == 0 )
6177 ++d,++s; // nothing
6178 else {
6179 unsigned char r = ((qRed(*s)-qRed(*d)) * a) / 256 + qRed(*d);
6180 unsigned char g = ((qGreen(*s)-qGreen(*d)) * a) / 256 + qGreen(*d);
6181 unsigned char b = ((qBlue(*s)-qBlue(*d)) * a) / 256 + qBlue(*d);
6182 a = qMax(qAlpha(*d),a); // alternatives...
6183 *d++ = qRgba(r,g,b,a);
6184 ++s;
6187 d += dd;
6188 s += ds;
6190 } else {
6191 QRgb* d = (QRgb*)dst->scanLine(dy) + dx;
6192 QRgb* s = (QRgb*)src->scanLine(sy) + sx;
6193 if ( sw < 64 ) {
6194 // Trust ourselves
6195 const int dd = dst->width() - sw;
6196 const int ds = src->width() - sw;
6197 while ( sh-- ) {
6198 for ( int t=sw; t--; )
6199 *d++ = *s++;
6200 d += dd;
6201 s += ds;
6203 } else {
6204 // Trust libc
6205 const int dd = dst->width();
6206 const int ds = src->width();
6207 const int b = sw*sizeof(QRgb);
6208 while ( sh-- ) {
6209 memcpy( d, s, b );
6210 d += dd;
6211 s += ds;
6215 break;
6216 #endif // QT_NO_IMAGE_TRUECOLOR
6222 Returns TRUE if this image and image \a i have the same contents;
6223 otherwise returns FALSE. The comparison can be slow, unless there
6224 is some obvious difference, such as different widths, in which
6225 case the function will return quickly.
6227 \sa operator=()
6230 bool QImage::operator==( const QImage & i ) const
6232 // same object, or shared?
6233 if ( i.data == data )
6234 return true;
6235 // obviously different stuff?
6236 if ( i.data->h != data->h ||
6237 i.data->w != data->w )
6238 return false;
6239 // that was the fast bit...
6240 QImage i1 = convertDepth( 32 );
6241 QImage i2 = i.convertDepth( 32 );
6242 int l;
6243 for( l=0; l < data->h; l++ )
6244 if ( memcmp( i1.scanLine( l ), i2.scanLine( l ), 4*data->w ) )
6245 return false;
6246 return true;
6251 Returns TRUE if this image and image \a i have different contents;
6252 otherwise returns FALSE. The comparison can be slow, unless there
6253 is some obvious difference, such as different widths, in which
6254 case the function will return quickly.
6256 \sa operator=()
6259 bool QImage::operator!=( const QImage & i ) const
6261 return !(*this == i);
6268 \fn int QImage::dotsPerMeterX() const
6270 Returns the number of pixels that fit horizontally in a physical
6271 meter. This and dotsPerMeterY() define the intended scale and
6272 aspect ratio of the image.
6274 \sa setDotsPerMeterX()
6278 \fn int QImage::dotsPerMeterY() const
6280 Returns the number of pixels that fit vertically in a physical
6281 meter. This and dotsPerMeterX() define the intended scale and
6282 aspect ratio of the image.
6284 \sa setDotsPerMeterY()
6288 Sets the value returned by dotsPerMeterX() to \a x.
6290 void QImage::setDotsPerMeterX(int x)
6292 data->dpmx = x;
6296 Sets the value returned by dotsPerMeterY() to \a y.
6298 void QImage::setDotsPerMeterY(int y)
6300 data->dpmy = y;
6304 \fn QPoint QImage::offset() const
6306 Returns the number of pixels by which the image is intended to be
6307 offset by when positioning relative to other images.
6311 Sets the value returned by offset() to \a p.
6313 void QImage::setOffset(const QPoint& p)
6315 data->offset = p;
6317 #ifndef QT_NO_IMAGE_TEXT
6319 \internal
6321 Returns the internal QImageDataMisc object. This object will be
6322 created if it doesn't already exist.
6324 QImageDataMisc& QImage::misc() const
6326 if ( !data->misc )
6327 data->misc = new QImageDataMisc;
6328 return *data->misc;
6332 Returns the string recorded for the keyword \a key in language \a
6333 lang, or in a default language if \a lang is 0.
6335 QString QImage::text(const char* key, const char* lang) const
6337 QImageTextKeyLang x(key,lang);
6338 return misc().text_lang[x];
6342 \overload
6344 Returns the string recorded for the keyword and language \a kl.
6346 QString QImage::text(const QImageTextKeyLang& kl) const
6348 return misc().text_lang[kl];
6352 Returns the language identifiers for which some texts are
6353 recorded.
6355 Note that if you want to iterate over the list, you should iterate
6356 over a copy, e.g.
6357 \code
6358 QStringList list = myImage.textLanguages();
6359 QStringList::const_iterator it = list.begin();
6360 while( it != list.end() ) {
6361 myProcessing( *it );
6362 ++it;
6364 \endcode
6366 \sa textList() text() setText() textKeys()
6368 QStringList QImage::textLanguages() const
6370 if ( !data->misc )
6371 return QStringList();
6372 return misc().languages();
6376 Returns the keywords for which some texts are recorded.
6378 Note that if you want to iterate over the list, you should iterate
6379 over a copy, e.g.
6380 \code
6381 QStringList list = myImage.textKeys();
6382 QStringList::const_iterator it = list.begin();
6383 while( it != list.end() ) {
6384 myProcessing( *it );
6385 ++it;
6387 \endcode
6389 \sa textList() text() setText() textLanguages()
6391 QStringList QImage::textKeys() const
6393 if ( !data->misc )
6394 return QStringList();
6395 return misc().keys();
6399 Returns a list of QImageTextKeyLang objects that enumerate all the
6400 texts key/language pairs set by setText() for this image.
6402 Note that if you want to iterate over the list, you should iterate
6403 over a copy, e.g.
6404 \code
6405 QValueList<QImageTextKeyLang> list = myImage.textList();
6406 QValueList<QImageTextKeyLang>::Iterator it = list.begin();
6407 while( it != list.end() ) {
6408 myProcessing( *it );
6409 ++it;
6411 \endcode
6413 QValueList<QImageTextKeyLang> QImage::textList() const
6415 if ( !data->misc )
6416 return QValueList<QImageTextKeyLang>();
6417 return misc().list();
6421 Records string \a s for the keyword \a key. The \a key should be
6422 a portable keyword recognizable by other software - some suggested
6423 values can be found in
6424 \link http://www.libpng.org/pub/png/spec/PNG-Chunks.html#C.Anc-text
6425 the PNG specification\endlink. \a s can be any text. \a lang should
6426 specify the language code (see
6427 \link ftp://ftp.isi.edu/in-notes/1766 RFC 1766\endlink) or 0.
6429 void QImage::setText(const char* key, const char* lang, const QString& s)
6431 QImageTextKeyLang x(key,lang);
6432 misc().text_lang.replace(x,s);
6435 #endif // QT_NO_IMAGE_TEXT
6437 #ifdef Q_WS_QWS
6439 \internal
6441 QGfx * QImage::graphicsContext()
6443 QGfx * ret=0;
6444 if(depth()) {
6445 int w = qt_screen->mapToDevice( QSize(width(),height()) ).width();
6446 int h = qt_screen->mapToDevice( QSize(width(),height()) ).height();
6447 ret=QGfx::createGfx(depth(),bits(),w,h,bytesPerLine());
6448 } else {
6449 qDebug("Trying to create image for null depth");
6450 return 0;
6452 if(depth()<=8) {
6453 QRgb * tmp=colorTable();
6454 int nc=numColors();
6455 if(tmp==0) {
6456 static QRgb table[2] = { qRgb(255,255,255), qRgb(0,0,0) };
6457 tmp=table;
6458 nc=2;
6460 ret->setClut(tmp,nc);
6462 return ret;
6465 #endif