diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp
index e34ea25c70740c46359a1193f44ffadb6647cecb..81ad7e92b9bf57425310e61c1d72a138e118d40b 100644
--- a/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -329,125 +329,106 @@ bool QTiffHandler::read(QImage *image)
     if (image->size() != d->size || image->format() != format)
         *image = QImage(d->size, format);
 
+    if (image->isNull()) {
+        d->close();
+        return false;
+    }
+
     TIFF *const tiff = d->tiff;
     const uint32 width = d->size.width();
     const uint32 height = d->size.height();
 
-    if (format == QImage::Format_Mono) {
-        QVector<QRgb> colortable(2);
-        if (d->photometric == PHOTOMETRIC_MINISBLACK) {
-            colortable[0] = 0xff000000;
-            colortable[1] = 0xffffffff;
-        } else {
-            colortable[0] = 0xffffffff;
-            colortable[1] = 0xff000000;
-        }
-        image->setColorTable(colortable);
-
-        if (!image->isNull()) {
-            for (uint32 y=0; y<height; ++y) {
-                if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
+    if (format == QImage::Format_Mono || format == QImage::Format_Indexed8 || format == QImage::Format_Grayscale8) {
+        if (format == QImage::Format_Mono) {
+            QVector<QRgb> colortable(2);
+            if (d->photometric == PHOTOMETRIC_MINISBLACK) {
+                colortable[0] = 0xff000000;
+                colortable[1] = 0xffffffff;
+            } else {
+                colortable[0] = 0xffffffff;
+                colortable[1] = 0xff000000;
+            }
+            image->setColorTable(colortable);
+        } else if (format == QImage::Format_Indexed8) {
+            const uint16 tableSize = 256;
+            QVector<QRgb> qtColorTable(tableSize);
+            if (d->grayscale) {
+                for (int i = 0; i<tableSize; ++i) {
+                    const int c = (d->photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i);
+                    qtColorTable[i] = qRgb(c, c, c);
+                }
+            } else {
+                // create the color table
+                uint16 *redTable = 0;
+                uint16 *greenTable = 0;
+                uint16 *blueTable = 0;
+                if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
                     d->close();
                     return false;
                 }
-            }
-        }
-    } else {
-        if (format == QImage::Format_Indexed8) {
-            if (!image->isNull()) {
-                const uint16 tableSize = 256;
-                QVector<QRgb> qtColorTable(tableSize);
-                if (d->grayscale) {
-                    for (int i = 0; i<tableSize; ++i) {
-                        const int c = (d->photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i);
-                        qtColorTable[i] = qRgb(c, c, c);
-                    }
-                } else {
-                    // create the color table
-                    uint16 *redTable = 0;
-                    uint16 *greenTable = 0;
-                    uint16 *blueTable = 0;
-                    if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
-                        d->close();
-                        return false;
-                    }
-                    if (!redTable || !greenTable || !blueTable) {
-                        d->close();
-                        return false;
-                    }
-
-                    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);
-                    }
+                if (!redTable || !greenTable || !blueTable) {
+                    d->close();
+                    return false;
                 }
 
-                image->setColorTable(qtColorTable);
-
-                if (TIFFIsTiled(tiff)) {
-                    quint32 tileWidth, tileLength;
-                    TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth);
-                    TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength);
-                    uchar *buf = (uchar *)_TIFFmalloc(TIFFTileSize(tiff));
-                    if (!tileWidth || !tileLength || !buf) {
-                        _TIFFfree(buf);
-                        d->close();
-                        return false;
-                    }
-                    for (quint32 y = 0; y < height; y += tileLength) {
-                        for (quint32 x = 0; x < width; x += tileWidth) {
-                            if (TIFFReadTile(tiff, buf, x, y, 0, 0) < 0) {
-                                _TIFFfree(buf);
-                                d->close();
-                                return false;
-                            }
-                            quint32 linesToCopy = qMin(tileLength, height - y);
-                            quint32 widthToCopy = qMin(tileWidth, width - x);
-                            for (quint32 i = 0; i < linesToCopy; i++)
-                                ::memcpy(image->scanLine(y + i) + x, buf + (i * tileWidth), widthToCopy);
-                        }
-                    }
-                    _TIFFfree(buf);
-                } else {
-                    for (uint32 y=0; y<height; ++y) {
-                        if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
-                            d->close();
-                            return false;
-                        }
-                    }
+                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);
+            // free redTable, greenTable and greenTable done by libtiff
+        }
 
-                // free redTable, greenTable and greenTable done by libtiff
+        if (TIFFIsTiled(tiff)) {
+            quint32 tileWidth, tileLength;
+            TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth);
+            TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength);
+            uchar *buf = (uchar *)_TIFFmalloc(TIFFTileSize(tiff));
+            if (!tileWidth || !tileLength || !buf) {
+                _TIFFfree(buf);
+                d->close();
+                return false;
             }
-        } else if (format == QImage::Format_Grayscale8) {
-            if (!image->isNull()) {
-                for (uint32 y = 0; y < height; ++y) {
-                    if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
+            quint32 byteWidth = (format == QImage::Format_Mono) ? (width + 7)/8 : width;
+            quint32 byteTileWidth = (format == QImage::Format_Mono) ? tileWidth/8 : tileWidth;
+            for (quint32 y = 0; y < height; y += tileLength) {
+                for (quint32 x = 0; x < width; x += tileWidth) {
+                    if (TIFFReadTile(tiff, buf, x, y, 0, 0) < 0) {
+                        _TIFFfree(buf);
                         d->close();
                         return false;
                     }
+                    quint32 linesToCopy = qMin(tileLength, height - y);
+                    quint32 byteOffset = (format == QImage::Format_Mono) ? x/8 : x;
+                    quint32 widthToCopy = qMin(byteTileWidth, byteWidth - byteOffset);
+                    for (quint32 i = 0; i < linesToCopy; i++) {
+                        ::memcpy(image->scanLine(y + i) + byteOffset, buf + (i * byteTileWidth), widthToCopy);
+                    }
                 }
             }
+            _TIFFfree(buf);
         } else {
-            if (!image->isNull()) {
-                const int stopOnError = 1;
-                if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), qt2Exif(d->transformation), stopOnError)) {
-                    for (uint32 y=0; y<height; ++y)
-                        convert32BitOrder(image->scanLine(y), width);
-                } else {
+            for (uint32 y=0; y<height; ++y) {
+                if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
                     d->close();
                     return false;
                 }
             }
         }
+    } else {
+        const int stopOnError = 1;
+        if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), qt2Exif(d->transformation), stopOnError)) {
+            for (uint32 y=0; y<height; ++y)
+                convert32BitOrder(image->scanLine(y), width);
+        } else {
+            d->close();
+            return false;
+        }
     }
 
-    if (image->isNull()) {
-        d->close();
-        return false;
-    }
 
     float resX = 0;
     float resY = 0;
diff --git a/tests/auto/tiff/tst_qtiff.cpp b/tests/auto/tiff/tst_qtiff.cpp
index bec2ca28199052e10172042b172c4775af6ef4b5..1a96ab381c04552aa03729784b809aa0d843033f 100644
--- a/tests/auto/tiff/tst_qtiff.cpp
+++ b/tests/auto/tiff/tst_qtiff.cpp
@@ -139,6 +139,7 @@ void tst_qtiff::readImage_data()
     QTest::newRow("mono_orientation_7") << QString("mono_orientation_7.tiff") << QSize(64, 64);
     QTest::newRow("mono_orientation_8") << QString("mono_orientation_8.tiff") << QSize(64, 64);
     QTest::newRow("original_indexed") << QString("original_indexed.tiff") << QSize(64, 64);
+    QTest::newRow("original_grayscale") << QString("original_grayscale.tiff") << QSize(64, 64);
     QTest::newRow("original_mono") << QString("original_mono.tiff") << QSize(64, 64);
     QTest::newRow("original_rgb") << QString("original_rgb.tiff") << QSize(64, 64);
     QTest::newRow("rgba_adobedeflate_littleendian") << QString("rgba_adobedeflate_littleendian.tif") << QSize(200, 200);
@@ -156,8 +157,14 @@ void tst_qtiff::readImage_data()
     QTest::newRow("rgb_orientation_7") << QString("rgb_orientation_7.tiff") << QSize(64, 64);
     QTest::newRow("rgb_orientation_8") << QString("rgb_orientation_8.tiff") << QSize(64, 64);
     QTest::newRow("teapot") << QString("teapot.tiff") << QSize(256, 256);
-    QTest::newRow("indexed_nontiled") << QString("indexed_nontiled.tif") << QSize(512, 384);
-    QTest::newRow("indexed_tiled") << QString("indexed_tiled.tif") << QSize(512, 384);
+    QTest::newRow("oddsize_grayscale") << QString("oddsize_grayscale.tiff") << QSize(59, 71);
+    QTest::newRow("oddsize_mono") << QString("oddsize_mono.tiff") << QSize(59, 71);
+    QTest::newRow("tiled_rgb") << QString("tiled_rgb.tiff") << QSize(64, 64);
+    QTest::newRow("tiled_indexed") << QString("tiled_indexed.tiff") << QSize(64, 64);
+    QTest::newRow("tiled_grayscale") << QString("tiled_grayscale.tiff") << QSize(64, 64);
+    QTest::newRow("tiled_mono") << QString("tiled_mono.tiff") << QSize(64, 64);
+    QTest::newRow("tiled_oddsize_grayscale") << QString("tiled_oddsize_grayscale.tiff") << QSize(59, 71);
+    QTest::newRow("tiled_oddsize_mono") << QString("tiled_oddsize_mono.tiff") << QSize(59, 71);
 }
 
 void tst_qtiff::readImage()
@@ -566,7 +573,12 @@ void tst_qtiff::tiled_data()
 {
     QTest::addColumn<QString>("expectedFile");
     QTest::addColumn<QString>("tiledFile");
-    QTest::newRow("Indexed") << "indexed_nontiled.tif" << "indexed_tiled.tif";
+    QTest::newRow("RGB") << "original_rgb.tiff" << "tiled_rgb.tiff";
+    QTest::newRow("Indexed") << "original_indexed.tiff" << "tiled_indexed.tiff";
+    QTest::newRow("Grayscale") << "original_grayscale.tiff" << "tiled_grayscale.tiff";
+    QTest::newRow("Mono") << "original_mono.tiff" << "tiled_mono.tiff";
+    QTest::newRow("Oddsize (Grayscale)") << "oddsize_grayscale.tiff" << "tiled_oddsize_grayscale.tiff";
+    QTest::newRow("Oddsize (Mono)") << "oddsize_mono.tiff" << "tiled_oddsize_mono.tiff";
 }
 
 void tst_qtiff::tiled()
@@ -576,6 +588,7 @@ void tst_qtiff::tiled()
 
     QImage expectedImage(prefix + expectedFile);
     QImage tiledImage(prefix + tiledFile);
+    QVERIFY(!tiledImage.isNull());
     QCOMPARE(expectedImage, tiledImage);
 }
 
diff --git a/tests/shared/images/tiff.qrc b/tests/shared/images/tiff.qrc
index 258acf0ba3286707139bcba61ca89e5a08b22916..19675ba656e49951f3d8f2d42a6cc835a9212d24 100644
--- a/tests/shared/images/tiff.qrc
+++ b/tests/shared/images/tiff.qrc
@@ -41,7 +41,14 @@
         <file>tiff/rgb_orientation_8.tiff</file>
         <file>tiff/teapot.tiff</file>
         <file>tiff/colorful.bmp</file>
-        <file>tiff/indexed_tiled.tif</file>
-        <file>tiff/indexed_nontiled.tif</file>
+        <file>tiff/tiled_grayscale.tiff</file>
+        <file>tiff/tiled_oddsize_grayscale.tiff</file>
+        <file>tiff/oddsize_grayscale.tiff</file>
+        <file>tiff/original_grayscale.tiff</file>
+        <file>tiff/tiled_indexed.tiff</file>
+        <file>tiff/tiled_mono.tiff</file>
+        <file>tiff/tiled_oddsize_mono.tiff</file>
+        <file>tiff/oddsize_mono.tiff</file>
+        <file>tiff/tiled_rgb.tiff</file>
     </qresource>
 </RCC>
diff --git a/tests/shared/images/tiff/indexed_nontiled.tif b/tests/shared/images/tiff/indexed_nontiled.tif
deleted file mode 100644
index d0b7cef9718969298f11c95f9dc9a20c66201d1e..0000000000000000000000000000000000000000
Binary files a/tests/shared/images/tiff/indexed_nontiled.tif and /dev/null differ
diff --git a/tests/shared/images/tiff/indexed_tiled.tif b/tests/shared/images/tiff/indexed_tiled.tif
deleted file mode 100644
index 4ed11dd7456c1497bf4450d153d370ff5d891a48..0000000000000000000000000000000000000000
Binary files a/tests/shared/images/tiff/indexed_tiled.tif and /dev/null differ
diff --git a/tests/shared/images/tiff/oddsize_grayscale.tiff b/tests/shared/images/tiff/oddsize_grayscale.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..d519cd2b9aef6c8d66bfb4f026a783cd43be00f4
Binary files /dev/null and b/tests/shared/images/tiff/oddsize_grayscale.tiff differ
diff --git a/tests/shared/images/tiff/oddsize_mono.tiff b/tests/shared/images/tiff/oddsize_mono.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..fbac0edca7ea4a38e3d8481702c5dc7e9a337c7b
Binary files /dev/null and b/tests/shared/images/tiff/oddsize_mono.tiff differ
diff --git a/tests/shared/images/tiff/original_grayscale.tiff b/tests/shared/images/tiff/original_grayscale.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..174c2cfe88b3fbf879d28da2b2e07f332e032d99
Binary files /dev/null and b/tests/shared/images/tiff/original_grayscale.tiff differ
diff --git a/tests/shared/images/tiff/tiled_grayscale.tiff b/tests/shared/images/tiff/tiled_grayscale.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..894ba8b1a0e298e2faefac0aa4d1421cfd787e03
Binary files /dev/null and b/tests/shared/images/tiff/tiled_grayscale.tiff differ
diff --git a/tests/shared/images/tiff/tiled_indexed.tiff b/tests/shared/images/tiff/tiled_indexed.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..2bd266a1c696ebe0f5db5030e665cd2bd3c87197
Binary files /dev/null and b/tests/shared/images/tiff/tiled_indexed.tiff differ
diff --git a/tests/shared/images/tiff/tiled_mono.tiff b/tests/shared/images/tiff/tiled_mono.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..cbcda19249aa6b704a91cea9a8f978b52589ab43
Binary files /dev/null and b/tests/shared/images/tiff/tiled_mono.tiff differ
diff --git a/tests/shared/images/tiff/tiled_oddsize_grayscale.tiff b/tests/shared/images/tiff/tiled_oddsize_grayscale.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..27bc9d45c659ef689744a7427a897ece5c1b4a86
Binary files /dev/null and b/tests/shared/images/tiff/tiled_oddsize_grayscale.tiff differ
diff --git a/tests/shared/images/tiff/tiled_oddsize_mono.tiff b/tests/shared/images/tiff/tiled_oddsize_mono.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..e858e90400886850aa055bf35117692ec66e1cbe
Binary files /dev/null and b/tests/shared/images/tiff/tiled_oddsize_mono.tiff differ
diff --git a/tests/shared/images/tiff/tiled_rgb.tiff b/tests/shared/images/tiff/tiled_rgb.tiff
new file mode 100644
index 0000000000000000000000000000000000000000..90291b9859c0d9dbddd488f7bd1439ab12eee77c
Binary files /dev/null and b/tests/shared/images/tiff/tiled_rgb.tiff differ