source: trunk/src/gui/image/qtiffhandler.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 23.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtiffhandler_p.h"
43#include <qvariant.h>
44#include <qdebug.h>
45#include <qimage.h>
46#include <qglobal.h>
47extern "C" {
48#include "tiffio.h"
49}
50
51QT_BEGIN_NAMESPACE
52
53tsize_t qtiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
54{
55 QIODevice* device = static_cast<QTiffHandler*>(fd)->device();
56 return device->isReadable() ? device->read(static_cast<char *>(buf), size) : -1;
57}
58
59tsize_t qtiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
60{
61 return static_cast<QTiffHandler*>(fd)->device()->write(static_cast<char *>(buf), size);
62}
63
64toff_t qtiffSeekProc(thandle_t fd, toff_t off, int whence)
65{
66 QIODevice *device = static_cast<QTiffHandler*>(fd)->device();
67 switch (whence) {
68 case SEEK_SET:
69 device->seek(off);
70 break;
71 case SEEK_CUR:
72 device->seek(device->pos() + off);
73 break;
74 case SEEK_END:
75 device->seek(device->size() + off);
76 break;
77 }
78
79 return device->pos();
80}
81
82int qtiffCloseProc(thandle_t /*fd*/)
83{
84 return 0;
85}
86
87toff_t qtiffSizeProc(thandle_t fd)
88{
89 return static_cast<QTiffHandler*>(fd)->device()->size();
90}
91
92int qtiffMapProc(thandle_t /*fd*/, tdata_t* /*pbase*/, toff_t* /*psize*/)
93{
94 return 0;
95}
96
97void qtiffUnmapProc(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/)
98{
99}
100
101// for 32 bits images
102inline void rotate_right_mirror_horizontal(QImage *const image)// rotate right->mirrored horizontal
103{
104 const int height = image->height();
105 const int width = image->width();
106 QImage generated(/* width = */ height, /* height = */ width, image->format());
107 const uint32 *originalPixel = reinterpret_cast<const uint32*>(image->bits());
108 uint32 *const generatedPixels = reinterpret_cast<uint32*>(generated.bits());
109 for (int row=0; row < height; ++row) {
110 for (int col=0; col < width; ++col) {
111 int idx = col * height + row;
112 generatedPixels[idx] = *originalPixel;
113 ++originalPixel;
114 }
115 }
116 *image = generated;
117}
118
119inline void rotate_right_mirror_vertical(QImage *const image) // rotate right->mirrored vertical
120{
121 const int height = image->height();
122 const int width = image->width();
123 QImage generated(/* width = */ height, /* height = */ width, image->format());
124 const int lastCol = width - 1;
125 const int lastRow = height - 1;
126 const uint32 *pixel = reinterpret_cast<const uint32*>(image->bits());
127 uint32 *const generatedBits = reinterpret_cast<uint32*>(generated.bits());
128 for (int row=0; row < height; ++row) {
129 for (int col=0; col < width; ++col) {
130 int idx = (lastCol - col) * height + (lastRow - row);
131 generatedBits[idx] = *pixel;
132 ++pixel;
133 }
134 }
135 *image = generated;
136}
137
138QTiffHandler::QTiffHandler() : QImageIOHandler()
139{
140 compression = NoCompression;
141}
142
143bool QTiffHandler::canRead() const
144{
145 if (canRead(device())) {
146 setFormat("tiff");
147 return true;
148 }
149 return false;
150}
151
152bool QTiffHandler::canRead(QIODevice *device)
153{
154 if (!device) {
155 qWarning("QTiffHandler::canRead() called with no device");
156 return false;
157 }
158
159 // current implementation uses TIFFClientOpen which needs to be
160 // able to seek, so sequential devices are not supported
161 QByteArray header = device->peek(4);
162 return header == QByteArray::fromRawData("\x49\x49\x2A\x00", 4)
163 || header == QByteArray::fromRawData("\x4D\x4D\x00\x2A", 4);
164}
165
166bool QTiffHandler::read(QImage *image)
167{
168 if (!canRead())
169 return false;
170
171 TIFF *const tiff = TIFFClientOpen("foo",
172 "r",
173 this,
174 qtiffReadProc,
175 qtiffWriteProc,
176 qtiffSeekProc,
177 qtiffCloseProc,
178 qtiffSizeProc,
179 qtiffMapProc,
180 qtiffUnmapProc);
181
182 if (!tiff) {
183 return false;
184 }
185 uint32 width;
186 uint32 height;
187 uint16 photometric;
188 if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width)
189 || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height)
190 || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) {
191 TIFFClose(tiff);
192 return false;
193 }
194
195 // BitsPerSample defaults to 1 according to the TIFF spec.
196 uint16 bitPerSample;
197 if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample))
198 bitPerSample = 1;
199
200 bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE;
201 if (grayscale && bitPerSample == 1) {
202 if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono)
203 *image = QImage(width, height, QImage::Format_Mono);
204 QVector<QRgb> colortable(2);
205 if (photometric == PHOTOMETRIC_MINISBLACK) {
206 colortable[0] = 0xff000000;
207 colortable[1] = 0xffffffff;
208 } else {
209 colortable[0] = 0xffffffff;
210 colortable[1] = 0xff000000;
211 }
212 image->setColorTable(colortable);
213
214 if (!image->isNull()) {
215 for (uint32 y=0; y<height; ++y) {
216 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
217 TIFFClose(tiff);
218 return false;
219 }
220 }
221 }
222 } else {
223 if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) {
224 if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8)
225 *image = QImage(width, height, QImage::Format_Indexed8);
226 if (!image->isNull()) {
227 const uint16 tableSize = 256;
228 QVector<QRgb> qtColorTable(tableSize);
229 if (grayscale) {
230 for (int i = 0; i<tableSize; ++i) {
231 const int c = (photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i);
232 qtColorTable[i] = qRgb(c, c, c);
233 }
234 } else {
235 // create the color table
236 uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
237 uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
238 uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
239 if (!redTable || !greenTable || !blueTable) {
240 TIFFClose(tiff);
241 return false;
242 }
243 if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
244 TIFFClose(tiff);
245 return false;
246 }
247
248 for (int i = 0; i<tableSize ;++i) {
249 const int red = redTable[i] / 257;
250 const int green = greenTable[i] / 257;
251 const int blue = blueTable[i] / 257;
252 qtColorTable[i] = qRgb(red, green, blue);
253 }
254 }
255
256 image->setColorTable(qtColorTable);
257 for (uint32 y=0; y<height; ++y) {
258 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
259 TIFFClose(tiff);
260 return false;
261 }
262 }
263
264 // free redTable, greenTable and greenTable done by libtiff
265 }
266 } else {
267 if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32)
268 *image = QImage(width, height, QImage::Format_ARGB32);
269 if (!image->isNull()) {
270 const int stopOnError = 1;
271 if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, stopOnError)) {
272 for (uint32 y=0; y<height; ++y)
273 convert32BitOrder(image->scanLine(y), width);
274 } else {
275 TIFFClose(tiff);
276 return false;
277 }
278 }
279 }
280 }
281
282 if (image->isNull()) {
283 TIFFClose(tiff);
284 return false;
285 }
286
287 float resX = 0;
288 float resY = 0;
289 uint16 resUnit = RESUNIT_NONE;
290 if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit)
291 && TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX)
292 && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) {
293
294 switch(resUnit) {
295 case RESUNIT_CENTIMETER:
296 image->setDotsPerMeterX(qRound(resX * 100));
297 image->setDotsPerMeterY(qRound(resY * 100));
298 break;
299 case RESUNIT_INCH:
300 image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
301 image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
302 break;
303 default:
304 // do nothing as defaults have already
305 // been set within the QImage class
306 break;
307 }
308 }
309
310 // rotate the image if the orientation is defined in the file
311 uint16 orientationTag;
312 if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &orientationTag)) {
313 if (image->format() == QImage::Format_ARGB32) {
314 // TIFFReadRGBAImageOriented() flip the image but does not rotate them
315 switch (orientationTag) {
316 case 5:
317 rotate_right_mirror_horizontal(image);
318 break;
319 case 6:
320 rotate_right_mirror_vertical(image);
321 break;
322 case 7:
323 rotate_right_mirror_horizontal(image);
324 break;
325 case 8:
326 rotate_right_mirror_vertical(image);
327 break;
328 }
329 } else {
330 switch (orientationTag) {
331 case 1: // default orientation
332 break;
333 case 2: // mirror horizontal
334 *image = image->mirrored(true, false);
335 break;
336 case 3: // mirror both
337 *image = image->mirrored(true, true);
338 break;
339 case 4: // mirror vertical
340 *image = image->mirrored(false, true);
341 break;
342 case 5: // rotate right mirror horizontal
343 {
344 QMatrix transformation;
345 transformation.rotate(90);
346 *image = image->transformed(transformation);
347 *image = image->mirrored(true, false);
348 break;
349 }
350 case 6: // rotate right
351 {
352 QMatrix transformation;
353 transformation.rotate(90);
354 *image = image->transformed(transformation);
355 break;
356 }
357 case 7: // rotate right, mirror vertical
358 {
359 QMatrix transformation;
360 transformation.rotate(90);
361 *image = image->transformed(transformation);
362 *image = image->mirrored(false, true);
363 break;
364 }
365 case 8: // rotate left
366 {
367 QMatrix transformation;
368 transformation.rotate(270);
369 *image = image->transformed(transformation);
370 break;
371 }
372 }
373 }
374 }
375
376
377 TIFFClose(tiff);
378 return true;
379}
380
381static bool checkGrayscale(const QVector<QRgb> &colorTable)
382{
383 if (colorTable.size() != 256)
384 return false;
385
386 const bool increasing = (colorTable.at(0) == 0xff000000);
387 for (int i = 0; i < 256; ++i) {
388 if ((increasing && colorTable.at(i) != qRgb(i, i, i))
389 || (!increasing && colorTable.at(i) != qRgb(255 - i, 255 - i, 255 - i)))
390 return false;
391 }
392 return true;
393}
394
395bool QTiffHandler::write(const QImage &image)
396{
397 if (!device()->isWritable())
398 return false;
399
400 TIFF *const tiff = TIFFClientOpen("foo",
401 "w",
402 this,
403 qtiffReadProc,
404 qtiffWriteProc,
405 qtiffSeekProc,
406 qtiffCloseProc,
407 qtiffSizeProc,
408 qtiffMapProc,
409 qtiffUnmapProc);
410 if (!tiff)
411 return false;
412
413 const int width = image.width();
414 const int height = image.height();
415
416 if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
417 || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
418 || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
419 TIFFClose(tiff);
420 return false;
421 }
422
423 // set the resolution
424 bool resolutionSet = false;
425 const int dotPerMeterX = image.dotsPerMeterX();
426 const int dotPerMeterY = image.dotsPerMeterY();
427 if ((dotPerMeterX % 100) == 0
428 && (dotPerMeterY % 100) == 0) {
429 resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
430 && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
431 && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
432 } else {
433 resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
434 && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast<float>(image.logicalDpiX()))
435 && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast<float>(image.logicalDpiY()));
436 }
437 if (!resolutionSet) {
438 TIFFClose(tiff);
439 return false;
440 }
441
442 // configure image depth
443 const QImage::Format format = image.format();
444 if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) {
445 uint16 photometric = PHOTOMETRIC_MINISBLACK;
446 if (image.colorTable().at(0) == 0xffffffff)
447 photometric = PHOTOMETRIC_MINISWHITE;
448 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
449 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)
450 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)) {
451 TIFFClose(tiff);
452 return false;
453 }
454
455 // try to do the conversion in chunks no greater than 16 MB
456 int chunks = (width * height / (1024 * 1024 * 16)) + 1;
457 int chunkHeight = qMax(height / chunks, 1);
458
459 int y = 0;
460 while (y < height) {
461 QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono);
462
463 int chunkStart = y;
464 int chunkEnd = y + chunk.height();
465 while (y < chunkEnd) {
466 if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
467 TIFFClose(tiff);
468 return false;
469 }
470 ++y;
471 }
472 }
473 TIFFClose(tiff);
474 } else if (format == QImage::Format_Indexed8) {
475 const QVector<QRgb> colorTable = image.colorTable();
476 bool isGrayscale = checkGrayscale(colorTable);
477 if (isGrayscale) {
478 uint16 photometric = PHOTOMETRIC_MINISBLACK;
479 if (image.colorTable().at(0) == 0xffffffff)
480 photometric = PHOTOMETRIC_MINISWHITE;
481 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
482 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
483 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
484 TIFFClose(tiff);
485 return false;
486 }
487 } else {
488 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE)
489 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
490 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
491 TIFFClose(tiff);
492 return false;
493 }
494 //// write the color table
495 // allocate the color tables
496 uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
497 uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
498 uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
499 if (!redTable || !greenTable || !blueTable) {
500 TIFFClose(tiff);
501 return false;
502 }
503
504 // set the color table
505 const int tableSize = colorTable.size();
506 Q_ASSERT(tableSize <= 256);
507 for (int i = 0; i<tableSize; ++i) {
508 const QRgb color = colorTable.at(i);
509 redTable[i] = qRed(color) * 257;
510 greenTable[i] = qGreen(color) * 257;
511 blueTable[i] = qBlue(color) * 257;
512 }
513
514 const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable);
515
516 qFree(redTable);
517 qFree(greenTable);
518 qFree(blueTable);
519
520 if (!setColorTableSuccess) {
521 TIFFClose(tiff);
522 return false;
523 }
524 }
525
526 //// write the data
527 // try to do the conversion in chunks no greater than 16 MB
528 int chunks = (width * height/ (1024 * 1024 * 16)) + 1;
529 int chunkHeight = qMax(height / chunks, 1);
530
531 int y = 0;
532 while (y < height) {
533 QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y));
534
535 int chunkStart = y;
536 int chunkEnd = y + chunk.height();
537 while (y < chunkEnd) {
538 if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
539 TIFFClose(tiff);
540 return false;
541 }
542 ++y;
543 }
544 }
545 TIFFClose(tiff);
546
547 } else {
548 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
549 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
550 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
551 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
552 TIFFClose(tiff);
553 return false;
554 }
555 // try to do the ARGB32 conversion in chunks no greater than 16 MB
556 int chunks = (width * height * 4 / (1024 * 1024 * 16)) + 1;
557 int chunkHeight = qMax(height / chunks, 1);
558
559 int y = 0;
560 while (y < height) {
561 QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_ARGB32);
562
563 int chunkStart = y;
564 int chunkEnd = y + chunk.height();
565 while (y < chunkEnd) {
566 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
567 convert32BitOrder(chunk.scanLine(y - chunkStart), width);
568 else
569 convert32BitOrderBigEndian(chunk.scanLine(y - chunkStart), width);
570
571 if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
572 TIFFClose(tiff);
573 return false;
574 }
575 ++y;
576 }
577 }
578 TIFFClose(tiff);
579 }
580
581 return true;
582}
583
584QByteArray QTiffHandler::name() const
585{
586 return "tiff";
587}
588
589QVariant QTiffHandler::option(ImageOption option) const
590{
591 if (option == Size && canRead()) {
592 QSize imageSize;
593 qint64 pos = device()->pos();
594 TIFF *tiff = TIFFClientOpen("foo",
595 "r",
596 const_cast<QTiffHandler*>(this),
597 qtiffReadProc,
598 qtiffWriteProc,
599 qtiffSeekProc,
600 qtiffCloseProc,
601 qtiffSizeProc,
602 qtiffMapProc,
603 qtiffUnmapProc);
604
605 if (tiff) {
606 uint32 width = 0;
607 uint32 height = 0;
608 TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
609 TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
610 imageSize = QSize(width, height);
611 TIFFClose(tiff);
612 }
613 device()->seek(pos);
614 if (imageSize.isValid())
615 return imageSize;
616 } else if (option == CompressionRatio) {
617 return compression;
618 } else if (option == ImageFormat) {
619 return QImage::Format_ARGB32;
620 }
621 return QVariant();
622}
623
624void QTiffHandler::setOption(ImageOption option, const QVariant &value)
625{
626 if (option == CompressionRatio && value.type() == QVariant::Int)
627 compression = value.toInt();
628}
629
630bool QTiffHandler::supportsOption(ImageOption option) const
631{
632 return option == CompressionRatio
633 || option == Size
634 || option == ImageFormat;
635}
636
637void QTiffHandler::convert32BitOrder(void *buffer, int width)
638{
639 uint32 *target = reinterpret_cast<uint32 *>(buffer);
640 for (int32 x=0; x<width; ++x) {
641 uint32 p = target[x];
642 // convert between ARGB and ABGR
643 target[x] = (p & 0xff000000)
644 | ((p & 0x00ff0000) >> 16)
645 | (p & 0x0000ff00)
646 | ((p & 0x000000ff) << 16);
647 }
648}
649
650void QTiffHandler::convert32BitOrderBigEndian(void *buffer, int width)
651{
652 uint32 *target = reinterpret_cast<uint32 *>(buffer);
653 for (int32 x=0; x<width; ++x) {
654 uint32 p = target[x];
655 target[x] = (p & 0xff000000) >> 24
656 | (p & 0x00ff0000) << 8
657 | (p & 0x0000ff00) << 8
658 | (p & 0x000000ff) << 8;
659 }
660}
661
662QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.