diff --git a/src/plugins/imageformats/dds/ddsheader.h b/src/plugins/imageformats/dds/ddsheader.h
index 7f6df0613e9adc9c95dbab563f2ce0f1115be7b7..7b2b80ce1f15cbb3169d321ed0755bfb7f7d2f3f 100644
--- a/src/plugins/imageformats/dds/ddsheader.h
+++ b/src/plugins/imageformats/dds/ddsheader.h
@@ -134,6 +134,9 @@ enum Format {
     FormatA2B10G10R10_XR_BIAS  = 119,
     FormatBinaryBuffer         = 199,
 
+    FormatP4,
+    FormatA4P4,
+
     FormatLast                 = 0x7fffffff
 };
 
@@ -143,6 +146,7 @@ struct DDSPixelFormat
         FlagAlphaPixels     = 0x00000001,
         FlagAlpha           = 0x00000002,
         FlagFourCC          = 0x00000004,
+        FlagPaletteIndexed4 = 0x00000008,
         FlagPaletteIndexed8 = 0x00000020,
         FlagRGB             = 0x00000040,
         FlagYUV             = 0x00000200,
diff --git a/src/plugins/imageformats/dds/qddshandler.cpp b/src/plugins/imageformats/dds/qddshandler.cpp
index c85e75d2fe957e2bd51c100a039053b6ee82a8ec..13bb9aafb77121e8fb56242bafdc658acdbf915b 100644
--- a/src/plugins/imageformats/dds/qddshandler.cpp
+++ b/src/plugins/imageformats/dds/qddshandler.cpp
@@ -221,7 +221,11 @@ static inline QRgb yuv2rgb(quint8 Y, quint8 U, quint8 V)
 static Format getFormat(const DDSHeader &dds)
 {
     const DDSPixelFormat &format = dds.pixelFormat;
-    if (format.flags & DDSPixelFormat::FlagFourCC) {
+    if (format.flags & DDSPixelFormat::FlagPaletteIndexed4) {
+        return FormatP4;
+    } else if (format.flags & DDSPixelFormat::FlagPaletteIndexed8) {
+        return FormatP8;
+    } else if (format.flags & DDSPixelFormat::FlagFourCC) {
         for (size_t i = 0; i < knownFourCCsSize; ++i) {
             if (dds.pixelFormat.fourCC == knownFourCCs[i])
                 return knownFourCCs[i];
@@ -729,7 +733,7 @@ static QImage readCxV8U8(QDataStream &s, const quint32 width, const quint32 heig
     return image;
 }
 
-static QImage readPaletteImage(QDataStream &s, quint32 width, quint32 height)
+static QImage readPalette8Image(QDataStream &s, quint32 width, quint32 height)
 {
     QImage image(width, height, QImage::Format_Indexed8);
     for (int i = 0; i < 256; ++i) {
@@ -749,6 +753,31 @@ static QImage readPaletteImage(QDataStream &s, quint32 width, quint32 height)
     return image;
 }
 
+static QImage readPalette4Image(QDataStream &s, quint32 width, quint32 height)
+{
+    QImage image(width, height, QImage::Format_Indexed8);
+    for (int i = 0; i < 16; ++i) {
+        quint8 r, g, b, a;
+        s >> r >> g >> b >> a;
+        image.setColor(i, qRgba(r, g, b, a));
+    }
+
+    for (quint32 y = 0; y < height; y++) {
+        quint8 index;
+        for (quint32 x = 0; x < width - 1; ) {
+            s >> index;
+            image.setPixel(x++, y, (index & 0x0f) >> 0);
+            image.setPixel(x++, y, (index & 0xf0) >> 4);
+        }
+        if (width % 2 == 1) {
+            s >> index;
+            image.setPixel(width - 1, y, (index & 0x0f) >> 0);
+        }
+    }
+
+    return image;
+}
+
 static QImage readARGB16(QDataStream &s, quint32 width, quint32 height)
 {
     QImage image(width, height, QImage::Format_ARGB32);
@@ -1004,9 +1033,11 @@ static QImage readLayer(QDataStream &s, const DDSHeader &dds, const int format,
     case FormatA2B10G10R10:
         return readA2R10G10B10(s, dds, width, height);
     case FormatP8:
-        return readPaletteImage(s, width, height);
     case FormatA8P8:
-        break;
+        return readPalette8Image(s, width, height);
+    case FormatP4:
+    case FormatA4P4:
+        return readPalette4Image(s, width, height);
     case FormatA16B16G16R16:
         return readARGB16(s, width, height);
     case FormatV8U8:
diff --git a/tests/auto/dds/tst_qdds.cpp b/tests/auto/dds/tst_qdds.cpp
index 4464b991d2c65985c084ef1b05bfca51632de78d..eb2584975c79e88cb0d4f451839de2d4528b2afc 100644
--- a/tests/auto/dds/tst_qdds.cpp
+++ b/tests/auto/dds/tst_qdds.cpp
@@ -108,6 +108,7 @@ void tst_qdds::readImage_data()
     QTest::newRow("45") << QString("YUY2") << QSize(64, 64);
     QTest::newRow("46") << QString("RXGB") << QSize(64, 64);
     QTest::newRow("47") << QString("ATI2") << QSize(64, 64);
+    QTest::newRow("48") << QString("P4") << QSize(64, 64);
 }
 
 void tst_qdds::readImage()
diff --git a/tests/shared/images/dds.qrc b/tests/shared/images/dds.qrc
index e19eee95956c01b14f46b6030f245088f807bade..128a38dee0068f552f38ec641f843a83032d9c44 100644
--- a/tests/shared/images/dds.qrc
+++ b/tests/shared/images/dds.qrc
@@ -28,6 +28,7 @@
         <file>dds/L8.dds</file>
         <file>dds/L16.dds</file>
         <file>dds/mipmaps.dds</file>
+        <file>dds/P4.dds</file>
         <file>dds/P8.dds</file>
         <file>dds/Q8W8V8U8.dds</file>
         <file>dds/Q16W16V16U16.dds</file>
diff --git a/tests/shared/images/dds/P4.dds b/tests/shared/images/dds/P4.dds
new file mode 100644
index 0000000000000000000000000000000000000000..c8c3e904bf3666cd1caae80f8784899769712311
Binary files /dev/null and b/tests/shared/images/dds/P4.dds differ
diff --git a/tests/shared/images/dds/P8.dds b/tests/shared/images/dds/P8.dds
index 936b870318f85c737daf8bbab821394c44e7c449..4bef9ec321f1b02e59b770285a2621c578c83134 100644
Binary files a/tests/shared/images/dds/P8.dds and b/tests/shared/images/dds/P8.dds differ