diff options
Diffstat (limited to 'src/plugins/imageformats')
-rw-r--r-- | src/plugins/imageformats/gif/gif.pro | 2 | ||||
-rw-r--r-- | src/plugins/imageformats/ico/ico.pro | 2 | ||||
-rw-r--r-- | src/plugins/imageformats/ico/qicohandler.cpp | 343 | ||||
-rw-r--r-- | src/plugins/imageformats/jpeg/jpeg.pro | 7 | ||||
-rw-r--r-- | src/plugins/imageformats/jpeg/qjpeghandler.cpp | 3 | ||||
-rw-r--r-- | src/plugins/imageformats/mng/mng.pro | 7 | ||||
-rw-r--r-- | src/plugins/imageformats/mng/qmnghandler.cpp | 2 | ||||
-rw-r--r-- | src/plugins/imageformats/mng/qmnghandler.h | 3 | ||||
-rw-r--r-- | src/plugins/imageformats/svg/svg.pro | 2 | ||||
-rw-r--r-- | src/plugins/imageformats/tiff/qtiffhandler.cpp | 437 | ||||
-rw-r--r-- | src/plugins/imageformats/tiff/tiff.pro | 5 |
11 files changed, 570 insertions, 243 deletions
diff --git a/src/plugins/imageformats/gif/gif.pro b/src/plugins/imageformats/gif/gif.pro index 74586b2..8a5c51a 100644 --- a/src/plugins/imageformats/gif/gif.pro +++ b/src/plugins/imageformats/gif/gif.pro @@ -8,3 +8,5 @@ SOURCES += main.cpp \ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/imageformats target.path += $$[QT_INSTALL_PLUGINS]/imageformats INSTALLS += target + +symbian:TARGET.UID3=0x2001E61A diff --git a/src/plugins/imageformats/ico/ico.pro b/src/plugins/imageformats/ico/ico.pro index 73665cd..eadff41 100644 --- a/src/plugins/imageformats/ico/ico.pro +++ b/src/plugins/imageformats/ico/ico.pro @@ -10,3 +10,5 @@ SOURCES += main.cpp \ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/imageformats target.path += $$[QT_INSTALL_PLUGINS]/imageformats INSTALLS += target + +symbian:TARGET.UID3=0x2001E616 diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 62f7782..b509d5e 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -57,38 +57,38 @@ // in an ICO file. typedef struct { - quint8 bWidth; // Width of the image - quint8 bHeight; // Height of the image (times 2) - quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ] - quint8 bReserved; // Reserved - quint16 wPlanes; // Color Planes - quint16 wBitCount; // Bits per pixel - quint32 dwBytesInRes; // how many bytes in this resource? - quint32 dwImageOffset; // where in the file is this image + quint8 bWidth; // Width of the image + quint8 bHeight; // Height of the image (times 2) + quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ] + quint8 bReserved; // Reserved + quint16 wPlanes; // Color Planes + quint16 wBitCount; // Bits per pixel + quint32 dwBytesInRes; // how many bytes in this resource? + quint32 dwImageOffset; // where in the file is this image } ICONDIRENTRY, *LPICONDIRENTRY; #define ICONDIRENTRY_SIZE 16 typedef struct { - quint16 idReserved; // Reserved - quint16 idType; // resource type (1 for icons) - quint16 idCount; // how many images? - ICONDIRENTRY idEntries[1]; // the entries for each image + quint16 idReserved; // Reserved + quint16 idType; // resource type (1 for icons) + quint16 idCount; // how many images? + ICONDIRENTRY idEntries[1]; // the entries for each image } ICONDIR, *LPICONDIR; #define ICONDIR_SIZE 6 // Exclude the idEntries field -typedef struct { // BMP information header - quint32 biSize; // size of this struct - quint32 biWidth; // pixmap width - quint32 biHeight; // pixmap height - quint16 biPlanes; // should be 1 - quint16 biBitCount; // number of bits per pixel - quint32 biCompression; // compression method - quint32 biSizeImage; // size of image - quint32 biXPelsPerMeter; // horizontal resolution - quint32 biYPelsPerMeter; // vertical resolution - quint32 biClrUsed; // number of colors used - quint32 biClrImportant; // number of important colors +typedef struct { // BMP information header + quint32 biSize; // size of this struct + quint32 biWidth; // pixmap width + quint32 biHeight; // pixmap height (specifies the combined height of the XOR and AND masks) + quint16 biPlanes; // should be 1 + quint16 biBitCount; // number of bits per pixel + quint32 biCompression; // compression method + quint32 biSizeImage; // size of image + quint32 biXPelsPerMeter; // horizontal resolution + quint32 biYPelsPerMeter; // vertical resolution + quint32 biClrUsed; // number of colors used + quint32 biClrImportant; // number of important colors } BMP_INFOHDR ,*LPBMP_INFOHDR; #define BMP_INFOHDR_SIZE 40 @@ -108,7 +108,7 @@ private: bool readHeader(); bool readIconEntry(int index, ICONDIRENTRY * iconEntry); - bool readBMPHeader(ICONDIRENTRY & iconEntry, BMP_INFOHDR * header); + bool readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header); void findColorInfo(QImage & image); void readColorTable(QImage & image); @@ -254,7 +254,7 @@ ICOReader::ICOReader(QIODevice * iodevice) int ICOReader::count() { if (readHeader()) - return iconDir.idCount; + return iconDir.idCount; return 0; } @@ -268,17 +268,17 @@ bool ICOReader::canRead(QIODevice *iodev) if (readIconDir(iodev, &ikonDir)) { qint64 readBytes = ICONDIR_SIZE; if (readIconDirEntry(iodev, &ikonDir.idEntries[0])) { - readBytes += ICONDIRENTRY_SIZE; - // ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file. - if ( ikonDir.idReserved == 0 - && ikonDir.idType == 1 - && ikonDir.idEntries[0].bReserved == 0 - && ikonDir.idEntries[0].wPlanes <= 1 - && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel - && ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40 - ) { - isProbablyICO = true; - } + readBytes += ICONDIRENTRY_SIZE; + // ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file. + if ( ikonDir.idReserved == 0 + && ikonDir.idType == 1 + && ikonDir.idEntries[0].bReserved == 0 + && ikonDir.idEntries[0].wPlanes <= 1 + && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel + && ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40 + ) { + isProbablyICO = true; + } if (iodev->isSequential()) { // Our structs might be padded due to alignment, so we need to fetch each member before we ungetChar() ! @@ -323,8 +323,7 @@ bool ICOReader::canRead(QIODevice *iodev) iodev->ungetChar((tmp >> 8) & 0xff); iodev->ungetChar(tmp & 0xff); } - - } + } if (!iodev->isSequential()) iodev->seek(oldPos); } @@ -334,21 +333,21 @@ bool ICOReader::canRead(QIODevice *iodev) bool ICOReader::readHeader() { if (iod && !headerRead) { - startpos = iod->pos(); - if (readIconDir(iod, &iconDir)) { - if (iconDir.idReserved == 0 || iconDir.idType == 1) - headerRead = true; - } + startpos = iod->pos(); + if (readIconDir(iod, &iconDir)) { + if (iconDir.idReserved == 0 || iconDir.idType == 1) + headerRead = true; + } } return headerRead; } -bool ICOReader::readIconEntry(int index, ICONDIRENTRY * iconEntry) +bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry) { if (iod) { - if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) { - return readIconDirEntry(iod, iconEntry); + if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) { + return readIconDirEntry(iod, iconEntry); } } return false; @@ -356,49 +355,24 @@ bool ICOReader::readIconEntry(int index, ICONDIRENTRY * iconEntry) -bool ICOReader::readBMPHeader(ICONDIRENTRY & iconEntry, BMP_INFOHDR * header) +bool ICOReader::readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header) { - memset(&icoAttrib, 0, sizeof(IcoAttrib)); if (iod) { - if (iod->seek(startpos + iconEntry.dwImageOffset)) { - if (readBMPInfoHeader(iod, header)) { - - icoAttrib.nbits = header->biBitCount ? header->biBitCount : iconEntry.wBitCount; - icoAttrib.h = header->biHeight / 2; // this height is always double the iconEntry height (for the mask) - icoAttrib.w = header->biWidth; - - switch (icoAttrib.nbits) { - case 32: - case 24: - case 16: - icoAttrib.depth = 32; - break; - case 8: - case 4: - icoAttrib.depth = 8; - break; - default: - icoAttrib.depth = 1; - } - - if ( icoAttrib.depth == 32 ) // there's no colormap - icoAttrib.ncolors = 0; - else // # colors used - icoAttrib.ncolors = header->biClrUsed ? header->biClrUsed : 1 << icoAttrib.nbits; - //qDebug() << "Bits:" << icoAttrib.nbits << "Depth:" << icoAttrib.depth << "Ncols:" << icoAttrib.ncolors; - return TRUE; - } - } + if (iod->seek(startpos + imageOffset)) { + if (readBMPInfoHeader(iod, header)) { + return TRUE; + } + } } return FALSE; } void ICOReader::findColorInfo(QImage & image) { - if (icoAttrib.ncolors > 0) { // set color table - readColorTable(image); + if (icoAttrib.ncolors > 0) { // set color table + readColorTable(image); } else if (icoAttrib.nbits == 16) { // don't support RGB values for 15/16 bpp - image = QImage(); + image = QImage(); } } @@ -406,29 +380,29 @@ void ICOReader::readColorTable(QImage & image) { if (iod) { image.setNumColors(icoAttrib.ncolors); - uchar rgb[4]; - for (int i=0; i<icoAttrib.ncolors; i++) { - if (iod->read((char*)rgb, 4) != 4) { - image = QImage(); - break; - } - image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0])); - } + uchar rgb[4]; + for (int i=0; i<icoAttrib.ncolors; i++) { + if (iod->read((char*)rgb, 4) != 4) { + image = QImage(); + break; + } + image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0])); + } } else { - image = QImage(); + image = QImage(); } } void ICOReader::readBMP(QImage & image) { - if (icoAttrib.nbits == 1) { // 1 bit BMP image - read1BitBMP(image); - } else if (icoAttrib.nbits == 4) { // 4 bit BMP image - read4BitBMP(image); + if (icoAttrib.nbits == 1) { // 1 bit BMP image + read1BitBMP(image); + } else if (icoAttrib.nbits == 4) { // 4 bit BMP image + read4BitBMP(image); } else if (icoAttrib.nbits == 8) { - read8BitBMP(image); + read8BitBMP(image); } else if (icoAttrib.nbits == 16 || icoAttrib.nbits == 24 || icoAttrib.nbits == 32 ) { // 16,24,32 bit BMP image - read16_24_32BMP(image); + read16_24_32BMP(image); } } @@ -442,17 +416,17 @@ void ICOReader::read1BitBMP(QImage & image) { if (iod) { - int h = image.height(); - int bpl = image.bytesPerLine(); + int h = image.height(); + int bpl = image.bytesPerLine(); - while (--h >= 0) { - if (iod->read((char*)image.scanLine(h),bpl) != bpl) { - image = QImage(); - break; - } - } + while (--h >= 0) { + if (iod->read((char*)image.scanLine(h),bpl) != bpl) { + image = QImage(); + break; + } + } } else { - image = QImage(); + image = QImage(); } } @@ -460,30 +434,30 @@ void ICOReader::read4BitBMP(QImage & image) { if (iod) { - int h = icoAttrib.h; - int buflen = ((icoAttrib.w+7)/8)*4; - uchar *buf = new uchar[buflen]; - Q_CHECK_PTR(buf); - - while (--h >= 0) { - if (iod->read((char*)buf,buflen) != buflen) { - image = QImage(); - break; - } - register uchar *p = image.scanLine(h); - uchar *b = buf; - for (int i=0; i<icoAttrib.w/2; i++) { // convert nibbles to bytes - *p++ = *b >> 4; - *p++ = *b++ & 0x0f; - } - if (icoAttrib.w & 1) // the last nibble - *p = *b >> 4; - } - - delete [] buf; + int h = icoAttrib.h; + int buflen = ((icoAttrib.w+7)/8)*4; + uchar *buf = new uchar[buflen]; + Q_CHECK_PTR(buf); + + while (--h >= 0) { + if (iod->read((char*)buf,buflen) != buflen) { + image = QImage(); + break; + } + register uchar *p = image.scanLine(h); + uchar *b = buf; + for (int i=0; i<icoAttrib.w/2; i++) { // convert nibbles to bytes + *p++ = *b >> 4; + *p++ = *b++ & 0x0f; + } + if (icoAttrib.w & 1) // the last nibble + *p = *b >> 4; + } + + delete [] buf; } else { - image = QImage(); + image = QImage(); } } @@ -491,52 +465,51 @@ void ICOReader::read8BitBMP(QImage & image) { if (iod) { - int h = icoAttrib.h; - int bpl = image.bytesPerLine(); + int h = icoAttrib.h; + int bpl = image.bytesPerLine(); - while (--h >= 0) { - if (iod->read((char *)image.scanLine(h), bpl) != bpl) { - image = QImage(); - break; - } - } + while (--h >= 0) { + if (iod->read((char *)image.scanLine(h), bpl) != bpl) { + image = QImage(); + break; + } + } } else { - image = QImage(); + image = QImage(); } } void ICOReader::read16_24_32BMP(QImage & image) { if (iod) { - - int h = icoAttrib.h; - register QRgb *p; - QRgb *end; - uchar *buf = new uchar[image.bytesPerLine()]; - int bpl = ((icoAttrib.w*icoAttrib.nbits+31)/32)*4; - uchar *b; - - while (--h >= 0) { - p = (QRgb *)image.scanLine(h); - end = p + icoAttrib.w; - if (iod->read((char *)buf, bpl) != bpl) { - image = QImage(); - break; - } - b = buf; - while (p < end) { + int h = icoAttrib.h; + register QRgb *p; + QRgb *end; + uchar *buf = new uchar[image.bytesPerLine()]; + int bpl = ((icoAttrib.w*icoAttrib.nbits+31)/32)*4; + uchar *b; + + while (--h >= 0) { + p = (QRgb *)image.scanLine(h); + end = p + icoAttrib.w; + if (iod->read((char *)buf, bpl) != bpl) { + image = QImage(); + break; + } + b = buf; + while (p < end) { if (icoAttrib.nbits == 24) *p++ = qRgb(*(b+2), *(b+1), *b); else if (icoAttrib.nbits == 32) *p++ = qRgba(*(b+2), *(b+1), *b, *(b+3)); - b += icoAttrib.nbits/8; - } - } + b += icoAttrib.nbits/8; + } + } - delete[] buf; + delete[] buf; } else { - image = QImage(); + image = QImage(); } } @@ -549,8 +522,41 @@ QImage ICOReader::iconAt(int index) ICONDIRENTRY iconEntry; if (readIconEntry(index, &iconEntry)) { + static const uchar pngMagicData[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + + iod->seek(iconEntry.dwImageOffset); + + const QByteArray pngMagic = QByteArray::fromRawData((char*)pngMagicData, sizeof(pngMagicData)); + const bool isPngImage = (iod->read(pngMagic.size()) == pngMagic); + + if (isPngImage) { + iod->seek(iconEntry.dwImageOffset); + return QImage::fromData(iod->read(iconEntry.dwBytesInRes), "png"); + } + BMP_INFOHDR header; - if (readBMPHeader(iconEntry, &header)) { + if (readBMPHeader(iconEntry.dwImageOffset, &header)) { + icoAttrib.nbits = header.biBitCount ? header.biBitCount : iconEntry.wBitCount; + + switch (icoAttrib.nbits) { + case 32: + case 24: + case 16: + icoAttrib.depth = 32; + break; + case 8: + case 4: + icoAttrib.depth = 8; + break; + default: + icoAttrib.depth = 1; + } + if (icoAttrib.depth == 32) // there's no colormap + icoAttrib.ncolors = 0; + else // # colors used + icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits; + icoAttrib.w = iconEntry.bWidth; + icoAttrib.h = iconEntry.bHeight; QImage::Format format = QImage::Format_ARGB32; if (icoAttrib.nbits == 24) @@ -605,8 +611,8 @@ QList<QImage> ICOReader::read(QIODevice * device) QList<QImage> images; ICOReader reader(device); - for (int i=0; i<reader.count(); i++) - images += reader.iconAt(i); + for (int i = 0; i < reader.count(); i++) + images += reader.iconAt(i); return images; } @@ -659,8 +665,8 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images) } maskImage = maskImage.convertToFormat(QImage::Format_Mono); - int nbits = 32; - int bpl_bmp = ((image.width()*nbits+31)/32)*4; + int nbits = 32; + int bpl_bmp = ((image.width()*nbits+31)/32)*4; entries[i].bColorCount = 0; entries[i].bReserved = 0; @@ -670,7 +676,7 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images) entries[i].dwBytesInRes = BMP_INFOHDR_SIZE + (bpl_bmp * image.height()) + (maskImage.bytesPerLine() * maskImage.height()); entries[i].wPlanes = 1; - if (i==0) + if (i == 0) entries[i].dwImageOffset = origOffset + ICONDIR_SIZE + (id.idCount * ICONDIRENTRY_SIZE); else @@ -695,7 +701,7 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images) uchar *b; memset( buf, 0, bpl_bmp ); int y; - for (y=image.height()-1; y>=0; y--) { // write the image bits + for (y = image.height() - 1; y >= 0; y--) { // write the image bits // 32 bits QRgb *p = (QRgb *)image.scanLine(y); QRgb *end = p + image.width(); @@ -717,13 +723,10 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images) maskImage.invertPixels(); // seems as though it needs this // NOTE! !! The mask is only flipped vertically - not horizontally !! - for (y=maskImage.height()-1; y>=0; y--) + for (y = maskImage.height() - 1; y >= 0; y--) buffer.write((char*)maskImage.scanLine(y), maskImage.bytesPerLine()); - } - - if (writeIconDir(device, id)) { int i; bool bOK = true; @@ -731,7 +734,7 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images) bOK = writeIconDirEntry(device, entries[i]); } if (bOK) { - for (i=0; i<id.idCount && bOK; i++) { + for (i = 0; i < id.idCount && bOK; i++) { bOK = writeBMPInfoHeader(device, bmpHeaders[i]); bOK &= (device->write(imageData[i]) == (int) imageData[i].size()); } diff --git a/src/plugins/imageformats/jpeg/jpeg.pro b/src/plugins/imageformats/jpeg/jpeg.pro index f310902..ebc79cc 100644 --- a/src/plugins/imageformats/jpeg/jpeg.pro +++ b/src/plugins/imageformats/jpeg/jpeg.pro @@ -13,6 +13,12 @@ wince*: { contains(CE_ARCH,x86):CONFIG += exceptions_off } +symbian: { + #Disable warnings in 3rdparty code due to unused arguments + QMAKE_CXXFLAGS.CW += -W nounusedarg + TARGET.UID3=0x2001E61B +} + contains(QT_CONFIG, system-jpeg) { unix:LIBS += -ljpeg win32:LIBS += libjpeg.lib @@ -71,3 +77,4 @@ contains(QT_CONFIG, system-jpeg) { QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/imageformats target.path += $$[QT_INSTALL_PLUGINS]/imageformats INSTALLS += target + diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 69a568e..39cf31d 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -790,7 +790,8 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage, #ifndef QT_NO_IMAGE_SMOOTHSCALE // If high quality not required, shrink image during decompression - if (scaledSize.isValid() && quality < HIGH_QUALITY_THRESHOLD && !params.contains(QLatin1String("GetHeaderInformation")) ) { + if (scaledSize.isValid() && !scaledSize.isEmpty() && quality < HIGH_QUALITY_THRESHOLD + && !params.contains(QLatin1String("GetHeaderInformation")) ) { cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(), cinfo.image_width / scaledSize.height()); if (cinfo.scale_denom < 2) { diff --git a/src/plugins/imageformats/mng/mng.pro b/src/plugins/imageformats/mng/mng.pro index f0943f5..de7dfa7 100644 --- a/src/plugins/imageformats/mng/mng.pro +++ b/src/plugins/imageformats/mng/mng.pro @@ -7,6 +7,12 @@ HEADERS += qmnghandler.h SOURCES += main.cpp \ qmnghandler.cpp +symbian: { + #Disable warnings in 3rdparty code due to unused variables and arguments + QMAKE_CXXFLAGS.CW += -W nounused + TARGET.UID3=0x2001E619 +} + contains(QT_CONFIG, system-mng) { unix:LIBS += -lmng win32:LIBS += libmng.lib @@ -47,3 +53,4 @@ contains(QT_CONFIG, system-zlib) { QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/imageformats target.path += $$[QT_INSTALL_PLUGINS]/imageformats INSTALLS += target + diff --git a/src/plugins/imageformats/mng/qmnghandler.cpp b/src/plugins/imageformats/mng/qmnghandler.cpp index 3f54553..148d976 100644 --- a/src/plugins/imageformats/mng/qmnghandler.cpp +++ b/src/plugins/imageformats/mng/qmnghandler.cpp @@ -375,8 +375,6 @@ QMngHandler::QMngHandler() QMngHandler::~QMngHandler() { - Q_D(QMngHandler); - delete d; } /*! \reimp */ diff --git a/src/plugins/imageformats/mng/qmnghandler.h b/src/plugins/imageformats/mng/qmnghandler.h index 6efb004..c750f4c 100644 --- a/src/plugins/imageformats/mng/qmnghandler.h +++ b/src/plugins/imageformats/mng/qmnghandler.h @@ -42,6 +42,7 @@ #ifndef QMNGHANDLER_H #define QMNGHANDLER_H +#include <QtCore/qscopedpointer.h> #include <QtGui/qimageiohandler.h> QT_BEGIN_NAMESPACE @@ -74,7 +75,7 @@ class QMngHandler : public QImageIOHandler private: Q_DECLARE_PRIVATE(QMngHandler) - QMngHandlerPrivate *d_ptr; + QScopedPointer<QMngHandlerPrivate> d_ptr; }; QT_END_NAMESPACE diff --git a/src/plugins/imageformats/svg/svg.pro b/src/plugins/imageformats/svg/svg.pro index 747d556..bcf4c21 100644 --- a/src/plugins/imageformats/svg/svg.pro +++ b/src/plugins/imageformats/svg/svg.pro @@ -9,3 +9,5 @@ QT += xml svg QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/imageformats target.path += $$[QT_INSTALL_PLUGINS]/imageformats INSTALLS += target + +symbian:TARGET.UID3=0x2001E618 diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index 0d99443..651fb4d 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -98,6 +98,43 @@ void qtiffUnmapProc(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/) { } +// for 32 bits images +inline void rotate_right_mirror_horizontal(QImage *const image)// rotate right->mirrored horizontal +{ + const int height = image->height(); + const int width = image->width(); + QImage generated(/* width = */ height, /* height = */ width, image->format()); + const uint32 *originalPixel = reinterpret_cast<const uint32*>(image->bits()); + uint32 *const generatedPixels = reinterpret_cast<uint32*>(generated.bits()); + for (int row=0; row < height; ++row) { + for (int col=0; col < width; ++col) { + int idx = col * height + row; + generatedPixels[idx] = *originalPixel; + ++originalPixel; + } + } + *image = generated; +} + +inline void rotate_right_mirror_vertical(QImage *const image) // rotate right->mirrored vertical +{ + const int height = image->height(); + const int width = image->width(); + QImage generated(/* width = */ height, /* height = */ width, image->format()); + const int lastCol = width - 1; + const int lastRow = height - 1; + const uint32 *pixel = reinterpret_cast<const uint32*>(image->bits()); + uint32 *const generatedBits = reinterpret_cast<uint32*>(generated.bits()); + for (int row=0; row < height; ++row) { + for (int col=0; col < width; ++col) { + int idx = (lastCol - col) * height + (lastRow - row); + generatedBits[idx] = *pixel; + ++pixel; + } + } + *image = generated; +} + QTiffHandler::QTiffHandler() : QImageIOHandler() { compression = NoCompression; @@ -131,58 +168,206 @@ bool QTiffHandler::read(QImage *image) if (!canRead()) return false; - TIFF *tiff = TIFFClientOpen("foo", - "r", - this, - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); - - if (tiff) { - uint32 width = 0; - uint32 height = 0; - TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height); - if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) - *image = QImage(width, height, QImage::Format_ARGB32); + TIFF *const tiff = TIFFClientOpen("foo", + "r", + this, + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc); + + if (!tiff) { + return false; + } + uint32 width; + uint32 height; + uint16 photometric; + if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width) + || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height) + || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) { + TIFFClose(tiff); + return false; + } + + if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) { + if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) + *image = QImage(width, height, QImage::Format_Mono); + QVector<QRgb> colortable(2); + if (photometric == PHOTOMETRIC_MINISBLACK) { + colortable[0] = 0xff000000; + colortable[1] = 0xffffffff; + } else { + colortable[0] = 0xffffffff; + colortable[1] = 0xff000000; + } + image->setColorTable(colortable); + if (!image->isNull()) { - if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, 0)) { - uint16 resUnit = RESUNIT_NONE; - float resX = 0; - float resY = 0; - TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit); - TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX); - TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY); - switch(resUnit) { - case RESUNIT_CENTIMETER: - image->setDotsPerMeterX(qRound(resX * 100)); - image->setDotsPerMeterY(qRound(resY * 100)); - break; - case RESUNIT_INCH: - image->setDotsPerMeterX(qRound(resX * (100 / 2.54))); - image->setDotsPerMeterY(qRound(resY * (100 / 2.54))); - break; - default: - // do nothing as defaults have already - // been set within the QImage class - break; + for (uint32 y=0; y<height; ++y) { + if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { + TIFFClose(tiff); + return false; + } + } + } + } else { + uint16 bitPerSample; + if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { + TIFFClose(tiff); + return false; + } + if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) { + if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) + *image = QImage(width, height, QImage::Format_Indexed8); + if (!image->isNull()) { + // create the color table + const uint16 tableSize = 256; + uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } + if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { + TIFFClose(tiff); + return false; + } + + QVector<QRgb> qtColorTable(tableSize); + for (int i = 0; i<tableSize ;++i) { + const int red = redTable[i] / 257; + const int green = greenTable[i] / 257; + const int blue = blueTable[i] / 257; + qtColorTable[i] = qRgb(red, green, blue); + + } + + image->setColorTable(qtColorTable); + for (uint32 y=0; y<height; ++y) { + if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { + TIFFClose(tiff); + return false; + } + } + + // free redTable, greenTable and greenTable done by libtiff + } + } else { + if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) + *image = QImage(width, height, QImage::Format_ARGB32); + if (!image->isNull()) { + const int stopOnError = 1; + if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, stopOnError)) { + for (uint32 y=0; y<height; ++y) + convert32BitOrder(image->scanLine(y), width); + } else { + TIFFClose(tiff); + return false; } - for (uint32 y=0; y<height; ++y) - convert32BitOrder(image->scanLine(y), width); - } else { - *image = QImage(); } } - TIFFClose(tiff); } - if (image->isNull()) + if (image->isNull()) { + TIFFClose(tiff); return false; + } + + float resX = 0; + float resY = 0; + uint16 resUnit = RESUNIT_NONE; + if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit) + && TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX) + && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) { + + switch(resUnit) { + case RESUNIT_CENTIMETER: + image->setDotsPerMeterX(qRound(resX * 100)); + image->setDotsPerMeterY(qRound(resY * 100)); + break; + case RESUNIT_INCH: + image->setDotsPerMeterX(qRound(resX * (100 / 2.54))); + image->setDotsPerMeterY(qRound(resY * (100 / 2.54))); + break; + default: + // do nothing as defaults have already + // been set within the QImage class + break; + } + } + // rotate the image if the orientation is defined in the file + uint16 orientationTag; + if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &orientationTag)) { + if (image->format() == QImage::Format_ARGB32) { + // TIFFReadRGBAImageOriented() flip the image but does not rotate them + switch (orientationTag) { + case 5: + rotate_right_mirror_horizontal(image); + break; + case 6: + rotate_right_mirror_vertical(image); + break; + case 7: + rotate_right_mirror_horizontal(image); + break; + case 8: + rotate_right_mirror_vertical(image); + break; + } + } else { + switch (orientationTag) { + case 1: // default orientation + break; + case 2: // mirror horizontal + *image = image->mirrored(true, false); + break; + case 3: // mirror both + *image = image->mirrored(true, true); + break; + case 4: // mirror vertical + *image = image->mirrored(false, true); + break; + case 5: // rotate right mirror horizontal + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + *image = image->mirrored(true, false); + break; + } + case 6: // rotate right + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + break; + } + case 7: // rotate right, mirror vertical + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + *image = image->mirrored(false, true); + break; + } + case 8: // rotate left + { + QMatrix transformation; + transformation.rotate(270); + *image = image->transformed(transformation); + break; + } + } + } + } + + + TIFFClose(tiff); return true; } @@ -191,33 +376,148 @@ bool QTiffHandler::write(const QImage &image) if (!device()->isWritable()) return false; - TIFF *tiff = TIFFClientOpen("foo", - "w", - this, - qtiffReadProc, - qtiffWriteProc, - qtiffSeekProc, - qtiffCloseProc, - qtiffSizeProc, - qtiffMapProc, - qtiffUnmapProc); - - if (tiff) { - int width = image.width(); - int height = image.height(); - int depth = 32; - - if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width) - || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height) - || !TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) - || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW) - || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, depth/8) - || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) - || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFF *const tiff = TIFFClientOpen("foo", + "w", + this, + qtiffReadProc, + qtiffWriteProc, + qtiffSeekProc, + qtiffCloseProc, + qtiffSizeProc, + qtiffMapProc, + qtiffUnmapProc); + if (!tiff) + return false; + + const int width = image.width(); + const int height = image.height(); + + if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width) + || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height) + || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) { + TIFFClose(tiff); + return false; + } + + // set the resolution + bool resolutionSet = false; + const int dotPerMeterX = image.dotsPerMeterX(); + const int dotPerMeterY = image.dotsPerMeterY(); + if ((dotPerMeterX % 100) == 0 + && (dotPerMeterY % 100) == 0) { + resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER) + && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0) + && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0); + } else { + resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH) + && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast<float>(image.logicalDpiX())) + && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast<float>(image.logicalDpiY())); + } + if (!resolutionSet) { + TIFFClose(tiff); + return false; + } + + // configure image depth + const QImage::Format format = image.format(); + if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) { + uint16 photometric = PHOTOMETRIC_MINISBLACK; + if (image.colorTable().at(0) == 0xffffffff) + photometric = PHOTOMETRIC_MINISWHITE; + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) { + TIFFClose(tiff); + return false; + } + + // try to do the conversion in chunks no greater than 16 MB + int chunks = (width * height / (1024 * 1024 * 16)) + 1; + int chunkHeight = qMax(height / chunks, 1); + + int y = 0; + while (y < height) { + QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono); + + int chunkStart = y; + int chunkEnd = y + chunk.height(); + while (y < chunkEnd) { + if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) { + TIFFClose(tiff); + return false; + } + ++y; + } + } + TIFFClose(tiff); + } else if (format == QImage::Format_Indexed8) { + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } + //// write the color table + // allocate the color tables + uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } + + // set the color table + const QVector<QRgb> colorTable = image.colorTable(); + + const int tableSize = colorTable.size(); + Q_ASSERT(tableSize <= 256); + for (int i = 0; i<tableSize; ++i) { + const QRgb color = colorTable.at(i); + redTable[i] = qRed(color) * 257; + greenTable[i] = qGreen(color) * 257; + blueTable[i] = qBlue(color) * 257; + } + + const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); + + qFree(redTable); + qFree(greenTable); + qFree(blueTable); + + if (!setColorTableSuccess) { TIFFClose(tiff); return false; } + //// write the data + // try to do the conversion in chunks no greater than 16 MB + int chunks = (width * height/ (1024 * 1024 * 16)) + 1; + int chunkHeight = qMax(height / chunks, 1); + + int y = 0; + while (y < height) { + QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)); + + int chunkStart = y; + int chunkEnd = y + chunk.height(); + while (y < chunkEnd) { + if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) { + TIFFClose(tiff); + return false; + } + ++y; + } + } + TIFFClose(tiff); + + } else { + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW) + || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } // try to do the ARGB32 conversion in chunks no greater than 16 MB int chunks = (width * height * 4 / (1024 * 1024 * 16)) + 1; int chunkHeight = qMax(height / chunks, 1); @@ -242,9 +542,8 @@ bool QTiffHandler::write(const QImage &image) } } TIFFClose(tiff); - } else { - return false; } + return true; } diff --git a/src/plugins/imageformats/tiff/tiff.pro b/src/plugins/imageformats/tiff/tiff.pro index 8930cf3..312f99c 100644 --- a/src/plugins/imageformats/tiff/tiff.pro +++ b/src/plugins/imageformats/tiff/tiff.pro @@ -56,6 +56,9 @@ contains(QT_CONFIG, system-tiff) { wince*: { SOURCES += ../../../corelib/kernel/qfunctions_wince.cpp } + symbian*: { + SOURCES += ../../../3rdparty/libtiff/port/lfind.c + } } contains(QT_CONFIG, system-zlib) { @@ -68,3 +71,5 @@ contains(QT_CONFIG, system-zlib) { QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/imageformats target.path += $$[QT_INSTALL_PLUGINS]/imageformats INSTALLS += target + +symbian:TARGET.UID3=0x2001E617 |