Changeset 561 for trunk/src/plugins/imageformats
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 25 edited
-
. (modified) (1 prop)
-
src/plugins/imageformats/gif/gif.pro (modified) (1 diff)
-
src/plugins/imageformats/gif/main.cpp (modified) (3 diffs)
-
src/plugins/imageformats/gif/qgifhandler.cpp (modified) (16 diffs)
-
src/plugins/imageformats/gif/qgifhandler.h (modified) (3 diffs)
-
src/plugins/imageformats/ico/ico.pro (modified) (1 diff)
-
src/plugins/imageformats/ico/main.cpp (modified) (3 diffs)
-
src/plugins/imageformats/ico/qicohandler.cpp (modified) (27 diffs)
-
src/plugins/imageformats/ico/qicohandler.h (modified) (3 diffs)
-
src/plugins/imageformats/jpeg/jpeg.pro (modified) (2 diffs)
-
src/plugins/imageformats/jpeg/main.cpp (modified) (3 diffs)
-
src/plugins/imageformats/jpeg/qjpeghandler.cpp (modified) (25 diffs)
-
src/plugins/imageformats/jpeg/qjpeghandler.h (modified) (5 diffs)
-
src/plugins/imageformats/mng/main.cpp (modified) (3 diffs)
-
src/plugins/imageformats/mng/mng.pro (modified) (2 diffs)
-
src/plugins/imageformats/mng/qmnghandler.cpp (modified) (4 diffs)
-
src/plugins/imageformats/mng/qmnghandler.h (modified) (5 diffs)
-
src/plugins/imageformats/svg/main.cpp (modified) (3 diffs)
-
src/plugins/imageformats/svg/qsvgiohandler.cpp (modified) (7 diffs)
-
src/plugins/imageformats/svg/qsvgiohandler.h (modified) (3 diffs)
-
src/plugins/imageformats/svg/svg.pro (modified) (1 diff)
-
src/plugins/imageformats/tiff/main.cpp (modified) (3 diffs)
-
src/plugins/imageformats/tiff/qtiffhandler.cpp (modified) (7 diffs)
-
src/plugins/imageformats/tiff/qtiffhandler.h (modified) (3 diffs)
-
src/plugins/imageformats/tiff/tiff.pro (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/plugins/imageformats/gif/gif.pro
r2 r561 9 9 target.path += $$[QT_INSTALL_PLUGINS]/imageformats 10 10 INSTALLS += target 11 12 symbian:TARGET.UID3=0x2001E61A -
trunk/src/plugins/imageformats/gif/main.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/gif/qgifhandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 54 54 55 55 #define Q_TRANSPARENT 0x00ffffff 56 57 // avoid going through QImage::scanLine() which calls detach 58 #define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl) 59 56 60 57 61 /* … … 136 140 bool out_of_bounds; 137 141 bool digress; 138 void nextY( QImage *image);142 void nextY(unsigned char *bits, int bpl); 139 143 void disposePrevious(QImage *image); 140 144 }; … … 233 237 // CompuServe Incorporated." 234 238 239 image->detach(); 240 int bpl = image->bytesPerLine(); 241 unsigned char *bits = image->bits(); 242 235 243 #define LM(l, m) (((m)<<8)|l) 236 244 digress = false; 237 int initial = length;245 const int initial = length; 238 246 while (!digress && length) { 239 247 length--; … … 334 342 335 343 QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; 336 if (image->isNull() || (image->size() != QSize(swidth, sheight)) || image->format() != format) {344 if (image->isNull()) { 337 345 (*image) = QImage(swidth, sheight, format); 338 memset(image->bits(), 0, image->numBytes()); 346 bpl = image->bytesPerLine(); 347 bits = image->bits(); 348 memset(bits, 0, image->byteCount()); 339 349 340 350 // ### size of the upcoming frame, should rather … … 394 404 qMax(backingstore.height(), h), 395 405 QImage::Format_RGB32); 396 memset( image->bits(), 0, image->numBytes());406 memset(bits, 0, image->byteCount()); 397 407 } 408 const int dest_bpl = backingstore.bytesPerLine(); 409 unsigned char *dest_data = backingstore.bits(); 398 410 for (int ln=0; ln<h; ln++) { 399 memcpy( backingstore.scanLine(ln),400 image->scanLine(t+ln)+l, w*sizeof(QRgb));411 memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln), 412 FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb)); 401 413 } 402 414 } … … 471 483 firstcode=oldcode=code; 472 484 if (!out_of_bounds && image->height() > y && firstcode!=trans_index) 473 ((QRgb*) image->scanLine(y))[x] = color(firstcode);485 ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode); 474 486 x++; 475 487 if (x>=swidth) out_of_bounds = true; … … 478 490 x=left; 479 491 out_of_bounds = left>=swidth || y>=sheight; 480 nextY( image);492 nextY(bits, bpl); 481 493 } 482 494 } else { … … 516 528 QRgb *line = 0; 517 529 if (!out_of_bounds && h > y) 518 line = (QRgb*) image->scanLine(y);530 line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); 519 531 while (sp>stack) { 520 532 const uchar index = *(--sp); … … 530 542 x=left; 531 543 out_of_bounds = left>=swidth || y>=sheight; 532 nextY( image);544 nextY(bits, bpl); 533 545 if (!out_of_bounds && h > y) 534 line = (QRgb*) image->scanLine(y);546 line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); 535 547 } 536 548 } … … 645 657 } 646 658 647 void QGIFFormat::nextY( QImage *image)659 void QGIFFormat::nextY(unsigned char *bits, int bpl) 648 660 { 649 661 int my; … … 661 673 if (trans_index < 0) { 662 674 for (i=1; i<=my; i++) { 663 memcpy( image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb),675 memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), 664 676 (right-left+1)*sizeof(QRgb)); 665 677 } … … 690 702 if (trans_index < 0) { 691 703 for (i=1; i<=my; i++) { 692 memcpy( image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb),704 memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), 693 705 (right-left+1)*sizeof(QRgb)); 694 706 } … … 714 726 if (trans_index < 0) { 715 727 for (i=1; i<=my; i++) { 716 memcpy( image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb),728 memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), 717 729 (right-left+1)*sizeof(QRgb)); 718 730 } -
trunk/src/plugins/imageformats/gif/qgifhandler.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/ico/ico.pro
r2 r561 11 11 target.path += $$[QT_INSTALL_PLUGINS]/imageformats 12 12 INSTALLS += target 13 14 symbian:TARGET.UID3=0x2001E616 -
trunk/src/plugins/imageformats/ico/main.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/ico/qicohandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 58 58 typedef struct 59 59 { 60 quint8 bWidth; // Width of the image61 quint8 bHeight; // Height of the image (times 2)62 quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ]63 quint8 bReserved; // Reserved64 quint16 wPlanes; // Color Planes65 quint16 wBitCount; // Bits per pixel66 quint32 dwBytesInRes; // how many bytes in this resource?67 quint32 dwImageOffset; // where in the file is this image60 quint8 bWidth; // Width of the image 61 quint8 bHeight; // Height of the image (times 2) 62 quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ] 63 quint8 bReserved; // Reserved 64 quint16 wPlanes; // Color Planes 65 quint16 wBitCount; // Bits per pixel 66 quint32 dwBytesInRes; // how many bytes in this resource? 67 quint32 dwImageOffset; // where in the file is this image 68 68 } ICONDIRENTRY, *LPICONDIRENTRY; 69 69 #define ICONDIRENTRY_SIZE 16 … … 71 71 typedef struct 72 72 { 73 quint16 idReserved; // Reserved74 quint16 idType; // resource type (1 for icons)75 quint16 idCount; // how many images?76 ICONDIRENTRY idEntries[1]; // the entries for each image73 quint16 idReserved; // Reserved 74 quint16 idType; // resource type (1 for icons) 75 quint16 idCount; // how many images? 76 ICONDIRENTRY idEntries[1]; // the entries for each image 77 77 } ICONDIR, *LPICONDIR; 78 78 #define ICONDIR_SIZE 6 // Exclude the idEntries field 79 79 80 typedef struct { // BMP information header81 quint32 biSize;// size of this struct82 quint32 biWidth;// pixmap width83 quint32 biHeight; // pixmap height84 quint16 biPlanes;// should be 185 quint16 biBitCount;// number of bits per pixel86 quint32 biCompression;// compression method87 quint32 biSizeImage;// size of image88 quint32 biXPelsPerMeter;// horizontal resolution89 quint32 biYPelsPerMeter;// vertical resolution90 quint32 biClrUsed;// number of colors used91 quint32 biClrImportant;// number of important colors80 typedef struct { // BMP information header 81 quint32 biSize; // size of this struct 82 quint32 biWidth; // pixmap width 83 quint32 biHeight; // pixmap height (specifies the combined height of the XOR and AND masks) 84 quint16 biPlanes; // should be 1 85 quint16 biBitCount; // number of bits per pixel 86 quint32 biCompression; // compression method 87 quint32 biSizeImage; // size of image 88 quint32 biXPelsPerMeter; // horizontal resolution 89 quint32 biYPelsPerMeter; // vertical resolution 90 quint32 biClrUsed; // number of colors used 91 quint32 biClrImportant; // number of important colors 92 92 } BMP_INFOHDR ,*LPBMP_INFOHDR; 93 93 #define BMP_INFOHDR_SIZE 40 … … 109 109 bool readIconEntry(int index, ICONDIRENTRY * iconEntry); 110 110 111 bool readBMPHeader( ICONDIRENTRY & iconEntry, BMP_INFOHDR * header);111 bool readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header); 112 112 void findColorInfo(QImage & image); 113 113 void readColorTable(QImage & image); … … 255 255 { 256 256 if (readHeader()) 257 return iconDir.idCount;257 return iconDir.idCount; 258 258 return 0; 259 259 } … … 269 269 qint64 readBytes = ICONDIR_SIZE; 270 270 if (readIconDirEntry(iodev, &ikonDir.idEntries[0])) { 271 readBytes += ICONDIRENTRY_SIZE;272 // ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file.273 if ( ikonDir.idReserved == 0274 && ikonDir.idType == 1275 && ikonDir.idEntries[0].bReserved == 0276 && ikonDir.idEntries[0].wPlanes <= 1277 && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel278 && ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40279 ) {280 isProbablyICO = true;281 }271 readBytes += ICONDIRENTRY_SIZE; 272 // ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file. 273 if ( ikonDir.idReserved == 0 274 && ikonDir.idType == 1 275 && ikonDir.idEntries[0].bReserved == 0 276 && ikonDir.idEntries[0].wPlanes <= 1 277 && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel 278 && ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40 279 ) { 280 isProbablyICO = true; 281 } 282 282 283 283 if (iodev->isSequential()) { … … 324 324 iodev->ungetChar(tmp & 0xff); 325 325 } 326 327 } 326 } 328 327 if (!iodev->isSequential()) iodev->seek(oldPos); 329 328 } … … 335 334 { 336 335 if (iod && !headerRead) { 337 startpos = iod->pos();338 if (readIconDir(iod, &iconDir)) {339 if (iconDir.idReserved == 0 || iconDir.idType == 1)340 headerRead = true;341 }336 startpos = iod->pos(); 337 if (readIconDir(iod, &iconDir)) { 338 if (iconDir.idReserved == 0 || iconDir.idType == 1) 339 headerRead = true; 340 } 342 341 } 343 342 … … 345 344 } 346 345 347 bool ICOReader::readIconEntry(int index, ICONDIRENTRY * iconEntry)346 bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry) 348 347 { 349 348 if (iod) { 350 if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) {351 return readIconDirEntry(iod, iconEntry);349 if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) { 350 return readIconDirEntry(iod, iconEntry); 352 351 } 353 352 } … … 357 356 358 357 359 bool ICOReader::readBMPHeader(ICONDIRENTRY & iconEntry, BMP_INFOHDR * header) 360 { 361 memset(&icoAttrib, 0, sizeof(IcoAttrib)); 358 bool ICOReader::readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header) 359 { 362 360 if (iod) { 363 if (iod->seek(startpos + iconEntry.dwImageOffset)) { 364 if (readBMPInfoHeader(iod, header)) { 365 366 icoAttrib.nbits = header->biBitCount ? header->biBitCount : iconEntry.wBitCount; 367 icoAttrib.h = header->biHeight / 2; // this height is always double the iconEntry height (for the mask) 368 icoAttrib.w = header->biWidth; 369 370 switch (icoAttrib.nbits) { 371 case 32: 372 case 24: 373 case 16: 374 icoAttrib.depth = 32; 375 break; 376 case 8: 377 case 4: 378 icoAttrib.depth = 8; 379 break; 380 default: 381 icoAttrib.depth = 1; 382 } 383 384 if ( icoAttrib.depth == 32 ) // there's no colormap 385 icoAttrib.ncolors = 0; 386 else // # colors used 387 icoAttrib.ncolors = header->biClrUsed ? header->biClrUsed : 1 << icoAttrib.nbits; 388 //qDebug() << "Bits:" << icoAttrib.nbits << "Depth:" << icoAttrib.depth << "Ncols:" << icoAttrib.ncolors; 389 return TRUE; 390 } 391 } 361 if (iod->seek(startpos + imageOffset)) { 362 if (readBMPInfoHeader(iod, header)) { 363 return TRUE; 364 } 365 } 392 366 } 393 367 return FALSE; … … 396 370 void ICOReader::findColorInfo(QImage & image) 397 371 { 398 if (icoAttrib.ncolors > 0) { // set color table399 readColorTable(image);372 if (icoAttrib.ncolors > 0) { // set color table 373 readColorTable(image); 400 374 } else if (icoAttrib.nbits == 16) { // don't support RGB values for 15/16 bpp 401 image = QImage();375 image = QImage(); 402 376 } 403 377 } … … 406 380 { 407 381 if (iod) { 408 image.set NumColors(icoAttrib.ncolors);409 uchar rgb[4];410 for (int i=0; i<icoAttrib.ncolors; i++) {411 if (iod->read((char*)rgb, 4) != 4) {412 image = QImage();413 break;414 }415 image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0]));416 }382 image.setColorCount(icoAttrib.ncolors); 383 uchar rgb[4]; 384 for (int i=0; i<icoAttrib.ncolors; i++) { 385 if (iod->read((char*)rgb, 4) != 4) { 386 image = QImage(); 387 break; 388 } 389 image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0])); 390 } 417 391 } else { 418 image = QImage();392 image = QImage(); 419 393 } 420 394 } … … 422 396 void ICOReader::readBMP(QImage & image) 423 397 { 424 if (icoAttrib.nbits == 1) { // 1 bit BMP image425 read1BitBMP(image);426 } else if (icoAttrib.nbits == 4) { // 4 bit BMP image427 read4BitBMP(image);398 if (icoAttrib.nbits == 1) { // 1 bit BMP image 399 read1BitBMP(image); 400 } else if (icoAttrib.nbits == 4) { // 4 bit BMP image 401 read4BitBMP(image); 428 402 } else if (icoAttrib.nbits == 8) { 429 read8BitBMP(image);403 read8BitBMP(image); 430 404 } else if (icoAttrib.nbits == 16 || icoAttrib.nbits == 24 || icoAttrib.nbits == 32 ) { // 16,24,32 bit BMP image 431 read16_24_32BMP(image);405 read16_24_32BMP(image); 432 406 } 433 407 } … … 443 417 if (iod) { 444 418 445 int h = image.height();446 int bpl = image.bytesPerLine();447 448 while (--h >= 0) {449 if (iod->read((char*)image.scanLine(h),bpl) != bpl) {450 image = QImage();451 break;452 }453 }419 int h = image.height(); 420 int bpl = image.bytesPerLine(); 421 422 while (--h >= 0) { 423 if (iod->read((char*)image.scanLine(h),bpl) != bpl) { 424 image = QImage(); 425 break; 426 } 427 } 454 428 } else { 455 image = QImage();429 image = QImage(); 456 430 } 457 431 } … … 461 435 if (iod) { 462 436 463 int h = icoAttrib.h;464 int buflen = ((icoAttrib.w+7)/8)*4;465 uchar *buf = new uchar[buflen];466 Q_CHECK_PTR(buf);467 468 while (--h >= 0) {469 if (iod->read((char*)buf,buflen) != buflen) {470 image = QImage();471 break;472 }473 register uchar *p = image.scanLine(h);474 uchar *b = buf;475 for (int i=0; i<icoAttrib.w/2; i++) {// convert nibbles to bytes476 *p++ = *b >> 4;477 *p++ = *b++ & 0x0f;478 }479 if (icoAttrib.w & 1)// the last nibble480 *p = *b >> 4;481 }482 483 delete [] buf;437 int h = icoAttrib.h; 438 int buflen = ((icoAttrib.w+7)/8)*4; 439 uchar *buf = new uchar[buflen]; 440 Q_CHECK_PTR(buf); 441 442 while (--h >= 0) { 443 if (iod->read((char*)buf,buflen) != buflen) { 444 image = QImage(); 445 break; 446 } 447 register uchar *p = image.scanLine(h); 448 uchar *b = buf; 449 for (int i=0; i<icoAttrib.w/2; i++) { // convert nibbles to bytes 450 *p++ = *b >> 4; 451 *p++ = *b++ & 0x0f; 452 } 453 if (icoAttrib.w & 1) // the last nibble 454 *p = *b >> 4; 455 } 456 457 delete [] buf; 484 458 485 459 } else { 486 image = QImage();460 image = QImage(); 487 461 } 488 462 } … … 492 466 if (iod) { 493 467 494 int h = icoAttrib.h;495 int bpl = image.bytesPerLine();496 497 while (--h >= 0) {498 if (iod->read((char *)image.scanLine(h), bpl) != bpl) {499 image = QImage();500 break;501 }502 }468 int h = icoAttrib.h; 469 int bpl = image.bytesPerLine(); 470 471 while (--h >= 0) { 472 if (iod->read((char *)image.scanLine(h), bpl) != bpl) { 473 image = QImage(); 474 break; 475 } 476 } 503 477 } else { 504 image = QImage();478 image = QImage(); 505 479 } 506 480 } … … 509 483 { 510 484 if (iod) { 511 512 int h = icoAttrib.h; 513 register QRgb *p; 514 QRgb *end; 515 uchar *buf = new uchar[image.bytesPerLine()]; 516 int bpl = ((icoAttrib.w*icoAttrib.nbits+31)/32)*4; 517 uchar *b; 518 519 while (--h >= 0) { 520 p = (QRgb *)image.scanLine(h); 521 end = p + icoAttrib.w; 522 if (iod->read((char *)buf, bpl) != bpl) { 523 image = QImage(); 524 break; 525 } 526 b = buf; 527 while (p < end) { 485 int h = icoAttrib.h; 486 register QRgb *p; 487 QRgb *end; 488 uchar *buf = new uchar[image.bytesPerLine()]; 489 int bpl = ((icoAttrib.w*icoAttrib.nbits+31)/32)*4; 490 uchar *b; 491 492 while (--h >= 0) { 493 p = (QRgb *)image.scanLine(h); 494 end = p + icoAttrib.w; 495 if (iod->read((char *)buf, bpl) != bpl) { 496 image = QImage(); 497 break; 498 } 499 b = buf; 500 while (p < end) { 528 501 if (icoAttrib.nbits == 24) 529 502 *p++ = qRgb(*(b+2), *(b+1), *b); 530 503 else if (icoAttrib.nbits == 32) 531 504 *p++ = qRgba(*(b+2), *(b+1), *b, *(b+3)); 532 b += icoAttrib.nbits/8;533 }534 }535 536 delete[] buf;505 b += icoAttrib.nbits/8; 506 } 507 } 508 509 delete[] buf; 537 510 538 511 } else { 539 image = QImage();512 image = QImage(); 540 513 } 541 514 } … … 550 523 if (readIconEntry(index, &iconEntry)) { 551 524 525 static const uchar pngMagicData[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; 526 527 iod->seek(iconEntry.dwImageOffset); 528 529 const QByteArray pngMagic = QByteArray::fromRawData((char*)pngMagicData, sizeof(pngMagicData)); 530 const bool isPngImage = (iod->read(pngMagic.size()) == pngMagic); 531 532 if (isPngImage) { 533 iod->seek(iconEntry.dwImageOffset); 534 return QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png"); 535 } 536 552 537 BMP_INFOHDR header; 553 if (readBMPHeader(iconEntry, &header)) { 538 if (readBMPHeader(iconEntry.dwImageOffset, &header)) { 539 icoAttrib.nbits = header.biBitCount ? header.biBitCount : iconEntry.wBitCount; 540 541 switch (icoAttrib.nbits) { 542 case 32: 543 case 24: 544 case 16: 545 icoAttrib.depth = 32; 546 break; 547 case 8: 548 case 4: 549 icoAttrib.depth = 8; 550 break; 551 default: 552 icoAttrib.depth = 1; 553 } 554 if (icoAttrib.depth == 32) // there's no colormap 555 icoAttrib.ncolors = 0; 556 else // # colors used 557 icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits; 558 icoAttrib.w = iconEntry.bWidth; 559 icoAttrib.h = iconEntry.bHeight; 554 560 555 561 QImage::Format format = QImage::Format_ARGB32; … … 569 575 QImage mask(image.width(), image.height(), QImage::Format_Mono); 570 576 if (!mask.isNull()) { 571 mask.set NumColors(2);577 mask.setColorCount(2); 572 578 mask.setColor(0, qRgba(255,255,255,0xff)); 573 579 mask.setColor(1, qRgba(0 ,0 ,0 ,0xff)); … … 606 612 607 613 ICOReader reader(device); 608 for (int i =0; i<reader.count(); i++)609 images += reader.iconAt(i);614 for (int i = 0; i < reader.count(); i++) 615 images += reader.iconAt(i); 610 616 611 617 return images; … … 660 666 maskImage = maskImage.convertToFormat(QImage::Format_Mono); 661 667 662 int nbits = 32;663 int bpl_bmp = ((image.width()*nbits+31)/32)*4;668 int nbits = 32; 669 int bpl_bmp = ((image.width()*nbits+31)/32)*4; 664 670 665 671 entries[i].bColorCount = 0; … … 671 677 + (maskImage.bytesPerLine() * maskImage.height()); 672 678 entries[i].wPlanes = 1; 673 if (i ==0)679 if (i == 0) 674 680 entries[i].dwImageOffset = origOffset + ICONDIR_SIZE 675 681 + (id.idCount * ICONDIRENTRY_SIZE); … … 696 702 memset( buf, 0, bpl_bmp ); 697 703 int y; 698 for (y =image.height()-1; y>=0; y--) {// write the image bits704 for (y = image.height() - 1; y >= 0; y--) { // write the image bits 699 705 // 32 bits 700 706 QRgb *p = (QRgb *)image.scanLine(y); … … 718 724 maskImage.invertPixels(); // seems as though it needs this 719 725 // NOTE! !! The mask is only flipped vertically - not horizontally !! 720 for (y =maskImage.height()-1; y>=0; y--)726 for (y = maskImage.height() - 1; y >= 0; y--) 721 727 buffer.write((char*)maskImage.scanLine(y), maskImage.bytesPerLine()); 722 723 } 724 725 728 } 726 729 727 730 if (writeIconDir(device, id)) { … … 732 735 } 733 736 if (bOK) { 734 for (i =0; i<id.idCount && bOK; i++) {737 for (i = 0; i < id.idCount && bOK; i++) { 735 738 bOK = writeBMPInfoHeader(device, bmpHeaders[i]); 736 739 bOK &= (device->write(imageData[i]) == (int) imageData[i].size()); -
trunk/src/plugins/imageformats/ico/qicohandler.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/jpeg/jpeg.pro
r2 r561 12 12 contains(CE_ARCH,x86):CONFIG -= stl exceptions 13 13 contains(CE_ARCH,x86):CONFIG += exceptions_off 14 } 15 16 symbian: { 17 #Disable warnings in 3rdparty code due to unused arguments 18 QMAKE_CXXFLAGS.CW += -W nounusedarg 19 TARGET.UID3=0x2001E61B 14 20 } 15 21 … … 72 78 target.path += $$[QT_INSTALL_PLUGINS]/imageformats 73 79 INSTALLS += target 80 -
trunk/src/plugins/imageformats/jpeg/main.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/jpeg/qjpeghandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 85 85 QImageSmoothScaler(const int w, const int h, const QImage &src); 86 86 QImageSmoothScaler(const int srcWidth, const int srcHeight, 87 const char *parameters);87 const int dstWidth, const int dstHeight); 88 88 89 89 virtual ~QImageSmoothScaler(void); 90 90 91 91 QImage scale(); 92 93 protected:94 int scaledWidth(void) const;95 92 96 93 private: … … 124 121 125 122 QImageSmoothScaler::QImageSmoothScaler(const int srcWidth, const int srcHeight, 126 const char *parameters) 127 { 128 char sModeStr[1024]; 129 int t1; 130 int t2; 131 int dstWidth; 132 int dstHeight; 133 134 sModeStr[0] = '\0'; 135 123 const int dstWidth, const int dstHeight) 124 { 136 125 d = new QImageSmoothScalerPrivate; 137 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400138 sscanf_s(parameters, "Scale( %i, %i, %1023s )", &dstWidth, &dstHeight, sModeStr, sizeof(sModeStr));139 #else140 sscanf(parameters, "Scale( %i, %i, %s )", &dstWidth, &dstHeight, sModeStr);141 #endif142 QString sModeQStr = QString::fromLatin1(sModeStr);143 144 t1 = srcWidth * dstHeight;145 t2 = srcHeight * dstWidth;146 147 if (((sModeQStr == QLatin1String("ScaleMin")) && (t1 > t2)) || ((sModeQStr == QLatin1String("ScaleMax")) && (t2 < t2))) {148 dstHeight = t2 / srcWidth;149 } else if (sModeQStr != QLatin1String("ScaleFree")) {150 dstWidth = t1 / srcHeight;151 }152 153 126 d->setup(srcWidth, srcHeight, dstWidth, dstHeight, 0); 154 127 } … … 163 136 newrows = dstHeight; 164 137 hasAlpha = hasAlphaChannel; 165 }166 167 int QImageSmoothScaler::scaledWidth() const168 {169 return d->cols;170 138 } 171 139 … … 197 165 QImage QImageSmoothScaler::scale() 198 166 { 199 long SCALE;200 long HALFSCALE;201 QRgb *xelrow = 0;202 QRgb *tempxelrow = 0;203 QRgb *xP;204 QRgb *nxP;205 int row, rowsread;206 int col, needtoreadrow;207 uchar maxval = 255;208 qreal xscale, yscale;209 long sxscale, syscale;210 long fracrowtofill, fracrowleft;211 long *as;212 long *rs;213 long *gs;214 long *bs;215 int rowswritten = 0;216 QImage dst;167 long SCALE; 168 long HALFSCALE; 169 QRgb *xelrow = 0; 170 QRgb *tempxelrow = 0; 171 QRgb *xP; 172 QRgb *nxP; 173 int row, rowsread; 174 int col, needtoreadrow; 175 uchar maxval = 255; 176 qreal xscale, yscale; 177 long sxscale, syscale; 178 long fracrowtofill, fracrowleft; 179 long *as; 180 long *rs; 181 long *gs; 182 long *bs; 183 int rowswritten = 0; 184 QImage dst; 217 185 218 186 if (d->cols > 4096) { 219 SCALE = 4096;220 HALFSCALE = 2048;187 SCALE = 4096; 188 HALFSCALE = 2048; 221 189 } else { 222 int fac = 4096; 223 while (d->cols * fac > 4096) { 224 fac /= 2; 225 } 226 227 SCALE = fac * d->cols; 228 HALFSCALE = fac * d->cols / 2; 229 } 230 231 xscale = (qreal) d->newcols / (qreal) d->cols; 232 yscale = (qreal) d->newrows / (qreal) d->rows; 190 int fac = 4096; 191 while (d->cols * fac > 4096) 192 fac /= 2; 193 194 SCALE = fac * d->cols; 195 HALFSCALE = fac * d->cols / 2; 196 } 197 198 xscale = (qreal)d->newcols / (qreal)d->cols; 199 yscale = (qreal)d->newrows / (qreal)d->rows; 233 200 sxscale = (long)(xscale * SCALE); 234 201 syscale = (long)(yscale * SCALE); 235 202 236 if ( d->newrows != d->rows ) /* shortcut Y scaling if possible */ 237 tempxelrow = new QRgb[d->cols]; 238 239 if ( d->hasAlpha ) { 240 as = new long[d->cols]; 241 for ( col = 0; col < d->cols; ++col ) 242 as[col] = HALFSCALE; 203 // shortcut Y scaling if possible 204 if (d->newrows != d->rows) 205 tempxelrow = new QRgb[d->cols]; 206 207 if (d->hasAlpha) { 208 as = new long[d->cols]; 209 for (col = 0; col < d->cols; ++col) 210 as[col] = HALFSCALE; 243 211 } else { 244 as = 0;212 as = 0; 245 213 } 246 214 rs = new long[d->cols]; … … 250 218 fracrowleft = syscale; 251 219 needtoreadrow = 1; 252 for ( col = 0; col < d->cols; ++col)253 rs[col] = gs[col] = bs[col] = HALFSCALE;220 for (col = 0; col < d->cols; ++col) 221 rs[col] = gs[col] = bs[col] = HALFSCALE; 254 222 fracrowtofill = SCALE; 255 223 256 dst = QImage( d->newcols, d->newrows, d->hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32 ); 257 258 for ( row = 0; row < d->newrows; ++row ) { 259 /* First scale Y from xelrow into tempxelrow. */ 260 if ( d->newrows == d->rows ) { 261 /* shortcut Y scaling if possible */ 262 tempxelrow = xelrow = scanLine(rowsread++, d->src); 263 } else { 264 while ( fracrowleft < fracrowtofill ) { 265 if ( needtoreadrow && rowsread < d->rows ) { 266 xelrow = scanLine(rowsread++, d->src); 267 } 268 for ( col = 0, xP = xelrow; col < d->cols; ++col, ++xP ) { 269 if (as) { 270 as[col] += fracrowleft * qAlpha( *xP ); 271 rs[col] += fracrowleft * qRed( *xP ) * qAlpha( *xP ) / 255; 272 gs[col] += fracrowleft * qGreen( *xP ) * qAlpha( *xP ) / 255; 273 bs[col] += fracrowleft * qBlue( *xP ) * qAlpha( *xP ) / 255; 274 } else { 275 rs[col] += fracrowleft * qRed( *xP ); 276 gs[col] += fracrowleft * qGreen( *xP ); 277 bs[col] += fracrowleft * qBlue( *xP ); 278 } 279 } 280 fracrowtofill -= fracrowleft; 281 fracrowleft = syscale; 282 needtoreadrow = 1; 283 } 284 /* Now fracrowleft is >= fracrowtofill, so we can produce a row. */ 285 if ( needtoreadrow && rowsread < d->rows) { 286 xelrow = scanLine(rowsread++, d->src); 287 needtoreadrow = 0; 288 } 289 for ( col = 0, xP = xelrow, nxP = tempxelrow; 290 col < d->cols; ++col, ++xP, ++nxP ) 291 { 292 register long a, r, g, b; 293 294 if ( as ) { 295 r = rs[col] + fracrowtofill * qRed( *xP ) * qAlpha( *xP ) / 255; 296 g = gs[col] + fracrowtofill * qGreen( *xP ) * qAlpha( *xP ) / 255; 297 b = bs[col] + fracrowtofill * qBlue( *xP ) * qAlpha( *xP ) / 255; 298 a = as[col] + fracrowtofill * qAlpha( *xP ); 299 if ( a ) { 300 r = r * 255 / a * SCALE; 301 g = g * 255 / a * SCALE; 302 b = b * 255 / a * SCALE; 303 } 304 } else { 305 r = rs[col] + fracrowtofill * qRed( *xP ); 306 g = gs[col] + fracrowtofill * qGreen( *xP ); 307 b = bs[col] + fracrowtofill * qBlue( *xP ); 308 a = 0; // unwarn 309 } 310 r /= SCALE; 311 if ( r > maxval ) r = maxval; 312 g /= SCALE; 313 if ( g > maxval ) g = maxval; 314 b /= SCALE; 315 if ( b > maxval ) b = maxval; 316 if ( as ) { 317 a /= SCALE; 318 if ( a > maxval ) a = maxval; 319 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a ); 320 as[col] = HALFSCALE; 321 } else { 322 *nxP = qRgb( (int)r, (int)g, (int)b ); 323 } 324 rs[col] = gs[col] = bs[col] = HALFSCALE; 325 } 326 fracrowleft -= fracrowtofill; 327 if ( fracrowleft == 0 ) { 328 fracrowleft = syscale; 329 needtoreadrow = 1; 330 } 331 fracrowtofill = SCALE; 332 } 333 334 /* Now scale X from tempxelrow into dst and write it out. */ 335 if ( d->newcols == d->cols ) { 336 /* shortcut X scaling if possible */ 337 memcpy(dst.scanLine(rowswritten++), tempxelrow, d->newcols*4); 338 } else { 339 register long a, r, g, b; 340 register long fraccoltofill, fraccolleft = 0; 341 register int needcol; 342 343 nxP = (QRgb*)dst.scanLine(rowswritten++); 344 fraccoltofill = SCALE; 345 a = r = g = b = HALFSCALE; 346 needcol = 0; 347 for ( col = 0, xP = tempxelrow; col < d->cols; ++col, ++xP ) { 348 fraccolleft = sxscale; 349 while ( fraccolleft >= fraccoltofill ) { 350 if ( needcol ) { 351 ++nxP; 352 a = r = g = b = HALFSCALE; 353 } 354 if ( as ) { 355 r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255; 356 g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255; 357 b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255; 358 a += fraccoltofill * qAlpha( *xP ); 359 if ( a ) { 360 r = r * 255 / a * SCALE; 361 g = g * 255 / a * SCALE; 362 b = b * 255 / a * SCALE; 363 } 364 } else { 365 r += fraccoltofill * qRed( *xP ); 366 g += fraccoltofill * qGreen( *xP ); 367 b += fraccoltofill * qBlue( *xP ); 368 } 369 r /= SCALE; 370 if ( r > maxval ) r = maxval; 371 g /= SCALE; 372 if ( g > maxval ) g = maxval; 373 b /= SCALE; 374 if ( b > maxval ) b = maxval; 375 if (as) { 376 a /= SCALE; 377 if ( a > maxval ) a = maxval; 378 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a ); 379 } else { 380 *nxP = qRgb( (int)r, (int)g, (int)b ); 381 } 382 fraccolleft -= fraccoltofill; 383 fraccoltofill = SCALE; 384 needcol = 1; 385 } 386 if ( fraccolleft > 0 ) { 387 if ( needcol ) { 388 ++nxP; 389 a = r = g = b = HALFSCALE; 390 needcol = 0; 391 } 392 if (as) { 393 a += fraccolleft * qAlpha( *xP ); 394 r += fraccolleft * qRed( *xP ) * qAlpha( *xP ) / 255; 395 g += fraccolleft * qGreen( *xP ) * qAlpha( *xP ) / 255; 396 b += fraccolleft * qBlue( *xP ) * qAlpha( *xP ) / 255; 397 } else { 398 r += fraccolleft * qRed( *xP ); 399 g += fraccolleft * qGreen( *xP ); 400 b += fraccolleft * qBlue( *xP ); 401 } 402 fraccoltofill -= fraccolleft; 403 } 404 } 405 if ( fraccoltofill > 0 ) { 406 --xP; 407 if (as) { 408 a += fraccolleft * qAlpha( *xP ); 409 r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255; 410 g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255; 411 b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255; 412 if ( a ) { 413 r = r * 255 / a * SCALE; 414 g = g * 255 / a * SCALE; 415 b = b * 255 / a * SCALE; 416 } 417 } else { 418 r += fraccoltofill * qRed( *xP ); 419 g += fraccoltofill * qGreen( *xP ); 420 b += fraccoltofill * qBlue( *xP ); 421 } 422 } 423 if ( ! needcol ) { 424 r /= SCALE; 425 if ( r > maxval ) r = maxval; 426 g /= SCALE; 427 if ( g > maxval ) g = maxval; 428 b /= SCALE; 429 if ( b > maxval ) b = maxval; 430 if (as) { 431 a /= SCALE; 432 if ( a > maxval ) a = maxval; 433 *nxP = qRgba( (int)r, (int)g, (int)b, (int)a ); 434 } else { 435 *nxP = qRgb( (int)r, (int)g, (int)b ); 436 } 437 } 438 } 439 } 440 441 if ( d->newrows != d->rows && tempxelrow )// Robust, tempxelrow might be 0 1 day 442 delete [] tempxelrow; 443 if ( as ) // Avoid purify complaint 444 delete [] as; 445 if ( rs ) // Robust, rs might be 0 one day 446 delete [] rs; 447 if ( gs ) // Robust, gs might be 0 one day 448 delete [] gs; 449 if ( bs ) // Robust, bs might be 0 one day 450 delete [] bs; 224 dst = QImage(d->newcols, d->newrows, d->hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); 225 226 for (row = 0; row < d->newrows; ++row) { 227 // First scale Y from xelrow into tempxelrow. 228 if (d->newrows == d->rows) { 229 // shortcut Y scaling if possible 230 tempxelrow = xelrow = scanLine(rowsread++, d->src); 231 } else { 232 while (fracrowleft < fracrowtofill) { 233 if (needtoreadrow && rowsread < d->rows) 234 xelrow = scanLine(rowsread++, d->src); 235 for (col = 0, xP = xelrow; col < d->cols; ++col, ++xP) { 236 if (as) { 237 as[col] += fracrowleft * qAlpha(*xP); 238 rs[col] += fracrowleft * qRed(*xP) * qAlpha(*xP) / 255; 239 gs[col] += fracrowleft * qGreen(*xP) * qAlpha(*xP) / 255; 240 bs[col] += fracrowleft * qBlue(*xP) * qAlpha(*xP) / 255; 241 } else { 242 rs[col] += fracrowleft * qRed(*xP); 243 gs[col] += fracrowleft * qGreen(*xP); 244 bs[col] += fracrowleft * qBlue(*xP); 245 } 246 } 247 fracrowtofill -= fracrowleft; 248 fracrowleft = syscale; 249 needtoreadrow = 1; 250 } 251 // Now fracrowleft is >= fracrowtofill, so we can produce a row. 252 if (needtoreadrow && rowsread < d->rows) { 253 xelrow = scanLine(rowsread++, d->src); 254 needtoreadrow = 0; 255 } 256 for (col = 0, xP = xelrow, nxP = tempxelrow; col < d->cols; ++col, ++xP, ++nxP) { 257 register long a, r, g, b; 258 259 if (as) { 260 r = rs[col] + fracrowtofill * qRed(*xP) * qAlpha(*xP) / 255; 261 g = gs[col] + fracrowtofill * qGreen(*xP) * qAlpha(*xP) / 255; 262 b = bs[col] + fracrowtofill * qBlue(*xP) * qAlpha(*xP) / 255; 263 a = as[col] + fracrowtofill * qAlpha(*xP); 264 if (a) { 265 r = r * 255 / a * SCALE; 266 g = g * 255 / a * SCALE; 267 b = b * 255 / a * SCALE; 268 } 269 } else { 270 r = rs[col] + fracrowtofill * qRed(*xP); 271 g = gs[col] + fracrowtofill * qGreen(*xP); 272 b = bs[col] + fracrowtofill * qBlue(*xP); 273 a = 0; // unwarn 274 } 275 r /= SCALE; 276 if (r > maxval) 277 r = maxval; 278 g /= SCALE; 279 if (g > maxval) 280 g = maxval; 281 b /= SCALE; 282 if (b > maxval) 283 b = maxval; 284 if (as) { 285 a /= SCALE; 286 if (a > maxval) 287 a = maxval; 288 *nxP = qRgba((int)r, (int)g, (int)b, (int)a); 289 as[col] = HALFSCALE; 290 } else { 291 *nxP = qRgb((int)r, (int)g, (int)b); 292 } 293 rs[col] = gs[col] = bs[col] = HALFSCALE; 294 } 295 fracrowleft -= fracrowtofill; 296 if (fracrowleft == 0) { 297 fracrowleft = syscale; 298 needtoreadrow = 1; 299 } 300 fracrowtofill = SCALE; 301 } 302 303 // Now scale X from tempxelrow into dst and write it out. 304 if (d->newcols == d->cols) { 305 // shortcut X scaling if possible 306 memcpy(dst.scanLine(rowswritten++), tempxelrow, d->newcols * 4); 307 } else { 308 register long a, r, g, b; 309 register long fraccoltofill, fraccolleft = 0; 310 register int needcol; 311 312 nxP = (QRgb *)dst.scanLine(rowswritten++); 313 QRgb *nxPEnd = nxP + d->newcols; 314 fraccoltofill = SCALE; 315 a = r = g = b = HALFSCALE; 316 needcol = 0; 317 for (col = 0, xP = tempxelrow; col < d->cols; ++col, ++xP) { 318 fraccolleft = sxscale; 319 while (fraccolleft >= fraccoltofill) { 320 if (needcol) { 321 ++nxP; 322 a = r = g = b = HALFSCALE; 323 } 324 if (as) { 325 r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255; 326 g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255; 327 b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255; 328 a += fraccoltofill * qAlpha(*xP); 329 if (a) { 330 r = r * 255 / a * SCALE; 331 g = g * 255 / a * SCALE; 332 b = b * 255 / a * SCALE; 333 } 334 } else { 335 r += fraccoltofill * qRed(*xP); 336 g += fraccoltofill * qGreen(*xP); 337 b += fraccoltofill * qBlue(*xP); 338 } 339 r /= SCALE; 340 if (r > maxval) 341 r = maxval; 342 g /= SCALE; 343 if (g > maxval) 344 g = maxval; 345 b /= SCALE; 346 if (b > maxval) 347 b = maxval; 348 if (as) { 349 a /= SCALE; 350 if (a > maxval) 351 a = maxval; 352 *nxP = qRgba((int)r, (int)g, (int)b, (int)a); 353 } else { 354 *nxP = qRgb((int)r, (int)g, (int)b); 355 } 356 fraccolleft -= fraccoltofill; 357 fraccoltofill = SCALE; 358 needcol = 1; 359 } 360 if (fraccolleft > 0) { 361 if (needcol) { 362 ++nxP; 363 a = r = g = b = HALFSCALE; 364 needcol = 0; 365 } 366 if (as) { 367 a += fraccolleft * qAlpha(*xP); 368 r += fraccolleft * qRed(*xP) * qAlpha(*xP) / 255; 369 g += fraccolleft * qGreen(*xP) * qAlpha(*xP) / 255; 370 b += fraccolleft * qBlue(*xP) * qAlpha(*xP) / 255; 371 } else { 372 r += fraccolleft * qRed(*xP); 373 g += fraccolleft * qGreen(*xP); 374 b += fraccolleft * qBlue(*xP); 375 } 376 fraccoltofill -= fraccolleft; 377 } 378 } 379 if (fraccoltofill > 0) { 380 --xP; 381 if (as) { 382 a += fraccolleft * qAlpha(*xP); 383 r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255; 384 g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255; 385 b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255; 386 if (a) { 387 r = r * 255 / a * SCALE; 388 g = g * 255 / a * SCALE; 389 b = b * 255 / a * SCALE; 390 } 391 } else { 392 r += fraccoltofill * qRed(*xP); 393 g += fraccoltofill * qGreen(*xP); 394 b += fraccoltofill * qBlue(*xP); 395 } 396 } 397 if (nxP < nxPEnd) { 398 r /= SCALE; 399 if (r > maxval) 400 r = maxval; 401 g /= SCALE; 402 if (g > maxval) 403 g = maxval; 404 b /= SCALE; 405 if (b > maxval) 406 b = maxval; 407 if (as) { 408 a /= SCALE; 409 if (a > maxval) 410 a = maxval; 411 *nxP = qRgba((int)r, (int)g, (int)b, (int)a); 412 } else { 413 *nxP = qRgb((int)r, (int)g, (int)b); 414 } 415 while (++nxP != nxPEnd) 416 nxP[0] = nxP[-1]; 417 } 418 } 419 } 420 421 if (d->newrows != d->rows && tempxelrow)// Robust, tempxelrow might be 0 1 day 422 delete [] tempxelrow; 423 if (as) // Avoid purify complaint 424 delete [] as; 425 if (rs) // Robust, rs might be 0 one day 426 delete [] rs; 427 if (gs) // Robust, gs might be 0 one day 428 delete [] gs; 429 if (bs) // Robust, bs might be 0 one day 430 delete [] bs; 451 431 452 432 return dst; … … 456 436 { 457 437 public: 458 jpegSmoothScaler(struct jpeg_decompress_struct *info, const char *params): 459 QImageSmoothScaler(info->output_width, info->output_height, params) 438 jpegSmoothScaler(struct jpeg_decompress_struct *info, const QSize& dstSize, const QRect& clipRect) 439 : QImageSmoothScaler(clipRect.width(), clipRect.height(), 440 dstSize.width(), dstSize.height()) 460 441 { 461 cinfo = info; 462 cols24Bit = scaledWidth() * 3; 463 464 cacheHeight = 1; 465 imageCache = QImage( info->output_width, cacheHeight, QImage::Format_RGB32 ); 442 cinfo = info; 443 clip = clipRect; 444 imageCache = QImage(info->output_width, 1, QImage::Format_RGB32); 466 445 } 467 446 468 447 private: 469 int cols24Bit;448 QRect clip; 470 449 QImage imageCache; 471 int cacheHeight;472 450 struct jpeg_decompress_struct *cinfo; 473 451 … … 481 459 482 460 uchar* data = imageCache.bits(); 461 462 // Read ahead if we haven't reached the first clipped scanline yet. 463 while (int(cinfo->output_scanline) < clip.y() && 464 cinfo->output_scanline < cinfo->output_height) 465 jpeg_read_scanlines(cinfo, &data, 1); 466 467 // Read the next scanline. We assume that "line" 468 // will never be >= clip.height(). 483 469 jpeg_read_scanlines(cinfo, &data, 1); 484 out = (QRgb*)imageCache.scanLine(0); 470 if (cinfo->output_scanline == cinfo->output_height) 471 jpeg_finish_decompress(cinfo); 472 473 out = ((QRgb*)data) + clip.x(); 485 474 486 475 // … … 489 478 // 490 479 if (cinfo->output_components == 1) { 491 in = (uchar*)out + scaledWidth(); 492 for (uint i = scaledWidth(); i--; ) { 480 in = data + clip.right(); 481 for (int i = clip.width(); i--; ) { 482 out[i] = qRgb(*in, *in, *in); 493 483 in--; 494 out[i] = qRgb(*in, *in, *in);495 484 } 496 } else { 497 in = (uchar*)out + cols24Bit; 498 for (uint i = scaledWidth(); i--; ) { 485 } else if (cinfo->out_color_space == JCS_CMYK) { 486 in = data + clip.right() * 4; 487 for (int i = clip.width(); i--; ) { 488 int k = in[3]; 489 out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255); 490 in -= 4; 491 } 492 } else { 493 in = data + clip.right() * 3; 494 for (int i = clip.width(); i--; ) { 495 out[i] = qRgb(in[0], in[1], in[2]); 499 496 in -= 3; 500 out[i] = qRgb(in[0], in[1], in[2]);501 497 } 502 498 } … … 616 612 } 617 613 618 619 static void scaleSize(int &reqW, int &reqH, int imgW, int imgH, Qt::AspectRatioMode mode)620 {621 if (mode == Qt::IgnoreAspectRatio)622 return;623 int t1 = imgW * reqH;624 int t2 = reqW * imgH;625 if ((mode == Qt::KeepAspectRatio && (t1 > t2)) || (mode == Qt::KeepAspectRatioByExpanding && (t1 < t2)))626 reqH = t2 / imgW;627 else628 reqW = t1 / imgH;629 }630 614 631 615 static bool read_jpeg_size(QIODevice *device, int &w, int &h) … … 709 693 710 694 static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, 711 bool dummy = false)695 const QSize& size) 712 696 { 713 697 QImage::Format format; … … 724 708 } 725 709 726 const QSize size(info->output_width, info->output_height);727 710 if (dest->size() != size || dest->format() != format) { 728 static uchar dummyImage[1]; 729 if (dummy) // Create QImage but don't read the pixels 730 *dest = QImage(dummyImage, size.width(), size.height(), format); 731 else 732 *dest = QImage(size, format); 711 *dest = QImage(size, format); 733 712 734 713 if (format == QImage::Format_Indexed8) { 735 dest->set NumColors(256);714 dest->setColorCount(256); 736 715 for (int i = 0; i < 256; i++) 737 716 dest->setColor(i, qRgb(i,i,i)); … … 743 722 744 723 static bool read_jpeg_image(QIODevice *device, QImage *outImage, 745 const QByteArray ¶meters, QSize scaledSize, 746 int inQuality ) 747 { 748 #ifdef QT_NO_IMAGE_SMOOTHSCALE 749 Q_UNUSED( scaledSize ); 750 #endif 751 724 QSize scaledSize, QRect scaledClipRect, 725 QRect clipRect, int inQuality ) 726 { 752 727 struct jpeg_decompress_struct cinfo; 753 728 … … 774 749 quality = 75; 775 750 776 QString params = QString::fromLatin1(parameters); 777 params.simplified(); 778 int sWidth = 0, sHeight = 0; 779 char sModeStr[1024] = ""; 780 Qt::AspectRatioMode sMode; 781 782 #ifndef QT_NO_IMAGE_SMOOTHSCALE 783 // If high quality not required, shrink image during decompression 784 if (scaledSize.isValid() && quality < HIGH_QUALITY_THRESHOLD && !params.contains(QLatin1String("GetHeaderInformation")) ) { 785 cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(), 786 cinfo.image_width / scaledSize.height()); 751 // If possible, merge the scaledClipRect into either scaledSize 752 // or clipRect to avoid doing a separate scaled clipping pass. 753 // Best results are achieved by clipping before scaling, not after. 754 if (!scaledClipRect.isEmpty()) { 755 if (scaledSize.isEmpty() && clipRect.isEmpty()) { 756 // No clipping or scaling before final clip. 757 clipRect = scaledClipRect; 758 scaledClipRect = QRect(); 759 } else if (scaledSize.isEmpty()) { 760 // Clipping, but no scaling: combine the clip regions. 761 scaledClipRect.translate(clipRect.topLeft()); 762 clipRect = scaledClipRect.intersected(clipRect); 763 scaledClipRect = QRect(); 764 } else if (clipRect.isEmpty()) { 765 // No clipping, but scaling: if we can map back to an 766 // integer pixel boundary, then clip before scaling. 767 if ((cinfo.image_width % scaledSize.width()) == 0 && 768 (cinfo.image_height % scaledSize.height()) == 0) { 769 int x = scaledClipRect.x() * cinfo.image_width / 770 scaledSize.width(); 771 int y = scaledClipRect.y() * cinfo.image_height / 772 scaledSize.height(); 773 int width = (scaledClipRect.right() + 1) * 774 cinfo.image_width / scaledSize.width() - x; 775 int height = (scaledClipRect.bottom() + 1) * 776 cinfo.image_height / scaledSize.height() - y; 777 clipRect = QRect(x, y, width, height); 778 scaledSize = scaledClipRect.size(); 779 scaledClipRect = QRect(); 780 } 781 } else { 782 // Clipping and scaling: too difficult to figure out, 783 // and not a likely use case, so do it the long way. 784 } 785 } 786 787 // Determine the scale factor to pass to libjpeg for quick downscaling. 788 if (!scaledSize.isEmpty()) { 789 if (clipRect.isEmpty()) { 790 cinfo.scale_denom = 791 qMin(cinfo.image_width / scaledSize.width(), 792 cinfo.image_height / scaledSize.height()); 793 } else { 794 cinfo.scale_denom = 795 qMin(clipRect.width() / scaledSize.width(), 796 clipRect.height() / scaledSize.height()); 797 } 787 798 if (cinfo.scale_denom < 2) { 788 799 cinfo.scale_denom = 1; … … 795 806 } 796 807 cinfo.scale_num = 1; 797 } 798 #endif 799 808 if (!clipRect.isEmpty()) { 809 // Correct the scale factor so that we clip accurately. 810 // It is recommended that the clip rectangle be aligned 811 // on an 8-pixel boundary for best performance. 812 while (cinfo.scale_denom > 1 && 813 ((clipRect.x() % cinfo.scale_denom) != 0 || 814 (clipRect.y() % cinfo.scale_denom) != 0 || 815 (clipRect.width() % cinfo.scale_denom) != 0 || 816 (clipRect.height() % cinfo.scale_denom) != 0)) { 817 cinfo.scale_denom /= 2; 818 } 819 } 820 } 800 821 801 822 // If high quality not required, use fast decompression … … 805 826 } 806 827 807 808 (void) jpeg_start_decompress(&cinfo); 809 810 if (params.contains(QLatin1String("GetHeaderInformation"))) { 811 if (!ensureValidImage(outImage, &cinfo, true)) 828 (void) jpeg_calc_output_dimensions(&cinfo); 829 830 // Determine the clip region to extract. 831 QRect imageRect(0, 0, cinfo.output_width, cinfo.output_height); 832 QRect clip; 833 if (clipRect.isEmpty()) { 834 clip = imageRect; 835 } else if (cinfo.scale_denom == 1) { 836 clip = clipRect.intersected(imageRect); 837 } else { 838 // The scale factor was corrected above to ensure that 839 // we don't miss pixels when we scale the clip rectangle. 840 clip = QRect(clipRect.x() / int(cinfo.scale_denom), 841 clipRect.y() / int(cinfo.scale_denom), 842 clipRect.width() / int(cinfo.scale_denom), 843 clipRect.height() / int(cinfo.scale_denom)); 844 clip = clip.intersected(imageRect); 845 } 846 847 #ifndef QT_NO_IMAGE_SMOOTHSCALE 848 if (scaledSize.isValid() && scaledSize != clip.size() 849 && quality >= HIGH_QUALITY_THRESHOLD) { 850 851 (void) jpeg_start_decompress(&cinfo); 852 853 jpegSmoothScaler scaler(&cinfo, scaledSize, clip); 854 *outImage = scaler.scale(); 855 } else 856 #endif 857 { 858 // Allocate memory for the clipped QImage. 859 if (!ensureValidImage(outImage, &cinfo, clip.size())) 812 860 longjmp(jerr.setjmp_buffer, 1); 813 } else if (params.contains(QLatin1String("Scale"))) { 814 #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE) 815 sscanf_s(params.toLatin1().data(), "Scale(%i, %i, %1023s)", 816 &sWidth, &sHeight, sModeStr, sizeof(sModeStr)); 817 #else 818 sscanf(params.toLatin1().data(), "Scale(%i, %i, %1023s)", 819 &sWidth, &sHeight, sModeStr); 820 #endif 821 822 QString sModeQStr(QString::fromLatin1(sModeStr)); 823 if (sModeQStr == QLatin1String("IgnoreAspectRatio")) { 824 sMode = Qt::IgnoreAspectRatio; 825 } else if (sModeQStr == QLatin1String("KeepAspectRatio")) { 826 sMode = Qt::KeepAspectRatio; 827 } else if (sModeQStr == QLatin1String("KeepAspectRatioByExpanding")) { 828 sMode = Qt::KeepAspectRatioByExpanding; 829 } else { 830 qDebug("read_jpeg_image: invalid aspect ratio mode \"%s\", see QImage::AspectRatioMode documentation", sModeStr); 831 sMode = Qt::KeepAspectRatio; 832 } 833 834 // qDebug("Parameters ask to scale the image to %i x %i AspectRatioMode: %s", sWidth, sHeight, sModeStr); 835 scaleSize(sWidth, sHeight, cinfo.output_width, cinfo.output_height, sMode); 836 // qDebug("Scaling the jpeg to %i x %i", sWidth, sHeight, sModeStr); 837 838 if (cinfo.output_components == 3 || cinfo.output_components == 4) { 839 if (outImage->size() != QSize(sWidth, sHeight) || outImage->format() != QImage::Format_RGB32) 840 *outImage = QImage(sWidth, sHeight, QImage::Format_RGB32); 841 } else if (cinfo.output_components == 1) { 842 if (outImage->size() != QSize(sWidth, sHeight) || outImage->format() != QImage::Format_Indexed8) 843 *outImage = QImage(sWidth, sHeight, QImage::Format_Indexed8); 844 outImage->setNumColors(256); 845 for (int i = 0; i < 256; ++i) 846 outImage->setColor(i, qRgb(i,i,i)); 847 } else { 848 // Unsupported format 849 } 850 if (outImage->isNull()) 851 longjmp(jerr.setjmp_buffer, 1); 852 853 if (!outImage->isNull()) { 854 QImage tmpImage(cinfo.output_width, 1, QImage::Format_RGB32); 855 uchar* inData = tmpImage.bits(); 856 uchar* outData = outImage->bits(); 857 int out_bpl = outImage->bytesPerLine(); 861 862 // Avoid memcpy() overhead if grayscale with no clipping. 863 bool quickGray = (cinfo.output_components == 1 && 864 clip == imageRect); 865 if (!quickGray) { 866 // Ask the jpeg library to allocate a temporary row. 867 // The library will automatically delete it for us later. 868 // The libjpeg docs say we should do this before calling 869 // jpeg_start_decompress(). We can't use "new" here 870 // because we are inside the setjmp() block and an error 871 // in the jpeg input stream would cause a memory leak. 872 JSAMPARRAY rows = (cinfo.mem->alloc_sarray) 873 ((j_common_ptr)&cinfo, JPOOL_IMAGE, 874 cinfo.output_width * cinfo.output_components, 1); 875 876 (void) jpeg_start_decompress(&cinfo); 877 858 878 while (cinfo.output_scanline < cinfo.output_height) { 859 int outputLine = sHeight * cinfo.output_scanline / cinfo.output_height; 860 (void) jpeg_read_scanlines(&cinfo, &inData, 1); 879 int y = int(cinfo.output_scanline) - clip.y(); 880 if (y >= clip.height()) 881 break; // We've read the entire clip region, so abort. 882 883 (void) jpeg_read_scanlines(&cinfo, rows, 1); 884 885 if (y < 0) 886 continue; // Haven't reached the starting line yet. 887 861 888 if (cinfo.output_components == 3) { 862 uchar *in = inData; 863 QRgb *out = (QRgb*)outData + outputLine * out_bpl; 864 for (uint i=0; i<cinfo.output_width; i++) { 865 // ### Only scaling down an image works, I don't think scaling up will work at the moment 866 // ### An idea I have to make this a smooth scale is to progressively add the pixel values up 867 // When scaling down, multiple values are being over drawn in to the output buffer. 868 // Instead, a weighting based on the distance the line or pixel is from the output pixel determines 869 // the weight of it when added to the output buffer. At present it is a non-smooth scale which is 870 // inefficently implemented, it still uncompresses all the jpeg, an optimization for progressive 871 // jpegs could be made if scaling by say 50% or some other special cases 872 out[sWidth * i / cinfo.output_width] = qRgb(in[0], in[1], in[2]); 889 // Expand 24->32 bpp. 890 uchar *in = rows[0] + clip.x() * 3; 891 QRgb *out = (QRgb*)outImage->scanLine(y); 892 for (int i = 0; i < clip.width(); ++i) { 893 *out++ = qRgb(in[0], in[1], in[2]); 873 894 in += 3; 874 895 } 875 } else { 876 // ### Need to test the case where the jpeg is grayscale, need some black and white jpegs to test 877 // this code. (also only scales down and probably won't scale to a larger size) 878 uchar *in = inData; 879 uchar *out = outData + outputLine*out_bpl; 880 for (uint i=0; i<cinfo.output_width; i++) { 881 out[sWidth * i / cinfo.output_width] = in[i]; 896 } else if (cinfo.out_color_space == JCS_CMYK) { 897 // Convert CMYK->RGB. 898 uchar *in = rows[0] + clip.x() * 4; 899 QRgb *out = (QRgb*)outImage->scanLine(y); 900 for (int i = 0; i < clip.width(); ++i) { 901 int k = in[3]; 902 *out++ = qRgb(k * in[0] / 255, k * in[1] / 255, 903 k * in[2] / 255); 904 in += 4; 882 905 } 906 } else if (cinfo.output_components == 1) { 907 // Grayscale. 908 memcpy(outImage->scanLine(y), 909 rows[0] + clip.x(), clip.width()); 883 910 } 884 911 } 912 } else { 913 // Load unclipped grayscale data directly into the QImage. 914 (void) jpeg_start_decompress(&cinfo); 915 while (cinfo.output_scanline < cinfo.output_height) { 916 uchar *row = outImage->scanLine(cinfo.output_scanline); 917 (void) jpeg_read_scanlines(&cinfo, &row, 1); 918 } 919 } 920 921 if (cinfo.output_scanline == cinfo.output_height) 885 922 (void) jpeg_finish_decompress(&cinfo); 886 } 887 #ifndef QT_NO_IMAGE_SMOOTHSCALE 888 } else if (scaledSize.isValid()) { 889 890 jpegSmoothScaler scaler(&cinfo, QString().sprintf("Scale( %d, %d, ScaleFree )", 891 scaledSize.width(), 892 scaledSize.height()).toLatin1().data()); 893 *outImage = scaler.scale(); 894 #endif 895 } else { 896 if (!ensureValidImage(outImage, &cinfo)) 897 longjmp(jerr.setjmp_buffer, 1); 898 899 uchar* data = outImage->bits(); 900 int bpl = outImage->bytesPerLine(); 901 while (cinfo.output_scanline < cinfo.output_height) { 902 uchar *d = data + cinfo.output_scanline * bpl; 903 (void) jpeg_read_scanlines(&cinfo, 904 &d, 905 1); 906 } 907 (void) jpeg_finish_decompress(&cinfo); 908 909 if (cinfo.output_components == 3) { 910 // Expand 24->32 bpp. 911 for (uint j=0; j<cinfo.output_height; j++) { 912 uchar *in = outImage->scanLine(j) + cinfo.output_width * 3; 913 QRgb *out = (QRgb*)outImage->scanLine(j); 914 915 for (uint i=cinfo.output_width; i--;) { 916 in-=3; 917 out[i] = qRgb(in[0], in[1], in[2]); 918 } 919 } 920 } else if (cinfo.out_color_space == JCS_CMYK) { 921 for (uint j = 0; j < cinfo.output_height; ++j) { 922 uchar *in = outImage->scanLine(j) + cinfo.output_width * 4; 923 QRgb *out = (QRgb*)outImage->scanLine(j); 924 925 for (uint i = cinfo.output_width; i--; ) { 926 in-=4; 927 int k = in[3]; 928 out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255); 929 } 930 } 931 } 923 932 924 if (cinfo.density_unit == 1) { 933 925 outImage->setDotsPerMeterX(int(100. * cinfo.X_density / 2.54)); … … 937 929 outImage->setDotsPerMeterY(int(100. * cinfo.Y_density)); 938 930 } 931 932 if (scaledSize.isValid() && scaledSize != clip.size()) 933 *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::FastTransformation); 939 934 } 940 935 } … … 942 937 jpeg_destroy_decompress(&cinfo); 943 938 delete iod_src; 939 if (!scaledClipRect.isEmpty()) 940 *outImage = outImage->copy(scaledClipRect); 944 941 return !outImage->isNull(); 945 942 } … … 1041 1038 case QImage::Format_Indexed8: 1042 1039 gray = true; 1043 for (int i = image. numColors(); gray && i--;) {1040 for (int i = image.colorCount(); gray && i--;) { 1044 1041 gray = gray & (qRed(cmap[i]) == qGreen(cmap[i]) && 1045 1042 qRed(cmap[i]) == qBlue(cmap[i])); … … 1199 1196 if (!canRead()) 1200 1197 return false; 1201 return read_jpeg_image(device(), image, parameters, scaledSize, quality);1198 return read_jpeg_image(device(), image, scaledSize, scaledClipRect, clipRect, quality); 1202 1199 } 1203 1200 … … 1210 1207 { 1211 1208 return option == Quality 1212 #ifndef QT_NO_IMAGE_SMOOTHSCALE1213 1209 || option == ScaledSize 1214 #endif 1210 || option == ScaledClipRect 1211 || option == ClipRect 1215 1212 || option == Size 1216 1213 || option == ImageFormat; … … 1221 1218 if (option == Quality) { 1222 1219 return quality; 1223 #ifndef QT_NO_IMAGE_SMOOTHSCALE1224 1220 } else if (option == ScaledSize) { 1225 1221 return scaledSize; 1226 #endif 1222 } else if (option == ScaledClipRect) { 1223 return scaledClipRect; 1224 } else if (option == ClipRect) { 1225 return clipRect; 1227 1226 } else if (option == Size) { 1228 1227 if (canRead() && !device()->isSequential()) { … … 1251 1250 if (option == Quality) 1252 1251 quality = value.toInt(); 1253 #ifndef QT_NO_IMAGE_SMOOTHSCALE1254 1252 else if ( option == ScaledSize ) 1255 1253 scaledSize = value.toSize(); 1256 #endif 1254 else if ( option == ScaledClipRect ) 1255 scaledClipRect = value.toRect(); 1256 else if ( option == ClipRect ) 1257 clipRect = value.toRect(); 1257 1258 } 1258 1259 -
trunk/src/plugins/imageformats/jpeg/qjpeghandler.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 45 45 #include <QtGui/qimageiohandler.h> 46 46 #include <QtCore/QSize> 47 #include <QtCore/QRect> 47 48 48 49 QT_BEGIN_NAMESPACE … … 67 68 private: 68 69 int quality; 69 QByteArray parameters;70 70 QSize scaledSize; 71 QRect scaledClipRect; 72 QRect clipRect; 71 73 }; 72 74 -
trunk/src/plugins/imageformats/mng/main.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/mng/mng.pro
r2 r561 7 7 SOURCES += main.cpp \ 8 8 qmnghandler.cpp 9 10 symbian: { 11 #Disable warnings in 3rdparty code due to unused variables and arguments 12 QMAKE_CXXFLAGS.CW += -W nounused 13 TARGET.UID3=0x2001E619 14 } 9 15 10 16 contains(QT_CONFIG, system-mng) { … … 48 54 target.path += $$[QT_INSTALL_PLUGINS]/imageformats 49 55 INSTALLS += target 56 -
trunk/src/plugins/imageformats/mng/qmnghandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 376 376 QMngHandler::~QMngHandler() 377 377 { 378 Q_D(QMngHandler);379 delete d;380 378 } 381 379 -
trunk/src/plugins/imageformats/mng/qmnghandler.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 43 43 #define QMNGHANDLER_H 44 44 45 #include <QtCore/qscopedpointer.h> 45 46 #include <QtGui/qimageiohandler.h> 46 47 … … 75 76 private: 76 77 Q_DECLARE_PRIVATE(QMngHandler) 77 Q MngHandlerPrivate *d_ptr;78 QScopedPointer<QMngHandlerPrivate> d_ptr; 78 79 }; 79 80 -
trunk/src/plugins/imageformats/svg/main.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/svg/qsvgiohandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 65 65 66 66 bool load(QIODevice *device); 67 static bool findSvgTag(QIODevice *device); 67 68 68 69 QSvgRenderer *r; … … 87 88 } 88 89 90 bool QSvgIOHandlerPrivate::findSvgTag(QIODevice *device) 91 { 92 qint64 pos = device->pos(); 93 device->seek(0); 94 char buffer[256]; 95 const char svg_tag[] = "<svg"; 96 97 while (1) { 98 int size = device->read(buffer, 256); 99 for (int i=0; i<size - 5; ++i) { 100 if (!memcmp(buffer + i, svg_tag, 4)) { 101 if (buffer[i+4] == ' ' || buffer[i+4] == '\t' 102 || buffer[i+4] == '\n' || buffer[i+4] == '\r') 103 { 104 device->seek(pos); 105 return true; 106 } 107 } 108 } 109 if (device->atEnd()) 110 break; 111 device->seek(device->pos()-4); 112 } 113 device->seek(pos); 114 return false; 115 } 116 89 117 QSvgIOHandler::QSvgIOHandler() 90 118 : d(new QSvgIOHandlerPrivate()) … … 102 130 bool QSvgIOHandler::canRead() const 103 131 { 104 QByteArray contents = device()->peek(80); 105 106 return contents.contains("<svg"); 132 return QSvgIOHandlerPrivate::findSvgTag(device()); 107 133 } 108 134 … … 183 209 bool QSvgIOHandler::canRead(QIODevice *device) 184 210 { 185 QByteArray contents = device->peek(80); 186 return contents.contains("<svg"); 211 return QSvgIOHandlerPrivate::findSvgTag(device); 187 212 } 188 213 -
trunk/src/plugins/imageformats/svg/qsvgiohandler.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/svg/svg.pro
r2 r561 10 10 target.path += $$[QT_INSTALL_PLUGINS]/imageformats 11 11 INSTALLS += target 12 13 symbian:TARGET.UID3=0x2001E618 -
trunk/src/plugins/imageformats/tiff/main.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/tiff/qtiffhandler.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 99 99 } 100 100 101 // for 32 bits images 102 inline 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 119 inline 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 101 138 QTiffHandler::QTiffHandler() : QImageIOHandler() 102 139 { … … 132 169 return false; 133 170 134 TIFF *tiff = TIFFClientOpen("foo", 135 "r", 136 this, 137 qtiffReadProc, 138 qtiffWriteProc, 139 qtiffSeekProc, 140 qtiffCloseProc, 141 qtiffSizeProc, 142 qtiffMapProc, 143 qtiffUnmapProc); 144 145 if (tiff) { 146 uint32 width = 0; 147 uint32 height = 0; 148 TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width); 149 TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height); 150 if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) 151 *image = QImage(width, height, QImage::Format_ARGB32); 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 152 214 if (!image->isNull()) { 153 if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, 0)) { 154 uint16 resUnit = RESUNIT_NONE; 155 float resX = 0; 156 float resY = 0; 157 TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit); 158 TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX); 159 TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY); 160 switch(resUnit) { 161 case RESUNIT_CENTIMETER: 162 image->setDotsPerMeterX(qRound(resX * 100)); 163 image->setDotsPerMeterY(qRound(resY * 100)); 164 break; 165 case RESUNIT_INCH: 166 image->setDotsPerMeterX(qRound(resX * (100 / 2.54))); 167 image->setDotsPerMeterY(qRound(resY * (100 / 2.54))); 168 break; 169 default: 170 // do nothing as defaults have already 171 // been set within the QImage class 172 break; 173 } 174 for (uint32 y=0; y<height; ++y) 175 convert32BitOrder(image->scanLine(y), width); 176 } else { 177 *image = QImage(); 178 } 179 } 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()) { 180 283 TIFFClose(tiff); 181 } 182 183 if (image->isNull()) 184 return false; 185 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); 186 378 return true; 187 379 } 188 380 381 static 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 189 395 bool QTiffHandler::write(const QImage &image) 190 396 { … … 192 398 return false; 193 399 194 TIFF *tiff = TIFFClientOpen("foo", 195 "w", 196 this, 197 qtiffReadProc, 198 qtiffWriteProc, 199 qtiffSeekProc, 200 qtiffCloseProc, 201 qtiffSizeProc, 202 qtiffMapProc, 203 qtiffUnmapProc); 204 205 if (tiff) { 206 int width = image.width(); 207 int height = image.height(); 208 int depth = 32; 209 210 if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width) 211 || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height) 212 || !TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) 213 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW) 214 || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, depth/8) 215 || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) 216 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { 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)) { 217 451 TIFFClose(tiff); 218 452 return false; 219 453 } 220 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 } 221 555 // try to do the ARGB32 conversion in chunks no greater than 16 MB 222 556 int chunks = (width * height * 4 / (1024 * 1024 * 16)) + 1; … … 243 577 } 244 578 TIFFClose(tiff); 245 } else { 246 return false; 247 } 579 } 580 248 581 return true; 249 582 } -
trunk/src/plugins/imageformats/tiff/qtiffhandler.h
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the plugins of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** -
trunk/src/plugins/imageformats/tiff/tiff.pro
r165 r561 60 60 SOURCES += ../../../corelib/kernel/qfunctions_wince.cpp 61 61 } 62 symbian*: { 63 SOURCES += ../../../3rdparty/libtiff/port/lfind.c 64 } 62 65 } 63 66 … … 72 75 target.path += $$[QT_INSTALL_PLUGINS]/imageformats 73 76 INSTALLS += target 77 78 symbian:TARGET.UID3=0x2001E617
Note:
See TracChangeset
for help on using the changeset viewer.
