Changeset 561 for trunk/src/plugins/imageformats
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 25 edited
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 61 quint8 62 quint8 63 quint8 64 quint16 65 quint16 66 quint32 67 quint32 60 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 74 quint16 75 quint16 76 ICONDIRENTRY 73 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 { 81 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 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 272 273 274 275 276 277 278 279 280 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 338 339 340 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 * 346 bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry) 348 347 { 349 348 if (iod) { 350 351 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) { 399 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 375 image = QImage(); 402 376 } 403 377 } … … 406 380 { 407 381 if (iod) { 408 image.set NumColors(icoAttrib.ncolors);409 410 411 412 413 414 415 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 392 image = QImage(); 419 393 } 420 394 } … … 422 396 void ICOReader::readBMP(QImage & image) 423 397 { 424 if (icoAttrib.nbits == 1) { 425 426 } else if (icoAttrib.nbits == 4) { 427 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 403 read8BitBMP(image); 430 404 } else if (icoAttrib.nbits == 16 || icoAttrib.nbits == 24 || icoAttrib.nbits == 32 ) { // 16,24,32 bit BMP image 431 405 read16_24_32BMP(image); 432 406 } 433 407 } … … 443 417 if (iod) { 444 418 445 446 447 448 449 450 451 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 429 image = QImage(); 456 430 } 457 431 } … … 461 435 if (iod) { 462 436 463 464 465 466 467 468 469 470 471 472 473 474 475 for (int i=0; i<icoAttrib.w/2; i++) {// convert nibbles to bytes476 477 478 479 if (icoAttrib.w & 1)// the last nibble480 481 482 483 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 460 image = QImage(); 487 461 } 488 462 } … … 492 466 if (iod) { 493 467 494 495 496 497 498 499 500 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 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 533 534 535 536 505 b += icoAttrib.nbits/8; 506 } 507 } 508 509 delete[] buf; 537 510 538 511 } else { 539 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 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 663 int 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 200 long 201 QRgb 202 QRgb 203 QRgb 204 QRgb 205 int 206 int 207 uchar 208 qreal 209 long 210 long 211 long 212 long 213 long 214 long 215 int 216 QImage 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 220 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 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 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.