source: vendor/trolltech/current/src/kernel/qimage.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 168.9 KB
Line 
1/****************************************************************************
2** $Id: qimage.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QImage and QImageIO classes
5**
6** Created : 950207
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qimage.h"
39#include "qregexp.h"
40#include "qfile.h"
41#include "qdatastream.h"
42#include "qtextstream.h"
43#include "qbuffer.h"
44#include "qptrlist.h"
45#include "qasyncimageio.h"
46#include "qpngio.h"
47#include "qmngio.h"
48#include "qjpegio.h"
49#include "qmap.h"
50#include <private/qpluginmanager_p.h>
51#include "qimageformatinterface_p.h"
52#include "qwmatrix.h"
53#include "qapplication.h"
54#include "qmime.h"
55#include "qdragobject.h"
56#include <ctype.h>
57#include <stdlib.h>
58
59#ifdef Q_WS_QWS
60#include "qgfx_qws.h"
61#endif
62
63// 16bpp images on supported on Qt/Embedded
64#if !defined( Q_WS_QWS ) && !defined(QT_NO_IMAGE_16_BIT)
65#define QT_NO_IMAGE_16_BIT
66#endif
67
68
69/*!
70 \class QImage
71 \brief The QImage class provides a hardware-independent pixmap
72 representation with direct access to the pixel data.
73
74 \ingroup images
75 \ingroup graphics
76 \ingroup shared
77 \mainclass
78
79 It is one of the two classes Qt provides for dealing with images,
80 the other being QPixmap. QImage is designed and optimized for I/O
81 and for direct pixel access/manipulation. QPixmap is designed and
82 optimized for drawing. There are (slow) functions to convert
83 between QImage and QPixmap: QPixmap::convertToImage() and
84 QPixmap::convertFromImage().
85
86 An image has the parameters \link width() width\endlink, \link
87 height() height\endlink and \link depth() depth\endlink (bits per
88 pixel, bpp), a color table and the actual \link bits()
89 pixels\endlink. QImage supports 1-bpp, 8-bpp and 32-bpp image
90 data. 1-bpp and 8-bpp images use a color lookup table; the pixel
91 value is a color table index.
92
93 32-bpp images encode an RGB value in 24 bits and ignore the color
94 table. The most significant byte is used for the \link
95 setAlphaBuffer() alpha buffer\endlink.
96
97 An entry in the color table is an RGB triplet encoded as a \c
98 uint. Use the \link ::qRed() qRed()\endlink, \link ::qGreen()
99 qGreen()\endlink and \link ::qBlue() qBlue()\endlink functions (\c
100 qcolor.h) to access the components, and \link ::qRgb()
101 qRgb\endlink to make an RGB triplet (see the QColor class
102 documentation).
103
104 1-bpp (monochrome) images have a color table with a most two
105 colors. There are two different formats: big endian (MSB first) or
106 little endian (LSB first) bit order. To access a single bit you
107 will must do some bit shifts:
108
109 \code
110 QImage image;
111 // sets bit at (x,y) to 1
112 if ( image.bitOrder() == QImage::LittleEndian )
113 *(image.scanLine(y) + (x >> 3)) |= 1 << (x & 7);
114 else
115 *(image.scanLine(y) + (x >> 3)) |= 1 << (7 - (x & 7));
116 \endcode
117
118 If this looks complicated, it might be a good idea to convert the
119 1-bpp image to an 8-bpp image using convertDepth().
120
121 8-bpp images are much easier to work with than 1-bpp images
122 because they have a single byte per pixel:
123
124 \code
125 QImage image;
126 // set entry 19 in the color table to yellow
127 image.setColor( 19, qRgb(255,255,0) );
128 // set 8 bit pixel at (x,y) to value yellow (in color table)
129 *(image.scanLine(y) + x) = 19;
130 \endcode
131
132 32-bpp images ignore the color table; instead, each pixel contains
133 the RGB triplet. 24 bits contain the RGB value; the most
134 significant byte is reserved for the alpha buffer.
135
136 \code
137 QImage image;
138 // sets 32 bit pixel at (x,y) to yellow.
139 uint *p = (uint *)image.scanLine(y) + x;
140 *p = qRgb(255,255,0);
141 \endcode
142
143 On Qt/Embedded, scanlines are aligned to the pixel depth and may
144 be padded to any degree, while on all other platforms, the
145 scanlines are 32-bit aligned for all depths. The constructor
146 taking a \c{uchar*} argument always expects 32-bit aligned data.
147 On Qt/Embedded, an additional constructor allows the number of
148 bytes-per-line to be specified.
149
150 QImage supports a variety of methods for getting information about
151 the image, for example, colorTable(), allGray(), isGrayscale(),
152 bitOrder(), bytesPerLine(), depth(), dotsPerMeterX() and
153 dotsPerMeterY(), hasAlphaBuffer(), numBytes(), numColors(), and
154 width() and height().
155
156 Pixel colors are retrieved with pixel() and set with setPixel().
157
158 QImage also supports a number of functions for creating a new
159 image that is a transformed version of the original. For example,
160 copy(), convertBitOrder(), convertDepth(), createAlphaMask(),
161 createHeuristicMask(), mirror(), scale(), smoothScale(), swapRGB()
162 and xForm(). There are also functions for changing attributes of
163 an image in-place, for example, setAlphaBuffer(), setColor(),
164 setDotsPerMeterX() and setDotsPerMeterY() and setNumColors().
165
166 Images can be loaded and saved in the supported formats. Images
167 are saved to a file with save(). Images are loaded from a file
168 with load() (or in the constructor) or from an array of data with
169 loadFromData(). The lists of supported formats are available from
170 inputFormatList() and outputFormatList().
171
172 Strings of text may be added to images using setText().
173
174 The QImage class uses explicit \link shclass.html sharing\endlink,
175 similar to that used by QMemArray.
176
177 New image formats can be added as \link plugins-howto.html
178 plugins\endlink.
179
180 \sa QImageIO QPixmap \link shclass.html Shared Classes\endlink
181*/
182
183
184/*!
185 \enum QImage::Endian
186
187 This enum type is used to describe the endianness of the CPU and
188 graphics hardware.
189
190 \value IgnoreEndian Endianness does not matter. Useful for some
191 operations that are independent of endianness.
192 \value BigEndian Network byte order, as on SPARC and Motorola CPUs.
193 \value LittleEndian PC/Alpha byte order.
194*/
195
196/*!
197 \enum Qt::ImageConversionFlags
198
199 The conversion flag is a bitwise-OR of the following values. The
200 options marked "(default)" are set if no other values from the
201 list are included (since the defaults are zero):
202
203 Color/Mono preference (ignored for QBitmap)
204 \value AutoColor (default) - If the image has \link
205 QImage::depth() depth\endlink 1 and contains only
206 black and white pixels, the pixmap becomes monochrome.
207 \value ColorOnly The pixmap is dithered/converted to the
208 \link QPixmap::defaultDepth() native display depth\endlink.
209 \value MonoOnly The pixmap becomes monochrome. If necessary,
210 it is dithered using the chosen dithering algorithm.
211
212 Dithering mode preference for RGB channels
213 \value DiffuseDither (default) - A high-quality dither.
214 \value OrderedDither A faster, more ordered dither.
215 \value ThresholdDither No dithering; closest color is used.
216
217 Dithering mode preference for alpha channel
218 \value ThresholdAlphaDither (default) - No dithering.
219 \value OrderedAlphaDither A faster, more ordered dither.
220 \value DiffuseAlphaDither A high-quality dither.
221 \value NoAlpha Not supported.
222
223 Color matching versus dithering preference
224 \value PreferDither (default when converting to a pixmap) - Always dither
225 32-bit images when the image is converted to 8 bits.
226 \value AvoidDither (default when converting for the purpose of saving to
227 file) - Dither 32-bit images only if the image has more than 256
228 colors and it is being converted to 8 bits.
229 \value AutoDither Not supported.
230
231 The following are not values that are used directly, but masks for
232 the above classes:
233 \value ColorMode_Mask Mask for the color mode.
234 \value Dither_Mask Mask for the dithering mode for RGB channels.
235 \value AlphaDither_Mask Mask for the dithering mode for the alpha channel.
236 \value DitherMode_Mask Mask for the mode that determines the preference of
237 color matching versus dithering.
238
239 Using 0 as the conversion flag sets all the default options.
240*/
241
242#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
243#pragma message disable narrowptr
244#endif
245
246#ifndef QT_NO_IMAGE_TEXT
247class QImageDataMisc {
248public:
249 QImageDataMisc() { }
250 QImageDataMisc( const QImageDataMisc& o ) :
251 text_lang(o.text_lang) { }
252
253 QImageDataMisc& operator=(const QImageDataMisc& o)
254 {
255 text_lang = o.text_lang;
256 return *this;
257 }
258 QValueList<QImageTextKeyLang> list()
259 {
260 return text_lang.keys();
261 }
262
263 QStringList languages()
264 {
265 QStringList r;
266 QMap<QImageTextKeyLang,QString>::Iterator it = text_lang.begin();
267 for ( ; it != text_lang.end(); ++it ) {
268 r.remove( it.key().lang );
269 r.append( it.key().lang );
270 }
271 return r;
272 }
273 QStringList keys()
274 {
275 QStringList r;
276 QMap<QImageTextKeyLang,QString>::Iterator it = text_lang.begin();
277 for ( ; it != text_lang.end(); ++it ) {
278 r.remove( it.key().key );
279 r.append( it.key().key );
280 }
281 return r;
282 }
283
284 QMap<QImageTextKeyLang,QString> text_lang;
285};
286#endif // QT_NO_IMAGE_TEXT
287
288
289
290/*****************************************************************************
291 QImage member functions
292 *****************************************************************************/
293
294// table to flip bits
295static const uchar bitflip[256] = {
296 /*
297 open OUT, "| fmt";
298 for $i (0..255) {
299 print OUT (($i >> 7) & 0x01) | (($i >> 5) & 0x02) |
300 (($i >> 3) & 0x04) | (($i >> 1) & 0x08) |
301 (($i << 7) & 0x80) | (($i << 5) & 0x40) |
302 (($i << 3) & 0x20) | (($i << 1) & 0x10), ", ";
303 }
304 close OUT;
305 */
306 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
307 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
308 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
309 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
310 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
311 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
312 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
313 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
314 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
315 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
316 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
317 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
318 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
319 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
320 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
321 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
322};
323
324const uchar *qt_get_bitflip_array() // called from QPixmap code
325{
326 return bitflip;
327}
328
329
330/*!
331 Constructs a null image.
332
333 \sa isNull()
334*/
335
336QImage::QImage()
337{
338 init();
339}
340
341/*!
342 Constructs an image with \a w width, \a h height, \a depth bits
343 per pixel, \a numColors colors and bit order \a bitOrder.
344
345 Using this constructor is the same as first constructing a null
346 image and then calling the create() function.
347
348 \sa create()
349*/
350
351QImage::QImage( int w, int h, int depth, int numColors, Endian bitOrder )
352{
353 init();
354 create( w, h, depth, numColors, bitOrder );
355}
356
357/*!
358 Constructs an image with size \a size pixels, depth \a depth bits,
359 \a numColors and \a bitOrder endianness.
360
361 Using this constructor is the same as first constructing a null
362 image and then calling the create() function.
363
364 \sa create()
365*/
366QImage::QImage( const QSize& size, int depth, int numColors, Endian bitOrder )
367{
368 init();
369 create( size, depth, numColors, bitOrder );
370}
371
372#ifndef QT_NO_IMAGEIO
373/*!
374 Constructs an image and tries to load the image from the file \a
375 fileName.
376
377 If \a format is specified, the loader attempts to read the image
378 using the specified format. If \a format is not specified (which
379 is the default), the loader reads a few bytes from the header to
380 guess the file format.
381
382 If the loading of the image failed, this object is a \link
383 isNull() null\endlink image.
384
385 The QImageIO documentation lists the supported image formats and
386 explains how to add extra formats.
387
388 \sa load() isNull() QImageIO
389*/
390
391QImage::QImage( const QString &fileName, const char* format )
392{
393 init();
394 load( fileName, format );
395}
396
397#ifndef QT_NO_IMAGEIO_XPM
398// helper
399static void read_xpm_image_or_array( QImageIO *, const char * const *, QImage & );
400#endif
401/*!
402 Constructs an image from \a xpm, which must be a valid XPM image.
403
404 Errors are silently ignored.
405
406 Note that it's possible to squeeze the XPM variable a little bit
407 by using an unusual declaration:
408
409 \code
410 static const char * const start_xpm[]={
411 "16 15 8 1",
412 "a c #cec6bd",
413 ....
414 \endcode
415
416 The extra \c const makes the entire definition read-only, which is
417 slightly more efficient (e.g. when the code is in a shared
418 library) and ROMable when the application is to be stored in ROM.
419*/
420
421QImage::QImage( const char * const xpm[] )
422{
423 init();
424#ifndef QT_NO_IMAGEIO_XPM
425 read_xpm_image_or_array( 0, xpm, *this );
426#else
427 // We use a qFatal rather than disabling the whole function, as this
428 // constructor may be ambiguous.
429 qFatal("XPM not supported");
430#endif
431}
432
433/*!
434 Constructs an image from the binary data \a array. It tries to
435 guess the file format.
436
437 If the loading of the image failed, this object is a \link
438 isNull() null\endlink image.
439
440 \sa loadFromData() isNull() imageFormat()
441*/
442QImage::QImage( const QByteArray &array )
443{
444 init();
445 loadFromData(array);
446}
447#endif //QT_NO_IMAGEIO
448
449
450/*!
451 Constructs a \link shclass.html shallow copy\endlink of \a image.
452*/
453
454QImage::QImage( const QImage &image )
455{
456 data = image.data;
457 data->ref();
458}
459
460/*!
461 Constructs an image \a w pixels wide, \a h pixels high with a
462 color depth of \a depth, that uses an existing memory buffer, \a
463 yourdata. The buffer must remain valid throughout the life of the
464 QImage. The image does not delete the buffer at destruction.
465
466 If \a colortable is 0, a color table sufficient for \a numColors
467 will be allocated (and destructed later).
468
469 Note that \a yourdata must be 32-bit aligned.
470
471 The endianness is given in \a bitOrder.
472*/
473QImage::QImage( uchar* yourdata, int w, int h, int depth,
474 QRgb* colortable, int numColors,
475 Endian bitOrder )
476{
477 init();
478 if ( w <= 0 || h <= 0 || depth <= 0 || numColors < 0 )
479 return; // invalid parameter(s)
480 data->w = w;
481 data->h = h;
482 data->d = depth;
483 data->ncols = depth != 32 ? numColors : 0;
484 if ( !yourdata )
485 return; // Image header info can be saved without needing to allocate memory.
486 int bpl = ((w*depth+31)/32)*4; // bytes per scanline
487 data->nbytes = bpl*h;
488 if ( colortable || !data->ncols ) {
489 data->ctbl = colortable;
490 data->ctbl_mine = FALSE;
491 } else {
492 // calloc since we realloc, etc. later (ick)
493 data->ctbl = (QRgb*)calloc( data->ncols*sizeof(QRgb), data->ncols );
494 data->ctbl_mine = TRUE;
495 }
496 uchar** jt = (uchar**)malloc(h*sizeof(uchar*));
497 for (int j=0; j<h; j++) {
498 jt[j] = yourdata+j*bpl;
499 }
500 data->bits = jt;
501 data->bitordr = bitOrder;
502}
503
504#ifdef Q_WS_QWS
505
506/*!
507 Constructs an image that uses an existing memory buffer. The
508 buffer must remain valid for the life of the QImage. The image
509 does not delete the buffer at destruction. The buffer is passed as
510 \a yourdata. The image's width is \a w and its height is \a h. The
511 color depth is \a depth. \a bpl specifies the number of bytes per
512 line.
513
514 If \a colortable is 0, a color table sufficient for \a numColors
515 will be allocated (and destructed later).
516
517 The endianness is specified by \a bitOrder.
518
519 \warning This constructor is only available on Qt/Embedded.
520*/
521QImage::QImage( uchar* yourdata, int w, int h, int depth,
522 int bpl, QRgb* colortable, int numColors,
523 Endian bitOrder )
524{
525 init();
526 if ( !yourdata || w <= 0 || h <= 0 || depth <= 0 || numColors < 0 )
527 return; // invalid parameter(s)
528 data->w = w;
529 data->h = h;
530 data->d = depth;
531 data->ncols = numColors;
532 data->nbytes = bpl * h;
533 if ( colortable || !numColors ) {
534 data->ctbl = colortable;
535 data->ctbl_mine = FALSE;
536 } else {
537 // calloc since we realloc, etc. later (ick)
538 data->ctbl = (QRgb*)calloc( numColors*sizeof(QRgb), numColors );
539 data->ctbl_mine = TRUE;
540 }
541 uchar** jt = (uchar**)malloc(h*sizeof(uchar*));
542 for (int j=0; j<h; j++) {
543 jt[j] = yourdata+j*bpl;
544 }
545 data->bits = jt;
546 data->bitordr = bitOrder;
547}
548#endif // Q_WS_QWS
549
550/*!
551 Destroys the image and cleans up.
552*/
553
554QImage::~QImage()
555{
556 if ( data && data->deref() ) {
557 reset();
558 delete data;
559 }
560}
561
562
563
564
565/*! Convenience function. Gets the data associated with the absolute
566 name \a abs_name from the default mime source factory and decodes it
567 to an image.
568
569 \sa QMimeSourceFactory, QImage::fromMimeSource(), QImageDrag::decode()
570*/
571#ifndef QT_NO_MIME
572QImage QImage::fromMimeSource( const QString &abs_name )
573{
574 const QMimeSource *m = QMimeSourceFactory::defaultFactory()->data( abs_name );
575 if ( !m ) {
576#if defined(QT_CHECK_STATE)
577 qWarning("QImage::fromMimeSource: Cannot find image \"%s\" in the mime source factory", abs_name.latin1() );
578#endif
579 return QImage();
580 }
581 QImage img;
582 QImageDrag::decode( m, img );
583 return img;
584}
585#endif
586
587
588/*!
589 Assigns a \link shclass.html shallow copy\endlink of \a image to
590 this image and returns a reference to this image.
591
592 \sa copy()
593*/
594
595QImage &QImage::operator=( const QImage &image )
596{
597 image.data->ref(); // avoid 'x = x'
598 if ( data->deref() ) {
599 reset();
600 delete data;
601 }
602 data = image.data;
603 return *this;
604}
605
606/*!
607 \overload
608
609 Sets the image bits to the \a pixmap contents and returns a
610 reference to the image.
611
612 If the image shares data with other images, it will first
613 dereference the shared data.
614
615 Makes a call to QPixmap::convertToImage().
616*/
617
618QImage &QImage::operator=( const QPixmap &pixmap )
619{
620 *this = pixmap.convertToImage();
621 return *this;
622}
623
624/*!
625 Detaches from shared image data and makes sure that this image is
626 the only one referring to the data.
627
628 If multiple images share common data, this image makes a copy of
629 the data and detaches itself from the sharing mechanism.
630 Nothing is done if there is just a single reference.
631
632 \sa copy()
633*/
634
635void QImage::detach()
636{
637 if ( data->count != 1 )
638 *this = copy();
639}
640
641/*!
642 Returns a \link shclass.html deep copy\endlink of the image.
643
644 \sa detach()
645*/
646
647QImage QImage::copy() const
648{
649 if ( isNull() ) {
650 // maintain the fields of invalid QImages when copied
651 return QImage( 0, width(), height(), depth(), colorTable(), numColors(), bitOrder() );
652 } else {
653 QImage image;
654 image.create( width(), height(), depth(), numColors(), bitOrder() );
655#ifdef Q_WS_QWS
656 // Qt/Embedded can create images with non-default bpl
657 // make sure we don't crash.
658 if ( image.numBytes() != numBytes() )
659 for ( int i = 0; i < height(); i++ )
660 memcpy( image.scanLine(i), scanLine(i), image.bytesPerLine() );
661 else
662#endif
663 memcpy( image.bits(), bits(), numBytes() );
664 memcpy( image.colorTable(), colorTable(), numColors() * sizeof(QRgb) );
665 image.setAlphaBuffer( hasAlphaBuffer() );
666 image.data->dpmx = dotsPerMeterX();
667 image.data->dpmy = dotsPerMeterY();
668 image.data->offset = offset();
669#ifndef QT_NO_IMAGE_TEXT
670 if ( data->misc ) {
671 image.data->misc = new QImageDataMisc;
672 *image.data->misc = misc();
673 }
674#endif
675 return image;
676 }
677}
678
679/*!
680 \overload
681
682 Returns a \link shclass.html deep copy\endlink of a sub-area of
683 the image.
684
685 The returned image is always \a w by \a h pixels in size, and is
686 copied from position \a x, \a y in this image. In areas beyond
687 this image pixels are filled with pixel 0.
688
689 If the image needs to be modified to fit in a lower-resolution
690 result (e.g. converting from 32-bit to 8-bit), use the \a
691 conversion_flags to specify how you'd prefer this to happen.
692
693 \sa bitBlt() Qt::ImageConversionFlags
694*/
695
696QImage QImage::copy(int x, int y, int w, int h, int conversion_flags) const
697{
698 int dx = 0;
699 int dy = 0;
700 if ( w <= 0 || h <= 0 ) return QImage(); // Nothing to copy
701
702 QImage image( w, h, depth(), numColors(), bitOrder() );
703
704 if ( x < 0 || y < 0 || x + w > width() || y + h > height() ) {
705 // bitBlt will not cover entire image - clear it.
706 // ### should deal with each side separately for efficiency
707 image.fill(0);
708 if ( x < 0 ) {
709 dx = -x;
710 x = 0;
711 }
712 if ( y < 0 ) {
713 dy = -y;
714 y = 0;
715 }
716 }
717
718 bool has_alpha = hasAlphaBuffer();
719 if ( has_alpha ) {
720 // alpha channel should be only copied, not used by bitBlt(), and
721 // this is mutable, we will restore the image state before returning
722 QImage *that = (QImage *) this;
723 that->setAlphaBuffer( FALSE );
724 }
725 memcpy( image.colorTable(), colorTable(), numColors()*sizeof(QRgb) );
726 bitBlt( &image, dx, dy, this, x, y, -1, -1, conversion_flags );
727 if ( has_alpha ) {
728 // restore image state
729 QImage *that = (QImage *) this;
730 that->setAlphaBuffer( TRUE );
731 }
732 image.setAlphaBuffer(hasAlphaBuffer());
733 return image;
734}
735
736/*!
737 \overload QImage QImage::copy(const QRect& r) const
738
739 Returns a \link shclass.html deep copy\endlink of a sub-area of
740 the image.
741
742 The returned image always has the size of the rectangle \a r. In
743 areas beyond this image pixels are filled with pixel 0.
744*/
745
746/*!
747 \fn bool QImage::isNull() const
748
749 Returns TRUE if it is a null image; otherwise returns FALSE.
750
751 A null image has all parameters set to zero and no allocated data.
752*/
753
754
755/*!
756 \fn int QImage::width() const
757
758 Returns the width of the image.
759
760 \sa height() size() rect()
761*/
762
763/*!
764 \fn int QImage::height() const
765
766 Returns the height of the image.
767
768 \sa width() size() rect()
769*/
770
771/*!
772 \fn QSize QImage::size() const
773
774 Returns the size of the image, i.e. its width and height.
775
776 \sa width() height() rect()
777*/
778
779/*!
780 \fn QRect QImage::rect() const
781
782 Returns the enclosing rectangle (0, 0, width(), height()) of the
783 image.
784
785 \sa width() height() size()
786*/
787
788/*!
789 \fn int QImage::depth() const
790
791 Returns the depth of the image.
792
793 The image depth is the number of bits used to encode a single
794 pixel, also called bits per pixel (bpp) or bit planes of an image.
795
796 The supported depths are 1, 8, 16 (Qt/Embedded only) and 32.
797
798 \sa convertDepth()
799*/
800
801/*!
802 \fn int QImage::numColors() const
803
804 Returns the size of the color table for the image.
805
806 Notice that numColors() returns 0 for 16-bpp (Qt/Embedded only)
807 and 32-bpp images because these images do not use color tables,
808 but instead encode pixel values as RGB triplets.
809
810 \sa setNumColors() colorTable()
811*/
812
813/*!
814 \fn QImage::Endian QImage::bitOrder() const
815
816 Returns the bit order for the image.
817
818 If it is a 1-bpp image, this function returns either
819 QImage::BigEndian or QImage::LittleEndian.
820
821 If it is not a 1-bpp image, this function returns
822 QImage::IgnoreEndian.
823
824 \sa depth()
825*/
826
827/*!
828 \fn uchar **QImage::jumpTable() const
829
830 Returns a pointer to the scanline pointer table.
831
832 This is the beginning of the data block for the image.
833
834 \sa bits() scanLine()
835*/
836
837/*!
838 \fn QRgb *QImage::colorTable() const
839
840 Returns a pointer to the color table.
841
842 \sa numColors()
843*/
844
845/*!
846 \fn int QImage::numBytes() const
847
848 Returns the number of bytes occupied by the image data.
849
850 \sa bytesPerLine() bits()
851*/
852
853/*!
854 \fn int QImage::bytesPerLine() const
855
856 Returns the number of bytes per image scanline. This is equivalent
857 to numBytes()/height().
858
859 \sa numBytes() scanLine()
860*/
861
862/*!
863 \fn QRgb QImage::color( int i ) const
864
865 Returns the color in the color table at index \a i. The first
866 color is at index 0.
867
868 A color value is an RGB triplet. Use the \link ::qRed()
869 qRed()\endlink, \link ::qGreen() qGreen()\endlink and \link
870 ::qBlue() qBlue()\endlink functions (defined in \c qcolor.h) to
871 get the color value components.
872
873 \sa setColor() numColors() QColor
874*/
875
876/*!
877 \fn void QImage::setColor( int i, QRgb c )
878
879 Sets a color in the color table at index \a i to \a c.
880
881 A color value is an RGB triplet. Use the \link ::qRgb()
882 qRgb()\endlink function (defined in \c qcolor.h) to make RGB
883 triplets.
884
885 \sa color() setNumColors() numColors()
886*/
887
888/*!
889 \fn uchar *QImage::scanLine( int i ) const
890
891 Returns a pointer to the pixel data at the scanline with index \a
892 i. The first scanline is at index 0.
893
894 The scanline data is aligned on a 32-bit boundary.
895
896 \warning If you are accessing 32-bpp image data, cast the returned
897 pointer to \c{QRgb*} (QRgb has a 32-bit size) and use it to
898 read/write the pixel value. You cannot use the \c{uchar*} pointer
899 directly, because the pixel format depends on the byte order on
900 the underlying platform. Hint: use \link ::qRed() qRed()\endlink,
901 \link ::qGreen() qGreen()\endlink and \link ::qBlue()
902 qBlue()\endlink, etc. (qcolor.h) to access the pixels.
903
904 \warning If you are accessing 16-bpp image data, you must handle
905 endianness yourself. (Qt/Embedded only)
906
907 \sa bytesPerLine() bits() jumpTable()
908*/
909
910/*!
911 \fn uchar *QImage::bits() const
912
913 Returns a pointer to the first pixel data. This is equivalent to
914 scanLine(0).
915
916 \sa numBytes() scanLine() jumpTable()
917*/
918
919
920
921void QImage::warningIndexRange( const char *func, int i )
922{
923#if defined(QT_CHECK_RANGE)
924 qWarning( "QImage::%s: Index %d out of range", func, i );
925#else
926 Q_UNUSED( func )
927 Q_UNUSED( i )
928#endif
929}
930
931
932/*!
933 Resets all image parameters and deallocates the image data.
934*/
935
936void QImage::reset()
937{
938 freeBits();
939 setNumColors( 0 );
940#ifndef QT_NO_IMAGE_TEXT
941 delete data->misc;
942#endif
943 reinit();
944}
945
946
947/*!
948 Fills the entire image with the pixel value \a pixel.
949
950 If the \link depth() depth\endlink of this image is 1, only the
951 lowest bit is used. If you say fill(0), fill(2), etc., the image
952 is filled with 0s. If you say fill(1), fill(3), etc., the image is
953 filled with 1s. If the depth is 8, the lowest 8 bits are used.
954
955 If the depth is 32 and the image has no alpha buffer, the \a pixel
956 value is written to each pixel in the image. If the image has an
957 alpha buffer, only the 24 RGB bits are set and the upper 8 bits
958 (alpha value) are left unchanged.
959
960 Note: QImage::pixel() returns the color of the pixel at the given
961 coordinates; QColor::pixel() returns the pixel value of the
962 underlying window system (essentially an index value), so normally
963 you will want to use QImage::pixel() to use a color from an
964 existing image or QColor::rgb() to use a specific color.
965
966 \sa invertPixels() depth() hasAlphaBuffer() create()
967*/
968
969void QImage::fill( uint pixel )
970{
971 if ( depth() == 1 || depth() == 8 ) {
972 if ( depth() == 1 ) {
973 if ( pixel & 1 )
974 pixel = 0xffffffff;
975 else
976 pixel = 0;
977 } else {
978 uint c = pixel & 0xff;
979 pixel = c | ((c << 8) & 0xff00) | ((c << 16) & 0xff0000) |
980 ((c << 24) & 0xff000000);
981 }
982 int bpl = bytesPerLine();
983 for ( int i=0; i<height(); i++ )
984 memset( scanLine(i), pixel, bpl );
985#ifndef QT_NO_IMAGE_16_BIT
986 } else if ( depth() == 16 ) {
987 for ( int i=0; i<height(); i++ ) {
988 //optimize with 32-bit writes, since image is always aligned
989 uint *p = (uint *)scanLine(i);
990 uint *end = (uint*)(((ushort*)p) + width());
991 uint fill;
992 ushort *f = (ushort*)&fill;
993 f[0]=pixel;
994 f[1]=pixel;
995 while ( p < end )
996 *p++ = fill;
997 }
998#endif // QT_NO_IMAGE_16_BIT
999#ifndef QT_NO_IMAGE_TRUECOLOR
1000 } else if ( depth() == 32 ) {
1001 if ( hasAlphaBuffer() ) {
1002 pixel &= 0x00ffffff;
1003 for ( int i=0; i<height(); i++ ) {
1004 uint *p = (uint *)scanLine(i);
1005 uint *end = p + width();
1006 while ( p < end ) {
1007 *p = (*p & 0xff000000) | pixel;
1008 p++;
1009 }
1010 }
1011 } else {
1012 for ( int i=0; i<height(); i++ ) {
1013 uint *p = (uint *)scanLine(i);
1014 uint *end = p + width();
1015 while ( p < end )
1016 *p++ = pixel;
1017 }
1018 }
1019#endif // QT_NO_IMAGE_TRUECOLOR
1020 }
1021}
1022
1023
1024/*!
1025 Inverts all pixel values in the image.
1026
1027 If the depth is 32: if \a invertAlpha is TRUE, the alpha bits are
1028 also inverted, otherwise they are left unchanged.
1029
1030 If the depth is not 32, the argument \a invertAlpha has no
1031 meaning.
1032
1033 Note that inverting an 8-bit image means to replace all pixels
1034 using color index \e i with a pixel using color index 255 minus \e
1035 i. Similarly for a 1-bit image. The color table is not changed.
1036
1037 \sa fill() depth() hasAlphaBuffer()
1038*/
1039
1040void QImage::invertPixels( bool invertAlpha )
1041{
1042 Q_UINT32 n = numBytes();
1043 if ( n % 4 ) {
1044 Q_UINT8 *p = (Q_UINT8*)bits();
1045 Q_UINT8 *end = p + n;
1046 while ( p < end )
1047 *p++ ^= 0xff;
1048 } else {
1049 Q_UINT32 *p = (Q_UINT32*)bits();
1050 Q_UINT32 *end = p + n/4;
1051 uint xorbits = invertAlpha && depth() == 32 ? 0x00ffffff : 0xffffffff;
1052 while ( p < end )
1053 *p++ ^= xorbits;
1054 }
1055}
1056
1057
1058/*!
1059 Determines the host computer byte order. Returns
1060 QImage::LittleEndian (LSB first) or QImage::BigEndian (MSB first).
1061
1062 \sa systemBitOrder()
1063*/
1064
1065QImage::Endian QImage::systemByteOrder()
1066{
1067 static Endian sbo = IgnoreEndian;
1068 if ( sbo == IgnoreEndian ) { // initialize
1069 int ws;
1070 bool be;
1071 qSysInfo( &ws, &be );
1072 sbo = be ? BigEndian : LittleEndian;
1073 }
1074 return sbo;
1075}
1076
1077
1078#if defined(Q_WS_X11)
1079#include <X11/Xlib.h> // needed for systemBitOrder
1080#include <X11/Xutil.h>
1081#include <X11/Xos.h>
1082#if defined(Q_OS_WIN32)
1083#undef open
1084#undef close
1085#undef read
1086#undef write
1087#endif
1088#endif
1089
1090// POSIX Large File Support redefines open -> open64
1091#if defined(open)
1092# undef open
1093#endif
1094
1095// POSIX Large File Support redefines truncate -> truncate64
1096#if defined(truncate)
1097# undef truncate
1098#endif
1099
1100/*!
1101 Determines the bit order of the display hardware. Returns
1102 QImage::LittleEndian (LSB first) or QImage::BigEndian (MSB first).
1103
1104 \sa systemByteOrder()
1105*/
1106
1107QImage::Endian QImage::systemBitOrder()
1108{
1109#if defined(Q_WS_X11)
1110 return BitmapBitOrder(qt_xdisplay()) == MSBFirst ? BigEndian :LittleEndian;
1111#else
1112 return BigEndian;
1113#endif
1114}
1115
1116
1117/*!
1118 Resizes the color table to \a numColors colors.
1119
1120 If the color table is expanded all the extra colors will be set to
1121 black (RGB 0,0,0).
1122
1123 \sa numColors() color() setColor() colorTable()
1124*/
1125
1126void QImage::setNumColors( int numColors )
1127{
1128 if ( numColors == data->ncols )
1129 return;
1130 if ( numColors == 0 ) { // use no color table
1131 if ( data->ctbl ) {
1132 if ( data->ctbl_mine )
1133 free( data->ctbl );
1134 else
1135 data->ctbl_mine = TRUE;
1136 data->ctbl = 0;
1137 }
1138 data->ncols = 0;
1139 return;
1140 }
1141 if ( data->ctbl && data->ctbl_mine ) { // already has color table
1142 data->ctbl = (QRgb*)realloc( data->ctbl, numColors*sizeof(QRgb) );
1143 if ( data->ctbl && numColors > data->ncols )
1144 memset( (char *)&data->ctbl[data->ncols], 0,
1145 (numColors-data->ncols)*sizeof(QRgb) );
1146 } else { // create new color table
1147 data->ctbl = (QRgb*)calloc( numColors*sizeof(QRgb), 1 );
1148 data->ctbl_mine = TRUE;
1149 }
1150 data->ncols = data->ctbl == 0 ? 0 : numColors;
1151}
1152
1153
1154/*!
1155 \fn bool QImage::hasAlphaBuffer() const
1156
1157 Returns TRUE if alpha buffer mode is enabled; otherwise returns
1158 FALSE.
1159
1160 \sa setAlphaBuffer()
1161*/
1162
1163/*!
1164 Enables alpha buffer mode if \a enable is TRUE, otherwise disables
1165 it. The default setting is disabled.
1166
1167 An 8-bpp image has 8-bit pixels. A pixel is an index into the
1168 \link color() color table\endlink, which contains 32-bit color
1169 values. In a 32-bpp image, the 32-bit pixels are the color values.
1170
1171 This 32-bit value is encoded as follows: The lower 24 bits are
1172 used for the red, green, and blue components. The upper 8 bits
1173 contain the alpha component.
1174
1175 The alpha component specifies the transparency of a pixel. 0 means
1176 completely transparent and 255 means opaque. The alpha component
1177 is ignored if you do not enable alpha buffer mode.
1178
1179 The alpha buffer is used to set a mask when a QImage is translated
1180 to a QPixmap.
1181
1182 \sa hasAlphaBuffer() createAlphaMask()
1183*/
1184
1185void QImage::setAlphaBuffer( bool enable )
1186{
1187 data->alpha = enable;
1188}
1189
1190
1191/*!
1192 Sets the image \a width, \a height, \a depth, its number of colors
1193 (in \a numColors), and bit order. Returns TRUE if successful, or
1194 FALSE if the parameters are incorrect or if memory cannot be
1195 allocated.
1196
1197 The \a width and \a height is limited to 32767. \a depth must be
1198 1, 8, or 32. If \a depth is 1, \a bitOrder must be set to
1199 either QImage::LittleEndian or QImage::BigEndian. For other depths
1200 \a bitOrder must be QImage::IgnoreEndian.
1201
1202 This function allocates a color table and a buffer for the image
1203 data. The image data is not initialized.
1204
1205 The image buffer is allocated as a single block that consists of a
1206 table of \link scanLine() scanline\endlink pointers (jumpTable())
1207 and the image data (bits()).
1208
1209 \sa fill() width() height() depth() numColors() bitOrder()
1210 jumpTable() scanLine() bits() bytesPerLine() numBytes()
1211*/
1212
1213bool QImage::create( int width, int height, int depth, int numColors,
1214 Endian bitOrder )
1215{
1216 reset(); // reset old data
1217 if ( width <= 0 || height <= 0 || depth <= 0 || numColors < 0 )
1218 return FALSE; // invalid parameter(s)
1219 if ( depth == 1 && bitOrder == IgnoreEndian ) {
1220#if defined(QT_CHECK_RANGE)
1221 qWarning( "QImage::create: Bit order is required for 1 bpp images" );
1222#endif
1223 return FALSE;
1224 }
1225 if ( depth != 1 )
1226 bitOrder = IgnoreEndian;
1227
1228#if defined(QT_CHECK_RANGE)
1229 if ( depth == 24 )
1230 qWarning( "QImage::create: 24-bpp images no longer supported, "
1231 "use 32-bpp instead" );
1232#endif
1233 switch ( depth ) {
1234 case 1:
1235 case 8:
1236#ifndef QT_NO_IMAGE_16_BIT
1237 case 16:
1238#endif
1239#ifndef QT_NO_IMAGE_TRUECOLOR
1240 case 32:
1241#endif
1242 break;
1243 default: // invalid depth
1244 return FALSE;
1245 }
1246
1247 if ( depth == 32 )
1248 numColors = 0;
1249 setNumColors( numColors );
1250 if ( data->ncols != numColors ) // could not alloc color table
1251 return FALSE;
1252
1253 if ( INT_MAX / depth < width) { // sanity check for potential overflow
1254 setNumColors( 0 );
1255 return FALSE;
1256 }
1257// Qt/Embedded doesn't waste memory on unnecessary padding.
1258#ifdef Q_WS_QWS
1259 const int bpl = (width*depth+7)/8; // bytes per scanline
1260 const int pad = 0;
1261#else
1262 const int bpl = ((width*depth+31)/32)*4; // bytes per scanline
1263 // #### WWA: shouldn't this be (width*depth+7)/8:
1264 const int pad = bpl - (width*depth)/8; // pad with zeros
1265#endif
1266 if (INT_MAX / bpl < height) { // sanity check for potential overflow
1267 setNumColors( 0 );
1268 return FALSE;
1269 }
1270 int nbytes = bpl*height; // image size
1271 int ptbl = height*sizeof(uchar*); // pointer table size
1272 int size = nbytes + ptbl; // total size of data block
1273 uchar **p = (uchar **)malloc( size ); // alloc image bits
1274 Q_CHECK_PTR(p);
1275 if ( !p ) { // no memory
1276 setNumColors( 0 );
1277 return FALSE;
1278 }
1279 data->w = width;
1280 data->h = height;
1281 data->d = depth;
1282 data->nbytes = nbytes;
1283 data->bitordr = bitOrder;
1284 data->bits = p; // set image pointer
1285 //uchar *d = (uchar*)p + ptbl; // setup scanline pointers
1286 uchar *d = (uchar*)(p + height); // setup scanline pointers
1287 while ( height-- ) {
1288 *p++ = d;
1289 if ( pad )
1290 memset( d+bpl-pad, 0, pad );
1291 d += bpl;
1292 }
1293 return TRUE;
1294}
1295
1296/*!
1297 \overload bool QImage::create( const QSize&, int depth, int numColors, Endian bitOrder )
1298*/
1299bool QImage::create( const QSize& size, int depth, int numColors,
1300 QImage::Endian bitOrder )
1301{
1302 return create(size.width(), size.height(), depth, numColors, bitOrder);
1303}
1304
1305/*!
1306 \internal
1307 Initializes the image data structure.
1308*/
1309
1310void QImage::init()
1311{
1312 data = new QImageData;
1313 Q_CHECK_PTR( data );
1314 reinit();
1315}
1316
1317void QImage::reinit()
1318{
1319 data->w = data->h = data->d = data->ncols = 0;
1320 data->nbytes = 0;
1321 data->ctbl = 0;
1322 data->bits = 0;
1323 data->bitordr = QImage::IgnoreEndian;
1324 data->alpha = FALSE;
1325#ifndef QT_NO_IMAGE_TEXT
1326 data->misc = 0;
1327#endif
1328 data->dpmx = 0;
1329 data->dpmy = 0;
1330 data->offset = QPoint(0,0);
1331}
1332
1333/*!
1334 \internal
1335 Deallocates the image data and sets the bits pointer to 0.
1336*/
1337
1338void QImage::freeBits()
1339{
1340 if ( data->bits ) { // dealloc image bits
1341 free( data->bits );
1342 data->bits = 0;
1343 }
1344}
1345
1346
1347/*****************************************************************************
1348 Internal routines for converting image depth.
1349 *****************************************************************************/
1350
1351//
1352// convert_32_to_8: Converts a 32 bits depth (true color) to an 8 bit
1353// image with a colormap. If the 32 bit image has more than 256 colors,
1354// we convert the red,green and blue bytes into a single byte encoded
1355// as 6 shades of each of red, green and blue.
1356//
1357// if dithering is needed, only 1 color at most is available for alpha.
1358//
1359#ifndef QT_NO_IMAGE_TRUECOLOR
1360struct QRgbMap {
1361 QRgbMap() : rgb(0xffffffff) { }
1362 bool used() const { return rgb!=0xffffffff; }
1363 uchar pix;
1364 QRgb rgb;
1365};
1366
1367static bool convert_32_to_8( const QImage *src, QImage *dst, int conversion_flags, QRgb* palette=0, int palette_count=0 )
1368{
1369 register QRgb *p;
1370 uchar *b;
1371 bool do_quant = FALSE;
1372 int y, x;
1373
1374 if ( !dst->create(src->width(), src->height(), 8, 256) )
1375 return FALSE;
1376
1377 const int tablesize = 997; // prime
1378 QRgbMap table[tablesize];
1379 int pix=0;
1380 QRgb amask = src->hasAlphaBuffer() ? 0xffffffff : 0x00ffffff;
1381 if ( src->hasAlphaBuffer() )
1382 dst->setAlphaBuffer(TRUE);
1383
1384 if ( palette ) {
1385 // Preload palette into table.
1386
1387 p = palette;
1388 // Almost same code as pixel insertion below
1389 while ( palette_count-- > 0 ) {
1390 // Find in table...
1391 int hash = (*p & amask) % tablesize;
1392 for (;;) {
1393 if ( table[hash].used() ) {
1394 if ( table[hash].rgb == (*p & amask) ) {
1395 // Found previous insertion - use it
1396 break;
1397 } else {
1398 // Keep searching...
1399 if (++hash == tablesize) hash = 0;
1400 }
1401 } else {
1402 // Cannot be in table
1403 Q_ASSERT ( pix != 256 ); // too many colors
1404 // Insert into table at this unused position
1405 dst->setColor( pix, (*p & amask) );
1406 table[hash].pix = pix++;
1407 table[hash].rgb = *p & amask;
1408 break;
1409 }
1410 }
1411 p++;
1412 }
1413 }
1414
1415 if ( (conversion_flags & Qt::DitherMode_Mask) == Qt::PreferDither ) {
1416 do_quant = TRUE;
1417 } else {
1418 for ( y=0; y<src->height(); y++ ) { // check if <= 256 colors
1419 p = (QRgb *)src->scanLine(y);
1420 b = dst->scanLine(y);
1421 x = src->width();
1422 while ( x-- ) {
1423 // Find in table...
1424 int hash = (*p & amask) % tablesize;
1425 for (;;) {
1426 if ( table[hash].used() ) {
1427 if ( table[hash].rgb == (*p & amask) ) {
1428 // Found previous insertion - use it
1429 break;
1430 } else {
1431 // Keep searching...
1432 if (++hash == tablesize) hash = 0;
1433 }
1434 } else {
1435 // Cannot be in table
1436 if ( pix == 256 ) { // too many colors
1437 do_quant = TRUE;
1438 // Break right out
1439 x = 0;
1440 y = src->height();
1441 } else {
1442 // Insert into table at this unused position
1443 dst->setColor( pix, (*p & amask) );
1444 table[hash].pix = pix++;
1445 table[hash].rgb = (*p & amask);
1446 }
1447 break;
1448 }
1449 }
1450 *b++ = table[hash].pix; // May occur once incorrectly
1451 p++;
1452 }
1453 }
1454 }
1455 int ncols = do_quant ? 256 : pix;
1456
1457 static uint bm[16][16];
1458 static int init=0;
1459 if (!init) {
1460 // Build a Bayer Matrix for dithering
1461
1462 init = 1;
1463 int n, i, j;
1464
1465 bm[0][0]=0;
1466
1467 for (n=1; n<16; n*=2) {
1468 for (i=0; i<n; i++) {
1469 for (j=0; j<n; j++) {
1470 bm[i][j]*=4;
1471 bm[i+n][j]=bm[i][j]+2;
1472 bm[i][j+n]=bm[i][j]+3;
1473 bm[i+n][j+n]=bm[i][j]+1;
1474 }
1475 }
1476 }
1477
1478 for (i=0; i<16; i++)
1479 for (j=0; j<16; j++)
1480 bm[i][j]<<=8;
1481 }
1482
1483 dst->setNumColors( ncols );
1484
1485 if ( do_quant ) { // quantization needed
1486
1487#define MAX_R 5
1488#define MAX_G 5
1489#define MAX_B 5
1490#define INDEXOF(r,g,b) (((r)*(MAX_G+1)+(g))*(MAX_B+1)+(b))
1491
1492 int rc, gc, bc;
1493
1494 for ( rc=0; rc<=MAX_R; rc++ ) // build 6x6x6 color cube
1495 for ( gc=0; gc<=MAX_G; gc++ )
1496 for ( bc=0; bc<=MAX_B; bc++ ) {
1497 dst->setColor( INDEXOF(rc,gc,bc),
1498 (amask&0xff000000)
1499 | qRgb( rc*255/MAX_R, gc*255/MAX_G, bc*255/MAX_B ) );
1500 }
1501
1502 int sw = src->width();
1503
1504 int* line1[3];
1505 int* line2[3];
1506 int* pv[3];
1507 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::DiffuseDither ) {
1508 line1[0] = new int[src->width()];
1509 line2[0] = new int[src->width()];
1510 line1[1] = new int[src->width()];
1511 line2[1] = new int[src->width()];
1512 line1[2] = new int[src->width()];
1513 line2[2] = new int[src->width()];
1514 pv[0] = new int[sw];
1515 pv[1] = new int[sw];
1516 pv[2] = new int[sw];
1517 }
1518
1519 for ( y=0; y < src->height(); y++ ) {
1520 p = (QRgb *)src->scanLine(y);
1521 b = dst->scanLine(y);
1522 QRgb *end = p + sw;
1523
1524 // perform quantization
1525 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::ThresholdDither ) {
1526#define DITHER(p,m) ((uchar) ((p * (m) + 127) / 255))
1527 while ( p < end ) {
1528 rc = qRed( *p );
1529 gc = qGreen( *p );
1530 bc = qBlue( *p );
1531
1532 *b++ =
1533 INDEXOF(
1534 DITHER(rc, MAX_R),
1535 DITHER(gc, MAX_G),
1536 DITHER(bc, MAX_B)
1537 );
1538
1539 p++;
1540 }
1541#undef DITHER
1542 } else if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::OrderedDither ) {
1543#define DITHER(p,d,m) ((uchar) ((((256 * (m) + (m) + 1)) * (p) + (d)) / 65536 ))
1544
1545 int x = 0;
1546 while ( p < end ) {
1547 uint d = bm[y&15][x&15];
1548
1549 rc = qRed( *p );
1550 gc = qGreen( *p );
1551 bc = qBlue( *p );
1552
1553 *b++ =
1554 INDEXOF(
1555 DITHER(rc, d, MAX_R),
1556 DITHER(gc, d, MAX_G),
1557 DITHER(bc, d, MAX_B)
1558 );
1559
1560 p++;
1561 x++;
1562 }
1563#undef DITHER
1564 } else { // Diffuse
1565 int endian = (QImage::systemByteOrder() == QImage::BigEndian);
1566 int x;
1567 uchar* q = src->scanLine(y);
1568 uchar* q2 = src->scanLine(y+1 < src->height() ? y + 1 : 0);
1569 for (int chan = 0; chan < 3; chan++) {
1570 b = dst->scanLine(y);
1571 int *l1 = (y&1) ? line2[chan] : line1[chan];
1572 int *l2 = (y&1) ? line1[chan] : line2[chan];
1573 if ( y == 0 ) {
1574 for (int i=0; i<sw; i++)
1575 l1[i] = q[i*4+chan+endian];
1576 }
1577 if ( y+1 < src->height() ) {
1578 for (int i=0; i<sw; i++)
1579 l2[i] = q2[i*4+chan+endian];
1580 }
1581 // Bi-directional error diffusion
1582 if ( y&1 ) {
1583 for (x=0; x<sw; x++) {
1584 int pix = QMAX(QMIN(5, (l1[x] * 5 + 128)/ 255), 0);
1585 int err = l1[x] - pix * 255 / 5;
1586 pv[chan][x] = pix;
1587
1588 // Spread the error around...
1589 if ( x+1<sw ) {
1590 l1[x+1] += (err*7)>>4;
1591 l2[x+1] += err>>4;
1592 }
1593 l2[x]+=(err*5)>>4;
1594 if (x>1)
1595 l2[x-1]+=(err*3)>>4;
1596 }
1597 } else {
1598 for (x=sw; x-->0; ) {
1599 int pix = QMAX(QMIN(5, (l1[x] * 5 + 128)/ 255), 0);
1600 int err = l1[x] - pix * 255 / 5;
1601 pv[chan][x] = pix;
1602
1603 // Spread the error around...
1604 if ( x > 0 ) {
1605 l1[x-1] += (err*7)>>4;
1606 l2[x-1] += err>>4;
1607 }
1608 l2[x]+=(err*5)>>4;
1609 if (x+1 < sw)
1610 l2[x+1]+=(err*3)>>4;
1611 }
1612 }
1613 }
1614 if (endian) {
1615 for (x=0; x<sw; x++) {
1616 *b++ = INDEXOF(pv[0][x],pv[1][x],pv[2][x]);
1617 }
1618 } else {
1619 for (x=0; x<sw; x++) {
1620 *b++ = INDEXOF(pv[2][x],pv[1][x],pv[0][x]);
1621 }
1622 }
1623 }
1624 }
1625
1626#ifndef QT_NO_IMAGE_DITHER_TO_1
1627 if ( src->hasAlphaBuffer() ) {
1628 const int trans = 216;
1629 dst->setColor(trans, 0x00000000); // transparent
1630 QImage mask = src->createAlphaMask(conversion_flags);
1631 uchar* m;
1632 for ( y=0; y < src->height(); y++ ) {
1633 uchar bit = 0x80;
1634 m = mask.scanLine(y);
1635 b = dst->scanLine(y);
1636 int w = src->width();
1637 for ( x = 0; x<w; x++ ) {
1638 if ( !(*m&bit) )
1639 b[x] = trans;
1640 if (!(bit >>= 1)) {
1641 bit = 0x80;
1642 while ( x<w-1 && *++m == 0xff ) // skip chunks
1643 x+=8;
1644 }
1645 }
1646 }
1647 }
1648#endif
1649
1650 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::DiffuseDither ) {
1651 delete [] line1[0];
1652 delete [] line2[0];
1653 delete [] line1[1];
1654 delete [] line2[1];
1655 delete [] line1[2];
1656 delete [] line2[2];
1657 delete [] pv[0];
1658 delete [] pv[1];
1659 delete [] pv[2];
1660 }
1661
1662#undef MAX_R
1663#undef MAX_G
1664#undef MAX_B
1665#undef INDEXOF
1666
1667 }
1668
1669 return TRUE;
1670}
1671
1672
1673static bool convert_8_to_32( const QImage *src, QImage *dst )
1674{
1675 if ( !dst->create(src->width(), src->height(), 32) )
1676 return FALSE; // create failed
1677 dst->setAlphaBuffer( src->hasAlphaBuffer() );
1678 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
1679 register uint *p = (uint *)dst->scanLine(y);
1680 uchar *b = src->scanLine(y);
1681 uint *end = p + dst->width();
1682 while ( p < end )
1683 *p++ = src->color(*b++);
1684 }
1685 return TRUE;
1686}
1687
1688
1689static bool convert_1_to_32( const QImage *src, QImage *dst )
1690{
1691 if ( !dst->create(src->width(), src->height(), 32) )
1692 return FALSE; // could not create
1693 dst->setAlphaBuffer( src->hasAlphaBuffer() );
1694 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
1695 register uint *p = (uint *)dst->scanLine(y);
1696 uchar *b = src->scanLine(y);
1697 int x;
1698 if ( src->bitOrder() == QImage::BigEndian ) {
1699 for ( x=0; x<dst->width(); x++ ) {
1700 *p++ = src->color( (*b >> (7 - (x & 7))) & 1 );
1701 if ( (x & 7) == 7 )
1702 b++;
1703 }
1704 } else {
1705 for ( x=0; x<dst->width(); x++ ) {
1706 *p++ = src->color( (*b >> (x & 7)) & 1 );
1707 if ( (x & 7) == 7 )
1708 b++;
1709 }
1710 }
1711 }
1712 return TRUE;
1713}
1714#endif // QT_NO_IMAGE_TRUECOLOR
1715
1716static bool convert_1_to_8( const QImage *src, QImage *dst )
1717{
1718 if ( !dst->create(src->width(), src->height(), 8, 2) )
1719 return FALSE; // something failed
1720 dst->setAlphaBuffer( src->hasAlphaBuffer() );
1721 if (src->numColors() >= 2) {
1722 dst->setColor( 0, src->color(0) ); // copy color table
1723 dst->setColor( 1, src->color(1) );
1724 } else {
1725 // Unlikely, but they do exist
1726 if (src->numColors() >= 1)
1727 dst->setColor( 0, src->color(0) );
1728 else
1729 dst->setColor( 0, 0xffffffff );
1730 dst->setColor( 1, 0xff000000 );
1731 }
1732 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
1733 register uchar *p = dst->scanLine(y);
1734 uchar *b = src->scanLine(y);
1735 int x;
1736 if ( src->bitOrder() == QImage::BigEndian ) {
1737 for ( x=0; x<dst->width(); x++ ) {
1738 *p++ = (*b >> (7 - (x & 7))) & 1;
1739 if ( (x & 7) == 7 )
1740 b++;
1741 }
1742 } else {
1743 for ( x=0; x<dst->width(); x++ ) {
1744 *p++ = (*b >> (x & 7)) & 1;
1745 if ( (x & 7) == 7 )
1746 b++;
1747 }
1748 }
1749 }
1750 return TRUE;
1751}
1752
1753#ifndef QT_NO_IMAGE_DITHER_TO_1
1754//
1755// dither_to_1: Uses selected dithering algorithm.
1756//
1757
1758static bool dither_to_1( const QImage *src, QImage *dst,
1759 int conversion_flags, bool fromalpha )
1760{
1761 if ( !dst->create(src->width(), src->height(), 1, 2, QImage::BigEndian) )
1762 return FALSE; // something failed
1763
1764 enum { Threshold, Ordered, Diffuse } dithermode;
1765
1766 if ( fromalpha ) {
1767 if ( ( conversion_flags & Qt::AlphaDither_Mask ) == Qt::DiffuseAlphaDither )
1768 dithermode = Diffuse;
1769 else if ( ( conversion_flags & Qt::AlphaDither_Mask ) == Qt::OrderedAlphaDither )
1770 dithermode = Ordered;
1771 else
1772 dithermode = Threshold;
1773 } else {
1774 if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::ThresholdDither )
1775 dithermode = Threshold;
1776 else if ( ( conversion_flags & Qt::Dither_Mask ) == Qt::OrderedDither )
1777 dithermode = Ordered;
1778 else
1779 dithermode = Diffuse;
1780 }
1781
1782 dst->setColor( 0, qRgb(255, 255, 255) );
1783 dst->setColor( 1, qRgb( 0, 0, 0) );
1784 int w = src->width();
1785 int h = src->height();
1786 int d = src->depth();
1787 uchar gray[256]; // gray map for 8 bit images
1788 bool use_gray = d == 8;
1789 if ( use_gray ) { // make gray map
1790 if ( fromalpha ) {
1791 // Alpha 0x00 -> 0 pixels (white)
1792 // Alpha 0xFF -> 1 pixels (black)
1793 for ( int i=0; i<src->numColors(); i++ )
1794 gray[i] = (255 - (src->color(i) >> 24));
1795 } else {
1796 // Pixel 0x00 -> 1 pixels (black)
1797 // Pixel 0xFF -> 0 pixels (white)
1798 for ( int i=0; i<src->numColors(); i++ )
1799 gray[i] = qGray( src->color(i) & 0x00ffffff );
1800 }
1801 }
1802
1803 switch ( dithermode ) {
1804 case Diffuse: {
1805 int *line1 = new int[w];
1806 int *line2 = new int[w];
1807 int bmwidth = (w+7)/8;
1808 if ( !(line1 && line2) )
1809 return FALSE;
1810 register uchar *p;
1811 uchar *end;
1812 int *b1, *b2;
1813 int wbytes = w * (d/8);
1814 p = src->bits();
1815 end = p + wbytes;
1816 b2 = line2;
1817 if ( use_gray ) { // 8 bit image
1818 while ( p < end )
1819 *b2++ = gray[*p++];
1820#ifndef QT_NO_IMAGE_TRUECOLOR
1821 } else { // 32 bit image
1822 if ( fromalpha ) {
1823 while ( p < end ) {
1824 *b2++ = 255 - (*(uint*)p >> 24);
1825 p += 4;
1826 }
1827 } else {
1828 while ( p < end ) {
1829 *b2++ = qGray(*(uint*)p);
1830 p += 4;
1831 }
1832 }
1833#endif
1834 }
1835 int x, y;
1836 for ( y=0; y<h; y++ ) { // for each scan line...
1837 int *tmp = line1; line1 = line2; line2 = tmp;
1838 bool not_last_line = y < h - 1;
1839 if ( not_last_line ) { // calc. grayvals for next line
1840 p = src->scanLine(y+1);
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 { // 24 bit image
1848 if ( fromalpha ) {
1849 while ( p < end ) {
1850 *b2++ = 255 - (*(uint*)p >> 24);
1851 p += 4;
1852 }
1853 } else {
1854 while ( p < end ) {
1855 *b2++ = qGray(*(uint*)p);
1856 p += 4;
1857 }
1858 }
1859#endif
1860 }
1861 }
1862
1863 int err;
1864 p = dst->scanLine( y );
1865 memset( p, 0, bmwidth );
1866 b1 = line1;
1867 b2 = line2;
1868 int bit = 7;
1869 for ( x=1; x<=w; x++ ) {
1870 if ( *b1 < 128 ) { // black pixel
1871 err = *b1++;
1872 *p |= 1 << bit;
1873 } else { // white pixel
1874 err = *b1++ - 255;
1875 }
1876 if ( bit == 0 ) {
1877 p++;
1878 bit = 7;
1879 } else {
1880 bit--;
1881 }
1882 if ( x < w )
1883 *b1 += (err*7)>>4; // spread error to right pixel
1884 if ( not_last_line ) {
1885 b2[0] += (err*5)>>4; // pixel below
1886 if ( x > 1 )
1887 b2[-1] += (err*3)>>4; // pixel below left
1888 if ( x < w )
1889 b2[1] += err>>4; // pixel below right
1890 }
1891 b2++;
1892 }
1893 }
1894 delete [] line1;
1895 delete [] line2;
1896 } break;
1897 case Ordered: {
1898 static uint bm[16][16];
1899 static int init=0;
1900 if (!init) {
1901 // Build a Bayer Matrix for dithering
1902
1903 init = 1;
1904 int n, i, j;
1905
1906 bm[0][0]=0;
1907
1908 for (n=1; n<16; n*=2) {
1909 for (i=0; i<n; i++) {
1910 for (j=0; j<n; j++) {
1911 bm[i][j]*=4;
1912 bm[i+n][j]=bm[i][j]+2;
1913 bm[i][j+n]=bm[i][j]+3;
1914 bm[i+n][j+n]=bm[i][j]+1;
1915 }
1916 }
1917 }
1918
1919 // Force black to black
1920 bm[0][0]=1;
1921 }
1922
1923 dst->fill( 0 );
1924 uchar** mline = dst->jumpTable();
1925#ifndef QT_NO_IMAGE_TRUECOLOR
1926 if ( d == 32 ) {
1927 uint** line = (uint**)src->jumpTable();
1928 for ( int i=0; i<h; i++ ) {
1929 uint *p = line[i];
1930 uint *end = p + w;
1931 uchar *m = mline[i];
1932 int bit = 7;
1933 int j = 0;
1934 if ( fromalpha ) {
1935 while ( p < end ) {
1936 if ( (*p++ >> 24) >= bm[j++&15][i&15] )
1937 *m |= 1 << bit;
1938 if ( bit == 0 ) {
1939 m++;
1940 bit = 7;
1941 } else {
1942 bit--;
1943 }
1944 }
1945 } else {
1946 while ( p < end ) {
1947 if ( (uint)qGray(*p++) < bm[j++&15][i&15] )
1948 *m |= 1 << bit;
1949 if ( bit == 0 ) {
1950 m++;
1951 bit = 7;
1952 } else {
1953 bit--;
1954 }
1955 }
1956 }
1957 }
1958 } else
1959#endif // QT_NO_IMAGE_TRUECOLOR
1960 /* ( d == 8 ) */ {
1961 uchar** line = src->jumpTable();
1962 for ( int i=0; i<h; i++ ) {
1963 uchar *p = line[i];
1964 uchar *end = p + w;
1965 uchar *m = mline[i];
1966 int bit = 7;
1967 int j = 0;
1968 while ( p < end ) {
1969 if ( (uint)gray[*p++] < bm[j++&15][i&15] )
1970 *m |= 1 << bit;
1971 if ( bit == 0 ) {
1972 m++;
1973 bit = 7;
1974 } else {
1975 bit--;
1976 }
1977 }
1978 }
1979 }
1980 } break;
1981 default: { // Threshold:
1982 dst->fill( 0 );
1983 uchar** mline = dst->jumpTable();
1984#ifndef QT_NO_IMAGE_TRUECOLOR
1985 if ( d == 32 ) {
1986 uint** line = (uint**)src->jumpTable();
1987 for ( int i=0; i<h; i++ ) {
1988 uint *p = line[i];
1989 uint *end = p + w;
1990 uchar *m = mline[i];
1991 int bit = 7;
1992 if ( fromalpha ) {
1993 while ( p < end ) {
1994 if ( (*p++ >> 24) >= 128 )
1995 *m |= 1 << bit; // Set mask "on"
1996 if ( bit == 0 ) {
1997 m++;
1998 bit = 7;
1999 } else {
2000 bit--;
2001 }
2002 }
2003 } else {
2004 while ( p < end ) {
2005 if ( qGray(*p++) < 128 )
2006 *m |= 1 << bit; // Set pixel "black"
2007 if ( bit == 0 ) {
2008 m++;
2009 bit = 7;
2010 } else {
2011 bit--;
2012 }
2013 }
2014 }
2015 }
2016 } else
2017#endif //QT_NO_IMAGE_TRUECOLOR
2018 if ( d == 8 ) {
2019 uchar** line = src->jumpTable();
2020 for ( int i=0; i<h; i++ ) {
2021 uchar *p = line[i];
2022 uchar *end = p + w;
2023 uchar *m = mline[i];
2024 int bit = 7;
2025 while ( p < end ) {
2026 if ( gray[*p++] < 128 )
2027 *m |= 1 << bit; // Set mask "on"/ pixel "black"
2028 if ( bit == 0 ) {
2029 m++;
2030 bit = 7;
2031 } else {
2032 bit--;
2033 }
2034 }
2035 }
2036 }
2037 }
2038 }
2039 return TRUE;
2040}
2041#endif
2042
2043#ifndef QT_NO_IMAGE_16_BIT
2044//###### Endianness issues!
2045static inline bool is16BitGray( ushort c )
2046{
2047 int r=(c & 0xf800) >> 11;
2048 int g=(c & 0x07e0) >> 6; //green/2
2049 int b=(c & 0x001f);
2050 return r == g && g == b;
2051}
2052
2053
2054static bool convert_16_to_32( const QImage *src, QImage *dst )
2055{
2056 if ( !dst->create(src->width(), src->height(), 32) )
2057 return FALSE; // create failed
2058 dst->setAlphaBuffer( src->hasAlphaBuffer() );
2059 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
2060 register uint *p = (uint *)dst->scanLine(y);
2061 ushort *s = (ushort*)src->scanLine(y);
2062 uint *end = p + dst->width();
2063 while ( p < end )
2064 *p++ = qt_conv16ToRgb( *s++ );
2065 }
2066 return TRUE;
2067}
2068
2069
2070static bool convert_32_to_16( const QImage *src, QImage *dst )
2071{
2072 if ( !dst->create(src->width(), src->height(), 16) )
2073 return FALSE; // create failed
2074 dst->setAlphaBuffer( src->hasAlphaBuffer() );
2075 for ( int y=0; y<dst->height(); y++ ) { // for each scan line...
2076 register ushort *p = (ushort *)dst->scanLine(y);
2077 uint *s = (uint*)src->scanLine(y);
2078 ushort *end = p + dst->width();
2079 while ( p < end )
2080 *p++ = qt_convRgbTo16( *s++ );
2081 }
2082 return TRUE;
2083}
2084
2085
2086#endif
2087
2088/*!
2089 Converts the depth (bpp) of the image to \a depth and returns the
2090 converted image. The original image is not changed.
2091
2092 The \a depth argument must be 1, 8, 16 (Qt/Embedded only) or 32.
2093
2094 Returns \c *this if \a depth is equal to the image depth, or a
2095 \link isNull() null\endlink image if this image cannot be
2096 converted.
2097
2098 If the image needs to be modified to fit in a lower-resolution
2099 result (e.g. converting from 32-bit to 8-bit), use the \a
2100 conversion_flags to specify how you'd prefer this to happen.
2101
2102 \sa Qt::ImageConversionFlags depth() isNull()
2103*/
2104
2105QImage QImage::convertDepth( int depth, int conversion_flags ) const
2106{
2107 QImage image;
2108 if ( data->d == depth )
2109 image = *this; // no conversion
2110#ifndef QT_NO_IMAGE_DITHER_TO_1
2111 else if ( (data->d == 8 || data->d == 32) && depth == 1 ) // dither
2112 dither_to_1( this, &image, conversion_flags, FALSE );
2113#endif
2114#ifndef QT_NO_IMAGE_TRUECOLOR
2115 else if ( data->d == 32 && depth == 8 ) // 32 -> 8
2116 convert_32_to_8( this, &image, conversion_flags );
2117 else if ( data->d == 8 && depth == 32 ) // 8 -> 32
2118 convert_8_to_32( this, &image );
2119#endif
2120 else if ( data->d == 1 && depth == 8 ) // 1 -> 8
2121 convert_1_to_8( this, &image );
2122#ifndef QT_NO_IMAGE_TRUECOLOR
2123 else if ( data->d == 1 && depth == 32 ) // 1 -> 32
2124 convert_1_to_32( this, &image );
2125#endif
2126#ifndef QT_NO_IMAGE_16_BIT
2127 else if ( data->d == 16 && depth != 16 ) {
2128 QImage tmp;
2129 convert_16_to_32( this, &tmp );
2130 image = tmp.convertDepth( depth, conversion_flags );
2131 } else if ( data->d != 16 && depth == 16 ) {
2132 QImage tmp = convertDepth( 32, conversion_flags );
2133 convert_32_to_16( &tmp, &image );
2134 }
2135#endif
2136 else {
2137#if defined(QT_CHECK_RANGE)
2138 if ( isNull() )
2139 qWarning( "QImage::convertDepth: Image is a null image" );
2140 else
2141 qWarning( "QImage::convertDepth: Depth %d not supported", depth );
2142#endif
2143 }
2144 return image;
2145}
2146
2147/*!
2148 \overload
2149*/
2150
2151QImage QImage::convertDepth( int depth ) const
2152{
2153 return convertDepth( depth, 0 );
2154}
2155
2156/*!
2157 Returns TRUE if ( \a x, \a y ) is a valid coordinate in the image;
2158 otherwise returns FALSE.
2159
2160 \sa width() height() pixelIndex()
2161*/
2162
2163bool QImage::valid( int x, int y ) const
2164{
2165 return x >= 0 && x < width()
2166 && y >= 0 && y < height();
2167}
2168
2169/*!
2170 Returns the pixel index at the given coordinates.
2171
2172 If (\a x, \a y) is not \link valid() valid\endlink, or if the
2173 image is not a paletted image (depth() \> 8), the results are
2174 undefined.
2175
2176 \sa valid() depth()
2177*/
2178
2179int QImage::pixelIndex( int x, int y ) const
2180{
2181#if defined(QT_CHECK_RANGE)
2182 if ( x < 0 || x >= width() ) {
2183 qWarning( "QImage::pixel: x=%d out of range", x );
2184 return -12345;
2185 }
2186#endif
2187 uchar * s = scanLine( y );
2188 switch( depth() ) {
2189 case 1:
2190 if ( bitOrder() == QImage::LittleEndian )
2191 return (*(s + (x >> 3)) >> (x & 7)) & 1;
2192 else
2193 return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
2194 case 8:
2195 return (int)s[x];
2196#ifndef QT_NO_IMAGE_TRUECOLOR
2197#ifndef QT_NO_IMAGE_16_BIT
2198 case 16:
2199#endif
2200 case 32:
2201#if defined(QT_CHECK_RANGE)
2202 qWarning( "QImage::pixelIndex: Not applicable for %d-bpp images "
2203 "(no palette)", depth() );
2204#endif
2205 return 0;
2206#endif //QT_NO_IMAGE_TRUECOLOR
2207 }
2208 return 0;
2209}
2210
2211
2212/*!
2213 Returns the color of the pixel at the coordinates (\a x, \a y).
2214
2215 If (\a x, \a y) is not \link valid() on the image\endlink, the
2216 results are undefined.
2217
2218 \sa setPixel() qRed() qGreen() qBlue() valid()
2219*/
2220
2221QRgb QImage::pixel( int x, int y ) const
2222{
2223#if defined(QT_CHECK_RANGE)
2224 if ( x < 0 || x >= width() ) {
2225 qWarning( "QImage::pixel: x=%d out of range", x );
2226 return 12345;
2227 }
2228#endif
2229 uchar * s = scanLine( y );
2230 switch( depth() ) {
2231 case 1:
2232 if ( bitOrder() == QImage::LittleEndian )
2233 return color( (*(s + (x >> 3)) >> (x & 7)) & 1 );
2234 else
2235 return color( (*(s + (x >> 3)) >> (7- (x & 7))) & 1 );
2236 case 8:
2237 return color( (int)s[x] );
2238#ifndef QT_NO_IMAGE_16_BIT
2239 case 16:
2240 return qt_conv16ToRgb(((ushort*)s)[x]);
2241#endif
2242#ifndef QT_NO_IMAGE_TRUECOLOR
2243 case 32:
2244 return ((QRgb*)s)[x];
2245#endif
2246 default:
2247 return 100367;
2248 }
2249}
2250
2251
2252/*!
2253 Sets the pixel index or color at the coordinates (\a x, \a y) to
2254 \a index_or_rgb.
2255
2256 If (\a x, \a y) is not \link valid() valid\endlink, the result is
2257 undefined.
2258
2259 If the image is a paletted image (depth() \<= 8) and \a
2260 index_or_rgb \>= numColors(), the result is undefined.
2261
2262 \sa pixelIndex() pixel() qRgb() qRgba() valid()
2263*/
2264
2265void QImage::setPixel( int x, int y, uint index_or_rgb )
2266{
2267 if ( x < 0 || x >= width() ) {
2268#if defined(QT_CHECK_RANGE)
2269 qWarning( "QImage::setPixel: x=%d out of range", x );
2270#endif
2271 return;
2272 }
2273 if ( depth() == 1 ) {
2274 uchar * s = scanLine( y );
2275 if ( index_or_rgb > 1) {
2276#if defined(QT_CHECK_RANGE)
2277 qWarning( "QImage::setPixel: index=%d out of range",
2278 index_or_rgb );
2279#endif
2280 } else if ( bitOrder() == QImage::LittleEndian ) {
2281 if (index_or_rgb==0)
2282 *(s + (x >> 3)) &= ~(1 << (x & 7));
2283 else
2284 *(s + (x >> 3)) |= (1 << (x & 7));
2285 } else {
2286 if (index_or_rgb==0)
2287 *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
2288 else
2289 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
2290 }
2291 } else if ( depth() == 8 ) {
2292 if (index_or_rgb > (uint)numColors()) {
2293#if defined(QT_CHECK_RANGE)
2294 qWarning( "QImage::setPixel: index=%d out of range",
2295 index_or_rgb );
2296#endif
2297 return;
2298 }
2299 uchar * s = scanLine( y );
2300 s[x] = index_or_rgb;
2301#ifndef QT_NO_IMAGE_16_BIT
2302 } else if ( depth() == 16 ) {
2303 ushort * s = (ushort*)scanLine( y );
2304 s[x] = qt_convRgbTo16(index_or_rgb);
2305#endif
2306#ifndef QT_NO_IMAGE_TRUECOLOR
2307 } else if ( depth() == 32 ) {
2308 QRgb * s = (QRgb*)scanLine( y );
2309 s[x] = index_or_rgb;
2310#endif
2311 }
2312}
2313
2314
2315/*!
2316 Converts the bit order of the image to \a bitOrder and returns the
2317 converted image. The original image is not changed.
2318
2319 Returns \c *this if the \a bitOrder is equal to the image bit
2320 order, or a \link isNull() null\endlink image if this image cannot
2321 be converted.
2322
2323 \sa bitOrder() systemBitOrder() isNull()
2324*/
2325
2326QImage QImage::convertBitOrder( Endian bitOrder ) const
2327{
2328 if ( isNull() || data->d != 1 || // invalid argument(s)
2329 !(bitOrder == BigEndian || bitOrder == LittleEndian) ) {
2330 QImage nullImage;
2331 return nullImage;
2332 }
2333 if ( data->bitordr == bitOrder ) // nothing to do
2334 return copy();
2335
2336 QImage image( data->w, data->h, 1, data->ncols, bitOrder );
2337
2338 int bpl = (width() + 7) / 8;
2339 for ( int y = 0; y < data->h; y++ ) {
2340 register uchar *p = jumpTable()[y];
2341 uchar *end = p + bpl;
2342 uchar *b = image.jumpTable()[y];
2343 while ( p < end )
2344 *b++ = bitflip[*p++];
2345 }
2346 memcpy( image.colorTable(), colorTable(), numColors()*sizeof(QRgb) );
2347 return image;
2348}
2349
2350// ### Candidate (renamed) for qcolor.h
2351static
2352bool isGray(QRgb c)
2353{
2354 return qRed(c) == qGreen(c)
2355 && qRed(c) == qBlue(c);
2356}
2357
2358/*!
2359 Returns TRUE if all the colors in the image are shades of gray
2360 (i.e. their red, green and blue components are equal); otherwise
2361 returns FALSE.
2362
2363 This function is slow for large 16-bit (Qt/Embedded only) and 32-bit images.
2364
2365 \sa isGrayscale()
2366*/
2367bool QImage::allGray() const
2368{
2369#ifndef QT_NO_IMAGE_TRUECOLOR
2370 if (depth()==32) {
2371 int p = width()*height();
2372 QRgb* b = (QRgb*)bits();
2373 while (p--)
2374 if (!isGray(*b++))
2375 return FALSE;
2376#ifndef QT_NO_IMAGE_16_BIT
2377 } else if (depth()==16) {
2378 int p = width()*height();
2379 ushort* b = (ushort*)bits();
2380 while (p--)
2381 if (!is16BitGray(*b++))
2382 return FALSE;
2383#endif
2384 } else
2385#endif //QT_NO_IMAGE_TRUECOLOR
2386 {
2387 if (!data->ctbl) return TRUE;
2388 for (int i=0; i<numColors(); i++)
2389 if (!isGray(data->ctbl[i]))
2390 return FALSE;
2391 }
2392 return TRUE;
2393}
2394
2395/*!
2396 For 16-bit (Qt/Embedded only) and 32-bit images, this function is
2397 equivalent to allGray().
2398
2399 For 8-bpp images, this function returns TRUE if color(i) is
2400 QRgb(i,i,i) for all indices of the color table; otherwise returns
2401 FALSE.
2402
2403 \sa allGray() depth()
2404*/
2405bool QImage::isGrayscale() const
2406{
2407 switch (depth()) {
2408#ifndef QT_NO_IMAGE_TRUECOLOR
2409 case 32:
2410#ifndef QT_NO_IMAGE_16_BIT
2411 case 16:
2412#endif
2413 return allGray();
2414#endif //QT_NO_IMAGE_TRUECOLOR
2415 case 8: {
2416 for (int i=0; i<numColors(); i++)
2417 if (data->ctbl[i] != qRgb(i,i,i))
2418 return FALSE;
2419 return TRUE;
2420 }
2421 }
2422 return FALSE;
2423}
2424
2425#ifndef QT_NO_IMAGE_SMOOTHSCALE
2426static
2427void pnmscale(const QImage& src, QImage& dst)
2428{
2429 QRgb* xelrow = 0;
2430 QRgb* tempxelrow = 0;
2431 register QRgb* xP;
2432 register QRgb* nxP;
2433 int rows, cols, rowsread, newrows, newcols;
2434 register int row, col, needtoreadrow;
2435 const uchar maxval = 255;
2436 double xscale, yscale;
2437 long sxscale, syscale;
2438 register long fracrowtofill, fracrowleft;
2439 long* as;
2440 long* rs;
2441 long* gs;
2442 long* bs;
2443 int rowswritten = 0;
2444
2445 cols = src.width();
2446 rows = src.height();
2447 newcols = dst.width();
2448 newrows = dst.height();
2449
2450 long SCALE;
2451 long HALFSCALE;
2452
2453 if (cols > 4096)
2454 {
2455 SCALE = 4096;
2456 HALFSCALE = 2048;
2457 }
2458 else
2459 {
2460 int fac = 4096;
2461
2462 while (cols * fac > 4096)
2463 {
2464 fac /= 2;
2465 }
2466
2467 SCALE = fac * cols;
2468 HALFSCALE = fac * cols / 2;
2469 }
2470
2471 xscale = (double) newcols / (double) cols;
2472 yscale = (double) newrows / (double) rows;
2473
2474 sxscale = (long)(xscale * SCALE);
2475 syscale = (long)(yscale * SCALE);
2476
2477 if ( newrows != rows ) /* shortcut Y scaling if possible */
2478 tempxelrow = new QRgb[cols];
2479
2480 if ( src.hasAlphaBuffer() ) {
2481 dst.setAlphaBuffer(TRUE);
2482 as = new long[cols];
2483 for ( col = 0; col < cols; ++col )
2484 as[col] = HALFSCALE;
2485 } else {
2486 as = 0;
2487 }
2488 rs = new long[cols];
2489 gs = new long[cols];
2490 bs = new long[cols];
2491 rowsread = 0;
2492 fracrowleft = syscale;
2493 needtoreadrow = 1;
2494 for ( col = 0; col < cols; ++col )
2495 rs[col] = gs[col] = bs[col] = HALFSCALE;
2496 fracrowtofill = SCALE;
2497
2498 for ( row = 0; row < newrows; ++row ) {
2499 /* First scale Y from xelrow into tempxelrow. */
2500 if ( newrows == rows ) {
2501 /* shortcut Y scaling if possible */
2502 tempxelrow = xelrow = (QRgb*)src.scanLine(rowsread++);
2503 } else {
2504 while ( fracrowleft < fracrowtofill ) {
2505 if ( needtoreadrow && rowsread < rows )
2506 xelrow = (QRgb*)src.scanLine(rowsread++);
2507 for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) {
2508 if (as) {
2509 as[col] += fracrowleft * qAlpha( *xP );
2510 rs[col] += fracrowleft * qRed( *xP ) * qAlpha( *xP ) / 255;
2511 gs[col] += fracrowleft * qGreen( *xP ) * qAlpha( *xP ) / 255;
2512 bs[col] += fracrowleft * qBlue( *xP ) * qAlpha( *xP ) / 255;
2513 } else {
2514 rs[col] += fracrowleft * qRed( *xP );
2515 gs[col] += fracrowleft * qGreen( *xP );
2516 bs[col] += fracrowleft * qBlue( *xP );
2517 }
2518 }
2519 fracrowtofill -= fracrowleft;
2520 fracrowleft = syscale;
2521 needtoreadrow = 1;
2522 }
2523 /* Now fracrowleft is >= fracrowtofill, so we can produce a row. */
2524 if ( needtoreadrow && rowsread < rows ) {
2525 xelrow = (QRgb*)src.scanLine(rowsread++);
2526 needtoreadrow = 0;
2527 }
2528 register long a=0;
2529 for ( col = 0, xP = xelrow, nxP = tempxelrow;
2530 col < cols; ++col, ++xP, ++nxP )
2531 {
2532 register long r, g, b;
2533
2534 if ( as ) {
2535 r = rs[col] + fracrowtofill * qRed( *xP ) * qAlpha( *xP ) / 255;
2536 g = gs[col] + fracrowtofill * qGreen( *xP ) * qAlpha( *xP ) / 255;
2537 b = bs[col] + fracrowtofill * qBlue( *xP ) * qAlpha( *xP ) / 255;
2538 a = as[col] + fracrowtofill * qAlpha( *xP );
2539 if ( a ) {
2540 r = r * 255 / a * SCALE;
2541 g = g * 255 / a * SCALE;
2542 b = b * 255 / a * SCALE;
2543 }
2544 } else {
2545 r = rs[col] + fracrowtofill * qRed( *xP );
2546 g = gs[col] + fracrowtofill * qGreen( *xP );
2547 b = bs[col] + fracrowtofill * qBlue( *xP );
2548 }
2549 r /= SCALE;
2550 if ( r > maxval ) r = maxval;
2551 g /= SCALE;
2552 if ( g > maxval ) g = maxval;
2553 b /= SCALE;
2554 if ( b > maxval ) b = maxval;
2555 if ( as ) {
2556 a /= SCALE;
2557 if ( a > maxval ) a = maxval;
2558 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
2559 as[col] = HALFSCALE;
2560 } else {
2561 *nxP = qRgb( (int)r, (int)g, (int)b );
2562 }
2563 rs[col] = gs[col] = bs[col] = HALFSCALE;
2564 }
2565 fracrowleft -= fracrowtofill;
2566 if ( fracrowleft == 0 ) {
2567 fracrowleft = syscale;
2568 needtoreadrow = 1;
2569 }
2570 fracrowtofill = SCALE;
2571 }
2572
2573 /* Now scale X from tempxelrow into dst and write it out. */
2574 if ( newcols == cols ) {
2575 /* shortcut X scaling if possible */
2576 memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols*4);
2577 } else {
2578 register long a, r, g, b;
2579 register long fraccoltofill, fraccolleft = 0;
2580 register int needcol;
2581
2582 nxP = (QRgb*)dst.scanLine(rowswritten++);
2583 fraccoltofill = SCALE;
2584 a = r = g = b = HALFSCALE;
2585 needcol = 0;
2586 for ( col = 0, xP = tempxelrow; col < cols; ++col, ++xP ) {
2587 fraccolleft = sxscale;
2588 while ( fraccolleft >= fraccoltofill ) {
2589 if ( needcol ) {
2590 ++nxP;
2591 a = r = g = b = HALFSCALE;
2592 }
2593 if ( as ) {
2594 r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255;
2595 g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255;
2596 b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255;
2597 a += fraccoltofill * qAlpha( *xP );
2598 if ( a ) {
2599 r = r * 255 / a * SCALE;
2600 g = g * 255 / a * SCALE;
2601 b = b * 255 / a * SCALE;
2602 }
2603 } else {
2604 r += fraccoltofill * qRed( *xP );
2605 g += fraccoltofill * qGreen( *xP );
2606 b += fraccoltofill * qBlue( *xP );
2607 }
2608 r /= SCALE;
2609 if ( r > maxval ) r = maxval;
2610 g /= SCALE;
2611 if ( g > maxval ) g = maxval;
2612 b /= SCALE;
2613 if ( b > maxval ) b = maxval;
2614 if (as) {
2615 a /= SCALE;
2616 if ( a > maxval ) a = maxval;
2617 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
2618 } else {
2619 *nxP = qRgb( (int)r, (int)g, (int)b );
2620 }
2621 fraccolleft -= fraccoltofill;
2622 fraccoltofill = SCALE;
2623 needcol = 1;
2624 }
2625 if ( fraccolleft > 0 ) {
2626 if ( needcol ) {
2627 ++nxP;
2628 a = r = g = b = HALFSCALE;
2629 needcol = 0;
2630 }
2631 if (as) {
2632 a += fraccolleft * qAlpha( *xP );
2633 r += fraccolleft * qRed( *xP ) * qAlpha( *xP ) / 255;
2634 g += fraccolleft * qGreen( *xP ) * qAlpha( *xP ) / 255;
2635 b += fraccolleft * qBlue( *xP ) * qAlpha( *xP ) / 255;
2636 } else {
2637 r += fraccolleft * qRed( *xP );
2638 g += fraccolleft * qGreen( *xP );
2639 b += fraccolleft * qBlue( *xP );
2640 }
2641 fraccoltofill -= fraccolleft;
2642 }
2643 }
2644 if ( fraccoltofill > 0 ) {
2645 --xP;
2646 if (as) {
2647 a += fraccolleft * qAlpha( *xP );
2648 r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255;
2649 g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255;
2650 b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255;
2651 if ( a ) {
2652 r = r * 255 / a * SCALE;
2653 g = g * 255 / a * SCALE;
2654 b = b * 255 / a * SCALE;
2655 }
2656 } else {
2657 r += fraccoltofill * qRed( *xP );
2658 g += fraccoltofill * qGreen( *xP );
2659 b += fraccoltofill * qBlue( *xP );
2660 }
2661 }
2662 if ( ! needcol ) {
2663 r /= SCALE;
2664 if ( r > maxval ) r = maxval;
2665 g /= SCALE;
2666 if ( g > maxval ) g = maxval;
2667 b /= SCALE;
2668 if ( b > maxval ) b = maxval;
2669 if (as) {
2670 a /= SCALE;
2671 if ( a > maxval ) a = maxval;
2672 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
2673 } else {
2674 *nxP = qRgb( (int)r, (int)g, (int)b );
2675 }
2676 }
2677 }
2678 }
2679
2680 if ( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 1 day
2681 delete [] tempxelrow;
2682 if ( as ) // Avoid purify complaint
2683 delete [] as;
2684 if ( rs ) // Robust, rs might be 0 one day
2685 delete [] rs;
2686 if ( gs ) // Robust, gs might be 0 one day
2687 delete [] gs;
2688 if ( bs ) // Robust, bs might be 0 one day
2689 delete [] bs;
2690}
2691#endif
2692
2693/*!
2694 \enum QImage::ScaleMode
2695
2696 The functions scale() and smoothScale() use different modes for
2697 scaling the image. The purpose of these modes is to retain the
2698 ratio of the image if this is required.
2699
2700 \img scaling.png
2701
2702 \value ScaleFree The image is scaled freely: the resulting image
2703 fits exactly into the specified size; the ratio will not
2704 necessarily be preserved.
2705 \value ScaleMin The ratio of the image is preserved and the
2706 resulting image is guaranteed to fit into the specified size
2707 (it is as large as possible within these constraints) - the
2708 image might be smaller than the requested size.
2709 \value ScaleMax The ratio of the image is preserved and the
2710 resulting image fills the whole specified rectangle (it is as
2711 small as possible within these constraints) - the image might
2712 be larger than the requested size.
2713*/
2714
2715#ifndef QT_NO_IMAGE_SMOOTHSCALE
2716/*!
2717 Returns a smoothly scaled copy of the image. The returned image
2718 has a size of width \a w by height \a h pixels if \a mode is \c
2719 ScaleFree. The modes \c ScaleMin and \c ScaleMax may be used to
2720 preserve the ratio of the image: if \a mode is \c ScaleMin, the
2721 returned image is guaranteed to fit into the rectangle specified
2722 by \a w and \a h (it is as large as possible within the
2723 constraints); if \a mode is \c ScaleMax, the returned image fits
2724 at least into the specified rectangle (it is a small as possible
2725 within the constraints).
2726
2727 For 32-bpp images and 1-bpp/8-bpp color images the result will be
2728 32-bpp, whereas \link allGray() all-gray \endlink images
2729 (including black-and-white 1-bpp) will produce 8-bit \link
2730 isGrayscale() grayscale \endlink images with the palette spanning
2731 256 grays from black to white.
2732
2733 This function uses code based on pnmscale.c by Jef Poskanzer.
2734
2735 pnmscale.c - read a portable anymap and scale it
2736
2737 \legalese
2738
2739 Copyright (C) 1989, 1991 by Jef Poskanzer.
2740
2741 Permission to use, copy, modify, and distribute this software and
2742 its documentation for any purpose and without fee is hereby
2743 granted, provided that the above copyright notice appear in all
2744 copies and that both that copyright notice and this permission
2745 notice appear in supporting documentation. This software is
2746 provided "as is" without express or implied warranty.
2747
2748 \sa scale() mirror()
2749*/
2750QImage QImage::smoothScale( int w, int h, ScaleMode mode ) const
2751{
2752 return smoothScale( QSize( w, h ), mode );
2753}
2754#endif
2755
2756#ifndef QT_NO_IMAGE_SMOOTHSCALE
2757/*!
2758 \overload
2759
2760 The requested size of the image is \a s.
2761*/
2762QImage QImage::smoothScale( const QSize& s, ScaleMode mode ) const
2763{
2764 if ( isNull() ) {
2765#if defined(QT_CHECK_RANGE)
2766 qWarning( "QImage::smoothScale: Image is a null image" );
2767#endif
2768 return copy();
2769 }
2770
2771 QSize newSize = size();
2772 newSize.scale( s, (QSize::ScaleMode)mode ); // ### remove cast in Qt 4.0
2773 if ( newSize == size() )
2774 return copy();
2775
2776 if ( depth() == 32 ) {
2777 QImage img( newSize, 32 );
2778 // 32-bpp to 32-bpp
2779 pnmscale( *this, img );
2780 return img;
2781 } else if ( depth() != 16 && allGray() && !hasAlphaBuffer() ) {
2782 // Inefficient
2783 return convertDepth(32).smoothScale(newSize, mode).convertDepth(8);
2784 } else {
2785 // Inefficient
2786 return convertDepth(32).smoothScale(newSize, mode);
2787 }
2788}
2789#endif
2790
2791/*!
2792 Returns a copy of the image scaled to a rectangle of width \a w
2793 and height \a h according to the ScaleMode \a mode.
2794
2795 \list
2796 \i If \a mode is \c ScaleFree, the image is scaled to (\a w,
2797 \a h).
2798 \i If \a mode is \c ScaleMin, the image is scaled to a rectangle
2799 as large as possible inside (\a w, \a h), preserving the aspect
2800 ratio.
2801 \i If \a mode is \c ScaleMax, the image is scaled to a rectangle
2802 as small as possible outside (\a w, \a h), preserving the aspect
2803 ratio.
2804 \endlist
2805
2806 If either the width \a w or the height \a h is 0 or negative, this
2807 function returns a \link isNull() null\endlink image.
2808
2809 This function uses a simple, fast algorithm. If you need better
2810 quality, use smoothScale() instead.
2811
2812 \sa scaleWidth() scaleHeight() smoothScale() xForm()
2813*/
2814#ifndef QT_NO_IMAGE_TRANSFORMATION
2815QImage QImage::scale( int w, int h, ScaleMode mode ) const
2816{
2817 return scale( QSize( w, h ), mode );
2818}
2819#endif
2820
2821/*!
2822 \overload
2823
2824 The requested size of the image is \a s.
2825*/
2826#ifndef QT_NO_IMAGE_TRANSFORMATION
2827QImage QImage::scale( const QSize& s, ScaleMode mode ) const
2828{
2829 if ( isNull() ) {
2830#if defined(QT_CHECK_RANGE)
2831 qWarning( "QImage::scale: Image is a null image" );
2832#endif
2833 return copy();
2834 }
2835 if ( s.isEmpty() )
2836 return QImage();
2837
2838 QSize newSize = size();
2839 newSize.scale( s, (QSize::ScaleMode)mode ); // ### remove cast in Qt 4.0
2840 if ( newSize == size() )
2841 return copy();
2842
2843 QImage img;
2844 QWMatrix wm;
2845 wm.scale( (double)newSize.width() / width(), (double)newSize.height() / height() );
2846 img = xForm( wm );
2847 // ### I should test and resize the image if it has not the right size
2848// if ( img.width() != newSize.width() || img.height() != newSize.height() )
2849// img.resize( newSize.width(), newSize.height() );
2850 return img;
2851}
2852#endif
2853
2854/*!
2855 Returns a scaled copy of the image. The returned image has a width
2856 of \a w pixels. This function automatically calculates the height
2857 of the image so that the ratio of the image is preserved.
2858
2859 If \a w is 0 or negative a \link isNull() null\endlink image is
2860 returned.
2861
2862 \sa scale() scaleHeight() smoothScale() xForm()
2863*/
2864#ifndef QT_NO_IMAGE_TRANSFORMATION
2865QImage QImage::scaleWidth( int w ) const
2866{
2867 if ( isNull() ) {
2868#if defined(QT_CHECK_RANGE)
2869 qWarning( "QImage::scaleWidth: Image is a null image" );
2870#endif
2871 return copy();
2872 }
2873 if ( w <= 0 )
2874 return QImage();
2875
2876 QWMatrix wm;
2877 double factor = (double) w / width();
2878 wm.scale( factor, factor );
2879 return xForm( wm );
2880}
2881#endif
2882
2883/*!
2884 Returns a scaled copy of the image. The returned image has a
2885 height of \a h pixels. This function automatically calculates the
2886 width of the image so that the ratio of the image is preserved.
2887
2888 If \a h is 0 or negative a \link isNull() null\endlink image is
2889 returned.
2890
2891 \sa scale() scaleWidth() smoothScale() xForm()
2892*/
2893#ifndef QT_NO_IMAGE_TRANSFORMATION
2894QImage QImage::scaleHeight( int h ) const
2895{
2896 if ( isNull() ) {
2897#if defined(QT_CHECK_RANGE)
2898 qWarning( "QImage::scaleHeight: Image is a null image" );
2899#endif
2900 return copy();
2901 }
2902 if ( h <= 0 )
2903 return QImage();
2904
2905 QWMatrix wm;
2906 double factor = (double) h / height();
2907 wm.scale( factor, factor );
2908 return xForm( wm );
2909}
2910#endif
2911
2912
2913/*!
2914 Returns a copy of the image that is transformed using the
2915 transformation matrix, \a matrix.
2916
2917 The transformation \a matrix is internally adjusted to compensate
2918 for unwanted translation, i.e. xForm() returns the smallest image
2919 that contains all the transformed points of the original image.
2920
2921 \sa scale() QPixmap::xForm() QPixmap::trueMatrix() QWMatrix
2922*/
2923#ifndef QT_NO_IMAGE_TRANSFORMATION
2924QImage QImage::xForm( const QWMatrix &matrix ) const
2925{
2926 // This function uses the same algorithm as (and steals quite some
2927 // code from) QPixmap::xForm().
2928
2929 if ( isNull() )
2930 return copy();
2931
2932 if ( depth() == 16 ) {
2933 // inefficient
2934 return convertDepth( 32 ).xForm( matrix );
2935 }
2936
2937 // source image data
2938 int ws = width();
2939 int hs = height();
2940 int sbpl = bytesPerLine();
2941 uchar *sptr = bits();
2942
2943 // target image data
2944 int wd;
2945 int hd;
2946
2947 int bpp = depth();
2948
2949 // compute size of target image
2950 QWMatrix mat = QPixmap::trueMatrix( matrix, ws, hs );
2951 if ( mat.m12() == 0.0F && mat.m21() == 0.0F ) {
2952 if ( mat.m11() == 1.0F && mat.m22() == 1.0F ) // identity matrix
2953 return copy();
2954 hd = qRound( mat.m22() * hs );
2955 wd = qRound( mat.m11() * ws );
2956 hd = QABS( hd );
2957 wd = QABS( wd );
2958 } else { // rotation or shearing
2959 QPointArray a( QRect(0, 0, ws, hs) );
2960 a = mat.map( a );
2961 QRect r = a.boundingRect().normalize();
2962 wd = r.width();
2963 hd = r.height();
2964 }
2965
2966 bool invertible;
2967 mat = mat.invert( &invertible ); // invert matrix
2968 if ( hd == 0 || wd == 0 || !invertible ) // error, return null image
2969 return QImage();
2970
2971 // create target image (some of the code is from QImage::copy())
2972 QImage dImage( wd, hd, depth(), numColors(), bitOrder() );
2973 memcpy( dImage.colorTable(), colorTable(), numColors()*sizeof(QRgb) );
2974 dImage.setAlphaBuffer( hasAlphaBuffer() );
2975 dImage.data->dpmx = dotsPerMeterX();
2976 dImage.data->dpmy = dotsPerMeterY();
2977
2978 switch ( bpp ) {
2979 // initizialize the data
2980 case 1:
2981 memset( dImage.bits(), 0, dImage.numBytes() );
2982 break;
2983 case 8:
2984 if ( dImage.data->ncols < 256 ) {
2985 // colors are left in the color table, so pick that one as transparent
2986 dImage.setNumColors( dImage.data->ncols+1 );
2987 dImage.setColor( dImage.data->ncols-1, 0x00 );
2988 memset( dImage.bits(), dImage.data->ncols-1, dImage.numBytes() );
2989 } else {
2990 memset( dImage.bits(), 0, dImage.numBytes() );
2991 }
2992 break;
2993 case 16:
2994 memset( dImage.bits(), 0xff, dImage.numBytes() );
2995 break;
2996 case 32:
2997 memset( dImage.bits(), 0x00, dImage.numBytes() );
2998 break;
2999 }
3000
3001 int type;
3002 if ( bitOrder() == BigEndian )
3003 type = QT_XFORM_TYPE_MSBFIRST;
3004 else
3005 type = QT_XFORM_TYPE_LSBFIRST;
3006 int dbpl = dImage.bytesPerLine();
3007 qt_xForm_helper( mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl,
3008 ws, hs );
3009 return dImage;
3010}
3011#endif
3012
3013/*!
3014 Builds and returns a 1-bpp mask from the alpha buffer in this
3015 image. Returns a \link isNull() null\endlink image if \link
3016 setAlphaBuffer() alpha buffer mode\endlink is disabled.
3017
3018 See QPixmap::convertFromImage() for a description of the \a
3019 conversion_flags argument.
3020
3021 The returned image has little-endian bit order, which you can
3022 convert to big-endianness using convertBitOrder().
3023
3024 \sa createHeuristicMask() hasAlphaBuffer() setAlphaBuffer()
3025*/
3026#ifndef QT_NO_IMAGE_DITHER_TO_1
3027QImage QImage::createAlphaMask( int conversion_flags ) const
3028{
3029 if ( conversion_flags == 1 ) {
3030 // Old code is passing "TRUE".
3031 conversion_flags = Qt::DiffuseAlphaDither;
3032 }
3033
3034 if ( isNull() || !hasAlphaBuffer() )
3035 return QImage();
3036
3037 if ( depth() == 1 ) {
3038 // A monochrome pixmap, with alpha channels on those two colors.
3039 // Pretty unlikely, so use less efficient solution.
3040 return convertDepth(8, conversion_flags)
3041 .createAlphaMask( conversion_flags );
3042 }
3043
3044 QImage mask1;
3045 dither_to_1( this, &mask1, conversion_flags, TRUE );
3046 return mask1;
3047}
3048#endif
3049
3050#ifndef QT_NO_IMAGE_HEURISTIC_MASK
3051/*!
3052 Creates and returns a 1-bpp heuristic mask for this image. It
3053 works by selecting a color from one of the corners, then chipping
3054 away pixels of that color starting at all the edges.
3055
3056 The four corners vote for which color is to be masked away. In
3057 case of a draw (this generally means that this function is not
3058 applicable to the image), the result is arbitrary.
3059
3060 The returned image has little-endian bit order, which you can
3061 convert to big-endianness using convertBitOrder().
3062
3063 If \a clipTight is TRUE the mask is just large enough to cover the
3064 pixels; otherwise, the mask is larger than the data pixels.
3065
3066 This function disregards the \link hasAlphaBuffer() alpha buffer
3067 \endlink.
3068
3069 \sa createAlphaMask()
3070*/
3071
3072QImage QImage::createHeuristicMask( bool clipTight ) const
3073{
3074 if ( isNull() ) {
3075 QImage nullImage;
3076 return nullImage;
3077 }
3078 if ( depth() != 32 ) {
3079 QImage img32 = convertDepth(32);
3080 return img32.createHeuristicMask(clipTight);
3081 }
3082
3083#define PIX(x,y) (*((QRgb*)scanLine(y)+x) & 0x00ffffff)
3084
3085 int w = width();
3086 int h = height();
3087 QImage m(w, h, 1, 2, QImage::LittleEndian);
3088 m.setColor( 0, 0xffffff );
3089 m.setColor( 1, 0 );
3090 m.fill( 0xff );
3091
3092 QRgb background = PIX(0,0);
3093 if ( background != PIX(w-1,0) &&
3094 background != PIX(0,h-1) &&
3095 background != PIX(w-1,h-1) ) {
3096 background = PIX(w-1,0);
3097 if ( background != PIX(w-1,h-1) &&
3098 background != PIX(0,h-1) &&
3099 PIX(0,h-1) == PIX(w-1,h-1) ) {
3100 background = PIX(w-1,h-1);
3101 }
3102 }
3103
3104 int x,y;
3105 bool done = FALSE;
3106 uchar *ypp, *ypc, *ypn;
3107 while( !done ) {
3108 done = TRUE;
3109 ypn = m.scanLine(0);
3110 ypc = 0;
3111 for ( y = 0; y < h; y++ ) {
3112 ypp = ypc;
3113 ypc = ypn;
3114 ypn = (y == h-1) ? 0 : m.scanLine(y+1);
3115 QRgb *p = (QRgb *)scanLine(y);
3116 for ( x = 0; x < w; x++ ) {
3117 // slowness here - it's possible to do six of these tests
3118 // together in one go. oh well.
3119 if ( ( x == 0 || y == 0 || x == w-1 || y == h-1 ||
3120 !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
3121 !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
3122 !(*(ypp + (x >> 3)) & (1 << (x & 7))) ||
3123 !(*(ypn + (x >> 3)) & (1 << (x & 7))) ) &&
3124 ( (*(ypc + (x >> 3)) & (1 << (x & 7))) ) &&
3125 ( (*p & 0x00ffffff) == background ) ) {
3126 done = FALSE;
3127 *(ypc + (x >> 3)) &= ~(1 << (x & 7));
3128 }
3129 p++;
3130 }
3131 }
3132 }
3133
3134 if ( !clipTight ) {
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 if ( (*p & 0x00ffffff) != background ) {
3144 if ( x > 0 )
3145 *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
3146 if ( x < w-1 )
3147 *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
3148 if ( y > 0 )
3149 *(ypp + (x >> 3)) |= (1 << (x & 7));
3150 if ( y < h-1 )
3151 *(ypn + (x >> 3)) |= (1 << (x & 7));
3152 }
3153 p++;
3154 }
3155 }
3156 }
3157
3158#undef PIX
3159
3160 return m;
3161}
3162#endif //QT_NO_IMAGE_HEURISTIC_MASK
3163
3164#ifndef QT_NO_IMAGE_MIRROR
3165/*
3166 This code is contributed by Philipp Lang,
3167 GeneriCom Software Germany (www.generi.com)
3168 under the terms of the QPL, Version 1.0
3169*/
3170
3171/*!
3172 \overload
3173
3174 Returns a mirror of the image, mirrored in the horizontal and/or
3175 the vertical direction depending on whether \a horizontal and \a
3176 vertical are set to TRUE or FALSE. The original image is not
3177 changed.
3178
3179 \sa smoothScale()
3180*/
3181QImage QImage::mirror(bool horizontal, bool vertical) const
3182{
3183 int w = width();
3184 int h = height();
3185 if ( (w <= 1 && h <= 1) || (!horizontal && !vertical) )
3186 return copy();
3187
3188 // Create result image, copy colormap
3189 QImage result(w, h, depth(), numColors(), bitOrder());
3190 memcpy(result.colorTable(), colorTable(), numColors()*sizeof(QRgb));
3191 result.setAlphaBuffer(hasAlphaBuffer());
3192
3193 if (depth() == 1)
3194 w = (w+7)/8;
3195 int dxi = horizontal ? -1 : 1;
3196 int dxs = horizontal ? w-1 : 0;
3197 int dyi = vertical ? -1 : 1;
3198 int dy = vertical ? h-1: 0;
3199
3200 // 1 bit, 8 bit
3201 if (depth() == 1 || depth() == 8) {
3202 for (int sy = 0; sy < h; sy++, dy += dyi) {
3203 Q_UINT8* ssl = (Q_UINT8*)(data->bits[sy]);
3204 Q_UINT8* dsl = (Q_UINT8*)(result.data->bits[dy]);
3205 int dx = dxs;
3206 for (int sx = 0; sx < w; sx++, dx += dxi)
3207 dsl[dx] = ssl[sx];
3208 }
3209 }
3210#ifndef QT_NO_IMAGE_TRUECOLOR
3211#ifndef QT_NO_IMAGE_16_BIT
3212 // 16 bit
3213 else if (depth() == 16) {
3214 for (int sy = 0; sy < h; sy++, dy += dyi) {
3215 Q_UINT16* ssl = (Q_UINT16*)(data->bits[sy]);
3216 Q_UINT16* dsl = (Q_UINT16*)(result.data->bits[dy]);
3217 int dx = dxs;
3218 for (int sx = 0; sx < w; sx++, dx += dxi)
3219 dsl[dx] = ssl[sx];
3220 }
3221 }
3222#endif
3223 // 32 bit
3224 else if (depth() == 32) {
3225 for (int sy = 0; sy < h; sy++, dy += dyi) {
3226 Q_UINT32* ssl = (Q_UINT32*)(data->bits[sy]);
3227 Q_UINT32* dsl = (Q_UINT32*)(result.data->bits[dy]);
3228 int dx = dxs;
3229 for (int sx = 0; sx < w; sx++, dx += dxi)
3230 dsl[dx] = ssl[sx];
3231 }
3232 }
3233#endif
3234
3235 // special handling of 1 bit images for horizontal mirroring
3236 if (horizontal && depth() == 1) {
3237 int shift = width() % 8;
3238 for (int y = h-1; y >= 0; y--) {
3239 Q_UINT8* a0 = (Q_UINT8*)(result.data->bits[y]);
3240 // Swap bytes
3241 Q_UINT8* a = a0+dxs;
3242 while (a >= a0) {
3243 *a = bitflip[*a];
3244 a--;
3245 }
3246 // Shift bits if unaligned
3247 if (shift != 0) {
3248 a = a0+dxs;
3249 Q_UINT8 c = 0;
3250 if (bitOrder() == QImage::LittleEndian) {
3251 while (a >= a0) {
3252 Q_UINT8 nc = *a << shift;
3253 *a = (*a >> (8-shift)) | c;
3254 --a;
3255 c = nc;
3256 }
3257 } else {
3258 while (a >= a0) {
3259 Q_UINT8 nc = *a >> shift;
3260 *a = (*a << (8-shift)) | c;
3261 --a;
3262 c = nc;
3263 }
3264 }
3265 }
3266 }
3267 }
3268
3269 return result;
3270}
3271
3272/*!
3273 Returns a QImage which is a vertically mirrored copy of this
3274 image. The original QImage is not changed.
3275*/
3276
3277QImage QImage::mirror() const
3278{
3279 return mirror(FALSE,TRUE);
3280}
3281#endif //QT_NO_IMAGE_MIRROR
3282
3283/*!
3284 Returns a QImage in which the values of the red and blue
3285 components of all pixels have been swapped, effectively converting
3286 an RGB image to a BGR image. The original QImage is not changed.
3287*/
3288
3289QImage QImage::swapRGB() const
3290{
3291 QImage res = copy();
3292 if ( !isNull() ) {
3293#ifndef QT_NO_IMAGE_TRUECOLOR
3294 if ( depth() == 32 ) {
3295 for ( int i=0; i < height(); i++ ) {
3296 uint *p = (uint*)scanLine( i );
3297 uint *q = (uint*)res.scanLine( i );
3298 uint *end = p + width();
3299 while ( p < end ) {
3300 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) |
3301 (*p & 0xff00ff00);
3302 p++;
3303 q++;
3304 }
3305 }
3306#ifndef QT_NO_IMAGE_16_BIT
3307 } else if ( depth() == 16 ) {
3308 qWarning( "QImage::swapRGB not implemented for 16bpp" );
3309#endif
3310 } else
3311#endif //QT_NO_IMAGE_TRUECOLOR
3312 {
3313 uint* p = (uint*)colorTable();
3314 uint* q = (uint*)res.colorTable();
3315 if ( p && q ) {
3316 for ( int i=0; i < numColors(); i++ ) {
3317 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) |
3318 (*p & 0xff00ff00);
3319 p++;
3320 q++;
3321 }
3322 }
3323 }
3324 }
3325 return res;
3326}
3327
3328#ifndef QT_NO_IMAGEIO
3329/*!
3330 Returns a string that specifies the image format of the file \a
3331 fileName, or 0 if the file cannot be read or if the format is not
3332 recognized.
3333
3334 The QImageIO documentation lists the guaranteed supported image
3335 formats, or use QImage::inputFormats() and QImage::outputFormats()
3336 to get lists that include the installed formats.
3337
3338 \sa load() save()
3339*/
3340
3341const char* QImage::imageFormat( const QString &fileName )
3342{
3343 return QImageIO::imageFormat( fileName );
3344}
3345
3346/*!
3347 Returns a list of image formats that are supported for image
3348 input.
3349
3350 \sa outputFormats() inputFormatList() QImageIO
3351*/
3352QStrList QImage::inputFormats()
3353{
3354 return QImageIO::inputFormats();
3355}
3356#ifndef QT_NO_STRINGLIST
3357/*!
3358 Returns a list of image formats that are supported for image
3359 input.
3360
3361 Note that if you want to iterate over the list, you should iterate
3362 over a copy, e.g.
3363 \code
3364 QStringList list = myImage.inputFormatList();
3365 QStringList::Iterator it = list.begin();
3366 while( it != list.end() ) {
3367 myProcessing( *it );
3368 ++it;
3369 }
3370 \endcode
3371
3372 \sa outputFormatList() inputFormats() QImageIO
3373*/
3374QStringList QImage::inputFormatList()
3375{
3376 return QStringList::fromStrList(QImageIO::inputFormats());
3377}
3378
3379
3380/*!
3381 Returns a list of image formats that are supported for image
3382 output.
3383
3384 Note that if you want to iterate over the list, you should iterate
3385 over a copy, e.g.
3386 \code
3387 QStringList list = myImage.outputFormatList();
3388 QStringList::Iterator it = list.begin();
3389 while( it != list.end() ) {
3390 myProcessing( *it );
3391 ++it;
3392 }
3393 \endcode
3394
3395 \sa inputFormatList() outputFormats() QImageIO
3396*/
3397QStringList QImage::outputFormatList()
3398{
3399 return QStringList::fromStrList(QImageIO::outputFormats());
3400}
3401#endif //QT_NO_STRINGLIST
3402
3403/*!
3404 Returns a list of image formats that are supported for image
3405 output.
3406
3407 \sa inputFormats() outputFormatList() QImageIO
3408*/
3409QStrList QImage::outputFormats()
3410{
3411 return QImageIO::outputFormats();
3412}
3413
3414
3415/*!
3416 Loads an image from the file \a fileName. Returns TRUE if the
3417 image was successfully loaded; otherwise returns FALSE.
3418
3419 If \a format is specified, the loader attempts to read the image
3420 using the specified format. If \a format is not specified (which
3421 is the default), the loader reads a few bytes from the header to
3422 guess the file format.
3423
3424 The QImageIO documentation lists the supported image formats and
3425 explains how to add extra formats.
3426
3427 \sa loadFromData() save() imageFormat() QPixmap::load() QImageIO
3428*/
3429
3430bool QImage::load( const QString &fileName, const char* format )
3431{
3432 QImageIO io( fileName, format );
3433 bool result = io.read();
3434 if ( result )
3435 operator=( io.image() );
3436 return result;
3437}
3438
3439/*!
3440 Loads an image from the first \a len bytes of binary data in \a
3441 buf. Returns TRUE if the image was successfully loaded; otherwise
3442 returns FALSE.
3443
3444 If \a format is specified, the loader attempts to read the image
3445 using the specified format. If \a format is not specified (which
3446 is the default), the loader reads a few bytes from the header to
3447 guess the file format.
3448
3449 The QImageIO documentation lists the supported image formats and
3450 explains how to add extra formats.
3451
3452 \sa load() save() imageFormat() QPixmap::loadFromData() QImageIO
3453*/
3454
3455bool QImage::loadFromData( const uchar *buf, uint len, const char *format )
3456{
3457 QByteArray a;
3458 a.setRawData( (char *)buf, len );
3459 QBuffer b( a );
3460 b.open( IO_ReadOnly );
3461 QImageIO io( &b, format );
3462 bool result = io.read();
3463 b.close();
3464 a.resetRawData( (char *)buf, len );
3465 if ( result )
3466 operator=( io.image() );
3467 return result;
3468}
3469
3470/*!
3471 \overload
3472
3473 Loads an image from the QByteArray \a buf.
3474*/
3475bool QImage::loadFromData( QByteArray buf, const char *format )
3476{
3477 return loadFromData( (const uchar *)(buf.data()), buf.size(), format );
3478}
3479
3480/*!
3481 Saves the image to the file \a fileName, using the image file
3482 format \a format and a quality factor of \a quality. \a quality
3483 must be in the range 0..100 or -1. Specify 0 to obtain small
3484 compressed files, 100 for large uncompressed files, and -1 (the
3485 default) to use the default settings.
3486
3487 Returns TRUE if the image was successfully saved; otherwise
3488 returns FALSE.
3489
3490 \sa load() loadFromData() imageFormat() QPixmap::save() QImageIO
3491*/
3492
3493bool QImage::save( const QString &fileName, const char* format, int quality ) const
3494{
3495 if ( isNull() )
3496 return FALSE; // nothing to save
3497 QImageIO io( fileName, format );
3498 return doImageIO( &io, quality );
3499}
3500
3501/*!
3502 \overload
3503
3504 This function writes a QImage to the QIODevice, \a device. This
3505 can be used, for example, to save an image directly into a
3506 QByteArray:
3507 \code
3508 QImage image;
3509 QByteArray ba;
3510 QBuffer buffer( ba );
3511 buffer.open( IO_WriteOnly );
3512 image.save( &buffer, "PNG" ); // writes image into ba in PNG format
3513 \endcode
3514*/
3515
3516bool QImage::save( QIODevice* device, const char* format, int quality ) const
3517{
3518 if ( isNull() )
3519 return FALSE; // nothing to save
3520 QImageIO io( device, format );
3521 return doImageIO( &io, quality );
3522}
3523
3524/* \internal
3525*/
3526
3527bool QImage::doImageIO( QImageIO* io, int quality ) const
3528{
3529 if ( !io )
3530 return FALSE;
3531 io->setImage( *this );
3532#if defined(QT_CHECK_RANGE)
3533 if ( quality > 100 || quality < -1 )
3534 qWarning( "QPixmap::save: quality out of range [-1,100]" );
3535#endif
3536 if ( quality >= 0 )
3537 io->setQuality( QMIN(quality,100) );
3538 return io->write();
3539}
3540#endif //QT_NO_IMAGEIO
3541
3542/*****************************************************************************
3543 QImage stream functions
3544 *****************************************************************************/
3545#if !defined(QT_NO_DATASTREAM) && !defined(QT_NO_IMAGEIO)
3546/*!
3547 \relates QImage
3548
3549 Writes the image \a image to the stream \a s as a PNG image, or as a
3550 BMP image if the stream's version is 1.
3551
3552 Note that writing the stream to a file will not produce a valid image file.
3553
3554 \sa QImage::save()
3555 \link datastreamformat.html Format of the QDataStream operators \endlink
3556*/
3557
3558QDataStream &operator<<( QDataStream &s, const QImage &image )
3559{
3560 if ( s.version() >= 5 ) {
3561 if ( image.isNull() ) {
3562 s << (Q_INT32) 0; // null image marker
3563 return s;
3564 } else {
3565 s << (Q_INT32) 1;
3566 // continue ...
3567 }
3568 }
3569 QImageIO io;
3570 io.setIODevice( s.device() );
3571 if ( s.version() == 1 )
3572 io.setFormat( "BMP" );
3573 else
3574 io.setFormat( "PNG" );
3575
3576 io.setImage( image );
3577 io.write();
3578 return s;
3579}
3580
3581/*!
3582 \relates QImage
3583
3584 Reads an image from the stream \a s and stores it in \a image.
3585
3586 \sa QImage::load()
3587 \link datastreamformat.html Format of the QDataStream operators \endlink
3588*/
3589
3590QDataStream &operator>>( QDataStream &s, QImage &image )
3591{
3592 if ( s.version() >= 5 ) {
3593 Q_INT32 nullMarker;
3594 s >> nullMarker;
3595 if ( !nullMarker ) {
3596 image = QImage(); // null image
3597 return s;
3598 }
3599 }
3600 QImageIO io( s.device(), 0 );
3601 if ( io.read() )
3602 image = io.image();
3603 return s;
3604}
3605#endif
3606
3607/*****************************************************************************
3608 Standard image io handlers (defined below)
3609 *****************************************************************************/
3610
3611// standard image io handlers (defined below)
3612#ifndef QT_NO_IMAGEIO_BMP
3613static void read_bmp_image( QImageIO * );
3614static void write_bmp_image( QImageIO * );
3615#endif
3616#ifndef QT_NO_IMAGEIO_PPM
3617static void read_pbm_image( QImageIO * );
3618static void write_pbm_image( QImageIO * );
3619#endif
3620#ifndef QT_NO_IMAGEIO_XBM
3621static void read_xbm_image( QImageIO * );
3622static void write_xbm_image( QImageIO * );
3623#endif
3624#ifndef QT_NO_IMAGEIO_XPM
3625static void read_xpm_image( QImageIO * );
3626static void write_xpm_image( QImageIO * );
3627#endif
3628
3629#ifndef QT_NO_ASYNC_IMAGE_IO
3630static void read_async_image( QImageIO * ); // Not in table of handlers
3631#endif
3632
3633/*****************************************************************************
3634 Misc. utility functions
3635 *****************************************************************************/
3636#if !defined(QT_NO_IMAGEIO_XPM) || !defined(QT_NO_IMAGEIO_XBM)
3637static QString fbname( const QString &fileName ) // get file basename (sort of)
3638{
3639 QString s = fileName;
3640 if ( !s.isEmpty() ) {
3641 int i;
3642 if ( (i = s.findRev('/')) >= 0 )
3643 s = s.mid( i );
3644 if ( (i = s.findRev('\\')) >= 0 )
3645 s = s.mid( i );
3646 QRegExp r( QString::fromLatin1("[a-zA-Z][a-zA-Z0-9_]*") );
3647 int p = r.search( s );
3648 if ( p == -1 )
3649 s.truncate( 0 );
3650 else
3651 s = s.mid( p, r.matchedLength() );
3652 }
3653 if ( s.isEmpty() )
3654 s = QString::fromLatin1( "dummy" );
3655 return s;
3656}
3657#endif
3658
3659#ifndef QT_NO_IMAGEIO_BMP
3660static void swapPixel01( QImage *image ) // 1-bpp: swap 0 and 1 pixels
3661{
3662 int i;
3663 if ( image->depth() == 1 && image->numColors() == 2 ) {
3664 register uint *p = (uint *)image->bits();
3665 int nbytes = image->numBytes();
3666 for ( i=0; i<nbytes/4; i++ ) {
3667 *p = ~*p;
3668 p++;
3669 }
3670 uchar *p2 = (uchar *)p;
3671 for ( i=0; i<(nbytes&3); i++ ) {
3672 *p2 = ~*p2;
3673 p2++;
3674 }
3675 QRgb t = image->color(0); // swap color 0 and 1
3676 image->setColor( 0, image->color(1) );
3677 image->setColor( 1, t );
3678 }
3679}
3680#endif
3681
3682
3683/*****************************************************************************
3684 QImageIO member functions
3685 *****************************************************************************/
3686
3687/*!
3688 \class QImageIO qimage.h
3689
3690 \brief The QImageIO class contains parameters for loading and
3691 saving images.
3692
3693 \ingroup images
3694 \ingroup graphics
3695 \ingroup io
3696
3697 QImageIO contains a QIODevice object that is used for image data
3698 I/O. The programmer can install new image file formats in addition
3699 to those that Qt provides.
3700
3701 Qt currently supports the following image file formats: PNG, BMP,
3702 XBM, XPM and PNM. It may also support JPEG, MNG and GIF, if
3703 specially configured during compilation. The different PNM formats
3704 are: PBM (P1 or P4), PGM (P2 or P5), and PPM (P3 or P6).
3705
3706 You don't normally need to use this class; QPixmap::load(),
3707 QPixmap::save(), and QImage contain sufficient functionality.
3708
3709 For image files that contain sequences of images, only the first
3710 is read. See QMovie for loading multiple images.
3711
3712 PBM, PGM, and PPM format \e output is always in the more condensed
3713 raw format. PPM and PGM files with more than 256 levels of
3714 intensity are scaled down when reading.
3715
3716 \warning If you are in a country which recognizes software patents
3717 and in which Unisys holds a patent on LZW compression and/or
3718 decompression and you want to use GIF, Unisys may require you to
3719 license the technology. Such countries include Canada, Japan, the
3720 USA, France, Germany, Italy and the UK.
3721
3722 GIF support may be removed completely in a future version of Qt.
3723 We recommend using the PNG format.
3724
3725 \sa QImage QPixmap QFile QMovie
3726*/
3727
3728#ifndef QT_NO_IMAGEIO
3729struct QImageIOData
3730{
3731 const char *parameters;
3732 int quality;
3733 float gamma;
3734};
3735
3736/*!
3737 Constructs a QImageIO object with all parameters set to zero.
3738*/
3739
3740QImageIO::QImageIO()
3741{
3742 init();
3743}
3744
3745/*!
3746 Constructs a QImageIO object with the I/O device \a ioDevice and a
3747 \a format tag.
3748*/
3749
3750QImageIO::QImageIO( QIODevice *ioDevice, const char *format )
3751 : frmt(format)
3752{
3753 init();
3754 iodev = ioDevice;
3755}
3756
3757/*!
3758 Constructs a QImageIO object with the file name \a fileName and a
3759 \a format tag.
3760*/
3761
3762QImageIO::QImageIO( const QString &fileName, const char* format )
3763 : frmt(format), fname(fileName)
3764{
3765 init();
3766}
3767
3768/*!
3769 Contains initialization common to all QImageIO constructors.
3770*/
3771
3772void QImageIO::init()
3773{
3774 d = new QImageIOData();
3775 d->parameters = 0;
3776 d->quality = -1; // default quality of the current format
3777 d->gamma=0.0f;
3778 iostat = 0;
3779 iodev = 0;
3780}
3781
3782/*!
3783 Destroys the object and all related data.
3784*/
3785
3786QImageIO::~QImageIO()
3787{
3788 if ( d->parameters )
3789 delete [] (char*)d->parameters;
3790 delete d;
3791}
3792
3793
3794/*****************************************************************************
3795 QImageIO image handler functions
3796 *****************************************************************************/
3797
3798class QImageHandler
3799{
3800public:
3801 QImageHandler( const char *f, const char *h, const QCString& fl,
3802 image_io_handler r, image_io_handler w );
3803 QCString format; // image format
3804 QRegExp header; // image header pattern
3805 enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode;
3806 image_io_handler read_image; // image read function
3807 image_io_handler write_image; // image write function
3808 bool obsolete; // support not "published"
3809};
3810
3811QImageHandler::QImageHandler( const char *f, const char *h, const QCString& fl,
3812 image_io_handler r, image_io_handler w )
3813 : format(f), header(QString::fromLatin1(h))
3814{
3815 text_mode = Untranslated;
3816 if ( fl.contains('t') )
3817 text_mode = TranslateIn;
3818 else if ( fl.contains('T') )
3819 text_mode = TranslateInOut;
3820 obsolete = fl.contains('O');
3821 read_image = r;
3822 write_image = w;
3823}
3824
3825typedef QPtrList<QImageHandler> QIHList;// list of image handlers
3826static QIHList *imageHandlers = 0;
3827#ifndef QT_NO_COMPONENT
3828static QPluginManager<QImageFormatInterface> *plugin_manager = 0;
3829#else
3830static void *plugin_manager = 0;
3831#endif
3832
3833void qt_init_image_plugins()
3834{
3835#ifndef QT_NO_COMPONENT
3836 if ( plugin_manager )
3837 return;
3838
3839 plugin_manager = new QPluginManager<QImageFormatInterface>( IID_QImageFormat, QApplication::libraryPaths(), "/imageformats" );
3840
3841 QStringList features = plugin_manager->featureList();
3842 QStringList::Iterator it = features.begin();
3843 while ( it != features.end() ) {
3844 QString str = *it;
3845 ++it;
3846 QInterfacePtr<QImageFormatInterface> iface;
3847 plugin_manager->queryInterface( str, &iface );
3848 if ( iface )
3849 iface->installIOHandler( str );
3850 }
3851#endif
3852}
3853
3854static void cleanup()
3855{
3856 // make sure that image handlers are delete before plugin manager
3857 delete imageHandlers;
3858 imageHandlers = 0;
3859#ifndef QT_NO_COMPONENT
3860 delete plugin_manager;
3861 plugin_manager = 0;
3862#endif
3863}
3864
3865void qt_init_image_handlers() // initialize image handlers
3866{
3867 if ( !imageHandlers ) {
3868 imageHandlers = new QIHList;
3869 Q_CHECK_PTR( imageHandlers );
3870 imageHandlers->setAutoDelete( TRUE );
3871 qAddPostRoutine( cleanup );
3872#ifndef QT_NO_IMAGEIO_BMP
3873 QImageIO::defineIOHandler( "BMP", "^BM", 0,
3874 read_bmp_image, write_bmp_image );
3875#endif
3876#ifndef QT_NO_IMAGEIO_PPM
3877 QImageIO::defineIOHandler( "PBM", "^P1", "t",
3878 read_pbm_image, write_pbm_image );
3879 QImageIO::defineIOHandler( "PBMRAW", "^P4", "O",
3880 read_pbm_image, write_pbm_image );
3881 QImageIO::defineIOHandler( "PGM", "^P2", "t",
3882 read_pbm_image, write_pbm_image );
3883 QImageIO::defineIOHandler( "PGMRAW", "^P5", "O",
3884 read_pbm_image, write_pbm_image );
3885 QImageIO::defineIOHandler( "PPM", "^P3", "t",
3886 read_pbm_image, write_pbm_image );
3887 QImageIO::defineIOHandler( "PPMRAW", "^P6", "O",
3888 read_pbm_image, write_pbm_image );
3889#endif
3890#ifndef QT_NO_IMAGEIO_XBM
3891 QImageIO::defineIOHandler( "XBM", "^#define", "T",
3892 read_xbm_image, write_xbm_image );
3893#endif
3894#ifndef QT_NO_IMAGEIO_XPM
3895 QImageIO::defineIOHandler( "XPM", "/\\*.XPM.\\*/", "T",
3896 read_xpm_image, write_xpm_image );
3897#endif
3898#ifndef QT_NO_IMAGEIO_MNG
3899 qInitMngIO();
3900#endif
3901#ifndef QT_NO_IMAGEIO_PNG
3902 qInitPngIO();
3903#endif
3904#ifndef QT_NO_IMAGEIO_JPEG
3905 qInitJpegIO();
3906#endif
3907 }
3908}
3909
3910static QImageHandler *get_image_handler( const char *format )
3911{ // get pointer to handler
3912 qt_init_image_handlers();
3913 qt_init_image_plugins();
3914 register QImageHandler *p = imageHandlers->first();
3915 while ( p ) { // traverse list
3916 if ( p->format == format )
3917 return p;
3918 p = imageHandlers->next();
3919 }
3920 return 0; // no such handler
3921}
3922
3923
3924/*!
3925 Defines an image I/O handler for the image format called \a
3926 format, which is recognized using the \link qregexp.html#details
3927 regular expression\endlink \a header, read using \a readImage and
3928 written using \a writeImage.
3929
3930 \a flags is a string of single-character flags for this format.
3931 The only flag defined currently is T (upper case), so the only
3932 legal value for \a flags are "T" and the empty string. The "T"
3933 flag means that the image file is a text file, and Qt should treat
3934 all newline conventions as equivalent. (XPM files and some PPM
3935 files are text files for example.)
3936
3937 \a format is used to select a handler to write a QImage; \a header
3938 is used to select a handler to read an image file.
3939
3940 If \a readImage is a null pointer, the QImageIO will not be able
3941 to read images in \a format. If \a writeImage is a null pointer,
3942 the QImageIO will not be able to write images in \a format. If
3943 both are null, the QImageIO object is valid but useless.
3944
3945 Example:
3946 \code
3947 void readGIF( QImageIO *image )
3948 {
3949 // read the image using the image->ioDevice()
3950 }
3951
3952 void writeGIF( QImageIO *image )
3953 {
3954 // write the image using the image->ioDevice()
3955 }
3956
3957 // add the GIF image handler
3958
3959 QImageIO::defineIOHandler( "GIF",
3960 "^GIF[0-9][0-9][a-z]",
3961 0,
3962 readGIF,
3963 writeGIF );
3964 \endcode
3965
3966 Before the regex test, all the 0 bytes in the file header are
3967 converted to 1 bytes. This is done because when Qt was
3968 ASCII-based, QRegExp could not handle 0 bytes in strings.
3969
3970 The regexp is only applied on the first 14 bytes of the file.
3971
3972 (Note that if one handlerIO supports writing a format and another
3973 supports reading it, Qt supports both reading and writing. If two
3974 handlers support the same operation, Qt chooses one arbitrarily.)
3975*/
3976
3977void QImageIO::defineIOHandler( const char *format,
3978 const char *header,
3979 const char *flags,
3980 image_io_handler readImage,
3981 image_io_handler writeImage )
3982{
3983 qt_init_image_handlers();
3984 QImageHandler *p;
3985 p = new QImageHandler( format, header, flags,
3986 readImage, writeImage );
3987 Q_CHECK_PTR( p );
3988 imageHandlers->insert( 0, p );
3989}
3990
3991
3992/*****************************************************************************
3993 QImageIO normal member functions
3994 *****************************************************************************/
3995
3996/*!
3997 \fn const QImage &QImageIO::image() const
3998
3999 Returns the image currently set.
4000
4001 \sa setImage()
4002*/
4003
4004/*!
4005 \fn int QImageIO::status() const
4006
4007 Returns the image's IO status. A non-zero value indicates an
4008 error, whereas 0 means that the IO operation was successful.
4009
4010 \sa setStatus()
4011*/
4012
4013/*!
4014 \fn const char *QImageIO::format() const
4015
4016 Returns the image format string or 0 if no format has been
4017 explicitly set.
4018*/
4019
4020/*!
4021 \fn QIODevice *QImageIO::ioDevice() const
4022
4023 Returns the IO device currently set.
4024
4025 \sa setIODevice()
4026*/
4027
4028/*!
4029 \fn QString QImageIO::fileName() const
4030
4031 Returns the file name currently set.
4032
4033 \sa setFileName()
4034*/
4035
4036/*!
4037 \fn QString QImageIO::description() const
4038
4039 Returns the image description string.
4040
4041 \sa setDescription()
4042*/
4043
4044
4045/*!
4046 Sets the image to \a image.
4047
4048 \sa image()
4049*/
4050
4051void QImageIO::setImage( const QImage &image )
4052{
4053 im = image;
4054}
4055
4056/*!
4057 Sets the image IO status to \a status. A non-zero value indicates
4058 an error, whereas 0 means that the IO operation was successful.
4059
4060 \sa status()
4061*/
4062
4063void QImageIO::setStatus( int status )
4064{
4065 iostat = status;
4066}
4067
4068/*!
4069 Sets the image format to \a format for the image to be read or
4070 written.
4071
4072 It is necessary to specify a format before writing an image, but
4073 it is not necessary to specify a format before reading an image.
4074
4075 If no format has been set, Qt guesses the image format before
4076 reading it. If a format is set the image will only be read if it
4077 has that format.
4078
4079 \sa read() write() format()
4080*/
4081
4082void QImageIO::setFormat( const char *format )
4083{
4084 frmt = format;
4085}
4086
4087/*!
4088 Sets the IO device to be used for reading or writing an image.
4089
4090 Setting the IO device allows images to be read/written to any
4091 block-oriented QIODevice.
4092
4093 If \a ioDevice is not null, this IO device will override file name
4094 settings.
4095
4096 \sa setFileName()
4097*/
4098
4099void QImageIO::setIODevice( QIODevice *ioDevice )
4100{
4101 iodev = ioDevice;
4102}
4103
4104/*!
4105 Sets the name of the file to read or write an image from to \a
4106 fileName.
4107
4108 \sa setIODevice()
4109*/
4110
4111void QImageIO::setFileName( const QString &fileName )
4112{
4113 fname = fileName;
4114}
4115
4116/*!
4117 Returns the quality of the written image, related to the
4118 compression ratio.
4119
4120 \sa setQuality() QImage::save()
4121*/
4122
4123int QImageIO::quality() const
4124{
4125 return d->quality;
4126}
4127
4128/*!
4129 Sets the quality of the written image to \a q, related to the
4130 compression ratio.
4131
4132 \a q must be in the range -1..100. Specify 0 to obtain small
4133 compressed files, 100 for large uncompressed files. (-1 signifies
4134 the default compression.)
4135
4136 \sa quality() QImage::save()
4137*/
4138
4139void QImageIO::setQuality( int q )
4140{
4141 d->quality = q;
4142}
4143
4144/*!
4145 Returns the image's parameters string.
4146
4147 \sa setParameters()
4148*/
4149
4150const char *QImageIO::parameters() const
4151{
4152 return d->parameters;
4153}
4154
4155/*!
4156 Sets the image's parameter string to \a parameters. This is for
4157 image handlers that require special parameters.
4158
4159 Although the current image formats supported by Qt ignore the
4160 parameters string, it may be used in future extensions or by
4161 contributions (for example, JPEG).
4162
4163 \sa parameters()
4164*/
4165
4166void QImageIO::setParameters( const char *parameters )
4167{
4168 if ( d && d->parameters )
4169 delete [] (char*)d->parameters;
4170 d->parameters = qstrdup( parameters );
4171}
4172
4173/*!
4174 Sets the gamma value at which the image will be viewed to \a
4175 gamma. If the image format stores a gamma value for which the
4176 image is intended to be used, then this setting will be used to
4177 modify the image. Setting to 0.0 will disable gamma correction
4178 (i.e. any specification in the file will be ignored).
4179
4180 The default value is 0.0.
4181
4182 \sa gamma()
4183*/
4184void QImageIO::setGamma( float gamma )
4185{
4186 d->gamma=gamma;
4187}
4188
4189/*!
4190 Returns the gamma value at which the image will be viewed.
4191
4192 \sa setGamma()
4193*/
4194float QImageIO::gamma() const
4195{
4196 return d->gamma;
4197}
4198
4199/*!
4200 Sets the image description string for image handlers that support
4201 image descriptions to \a description.
4202
4203 Currently, no image format supported by Qt uses the description
4204 string.
4205*/
4206
4207void QImageIO::setDescription( const QString &description )
4208{
4209 descr = description;
4210}
4211
4212
4213/*!
4214 Returns a string that specifies the image format of the file \a
4215 fileName, or null if the file cannot be read or if the format is
4216 not recognized.
4217*/
4218
4219const char* QImageIO::imageFormat( const QString &fileName )
4220{
4221 QFile file( fileName );
4222 if ( !file.open(IO_ReadOnly) )
4223 return 0;
4224 const char* format = imageFormat( &file );
4225 file.close();
4226 return format;
4227}
4228
4229/*!
4230 \overload
4231
4232 Returns a string that specifies the image format of the image read
4233 from IO device \a d, or 0 if the device cannot be read or if the
4234 format is not recognized.
4235
4236 Make sure that \a d is at the right position in the device (for
4237 example, at the beginning of the file).
4238
4239 \sa QIODevice::at()
4240*/
4241
4242const char *QImageIO::imageFormat( QIODevice *d )
4243{
4244 // if you change this change the documentation for defineIOHandler()
4245 const int buflen = 14;
4246
4247 char buf[buflen];
4248 char buf2[buflen];
4249 qt_init_image_handlers();
4250 qt_init_image_plugins();
4251 int pos = d->at(); // save position
4252 int rdlen = d->readBlock( buf, buflen ); // read a few bytes
4253
4254 if ( rdlen != buflen )
4255 return 0;
4256
4257 memcpy( buf2, buf, buflen );
4258
4259 const char* format = 0;
4260 for ( int n = 0; n < rdlen; n++ )
4261 if ( buf[n] == '\0' )
4262 buf[n] = '\001';
4263 if ( d->status() == IO_Ok && rdlen > 0 ) {
4264 buf[rdlen - 1] = '\0';
4265 QString bufStr = QString::fromLatin1(buf);
4266 QImageHandler *p = imageHandlers->first();
4267 int bestMatch = -1;
4268 while ( p ) {
4269 if ( p->read_image && p->header.search(bufStr) != -1 ) {
4270 // try match with header if a read function is available
4271 if (p->header.matchedLength() > bestMatch) {
4272 // keep looking for best match
4273 format = p->format;
4274 bestMatch = p->header.matchedLength();
4275 }
4276 }
4277 p = imageHandlers->next();
4278 }
4279 }
4280 d->at( pos ); // restore position
4281#ifndef QT_NO_ASYNC_IMAGE_IO
4282 if ( !format )
4283 format = QImageDecoder::formatName( (uchar*)buf2, rdlen );
4284#endif
4285
4286 return format;
4287}
4288
4289/*!
4290 Returns a sorted list of image formats that are supported for
4291 image input.
4292*/
4293QStrList QImageIO::inputFormats()
4294{
4295 QStrList result;
4296
4297 qt_init_image_handlers();
4298 qt_init_image_plugins();
4299
4300#ifndef QT_NO_ASYNC_IMAGE_IO
4301 // Include asynchronous loaders first.
4302 result = QImageDecoder::inputFormats();
4303#endif
4304
4305 QImageHandler *p = imageHandlers->first();
4306 while ( p ) {
4307 if ( p->read_image
4308 && !p->obsolete
4309 && !result.contains(p->format) )
4310 {
4311 result.inSort(p->format);
4312 }
4313 p = imageHandlers->next();
4314 }
4315
4316 return result;
4317}
4318
4319/*!
4320 Returns a sorted list of image formats that are supported for
4321 image output.
4322*/
4323QStrList QImageIO::outputFormats()
4324{
4325 QStrList result;
4326
4327 qt_init_image_handlers();
4328 qt_init_image_plugins();
4329
4330 // Include asynchronous writers (!) first.
4331 // (None)
4332
4333 QImageHandler *p = imageHandlers->first();
4334 while ( p ) {
4335 if ( p->write_image
4336 && !p->obsolete
4337 && !result.contains(p->format) )
4338 {
4339 result.inSort(p->format);
4340 }
4341 p = imageHandlers->next();
4342 }
4343
4344 return result;
4345}
4346
4347
4348
4349/*!
4350 Reads an image into memory and returns TRUE if the image was
4351 successfully read; otherwise returns FALSE.
4352
4353 Before reading an image you must set an IO device or a file name.
4354 If both an IO device and a file name have been set, the IO device
4355 will be used.
4356
4357 Setting the image file format string is optional.
4358
4359 Note that this function does \e not set the \link format()
4360 format\endlink used to read the image. If you need that
4361 information, use the imageFormat() static functions.
4362
4363 Example:
4364
4365 \code
4366 QImageIO iio;
4367 QPixmap pixmap;
4368 iio.setFileName( "vegeburger.bmp" );
4369 if ( image.read() ) // ok
4370 pixmap = iio.image(); // convert to pixmap
4371 \endcode
4372
4373 \sa setIODevice() setFileName() setFormat() write() QPixmap::load()
4374*/
4375
4376bool QImageIO::read()
4377{
4378 QFile file;
4379 const char *image_format;
4380 QImageHandler *h;
4381
4382 if ( iodev ) { // read from io device
4383 // ok, already open
4384 } else if ( !fname.isEmpty() ) { // read from file
4385 file.setName( fname );
4386 if ( !file.open(IO_ReadOnly) )
4387 return FALSE; // cannot open file
4388 iodev = &file;
4389 } else { // no file name or io device
4390 return FALSE;
4391 }
4392 if (frmt.isEmpty()) {
4393 // Try to guess format
4394 image_format = imageFormat( iodev ); // get image format
4395 if ( !image_format ) {
4396 if ( file.isOpen() ) { // unknown format
4397 file.close();
4398 iodev = 0;
4399 }
4400 return FALSE;
4401 }
4402 } else {
4403 image_format = frmt;
4404 }
4405
4406 h = get_image_handler( image_format );
4407 if ( file.isOpen() ) {
4408#if !defined(Q_OS_UNIX)
4409 if ( h && h->text_mode ) { // reopen in translated mode
4410 file.close();
4411 file.open( IO_ReadOnly | IO_Translate );
4412 }
4413 else
4414#endif
4415 file.at( 0 ); // position to start
4416 }
4417 iostat = 1; // assume error
4418
4419 if ( h && h->read_image ) {
4420 (*h->read_image)( this );
4421 }
4422#ifndef QT_NO_ASYNC_IMAGE_IO
4423 else {
4424 // Format name, but no handler - must be an asychronous reader
4425 read_async_image( this );
4426 }
4427#endif
4428
4429 if ( file.isOpen() ) { // image was read using file
4430 file.close();
4431 iodev = 0;
4432 }
4433 return iostat == 0; // image successfully read?
4434}
4435
4436
4437/*!
4438 Writes an image to an IO device and returns TRUE if the image was
4439 successfully written; otherwise returns FALSE.
4440
4441 Before writing an image you must set an IO device or a file name.
4442 If both an IO device and a file name have been set, the IO device
4443 will be used.
4444
4445 The image will be written using the specified image format.
4446
4447 Example:
4448 \code
4449 QImageIO iio;
4450 QImage im;
4451 im = pixmap; // convert to image
4452 iio.setImage( im );
4453 iio.setFileName( "vegeburger.bmp" );
4454 iio.setFormat( "BMP" );
4455 if ( iio.write() )
4456 // returned TRUE if written successfully
4457 \endcode
4458
4459 \sa setIODevice() setFileName() setFormat() read() QPixmap::save()
4460*/
4461
4462bool QImageIO::write()
4463{
4464 if ( frmt.isEmpty() )
4465 return FALSE;
4466 QImageHandler *h = get_image_handler( frmt );
4467 if ( !h && !plugin_manager) {
4468 qt_init_image_plugins();
4469 h = get_image_handler( frmt );
4470 }
4471 if ( !h || !h->write_image ) {
4472#if defined(QT_CHECK_RANGE)
4473 qWarning( "QImageIO::write: No such image format handler: %s",
4474 format() );
4475#endif
4476 return FALSE;
4477 }
4478 QFile file;
4479 if ( !iodev && !fname.isEmpty() ) {
4480 file.setName( fname );
4481 bool translate = h->text_mode==QImageHandler::TranslateInOut;
4482 int fmode = translate ? IO_WriteOnly|IO_Translate : IO_WriteOnly;
4483 if ( !file.open(fmode) ) // couldn't create file
4484 return FALSE;
4485 iodev = &file;
4486 }
4487 iostat = 1;
4488 (*h->write_image)( this );
4489 if ( file.isOpen() ) { // image was written using file
4490 file.close();
4491 iodev = 0;
4492 }
4493 return iostat == 0; // image successfully written?
4494}
4495#endif //QT_NO_IMAGEIO
4496
4497#ifndef QT_NO_IMAGEIO_BMP
4498
4499/*****************************************************************************
4500 BMP (DIB) image read/write functions
4501 *****************************************************************************/
4502
4503const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data
4504
4505struct BMP_FILEHDR { // BMP file header
4506 char bfType[2]; // "BM"
4507 Q_INT32 bfSize; // size of file
4508 Q_INT16 bfReserved1;
4509 Q_INT16 bfReserved2;
4510 Q_INT32 bfOffBits; // pointer to the pixmap bits
4511};
4512
4513QDataStream &operator>>( QDataStream &s, BMP_FILEHDR &bf )
4514{ // read file header
4515 s.readRawBytes( bf.bfType, 2 );
4516 s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits;
4517 return s;
4518}
4519
4520QDataStream &operator<<( QDataStream &s, const BMP_FILEHDR &bf )
4521{ // write file header
4522 s.writeRawBytes( bf.bfType, 2 );
4523 s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits;
4524 return s;
4525}
4526
4527
4528const int BMP_OLD = 12; // old Windows/OS2 BMP size
4529const int BMP_WIN = 40; // new Windows BMP size
4530const int BMP_OS2 = 64; // new OS/2 BMP size
4531
4532const int BMP_RGB = 0; // no compression
4533const int BMP_RLE8 = 1; // run-length encoded, 8 bits
4534const int BMP_RLE4 = 2; // run-length encoded, 4 bits
4535const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields
4536
4537struct BMP_INFOHDR { // BMP information header
4538 Q_INT32 biSize; // size of this struct
4539 Q_INT32 biWidth; // pixmap width
4540 Q_INT32 biHeight; // pixmap height
4541 Q_INT16 biPlanes; // should be 1
4542 Q_INT16 biBitCount; // number of bits per pixel
4543 Q_INT32 biCompression; // compression method
4544 Q_INT32 biSizeImage; // size of image
4545 Q_INT32 biXPelsPerMeter; // horizontal resolution
4546 Q_INT32 biYPelsPerMeter; // vertical resolution
4547 Q_INT32 biClrUsed; // number of colors used
4548 Q_INT32 biClrImportant; // number of important colors
4549};
4550
4551
4552QDataStream &operator>>( QDataStream &s, BMP_INFOHDR &bi )
4553{
4554 s >> bi.biSize;
4555 if ( bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 ) {
4556 s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
4557 s >> bi.biCompression >> bi.biSizeImage;
4558 s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
4559 s >> bi.biClrUsed >> bi.biClrImportant;
4560 }
4561 else { // probably old Windows format
4562 Q_INT16 w, h;
4563 s >> w >> h >> bi.biPlanes >> bi.biBitCount;
4564 bi.biWidth = w;
4565 bi.biHeight = h;
4566 bi.biCompression = BMP_RGB; // no compression
4567 bi.biSizeImage = 0;
4568 bi.biXPelsPerMeter = bi.biYPelsPerMeter = 0;
4569 bi.biClrUsed = bi.biClrImportant = 0;
4570 }
4571 return s;
4572}
4573
4574QDataStream &operator<<( QDataStream &s, const BMP_INFOHDR &bi )
4575{
4576 s << bi.biSize;
4577 s << bi.biWidth << bi.biHeight;
4578 s << bi.biPlanes;
4579 s << bi.biBitCount;
4580 s << bi.biCompression;
4581 s << bi.biSizeImage;
4582 s << bi.biXPelsPerMeter << bi.biYPelsPerMeter;
4583 s << bi.biClrUsed << bi.biClrImportant;
4584 return s;
4585}
4586
4587static
4588int calc_shift(int mask)
4589{
4590 int result = 0;
4591 while (!(mask & 1)) {
4592 result++;
4593 mask >>= 1;
4594 }
4595 return result;
4596}
4597
4598static
4599bool read_dib( QDataStream& s, int offset, int startpos, QImage& image )
4600{
4601 BMP_INFOHDR bi;
4602 QIODevice* d = s.device();
4603
4604 s >> bi; // read BMP info header
4605 if ( d->atEnd() ) // end of stream/file
4606 return FALSE;
4607#if 0
4608 qDebug( "offset...........%d", offset );
4609 qDebug( "startpos.........%d", startpos );
4610 qDebug( "biSize...........%d", bi.biSize );
4611 qDebug( "biWidth..........%d", bi.biWidth );
4612 qDebug( "biHeight.........%d", bi.biHeight );
4613 qDebug( "biPlanes.........%d", bi.biPlanes );
4614 qDebug( "biBitCount.......%d", bi.biBitCount );
4615 qDebug( "biCompression....%d", bi.biCompression );
4616 qDebug( "biSizeImage......%d", bi.biSizeImage );
4617 qDebug( "biXPelsPerMeter..%d", bi.biXPelsPerMeter );
4618 qDebug( "biYPelsPerMeter..%d", bi.biYPelsPerMeter );
4619 qDebug( "biClrUsed........%d", bi.biClrUsed );
4620 qDebug( "biClrImportant...%d", bi.biClrImportant );
4621#endif
4622 int w = bi.biWidth, h = bi.biHeight, nbits = bi.biBitCount;
4623 int t = bi.biSize, comp = bi.biCompression;
4624 int red_mask, green_mask, blue_mask;
4625 int red_shift = 0;
4626 int green_shift = 0;
4627 int blue_shift = 0;
4628 int red_scale = 0;
4629 int green_scale = 0;
4630 int blue_scale = 0;
4631
4632 if ( !(nbits == 1 || nbits == 4 || nbits == 8 || nbits == 16 || nbits == 24 || nbits == 32) ||
4633 bi.biPlanes != 1 || comp > BMP_BITFIELDS )
4634 return FALSE; // weird BMP image
4635 if ( !(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) ||
4636 (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)) )
4637 return FALSE; // weird compression type
4638
4639 int ncols;
4640 int depth;
4641 switch ( nbits ) {
4642 case 32:
4643 case 24:
4644 case 16:
4645 depth = 32;
4646 break;
4647 case 8:
4648 case 4:
4649 depth = 8;
4650 break;
4651 default:
4652 depth = 1;
4653 }
4654 if ( depth == 32 ) // there's no colormap
4655 ncols = 0;
4656 else // # colors used
4657 ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
4658
4659 image.create( w, h, depth, ncols, nbits == 1 ?
4660 QImage::BigEndian : QImage::IgnoreEndian );
4661 if ( image.isNull() ) // could not create image
4662 return FALSE;
4663
4664 image.setDotsPerMeterX( bi.biXPelsPerMeter );
4665 image.setDotsPerMeterY( bi.biYPelsPerMeter );
4666
4667 d->at( startpos + BMP_FILEHDR_SIZE + bi.biSize ); // goto start of colormap
4668
4669 if ( ncols > 0 ) { // read color table
4670 uchar rgb[4];
4671 int rgb_len = t == BMP_OLD ? 3 : 4;
4672 for ( int i=0; i<ncols; i++ ) {
4673 if ( d->readBlock( (char *)rgb, rgb_len ) != rgb_len )
4674 return FALSE;
4675 image.setColor( i, qRgb(rgb[2],rgb[1],rgb[0]) );
4676 if ( d->atEnd() ) // truncated file
4677 return FALSE;
4678 }
4679 } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
4680 if ( (Q_ULONG)d->readBlock( (char *)&red_mask, sizeof(red_mask) ) != sizeof(red_mask) )
4681 return FALSE;
4682 if ( (Q_ULONG)d->readBlock( (char *)&green_mask, sizeof(green_mask) ) != sizeof(green_mask) )
4683 return FALSE;
4684 if ( (Q_ULONG)d->readBlock( (char *)&blue_mask, sizeof(blue_mask) ) != sizeof(blue_mask) )
4685 return FALSE;
4686 red_shift = calc_shift(red_mask);
4687 red_scale = 256 / ((red_mask >> red_shift) + 1);
4688 green_shift = calc_shift(green_mask);
4689 green_scale = 256 / ((green_mask >> green_shift) + 1);
4690 blue_shift = calc_shift(blue_mask);
4691 blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
4692 } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
4693 blue_mask = 0x000000ff;
4694 green_mask = 0x0000ff00;
4695 red_mask = 0x00ff0000;
4696 blue_shift = 0;
4697 green_shift = 8;
4698 red_shift = 16;
4699 blue_scale = green_scale = red_scale = 1;
4700 } else if (comp == BMP_RGB && nbits == 16) // don't support RGB values for 15/16 bpp
4701 return FALSE;
4702
4703 // offset can be bogus, be careful
4704 if (offset>=0 && startpos + offset > (Q_LONG)d->at() )
4705 d->at( startpos + offset ); // start of image data
4706
4707 int bpl = image.bytesPerLine();
4708#ifdef Q_WS_QWS
4709 //
4710 // Guess the number of bytes-per-line if we don't know how much
4711 // image data is in the file (bogus image ?).
4712 //
4713 int bmpbpl = bi.biSizeImage > 0 ?
4714 bi.biSizeImage / bi.biHeight :
4715 (d->size() - offset) / bi.biHeight;
4716 int pad = bmpbpl-bpl;
4717#endif
4718 uchar **line = image.jumpTable();
4719
4720 if ( nbits == 1 ) { // 1 bit BMP image
4721 while ( --h >= 0 ) {
4722 if ( d->readBlock((char*)line[h],bpl) != bpl )
4723 break;
4724#ifdef Q_WS_QWS
4725 if ( pad > 0 )
4726 d->at(d->at()+pad);
4727#endif
4728 }
4729 if ( ncols == 2 && qGray(image.color(0)) < qGray(image.color(1)) )
4730 swapPixel01( &image ); // pixel 0 is white!
4731 }
4732
4733 else if ( nbits == 4 ) { // 4 bit BMP image
4734 int buflen = ((w+7)/8)*4;
4735 uchar *buf = new uchar[buflen];
4736 Q_CHECK_PTR( buf );
4737 if ( comp == BMP_RLE4 ) { // run length compression
4738 int x=0, y=0, b, c, i;
4739 register uchar *p = line[h-1];
4740 uchar *endp = line[h-1]+w;
4741 while ( y < h ) {
4742 if ( (b=d->getch()) == EOF )
4743 break;
4744 if ( b == 0 ) { // escape code
4745 switch ( (b=d->getch()) ) {
4746 case 0: // end of line
4747 x = 0;
4748 y++;
4749 p = line[h-y-1];
4750 break;
4751 case 1: // end of image
4752 case EOF: // end of file
4753 y = h; // exit loop
4754 break;
4755 case 2: // delta (jump)
4756 x += d->getch();
4757 y += d->getch();
4758
4759 // Protection
4760 if ( (uint)x >= (uint)w )
4761 x = w-1;
4762 if ( (uint)y >= (uint)h )
4763 y = h-1;
4764
4765 p = line[h-y-1] + x;
4766 break;
4767 default: // absolute mode
4768 // Protection
4769 if ( p + b > endp )
4770 b = endp-p;
4771
4772 i = (c = b)/2;
4773 while ( i-- ) {
4774 b = d->getch();
4775 *p++ = b >> 4;
4776 *p++ = b & 0x0f;
4777 }
4778 if ( c & 1 )
4779 *p++ = d->getch() >> 4;
4780 if ( (((c & 3) + 1) & 2) == 2 )
4781 d->getch(); // align on word boundary
4782 x += c;
4783 }
4784 } else { // encoded mode
4785 // Protection
4786 if ( p + b > endp )
4787 b = endp-p;
4788
4789 i = (c = b)/2;
4790 b = d->getch(); // 2 pixels to be repeated
4791 while ( i-- ) {
4792 *p++ = b >> 4;
4793 *p++ = b & 0x0f;
4794 }
4795 if ( c & 1 )
4796 *p++ = b >> 4;
4797 x += c;
4798 }
4799 }
4800 } else if ( comp == BMP_RGB ) { // no compression
4801 while ( --h >= 0 ) {
4802 if ( d->readBlock((char*)buf,buflen) != buflen )
4803 break;
4804 register uchar *p = line[h];
4805 uchar *b = buf;
4806 for ( int i=0; i<w/2; i++ ) { // convert nibbles to bytes
4807 *p++ = *b >> 4;
4808 *p++ = *b++ & 0x0f;
4809 }
4810 if ( w & 1 ) // the last nibble
4811 *p = *b >> 4;
4812 }
4813 }
4814 delete [] buf;
4815 }
4816
4817 else if ( nbits == 8 ) { // 8 bit BMP image
4818 if ( comp == BMP_RLE8 ) { // run length compression
4819 int x=0, y=0, b;
4820 register uchar *p = line[h-1];
4821 while ( y < h ) {
4822 if ( (b=d->getch()) == EOF )
4823 break;
4824 if ( b == 0 ) { // escape code
4825 switch ( (b=d->getch()) ) {
4826 case 0: // end of line
4827 x = 0;
4828 y++;
4829 p = line[h-y-1];
4830 break;
4831 case 1: // end of image
4832 case EOF: // end of file
4833 y = h; // exit loop
4834 break;
4835 case 2: // delta (jump)
4836 x += d->getch();
4837 y += d->getch();
4838 p = line[h-y-1] + x;
4839 break;
4840 default: // absolute mode
4841 if ( d->readBlock( (char *)p, b ) != b )
4842 return FALSE;
4843 if ( (b & 1) == 1 )
4844 d->getch(); // align on word boundary
4845 x += b;
4846 p += b;
4847 }
4848 } else { // encoded mode
4849 memset( p, d->getch(), b ); // repeat pixel
4850 x += b;
4851 p += b;
4852 }
4853 }
4854 } else if ( comp == BMP_RGB ) { // uncompressed
4855 while ( --h >= 0 ) {
4856 if ( d->readBlock((char *)line[h],bpl) != bpl )
4857 break;
4858#ifdef Q_WS_QWS
4859 if ( pad > 0 )
4860 d->at(d->at()+pad);
4861#endif
4862 }
4863 }
4864 }
4865
4866 else if ( nbits == 16 || nbits == 24 || nbits == 32 ) { // 16,24,32 bit BMP image
4867 register QRgb *p;
4868 QRgb *end;
4869 uchar *buf24 = new uchar[bpl];
4870 int bpl24 = ((w*nbits+31)/32)*4;
4871 uchar *b;
4872 int c;
4873
4874 while ( --h >= 0 ) {
4875 p = (QRgb *)line[h];
4876 end = p + w;
4877 if ( d->readBlock( (char *)buf24,bpl24) != bpl24 )
4878 break;
4879 b = buf24;
4880 while ( p < end ) {
4881 c = *(uchar*)b | (*(uchar*)(b+1)<<8);
4882 if (nbits != 16)
4883 c |= *(uchar*)(b+2)<<16;
4884 *p++ = qRgb(((c & red_mask) >> red_shift) * red_scale,
4885 ((c & green_mask) >> green_shift) * green_scale,
4886 ((c & blue_mask) >> blue_shift) * blue_scale);
4887 b += nbits/8;
4888 }
4889 }
4890 delete[] buf24;
4891 }
4892
4893 return TRUE;
4894}
4895
4896bool qt_read_dib( QDataStream& s, QImage& image )
4897{
4898 return read_dib(s,-1,-BMP_FILEHDR_SIZE,image);
4899}
4900
4901
4902static void read_bmp_image( QImageIO *iio )
4903{
4904 QIODevice *d = iio->ioDevice();
4905 QDataStream s( d );
4906 BMP_FILEHDR bf;
4907 int startpos = d->at();
4908
4909 s.setByteOrder( QDataStream::LittleEndian );// Intel byte order
4910 s >> bf; // read BMP file header
4911
4912 if ( qstrncmp(bf.bfType,"BM",2) != 0 ) // not a BMP image
4913 return;
4914
4915 QImage image;
4916 if (read_dib( s, bf.bfOffBits, startpos, image )) {
4917 iio->setImage( image );
4918 iio->setStatus( 0 ); // image ok
4919 }
4920}
4921
4922bool qt_write_dib( QDataStream& s, QImage image )
4923{
4924 int nbits;
4925 int bpl_bmp;
4926 int bpl = image.bytesPerLine();
4927
4928 QIODevice* d = s.device();
4929
4930 if ( image.depth() == 8 && image.numColors() <= 16 ) {
4931 bpl_bmp = (((bpl+1)/2+3)/4)*4;
4932 nbits = 4;
4933 } else if ( image.depth() == 32 ) {
4934 bpl_bmp = ((image.width()*24+31)/32)*4;
4935 nbits = 24;
4936#ifdef Q_WS_QWS
4937 } else if ( image.depth() == 1 || image.depth() == 8 ) {
4938 // Qt/E doesn't word align.
4939 bpl_bmp = ((image.width()*image.depth()+31)/32)*4;
4940 nbits = image.depth();
4941#endif
4942 } else {
4943 bpl_bmp = bpl;
4944 nbits = image.depth();
4945 }
4946
4947 BMP_INFOHDR bi;
4948 bi.biSize = BMP_WIN; // build info header
4949 bi.biWidth = image.width();
4950 bi.biHeight = image.height();
4951 bi.biPlanes = 1;
4952 bi.biBitCount = nbits;
4953 bi.biCompression = BMP_RGB;
4954 bi.biSizeImage = bpl_bmp*image.height();
4955 bi.biXPelsPerMeter = image.dotsPerMeterX() ? image.dotsPerMeterX()
4956 : 2834; // 72 dpi default
4957 bi.biYPelsPerMeter = image.dotsPerMeterY() ? image.dotsPerMeterY() : 2834;
4958 bi.biClrUsed = image.numColors();
4959 bi.biClrImportant = image.numColors();
4960 s << bi; // write info header
4961
4962 if ( image.depth() != 32 ) { // write color table
4963 uchar *color_table = new uchar[4*image.numColors()];
4964 uchar *rgb = color_table;
4965 QRgb *c = image.colorTable();
4966 for ( int i=0; i<image.numColors(); i++ ) {
4967 *rgb++ = qBlue ( c[i] );
4968 *rgb++ = qGreen( c[i] );
4969 *rgb++ = qRed ( c[i] );
4970 *rgb++ = 0;
4971 }
4972 d->writeBlock( (char *)color_table, 4*image.numColors() );
4973 delete [] color_table;
4974 }
4975
4976 if ( image.depth() == 1 && image.bitOrder() != QImage::BigEndian )
4977 image = image.convertBitOrder( QImage::BigEndian );
4978
4979 int y;
4980
4981 if ( nbits == 1 || nbits == 8 ) { // direct output
4982#ifdef Q_WS_QWS
4983 // Qt/E doesn't word align.
4984 int pad = bpl_bmp - bpl;
4985 char padding[4];
4986#endif
4987 for ( y=image.height()-1; y>=0; y-- ) {
4988 d->writeBlock( (char*)image.scanLine(y), bpl );
4989#ifdef Q_WS_QWS
4990 d->writeBlock( padding, pad );
4991#endif
4992 }
4993 return TRUE;
4994 }
4995
4996 uchar *buf = new uchar[bpl_bmp];
4997 uchar *b, *end;
4998 register uchar *p;
4999
5000 memset( buf, 0, bpl_bmp );
5001 for ( y=image.height()-1; y>=0; y-- ) { // write the image bits
5002 if ( nbits == 4 ) { // convert 8 -> 4 bits
5003 p = image.scanLine(y);
5004 b = buf;
5005 end = b + image.width()/2;
5006 while ( b < end ) {
5007 *b++ = (*p << 4) | (*(p+1) & 0x0f);
5008 p += 2;
5009 }
5010 if ( image.width() & 1 )
5011 *b = *p << 4;
5012 } else { // 32 bits
5013 QRgb *p = (QRgb *)image.scanLine( y );
5014 QRgb *end = p + image.width();
5015 b = buf;
5016 while ( p < end ) {
5017 *b++ = qBlue(*p);
5018 *b++ = qGreen(*p);
5019 *b++ = qRed(*p);
5020 p++;
5021 }
5022 }
5023 if ( bpl_bmp != d->writeBlock( (char*)buf, bpl_bmp ) ) {
5024 delete[] buf;
5025 return FALSE;
5026 }
5027 }
5028 delete[] buf;
5029 return TRUE;
5030}
5031
5032
5033static void write_bmp_image( QImageIO *iio )
5034{
5035 QIODevice *d = iio->ioDevice();
5036 QImage image = iio->image();
5037 QDataStream s( d );
5038 BMP_FILEHDR bf;
5039 int bpl_bmp;
5040 int bpl = image.bytesPerLine();
5041
5042 // Code partially repeated in qt_write_dib
5043 if ( image.depth() == 8 && image.numColors() <= 16 ) {
5044 bpl_bmp = (((bpl+1)/2+3)/4)*4;
5045 } else if ( image.depth() == 32 ) {
5046 bpl_bmp = ((image.width()*24+31)/32)*4;
5047 } else {
5048 bpl_bmp = bpl;
5049 }
5050
5051 iio->setStatus( 0 );
5052 s.setByteOrder( QDataStream::LittleEndian );// Intel byte order
5053 strncpy( bf.bfType, "BM", 2 ); // build file header
5054 bf.bfReserved1 = bf.bfReserved2 = 0; // reserved, should be zero
5055 bf.bfOffBits = BMP_FILEHDR_SIZE + BMP_WIN + image.numColors()*4;
5056 bf.bfSize = bf.bfOffBits + bpl_bmp*image.height();
5057 s << bf; // write file header
5058
5059 if ( !qt_write_dib( s, image ) )
5060 iio->setStatus( 1 );
5061
5062}
5063
5064#endif // QT_NO_IMAGEIO_BMP
5065
5066#ifndef QT_NO_IMAGEIO_PPM
5067
5068/*****************************************************************************
5069 PBM/PGM/PPM (ASCII and RAW) image read/write functions
5070 *****************************************************************************/
5071
5072static int read_pbm_int( QIODevice *d )
5073{
5074 int c;
5075 int val = -1;
5076 bool digit;
5077 const int buflen = 100;
5078 char buf[buflen];
5079 for ( ;; ) {
5080 if ( (c=d->getch()) == EOF ) // end of file
5081 break;
5082 digit = isdigit( (uchar) c );
5083 if ( val != -1 ) {
5084 if ( digit ) {
5085 val = 10*val + c - '0';
5086 continue;
5087 } else {
5088 if ( c == '#' ) // comment
5089 d->readLine( buf, buflen );
5090 break;
5091 }
5092 }
5093 if ( digit ) // first digit
5094 val = c - '0';
5095 else if ( isspace((uchar) c) )
5096 continue;
5097 else if ( c == '#' )
5098 d->readLine( buf, buflen );
5099 else
5100 break;
5101 }
5102 return val;
5103}
5104
5105static void read_pbm_image( QImageIO *iio ) // read PBM image data
5106{
5107 const int buflen = 300;
5108 char buf[buflen];
5109 QIODevice *d = iio->ioDevice();
5110 int w, h, nbits, mcc, y;
5111 int pbm_bpl;
5112 char type;
5113 bool raw;
5114 QImage image;
5115
5116 if ( d->readBlock( buf, 3 ) != 3 ) // read P[1-6]<white-space>
5117 return;
5118 if ( !(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])) )
5119 return;
5120 switch ( (type=buf[1]) ) {
5121 case '1': // ascii PBM
5122 case '4': // raw PBM
5123 nbits = 1;
5124 break;
5125 case '2': // ascii PGM
5126 case '5': // raw PGM
5127 nbits = 8;
5128 break;
5129 case '3': // ascii PPM
5130 case '6': // raw PPM
5131 nbits = 32;
5132 break;
5133 default:
5134 return;
5135 }
5136 raw = type >= '4';
5137 w = read_pbm_int( d ); // get image width
5138 h = read_pbm_int( d ); // get image height
5139 if ( nbits == 1 )
5140 mcc = 1; // ignore max color component
5141 else
5142 mcc = read_pbm_int( d ); // get max color component
5143 if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 )
5144 return; // weird P.M image
5145
5146 int maxc = mcc;
5147 if ( maxc > 255 )
5148 maxc = 255;
5149 image.create( w, h, nbits, 0,
5150 nbits == 1 ? QImage::BigEndian : QImage::IgnoreEndian );
5151 if ( image.isNull() )
5152 return;
5153
5154 pbm_bpl = (nbits*w+7)/8; // bytes per scanline in PBM
5155
5156 if ( raw ) { // read raw data
5157 if ( nbits == 32 ) { // type 6
5158 pbm_bpl = 3*w;
5159 uchar *buf24 = new uchar[pbm_bpl], *b;
5160 QRgb *p;
5161 QRgb *end;
5162 for ( y=0; y<h; y++ ) {
5163 if ( d->readBlock( (char *)buf24, pbm_bpl ) != pbm_bpl ) {
5164 delete[] buf24;
5165 return;
5166 }
5167 p = (QRgb *)image.scanLine( y );
5168 end = p + w;
5169 b = buf24;
5170 while ( p < end ) {
5171 *p++ = qRgb(b[0],b[1],b[2]);
5172 b += 3;
5173 }
5174 }
5175 delete[] buf24;
5176 } else { // type 4,5
5177 for ( y=0; y<h; y++ ) {
5178 if ( d->readBlock( (char *)image.scanLine(y), pbm_bpl )
5179 != pbm_bpl )
5180 return;
5181 }
5182 }
5183 } else { // read ascii data
5184 register uchar *p;
5185 int n;
5186 for ( y=0; y<h; y++ ) {
5187 p = image.scanLine( y );
5188 n = pbm_bpl;
5189 if ( nbits == 1 ) {
5190 int b;
5191 while ( n-- ) {
5192 b = 0;
5193 for ( int i=0; i<8; i++ )
5194 b = (b << 1) | (read_pbm_int(d) & 1);
5195 *p++ = b;
5196 }
5197 } else if ( nbits == 8 ) {
5198 if ( mcc == maxc ) {
5199 while ( n-- ) {
5200 *p++ = read_pbm_int( d );
5201 }
5202 } else {
5203 while ( n-- ) {
5204 *p++ = read_pbm_int( d ) * maxc / mcc;
5205 }
5206 }
5207 } else { // 32 bits
5208 n /= 4;
5209 int r, g, b;
5210 if ( mcc == maxc ) {
5211 while ( n-- ) {
5212 r = read_pbm_int( d );
5213 g = read_pbm_int( d );
5214 b = read_pbm_int( d );
5215 *((QRgb*)p) = qRgb( r, g, b );
5216 p += 4;
5217 }
5218 } else {
5219 while ( n-- ) {
5220 r = read_pbm_int( d ) * maxc / mcc;
5221 g = read_pbm_int( d ) * maxc / mcc;
5222 b = read_pbm_int( d ) * maxc / mcc;
5223 *((QRgb*)p) = qRgb( r, g, b );
5224 p += 4;
5225 }
5226 }
5227 }
5228 }
5229 }
5230
5231 if ( nbits == 1 ) { // bitmap
5232 image.setNumColors( 2 );
5233 image.setColor( 0, qRgb(255,255,255) ); // white
5234 image.setColor( 1, qRgb(0,0,0) ); // black
5235 } else if ( nbits == 8 ) { // graymap
5236 image.setNumColors( maxc+1 );
5237 for ( int i=0; i<=maxc; i++ )
5238 image.setColor( i, qRgb(i*255/maxc,i*255/maxc,i*255/maxc) );
5239 }
5240
5241 iio->setImage( image );
5242 iio->setStatus( 0 ); // image ok
5243}
5244
5245
5246static void write_pbm_image( QImageIO *iio )
5247{
5248 QIODevice* out = iio->ioDevice();
5249 QCString str;
5250
5251 QImage image = iio->image();
5252 QCString format = iio->format();
5253 format = format.left(3); // ignore RAW part
5254 bool gray = format == "PGM";
5255
5256 if ( format == "PBM" ) {
5257 image = image.convertDepth(1);
5258 } else if ( image.depth() == 1 ) {
5259 image = image.convertDepth(8);
5260 }
5261
5262 if ( image.depth() == 1 && image.numColors() == 2 ) {
5263 if ( qGray(image.color(0)) < qGray(image.color(1)) ) {
5264 // 0=dark/black, 1=light/white - invert
5265 image.detach();
5266 for ( int y=0; y<image.height(); y++ ) {
5267 uchar *p = image.scanLine(y);
5268 uchar *end = p + image.bytesPerLine();
5269 while ( p < end )
5270 *p++ ^= 0xff;
5271 }
5272 }
5273 }
5274
5275 uint w = image.width();
5276 uint h = image.height();
5277
5278 str.sprintf("P\n%d %d\n", w, h);
5279
5280 switch (image.depth()) {
5281 case 1: {
5282 str.insert(1, '4');
5283 if ((uint)out->writeBlock(str, str.length()) != str.length()) {
5284 iio->setStatus(1);
5285 return;
5286 }
5287 w = (w+7)/8;
5288 for (uint y=0; y<h; y++) {
5289 uchar* line = image.scanLine(y);
5290 if ( w != (uint)out->writeBlock((char*)line, w) ) {
5291 iio->setStatus(1);
5292 return;
5293 }
5294 }
5295 }
5296 break;
5297
5298 case 8: {
5299 str.insert(1, gray ? '5' : '6');
5300 str.append("255\n");
5301 if ((uint)out->writeBlock(str, str.length()) != str.length()) {
5302 iio->setStatus(1);
5303 return;
5304 }
5305 QRgb *color = image.colorTable();
5306 uint bpl = w*(gray ? 1 : 3);
5307 uchar *buf = new uchar[bpl];
5308 for (uint y=0; y<h; y++) {
5309 uchar *b = image.scanLine(y);
5310 uchar *p = buf;
5311 uchar *end = buf+bpl;
5312 if ( gray ) {
5313 while ( p < end ) {
5314 uchar g = (uchar)qGray(color[*b++]);
5315 *p++ = g;
5316 }
5317 } else {
5318 while ( p < end ) {
5319 QRgb rgb = color[*b++];
5320 *p++ = qRed(rgb);
5321 *p++ = qGreen(rgb);
5322 *p++ = qBlue(rgb);
5323 }
5324 }
5325 if ( bpl != (uint)out->writeBlock((char*)buf, bpl) ) {
5326 iio->setStatus(1);
5327 return;
5328 }
5329 }
5330 delete [] buf;
5331 }
5332 break;
5333
5334 case 32: {
5335 str.insert(1, gray ? '5' : '6');
5336 str.append("255\n");
5337 if ((uint)out->writeBlock(str, str.length()) != str.length()) {
5338 iio->setStatus(1);
5339 return;
5340 }
5341 uint bpl = w*(gray ? 1 : 3);
5342 uchar *buf = new uchar[bpl];
5343 for (uint y=0; y<h; y++) {
5344 QRgb *b = (QRgb*)image.scanLine(y);
5345 uchar *p = buf;
5346 uchar *end = buf+bpl;
5347 if ( gray ) {
5348 while ( p < end ) {
5349 uchar g = (uchar)qGray(*b++);
5350 *p++ = g;
5351 }
5352 } else {
5353 while ( p < end ) {
5354 QRgb rgb = *b++;
5355 *p++ = qRed(rgb);
5356 *p++ = qGreen(rgb);
5357 *p++ = qBlue(rgb);
5358 }
5359 }
5360 if ( bpl != (uint)out->writeBlock((char*)buf, bpl) ) {
5361 iio->setStatus(1);
5362 return;
5363 }
5364 }
5365 delete [] buf;
5366 }
5367 }
5368
5369 iio->setStatus(0);
5370}
5371
5372#endif // QT_NO_IMAGEIO_PPM
5373
5374#ifndef QT_NO_ASYNC_IMAGE_IO
5375
5376class QImageIOFrameGrabber : public QImageConsumer {
5377public:
5378 QImageIOFrameGrabber() : framecount(0) { }
5379
5380 QImageDecoder *decoder;
5381 int framecount;
5382
5383 void changed(const QRect&) { }
5384 void end() { }
5385 void frameDone(const QPoint&, const QRect&) { framecount++; }
5386 void frameDone() { framecount++; }
5387 void setLooping(int) { }
5388 void setFramePeriod(int) { }
5389 void setSize(int, int) { }
5390};
5391
5392static void read_async_image( QImageIO *iio )
5393{
5394 const int buf_len = 2048;
5395 uchar buffer[buf_len];
5396 QIODevice *d = iio->ioDevice();
5397 QImageIOFrameGrabber* consumer = new QImageIOFrameGrabber();
5398 QImageDecoder decoder(consumer);
5399 consumer->decoder = &decoder;
5400 int startAt = d->at();
5401 int totLen = 0;
5402
5403 for (;;) {
5404 int length = d->readBlock((char*)buffer, buf_len);
5405 if ( length <= 0 ) {
5406 iio->setStatus(length);
5407 break;
5408 }
5409 uchar* b = buffer;
5410 int r = -1;
5411 while (length > 0 && consumer->framecount==0) {
5412 r = decoder.decode(b, length);
5413 if ( r <= 0 ) break;
5414 b += r;
5415 totLen += r;
5416 length -= r;
5417 }
5418 if ( consumer->framecount ) {
5419 // Stopped after first frame
5420 if ( d->isDirectAccess() )
5421 d->at( startAt + totLen );
5422 else {
5423 // ### We have (probably) read too much from the stream into
5424 // the buffer, and there is no way to put it back!
5425 }
5426 iio->setImage(decoder.image());
5427 iio->setStatus(0);
5428 break;
5429 }
5430 if ( r <= 0 ) {
5431 iio->setStatus(r);
5432 break;
5433 }
5434 }
5435
5436 delete consumer;
5437}
5438
5439#endif // QT_NO_ASYNC_IMAGE_IO
5440
5441#ifndef QT_NO_IMAGEIO_XBM
5442
5443/*****************************************************************************
5444 X bitmap image read/write functions
5445 *****************************************************************************/
5446
5447static inline int hex2byte( register char *p )
5448{
5449 return ( (isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4 ) |
5450 ( isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10 );
5451}
5452
5453static void read_xbm_image( QImageIO *iio )
5454{
5455 const int buflen = 300;
5456 char buf[buflen];
5457 QRegExp r1, r2;
5458 QIODevice *d = iio->ioDevice();
5459 int w=-1, h=-1;
5460 QImage image;
5461
5462 r1 = QString::fromLatin1("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+");
5463 r2 = QString::fromLatin1("[0-9]+");
5464 d->readLine( buf, buflen ); // "#define .._width <num>"
5465 QString sbuf;
5466 sbuf = QString::fromLatin1(buf);
5467
5468 if ( r1.search(sbuf) == 0 &&
5469 r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() )
5470 w = atoi( &buf[r1.matchedLength()] );
5471
5472 d->readLine( buf, buflen ); // "#define .._height <num>"
5473 sbuf = QString::fromLatin1(buf);
5474
5475 if ( r1.search(sbuf) == 0 &&
5476 r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() )
5477 h = atoi( &buf[r1.matchedLength()] );
5478
5479 if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 )
5480 return; // format error
5481
5482 for ( ;; ) { // scan for data
5483 if ( d->readLine(buf, buflen) <= 0 ) // end of file
5484 return;
5485 if ( strstr(buf,"0x") != 0 ) // does line contain data?
5486 break;
5487 }
5488
5489 image.create( w, h, 1, 2, QImage::LittleEndian );
5490 if ( image.isNull() )
5491 return;
5492
5493 image.setColor( 0, qRgb(255,255,255) ); // white
5494 image.setColor( 1, qRgb(0,0,0) ); // black
5495
5496 int x = 0, y = 0;
5497 uchar *b = image.scanLine(0);
5498 char *p = strstr( buf, "0x" );
5499 w = (w+7)/8; // byte width
5500
5501 while ( y < h ) { // for all encoded bytes...
5502 if ( p ) { // p = "0x.."
5503 *b++ = hex2byte(p+2);
5504 p += 2;
5505 if ( ++x == w && ++y < h ) {
5506 b = image.scanLine(y);
5507 x = 0;
5508 }
5509 p = strstr( p, "0x" );
5510 } else { // read another line
5511 if ( d->readLine(buf,buflen) <= 0 ) // EOF ==> truncated image
5512 break;
5513 p = strstr( buf, "0x" );
5514 }
5515 }
5516
5517 iio->setImage( image );
5518 iio->setStatus( 0 ); // image ok
5519}
5520
5521
5522static void write_xbm_image( QImageIO *iio )
5523{
5524 QIODevice *d = iio->ioDevice();
5525 QImage image = iio->image();
5526 int w = image.width();
5527 int h = image.height();
5528 int i;
5529 QString s = fbname(iio->fileName()); // get file base name
5530 char buf[100];
5531
5532 sprintf( buf, "#define %s_width %d\n", s.ascii(), w );
5533 d->writeBlock( buf, qstrlen(buf) );
5534 sprintf( buf, "#define %s_height %d\n", s.ascii(), h );
5535 d->writeBlock( buf, qstrlen(buf) );
5536 sprintf( buf, "static char %s_bits[] = {\n ", s.ascii() );
5537 d->writeBlock( buf, qstrlen(buf) );
5538
5539 iio->setStatus( 0 );
5540
5541 if ( image.depth() != 1 )
5542 image = image.convertDepth( 1 ); // dither
5543 if ( image.bitOrder() != QImage::LittleEndian )
5544 image = image.convertBitOrder( QImage::LittleEndian );
5545
5546 bool invert = qGray(image.color(0)) < qGray(image.color(1));
5547 char hexrep[16];
5548 for ( i=0; i<10; i++ )
5549 hexrep[i] = '0' + i;
5550 for ( i=10; i<16; i++ )
5551 hexrep[i] = 'a' -10 + i;
5552 if ( invert ) {
5553 char t;
5554 for ( i=0; i<8; i++ ) {
5555 t = hexrep[15-i];
5556 hexrep[15-i] = hexrep[i];
5557 hexrep[i] = t;
5558 }
5559 }
5560 int bcnt = 0;
5561 register char *p = buf;
5562 uchar *b = image.scanLine(0);
5563 int x=0, y=0;
5564 int nbytes = image.numBytes();
5565 w = (w+7)/8;
5566 while ( nbytes-- ) { // write all bytes
5567 *p++ = '0'; *p++ = 'x';
5568 *p++ = hexrep[*b >> 4];
5569 *p++ = hexrep[*b++ & 0xf];
5570 if ( ++x == w && y < h-1 ) {
5571 b = image.scanLine(++y);
5572 x = 0;
5573 }
5574 if ( nbytes > 0 ) {
5575 *p++ = ',';
5576 if ( ++bcnt > 14 ) {
5577 *p++ = '\n';
5578 *p++ = ' ';
5579 *p = '\0';
5580 if ( (int)qstrlen(buf) != d->writeBlock( buf, qstrlen(buf) ) ) {
5581 iio->setStatus( 1 );
5582 return;
5583 }
5584 p = buf;
5585 bcnt = 0;
5586 }
5587 }
5588 }
5589 strcpy( p, " };\n" );
5590 if ( (int)qstrlen(buf) != d->writeBlock( buf, qstrlen(buf) ) )
5591 iio->setStatus( 1 );
5592}
5593
5594#endif // QT_NO_IMAGEIO_XBM
5595
5596
5597#ifndef QT_NO_IMAGEIO_XPM
5598
5599/*****************************************************************************
5600 XPM image read/write functions
5601 *****************************************************************************/
5602
5603
5604// Skip until ", read until the next ", return the rest in *buf
5605// Returns FALSE on error, TRUE on success
5606
5607static bool read_xpm_string( QCString &buf, QIODevice *d,
5608 const char * const *source, int &index )
5609{
5610 if ( source ) {
5611 buf = source[index++];
5612 return TRUE;
5613 }
5614
5615 if ( buf.size() < 69 ) //# just an approximation
5616 buf.resize( 123 );
5617
5618 buf[0] = '\0';
5619 int c;
5620 int i;
5621 while ( (c=d->getch()) != EOF && c != '"' ) { }
5622 if ( c == EOF ) {
5623 return FALSE;
5624 }
5625 i = 0;
5626 while ( (c=d->getch()) != EOF && c != '"' ) {
5627 if ( i == (int)buf.size() )
5628 buf.resize( i*2+42 );
5629 buf[i++] = c;
5630 }
5631 if ( c == EOF ) {
5632 return FALSE;
5633 }
5634
5635 if ( i == (int)buf.size() ) // always use a 0 terminator
5636 buf.resize( i+1 );
5637 buf[i] = '\0';
5638 return TRUE;
5639}
5640
5641
5642//
5643// INTERNAL
5644//
5645// Reads an .xpm from either the QImageIO or from the QString *.
5646// One of the two HAS to be 0, the other one is used.
5647//
5648
5649static void read_xpm_image_or_array( QImageIO * iio, const char * const * source,
5650 QImage & image)
5651{
5652 QCString buf;
5653 QIODevice *d = 0;
5654 buf.resize( 200 );
5655
5656 int i, cpp, ncols, w, h, index = 0;
5657
5658 if ( iio ) {
5659 iio->setStatus( 1 );
5660 d = iio ? iio->ioDevice() : 0;
5661 d->readLine( buf.data(), buf.size() ); // "/* XPM */"
5662 QRegExp r( QString::fromLatin1("/\\*.XPM.\\*/") );
5663 if ( buf.find(r) == -1 )
5664 return; // bad magic
5665 } else if ( !source ) {
5666 return;
5667 }
5668
5669 if ( !read_xpm_string( buf, d, source, index ) )
5670 return;
5671
5672 if ( sscanf( buf, "%d %d %d %d", &w, &h, &ncols, &cpp ) < 4 )
5673 return; // < 4 numbers parsed
5674
5675 if ( cpp > 15 )
5676 return;
5677
5678 if ( ncols > 256 ) {
5679 image.create( w, h, 32 );
5680 } else {
5681 image.create( w, h, 8, ncols );
5682 }
5683
5684 QMap<QString, int> colorMap;
5685 int currentColor;
5686
5687 for( currentColor=0; currentColor < ncols; ++currentColor ) {
5688 if ( !read_xpm_string( buf, d, source, index ) ) {
5689#if defined(QT_CHECK_RANGE)
5690 qWarning( "QImage: XPM color specification missing");
5691#endif
5692 return;
5693 }
5694 QString index;
5695 index = buf.left( cpp );
5696 buf = buf.mid( cpp ).simplifyWhiteSpace().lower();
5697 buf.prepend( " " );
5698 i = buf.find( " c " );
5699 if ( i < 0 )
5700 i = buf.find( " g " );
5701 if ( i < 0 )
5702 i = buf.find( " g4 " );
5703 if ( i < 0 )
5704 i = buf.find( " m " );
5705 if ( i < 0 ) {
5706#if defined(QT_CHECK_RANGE)
5707 qWarning( "QImage: XPM color specification is missing: %s", buf.data());
5708#endif
5709 return; // no c/g/g4/m specification at all
5710 }
5711 buf = buf.mid( i+3 );
5712 // Strip any other colorspec
5713 int end = buf.find(' ', 4);
5714 if ( end >= 0 )
5715 buf.truncate(end);
5716 buf = buf.stripWhiteSpace();
5717 if ( buf == "none" ) {
5718 image.setAlphaBuffer( TRUE );
5719 int transparentColor = currentColor;
5720 if ( image.depth() == 8 ) {
5721 image.setColor( transparentColor,
5722 RGB_MASK & qRgb(198,198,198) );
5723 colorMap.insert( index, transparentColor );
5724 } else {
5725 QRgb rgb = RGB_MASK & qRgb(198,198,198);
5726 colorMap.insert( index, rgb );
5727 }
5728 } else {
5729 if ( ((buf.length()-1) % 3) && (buf[0] == '#') ) {
5730 buf.truncate (((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
5731 }
5732 QColor c( buf.data() );
5733 if ( image.depth() == 8 ) {
5734 image.setColor( currentColor, 0xff000000 | c.rgb() );
5735 colorMap.insert( index, currentColor );
5736 } else {
5737 QRgb rgb = 0xff000000 | c.rgb();
5738 colorMap.insert( index, rgb );
5739 }
5740 }
5741 }
5742
5743 // Read pixels
5744 for( int y=0; y<h; y++ ) {
5745 if ( !read_xpm_string( buf, d, source, index ) ) {
5746#if defined(QT_CHECK_RANGE)
5747 qWarning( "QImage: XPM pixels missing on image line %d", y);
5748#endif
5749 return;
5750 }
5751 if ( image.depth() == 8 ) {
5752 uchar *p = image.scanLine(y);
5753 uchar *d = (uchar *)buf.data();
5754 uchar *end = d + buf.length();
5755 int x;
5756 if ( cpp == 1 ) {
5757 char b[2];
5758 b[1] = '\0';
5759 for ( x=0; x<w && d<end; x++ ) {
5760 b[0] = *d++;
5761 *p++ = (uchar)colorMap[b];
5762 }
5763 } else {
5764 char b[16];
5765 b[cpp] = '\0';
5766 for ( x=0; x<w && d<end; x++ ) {
5767 strncpy( b, (char *)d, cpp );
5768 *p++ = (uchar)colorMap[b];
5769 d += cpp;
5770 }
5771 }
5772 } else {
5773 QRgb *p = (QRgb*)image.scanLine(y);
5774 uchar *d = (uchar *)buf.data();
5775 uchar *end = d + buf.length();
5776 int x;
5777 char b[16];
5778 b[cpp] = '\0';
5779 for ( x=0; x<w && d<end; x++ ) {
5780 strncpy( b, (char *)d, cpp );
5781 *p++ = (QRgb)colorMap[b];
5782 d += cpp;
5783 }
5784 }
5785 }
5786 if ( iio ) {
5787 iio->setImage( image );
5788 iio->setStatus( 0 ); // image ok
5789 }
5790}
5791
5792
5793static void read_xpm_image( QImageIO * iio )
5794{
5795 QImage i;
5796 (void)read_xpm_image_or_array( iio, 0, i );
5797 return;
5798}
5799
5800
5801static const char* xpm_color_name( int cpp, int index )
5802{
5803 static char returnable[5];
5804 static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD"
5805 "EFGHIJKLMNOPQRSTUVWXYZ0123456789";
5806 // cpp is limited to 4 and index is limited to 64^cpp
5807 if ( cpp > 1 ) {
5808 if ( cpp > 2 ) {
5809 if ( cpp > 3 ) {
5810 returnable[3] = code[index % 64];
5811 index /= 64;
5812 } else
5813 returnable[3] = '\0';
5814 returnable[2] = code[index % 64];
5815 index /= 64;
5816 } else
5817 returnable[2] = '\0';
5818 // the following 4 lines are a joke!
5819 if ( index == 0 )
5820 index = 64*44+21;
5821 else if ( index == 64*44+21 )
5822 index = 0;
5823 returnable[1] = code[index % 64];
5824 index /= 64;
5825 } else
5826 returnable[1] = '\0';
5827 returnable[0] = code[index];
5828
5829 return returnable;
5830}
5831
5832
5833// write XPM image data
5834static void write_xpm_image( QImageIO * iio )
5835{
5836 if ( iio )
5837 iio->setStatus( 1 );
5838 else
5839 return;
5840
5841 // ### 8-bit case could be made faster
5842 QImage image;
5843 if ( iio->image().depth() != 32 )
5844 image = iio->image().convertDepth( 32 );
5845 else
5846 image = iio->image();
5847
5848 QMap<QRgb, int> colorMap;
5849
5850 int w = image.width(), h = image.height(), ncolors = 0;
5851 int x, y;
5852
5853 // build color table
5854 for( y=0; y<h; y++ ) {
5855 QRgb * yp = (QRgb *)image.scanLine( y );
5856 for( x=0; x<w; x++ ) {
5857 QRgb color = *(yp + x);
5858 if ( !colorMap.contains(color) )
5859 colorMap.insert( color, ncolors++ );
5860 }
5861 }
5862
5863 // number of 64-bit characters per pixel needed to encode all colors
5864 int cpp = 1;
5865 for ( int k = 64; ncolors > k; k *= 64 ) {
5866 ++cpp;
5867 // limit to 4 characters per pixel
5868 // 64^4 colors is enough for a 4096x4096 image
5869 if ( cpp > 4)
5870 break;
5871 }
5872
5873 QString line;
5874
5875 // write header
5876 QTextStream s( iio->ioDevice() );
5877 s << "/* XPM */" << endl
5878 << "static char *" << fbname(iio->fileName()) << "[]={" << endl
5879 << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\"";
5880
5881 // write palette
5882 QMap<QRgb, int>::Iterator c = colorMap.begin();
5883 while ( c != colorMap.end() ) {
5884 QRgb color = c.key();
5885 if ( image.hasAlphaBuffer() && color == (color & RGB_MASK) )
5886 line.sprintf( "\"%s c None\"",
5887 xpm_color_name(cpp, *c) );
5888 else
5889 line.sprintf( "\"%s c #%02x%02x%02x\"",
5890 xpm_color_name(cpp, *c),
5891 qRed(color),
5892 qGreen(color),
5893 qBlue(color) );
5894 ++c;
5895 s << "," << endl << line;
5896 }
5897
5898 // write pixels, limit to 4 characters per pixel
5899 line.truncate( cpp*w );
5900 for( y=0; y<h; y++ ) {
5901 QRgb * yp = (QRgb *) image.scanLine( y );
5902 int cc = 0;
5903 for( x=0; x<w; x++ ) {
5904 int color = (int)(*(yp + x));
5905 QCString chars = xpm_color_name( cpp, colorMap[color] );
5906 line[cc++] = chars[0];
5907 if ( cpp > 1 ) {
5908 line[cc++] = chars[1];
5909 if ( cpp > 2 ) {
5910 line[cc++] = chars[2];
5911 if ( cpp > 3 ) {
5912 line[cc++] = chars[3];
5913 }
5914 }
5915 }
5916 }
5917 s << "," << endl << "\"" << line << "\"";
5918 }
5919 s << "};" << endl;
5920
5921 iio->setStatus( 0 );
5922}
5923
5924#endif // QT_NO_IMAGEIO_XPM
5925
5926/*!
5927 Returns an image with depth \a d, using the \a palette_count
5928 colors pointed to by \a palette. If \a d is 1 or 8, the returned
5929 image will have its color table ordered the same as \a palette.
5930
5931 If the image needs to be modified to fit in a lower-resolution
5932 result (e.g. converting from 32-bit to 8-bit), use the \a
5933 conversion_flags to specify how you'd prefer this to happen.
5934
5935 Note: currently no closest-color search is made. If colors are
5936 found that are not in the palette, the palette may not be used at
5937 all. This result should not be considered valid because it may
5938 change in future implementations.
5939
5940 Currently inefficient for non-32-bit images.
5941
5942 \sa Qt::ImageConversionFlags
5943*/
5944#ifndef QT_NO_IMAGE_TRUECOLOR
5945QImage QImage::convertDepthWithPalette( int d, QRgb* palette, int palette_count, int conversion_flags ) const
5946{
5947 if ( depth() == 1 ) {
5948 return convertDepth( 8, conversion_flags )
5949 .convertDepthWithPalette( d, palette, palette_count, conversion_flags );
5950 } else if ( depth() == 8 ) {
5951 // ### this could be easily made more efficient
5952 return convertDepth( 32, conversion_flags )
5953 .convertDepthWithPalette( d, palette, palette_count, conversion_flags );
5954 } else {
5955 QImage result;
5956 convert_32_to_8( this, &result,
5957 (conversion_flags&~Qt::DitherMode_Mask) | Qt::AvoidDither,
5958 palette, palette_count );
5959 return result.convertDepth( d );
5960 }
5961}
5962#endif
5963static
5964bool
5965haveSamePalette(const QImage& a, const QImage& b)
5966{
5967 if (a.depth() != b.depth()) return FALSE;
5968 if (a.numColors() != b.numColors()) return FALSE;
5969 QRgb* ca = a.colorTable();
5970 QRgb* cb = b.colorTable();
5971 for (int i=a.numColors(); i--; ) {
5972 if (*ca++ != *cb++) return FALSE;
5973 }
5974 return TRUE;
5975}
5976
5977/*!
5978 \relates QImage
5979
5980 Copies a block of pixels from \a src to \a dst. The pixels
5981 copied from source (src) are converted according to
5982 \a conversion_flags if it is incompatible with the destination
5983 (\a dst).
5984
5985 \a sx, \a sy is the top-left pixel in \a src, \a dx, \a dy
5986 is the top-left position in \a dst and \a sw, \sh is the
5987 size of the copied block.
5988
5989 The copying is clipped if areas outside \a src or \a dst are
5990 specified.
5991
5992 If \a sw is -1, it is adjusted to src->width(). Similarly, if \a
5993 sh is -1, it is adjusted to src->height().
5994
5995 Currently inefficient for non 32-bit images.
5996*/
5997void bitBlt( QImage* dst, int dx, int dy, const QImage* src,
5998 int sx, int sy, int sw, int sh, int conversion_flags )
5999{
6000 // Parameter correction
6001 if ( sw < 0 ) sw = src->width();
6002 if ( sh < 0 ) sh = src->height();
6003 if ( sx < 0 ) { dx -= sx; sw += sx; sx = 0; }
6004 if ( sy < 0 ) { dy -= sy; sh += sy; sy = 0; }
6005 if ( dx < 0 ) { sx -= dx; sw += dx; dx = 0; }
6006 if ( dy < 0 ) { sy -= dy; sh += dy; dy = 0; }
6007 if ( sx + sw > src->width() ) sw = src->width() - sx;
6008 if ( sy + sh > src->height() ) sh = src->height() - sy;
6009 if ( dx + sw > dst->width() ) sw = dst->width() - dx;
6010 if ( dy + sh > dst->height() ) sh = dst->height() - dy;
6011 if ( sw <= 0 || sh <= 0 ) return; // Nothing left to copy
6012 if ( (dst->data == src->data) && dx==sx && dy==sy ) return; // Same pixels
6013
6014 // "Easy" to copy if both same depth and one of:
6015 // - 32 bit
6016 // - 8 bit, identical palette
6017 // - 1 bit, identical palette and byte-aligned area
6018 //
6019 if ( haveSamePalette(*dst,*src)
6020 && ( dst->depth() != 1 ||
6021 !( (dx&7) || (sx&7) ||
6022 ((sw&7) && (sx+sw < src->width()) ||
6023 (dx+sw < dst->width()) ) ) ) )
6024 {
6025 // easy to copy
6026 } else if ( dst->depth() != 32 ) {
6027#ifndef QT_NO_IMAGE_TRUECOLOR
6028
6029 QImage dstconv = dst->convertDepth( 32 );
6030 bitBlt( &dstconv, dx, dy, src, sx, sy, sw, sh,
6031 (conversion_flags&~Qt::DitherMode_Mask) | Qt::AvoidDither );
6032 *dst = dstconv.convertDepthWithPalette( dst->depth(),
6033 dst->colorTable(), dst->numColors() );
6034#endif
6035 return;
6036 }
6037
6038 // Now assume palette can be ignored
6039
6040 if ( dst->depth() != src->depth() ) {
6041 if ( sw == src->width() && sh == src->height() || dst->depth()==32 ) {
6042 QImage srcconv = src->convertDepth( dst->depth(), conversion_flags );
6043 bitBlt( dst, dx, dy, &srcconv, sx, sy, sw, sh, conversion_flags );
6044 } else {
6045 QImage srcconv = src->copy( sx, sy, sw, sh ); // ie. bitBlt
6046 bitBlt( dst, dx, dy, &srcconv, 0, 0, sw, sh, conversion_flags );
6047 }
6048 return;
6049 }
6050
6051 // Now assume both are the same depth.
6052
6053 // Now assume both are 32-bit or 8-bit with compatible palettes.
6054
6055 // "Easy"
6056
6057 switch ( dst->depth() ) {
6058 case 1:
6059 {
6060 uchar* d = dst->scanLine(dy) + dx/8;
6061 uchar* s = src->scanLine(sy) + sx/8;
6062 const int bw = (sw+7)/8;
6063 if ( bw < 64 ) {
6064 // Trust ourselves
6065 const int dd = dst->bytesPerLine() - bw;
6066 const int ds = src->bytesPerLine() - bw;
6067 while ( sh-- ) {
6068 for ( int t=bw; t--; )
6069 *d++ = *s++;
6070 d += dd;
6071 s += ds;
6072 }
6073 } else {
6074 // Trust libc
6075 const int dd = dst->bytesPerLine();
6076 const int ds = src->bytesPerLine();
6077 while ( sh-- ) {
6078 memcpy( d, s, bw );
6079 d += dd;
6080 s += ds;
6081 }
6082 }
6083 }
6084 break;
6085 case 8:
6086 {
6087 uchar* d = dst->scanLine(dy) + dx;
6088 uchar* s = src->scanLine(sy) + sx;
6089 if ( sw < 64 ) {
6090 // Trust ourselves
6091 const int dd = dst->bytesPerLine() - sw;
6092 const int ds = src->bytesPerLine() - sw;
6093 while ( sh-- ) {
6094 for ( int t=sw; t--; )
6095 *d++ = *s++;
6096 d += dd;
6097 s += ds;
6098 }
6099 } else {
6100 // Trust libc
6101 const int dd = dst->bytesPerLine();
6102 const int ds = src->bytesPerLine();
6103 while ( sh-- ) {
6104 memcpy( d, s, sw );
6105 d += dd;
6106 s += ds;
6107 }
6108 }
6109 }
6110 break;
6111#ifndef QT_NO_IMAGE_TRUECOLOR
6112 case 32:
6113 if ( src->hasAlphaBuffer() ) {
6114 QRgb* d = (QRgb*)dst->scanLine(dy) + dx;
6115 QRgb* s = (QRgb*)src->scanLine(sy) + sx;
6116 const int dd = dst->width() - sw;
6117 const int ds = src->width() - sw;
6118 while ( sh-- ) {
6119 for ( int t=sw; t--; ) {
6120 unsigned char a = qAlpha(*s);
6121 if ( a == 255 )
6122 *d++ = *s++;
6123 else if ( a == 0 )
6124 ++d,++s; // nothing
6125 else {
6126 unsigned char r = ((qRed(*s)-qRed(*d)) * a) / 256 + qRed(*d);
6127 unsigned char g = ((qGreen(*s)-qGreen(*d)) * a) / 256 + qGreen(*d);
6128 unsigned char b = ((qBlue(*s)-qBlue(*d)) * a) / 256 + qBlue(*d);
6129 a = QMAX(qAlpha(*d),a); // alternatives...
6130 *d++ = qRgba(r,g,b,a);
6131 ++s;
6132 }
6133 }
6134 d += dd;
6135 s += ds;
6136 }
6137 } else {
6138 QRgb* d = (QRgb*)dst->scanLine(dy) + dx;
6139 QRgb* s = (QRgb*)src->scanLine(sy) + sx;
6140 if ( sw < 64 ) {
6141 // Trust ourselves
6142 const int dd = dst->width() - sw;
6143 const int ds = src->width() - sw;
6144 while ( sh-- ) {
6145 for ( int t=sw; t--; )
6146 *d++ = *s++;
6147 d += dd;
6148 s += ds;
6149 }
6150 } else {
6151 // Trust libc
6152 const int dd = dst->width();
6153 const int ds = src->width();
6154 const int b = sw*sizeof(QRgb);
6155 while ( sh-- ) {
6156 memcpy( d, s, b );
6157 d += dd;
6158 s += ds;
6159 }
6160 }
6161 }
6162 break;
6163#endif // QT_NO_IMAGE_TRUECOLOR
6164 }
6165}
6166
6167
6168/*!
6169 Returns TRUE if this image and image \a i have the same contents;
6170 otherwise returns FALSE. The comparison can be slow, unless there
6171 is some obvious difference, such as different widths, in which
6172 case the function will return quickly.
6173
6174 \sa operator=()
6175*/
6176
6177bool QImage::operator==( const QImage & i ) const
6178{
6179 // same object, or shared?
6180 if ( i.data == data )
6181 return TRUE;
6182 // obviously different stuff?
6183 if ( i.data->h != data->h ||
6184 i.data->w != data->w )
6185 return FALSE;
6186 // that was the fast bit...
6187 QImage i1 = convertDepth( 32 );
6188 QImage i2 = i.convertDepth( 32 );
6189 int l;
6190 for( l=0; l < data->h; l++ )
6191 if ( memcmp( i1.scanLine( l ), i2.scanLine( l ), 4*data->w ) )
6192 return FALSE;
6193 return TRUE;
6194}
6195
6196
6197/*!
6198 Returns TRUE if this image and image \a i have different contents;
6199 otherwise returns FALSE. The comparison can be slow, unless there
6200 is some obvious difference, such as different widths, in which
6201 case the function will return quickly.
6202
6203 \sa operator=()
6204*/
6205
6206bool QImage::operator!=( const QImage & i ) const
6207{
6208 return !(*this == i);
6209}
6210
6211
6212
6213
6214/*!
6215 \fn int QImage::dotsPerMeterX() const
6216
6217 Returns the number of pixels that fit horizontally in a physical
6218 meter. This and dotsPerMeterY() define the intended scale and
6219 aspect ratio of the image.
6220
6221 \sa setDotsPerMeterX()
6222*/
6223
6224/*!
6225 \fn int QImage::dotsPerMeterY() const
6226
6227 Returns the number of pixels that fit vertically in a physical
6228 meter. This and dotsPerMeterX() define the intended scale and
6229 aspect ratio of the image.
6230
6231 \sa setDotsPerMeterY()
6232*/
6233
6234/*!
6235 Sets the value returned by dotsPerMeterX() to \a x.
6236*/
6237void QImage::setDotsPerMeterX(int x)
6238{
6239 data->dpmx = x;
6240}
6241
6242/*!
6243 Sets the value returned by dotsPerMeterY() to \a y.
6244*/
6245void QImage::setDotsPerMeterY(int y)
6246{
6247 data->dpmy = y;
6248}
6249
6250/*!
6251 \fn QPoint QImage::offset() const
6252
6253 Returns the number of pixels by which the image is intended to be
6254 offset by when positioning relative to other images.
6255*/
6256
6257/*!
6258 Sets the value returned by offset() to \a p.
6259*/
6260void QImage::setOffset(const QPoint& p)
6261{
6262 data->offset = p;
6263}
6264#ifndef QT_NO_IMAGE_TEXT
6265/*!
6266 \internal
6267
6268 Returns the internal QImageDataMisc object. This object will be
6269 created if it doesn't already exist.
6270*/
6271QImageDataMisc& QImage::misc() const
6272{
6273 if ( !data->misc )
6274 data->misc = new QImageDataMisc;
6275 return *data->misc;
6276}
6277
6278/*!
6279 Returns the string recorded for the keyword \a key in language \a
6280 lang, or in a default language if \a lang is 0.
6281*/
6282QString QImage::text(const char* key, const char* lang) const
6283{
6284 QImageTextKeyLang x(key,lang);
6285 return misc().text_lang[x];
6286}
6287
6288/*!
6289 \overload
6290
6291 Returns the string recorded for the keyword and language \a kl.
6292*/
6293QString QImage::text(const QImageTextKeyLang& kl) const
6294{
6295 return misc().text_lang[kl];
6296}
6297
6298/*!
6299 Returns the language identifiers for which some texts are
6300 recorded.
6301
6302 Note that if you want to iterate over the list, you should iterate
6303 over a copy, e.g.
6304 \code
6305 QStringList list = myImage.textLanguages();
6306 QStringList::Iterator it = list.begin();
6307 while( it != list.end() ) {
6308 myProcessing( *it );
6309 ++it;
6310 }
6311 \endcode
6312
6313 \sa textList() text() setText() textKeys()
6314*/
6315QStringList QImage::textLanguages() const
6316{
6317 if ( !data->misc )
6318 return QStringList();
6319 return misc().languages();
6320}
6321
6322/*!
6323 Returns the keywords for which some texts are recorded.
6324
6325 Note that if you want to iterate over the list, you should iterate
6326 over a copy, e.g.
6327 \code
6328 QStringList list = myImage.textKeys();
6329 QStringList::Iterator it = list.begin();
6330 while( it != list.end() ) {
6331 myProcessing( *it );
6332 ++it;
6333 }
6334 \endcode
6335
6336 \sa textList() text() setText() textLanguages()
6337*/
6338QStringList QImage::textKeys() const
6339{
6340 if ( !data->misc )
6341 return QStringList();
6342 return misc().keys();
6343}
6344
6345/*!
6346 Returns a list of QImageTextKeyLang objects that enumerate all the
6347 texts key/language pairs set by setText() for this image.
6348
6349 Note that if you want to iterate over the list, you should iterate
6350 over a copy, e.g.
6351 \code
6352 QValueList<QImageTextKeyLang> list = myImage.textList();
6353 QValueList<QImageTextKeyLang>::Iterator it = list.begin();
6354 while( it != list.end() ) {
6355 myProcessing( *it );
6356 ++it;
6357 }
6358 \endcode
6359*/
6360QValueList<QImageTextKeyLang> QImage::textList() const
6361{
6362 if ( !data->misc )
6363 return QValueList<QImageTextKeyLang>();
6364 return misc().list();
6365}
6366
6367/*!
6368 Records string \a s for the keyword \a key. The \a key should be
6369 a portable keyword recognizable by other software - some suggested
6370 values can be found in
6371 \link http://www.libpng.org/pub/png/spec/PNG-Chunks.html#C.Anc-text
6372 the PNG specification\endlink. \a s can be any text. \a lang should
6373 specify the language code (see
6374 \link ftp://ftp.isi.edu/in-notes/1766 RFC 1766\endlink) or 0.
6375*/
6376void QImage::setText(const char* key, const char* lang, const QString& s)
6377{
6378 QImageTextKeyLang x(key,lang);
6379 misc().text_lang.replace(x,s);
6380}
6381
6382#endif // QT_NO_IMAGE_TEXT
6383
6384#ifdef Q_WS_QWS
6385/*!
6386 \internal
6387*/
6388QGfx * QImage::graphicsContext()
6389{
6390 QGfx * ret=0;
6391 if(depth()) {
6392 int w = qt_screen->mapToDevice( QSize(width(),height()) ).width();
6393 int h = qt_screen->mapToDevice( QSize(width(),height()) ).height();
6394 ret=QGfx::createGfx(depth(),bits(),w,h,bytesPerLine());
6395 } else {
6396 qDebug("Trying to create image for null depth");
6397 return 0;
6398 }
6399 if(depth()<=8) {
6400 QRgb * tmp=colorTable();
6401 int nc=numColors();
6402 if(tmp==0) {
6403 static QRgb table[2] = { qRgb(255,255,255), qRgb(0,0,0) };
6404 tmp=table;
6405 nc=2;
6406 }
6407 ret->setClut(tmp,nc);
6408 }
6409 return ret;
6410}
6411
6412#endif
Note: See TracBrowser for help on using the repository browser.