-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

diff -u -3 -d -p -r1.4 -r1.4.2.1
- --- dds.cpp   2 Aug 2004 20:34:50 -0000       1.4
+++ dds.cpp     19 Apr 2005 11:11:09 -0000      1.4.2.1
@@ -26,6 +26,12 @@

#include <kdebug.h>

+#include <math.h> // sqrtf
+
+#ifndef __USE_ISOC99
+#define sqrtf(x) ((float)sqrt(x))
+#endif
+
typedef Q_UINT32 uint;
typedef Q_UINT16 ushort;
typedef Q_UINT8 uchar;
@@ -44,34 +50,71 @@ namespace { // Private.
#define VERTICAL 2
#define CUBE_LAYOUT    HORIZONTAL

+       struct Color8888
+       {
+               uchar r, g, b, a;
+       };

- -     const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
- -     const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
- -     const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
- -     const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
- -     const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
- -     const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
+       union Color565
+       {
+               struct {
+                       ushort b : 5;
+                       ushort g : 6;
+                       ushort r : 5;
+               } c;
+               ushort u;
+       };

- -     const uint DDSD_CAPS = 0x00000001l;
- -     const uint DDSD_PIXELFORMAT = 0x00001000l;
- -     const uint DDSD_WIDTH = 0x00000004l;
- -     const uint DDSD_HEIGHT = 0x00000002l;
- -     const uint DDSD_PITCH = 0x00000008l;
+       union Color1555 {
+               struct {
+                       ushort b : 5;
+                       ushort g : 5;
+                       ushort r : 5;
+                       ushort a : 1;
+               } c;
+               ushort u;
+       };

- -     const uint DDSCAPS_TEXTURE = 0x00001000l;
- -     const uint DDSCAPS2_VOLUME = 0x00200000l;
- -     const uint DDSCAPS2_CUBEMAP = 0x00000200l;
+       union Color4444 {
+               struct {
+                       ushort b : 4;
+                       ushort g : 4;
+                       ushort r : 4;
+                       ushort a : 4;
+               } c;
+               ushort u;
+       };

- -     const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400l;
- -     const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800l;
- -     const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000l;
- -     const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000l;
- -     const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000l;
- -     const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000l;

- -     const uint DDPF_RGB = 0x00000040l;
- -     const uint DDPF_FOURCC = 0x00000004l;
- -     const uint DDPF_ALPHAPIXELS = 0x00000001l;
+       static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
+       static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
+       static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
+       static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
+       static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
+       static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
+       static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
+       static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
+
+       static const uint DDSD_CAPS = 0x00000001l;
+       static const uint DDSD_PIXELFORMAT = 0x00001000l;
+       static const uint DDSD_WIDTH = 0x00000004l;
+       static const uint DDSD_HEIGHT = 0x00000002l;
+       static const uint DDSD_PITCH = 0x00000008l;
+
+       static const uint DDSCAPS_TEXTURE = 0x00001000l;
+       static const uint DDSCAPS2_VOLUME = 0x00200000l;
+       static const uint DDSCAPS2_CUBEMAP = 0x00000200l;
+
+       static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400l;
+       static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800l;
+       static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000l;
+       static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000l;
+       static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000l;
+       static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000l;
+
+       static const uint DDPF_RGB = 0x00000040l;
+       static const uint DDPF_FOURCC = 0x00000004l;
+       static const uint DDPF_ALPHAPIXELS = 0x00000001l;

       enum DDSType {
               DDS_A8R8G8B8 = 0,
@@ -84,6 +127,8 @@ namespace {  // Private.
               DDS_DXT3 = 7,
               DDS_DXT4 = 8,
               DDS_DXT5 = 9,
+               DDS_RXGB = 10,
+               DDS_ATI2 = 11,
               DDS_UNKNOWN
       };

@@ -99,7 +144,7 @@ namespace {  // Private.
               uint amask;
       };

- -     QDataStream & operator>> ( QDataStream & s, DDSPixelFormat & pf )
+       static QDataStream & operator>> ( QDataStream & s, DDSPixelFormat & pf )
       {
               s >> pf.size;
               s >> pf.flags;
@@ -119,7 +164,7 @@ namespace { // Private.
               uint caps4;
       };

- -     QDataStream & operator>> ( QDataStream & s, DDSCaps & caps )
+       static QDataStream & operator>> ( QDataStream & s, DDSCaps & caps )
       {
               s >> caps.caps1;
               s >> caps.caps2;
@@ -142,7 +187,7 @@ namespace { // Private.
               uint notused;
       };

- -     QDataStream & operator>> ( QDataStream & s, DDSHeader & header )
+       static QDataStream & operator>> ( QDataStream & s, DDSHeader & header )
       {
               s >> header.size;
               s >> header.flags;
@@ -160,7 +205,7 @@ namespace { // Private.
               return s;
       }

- -     bool IsValid( const DDSHeader & header )
+       static bool IsValid( const DDSHeader & header )
       {
               if( header.size != 124 ) {
                       return false;
@@ -180,7 +225,7 @@ namespace { // Private.


       // Get supported type. We currently support 10 different types.
- -     DDSType GetType( const DDSHeader & header )
+       static DDSType GetType( const DDSHeader & header )
       {
               if( header.pf.flags & DDPF_RGB ) {
                       if( header.pf.flags & DDPF_ALPHAPIXELS ) {
@@ -212,27 +257,28 @@ namespace {       // Private.
                                       return DDS_DXT4;
                               case FOURCC_DXT5:
                                       return DDS_DXT5;
+                               case FOURCC_RXGB:
+                                       return DDS_RXGB;
+                               case FOURCC_ATI2:
+                                       return DDS_ATI2;
                       }
               }
               return DDS_UNKNOWN;
       }


- -     bool HasAlpha( const DDSHeader & header )
+       static bool HasAlpha( const DDSHeader & header )
       {
               return header.pf.flags & DDPF_ALPHAPIXELS;
       }

- -     bool IsCubeMap( const DDSHeader & header )
+       static bool IsCubeMap( const DDSHeader & header )
       {
               return header.caps.caps2 & DDSCAPS2_CUBEMAP;
       }

- -     bool IsSupported( const DDSHeader & header )
+       static bool IsSupported( const DDSHeader & header )
       {
- -             /*if( IsCubeMap(header) ) {
- -                     return false;
- -             }*/
               if( header.caps.caps2 & DDSCAPS2_VOLUME ) {
                       return false;
               }
@@ -243,7 +289,7 @@ namespace { // Private.
       }


- -     bool LoadA8R8G8B8( QDataStream & s, const DDSHeader & header, QImage img  )
+       static bool LoadA8R8G8B8( QDataStream & s, const DDSHeader & header, QImage & img  )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -260,7 +306,7 @@ namespace { // Private.
               return true;
       }

- -     bool LoadR8G8B8( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadR8G8B8( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -277,7 +323,7 @@ namespace { // Private.
               return true;
       }

- -     bool LoadA1R5G5B5( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadA1R5G5B5( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -285,13 +331,12 @@ namespace {       // Private.
               for( uint y = 0; y < h; y++ ) {
                       QRgb * scanline = (QRgb *) img.scanLine( y );
                       for( uint x = 0; x < w; x++ ) {
- -                             ushort u;
- -                             s >> u;
- -                             uchar r, g, b, a;
- -                             a = (u & header.pf.amask) != 0 ? 0xFF : 0;
- -                             r = ((u & header.pf.rmask) >> 10) << 3;
- -                             g = ((u & header.pf.gmask) >> 5) << 3;
- -                             b = (u & header.pf.bmask) << 3;
+                               Color1555 color;
+                               s >> color.u;
+                               uchar a = (color.c.a != 0) ? 0xFF : 0;
+                               uchar r = (color.c.r << 3) | (color.c.r >> 2);
+                               uchar g = (color.c.g << 3) | (color.c.g >> 2);
+                               uchar b = (color.c.b << 3) | (color.c.b >> 2);
                               scanline[x] = qRgba(r, g, b, a);
                       }
               }
@@ -299,7 +344,7 @@ namespace { // Private.
               return true;
       }

- -     bool LoadA4R4G4B4( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadA4R4G4B4( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -307,13 +352,12 @@ namespace {       // Private.
               for( uint y = 0; y < h; y++ ) {
                       QRgb * scanline = (QRgb *) img.scanLine( y );
                       for( uint x = 0; x < w; x++ ) {
- -                             unsigned short u;
- -                             s >> u;
- -                             uchar r, g, b, a;
- -                             a = ((u & header.pf.amask) >> 12) << 4;
- -                             r = ((u & header.pf.rmask) >> 8) << 4;
- -                             g = ((u & header.pf.gmask) >> 4) << 4;
- -                             b = (u & header.pf.bmask) << 4;
+                               Color4444 color;
+                               s >> color.u;
+                               uchar a = (color.c.a << 4) | color.c.a;
+                               uchar r = (color.c.r << 4) | color.c.r;
+                               uchar g = (color.c.g << 4) | color.c.g;
+                               uchar b = (color.c.b << 4) | color.c.b;
                               scanline[x] = qRgba(r, g, b, a);
                       }
               }
@@ -321,7 +365,7 @@ namespace { // Private.
               return true;
       }

- -     bool LoadR5G6B5( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadR5G6B5( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -329,12 +373,11 @@ namespace {       // Private.
               for( uint y = 0; y < h; y++ ) {
                       QRgb * scanline = (QRgb *) img.scanLine( y );
                       for( uint x = 0; x < w; x++ ) {
- -                             unsigned short u;
- -                             s >> u;
- -                             uchar r, g, b;
- -                             r = ((u & header.pf.rmask) >> 11) << 3;
- -                             g = ((u & header.pf.gmask) >> 5) << 2;
- -                             b = (u & header.pf.bmask) << 3;
+                               Color565 color;
+                               s >> color.u;
+                               uchar r = (color.c.r << 3) | (color.c.r >> 2);
+                               uchar g = (color.c.g << 2) | (color.c.g >> 4);
+                               uchar b = (color.c.b << 3) | (color.c.b >> 2);
                               scanline[x] = qRgb(r, g, b);
                       }
               }
@@ -342,22 +385,7 @@ namespace {        // Private.
               return true;
       }

- -     struct Color8888
- -     {
- -             uchar r, g, b, a;
- -     };
- -
- -     union Color565
- -     {
- -             struct {
- -                     ushort b : 5;
- -                     ushort g : 6;
- -                     ushort r : 5;
- -             } c;
- -             ushort u;
- -     };
- -
- -     QDataStream & operator>> ( QDataStream & s, Color565 & c )
+       static QDataStream & operator>> ( QDataStream & s, Color565 & c )
       {
               return s >> c.u;
       }
@@ -400,17 +428,17 @@ namespace {       // Private.
                               color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
                               color_array[2].a = 0xFF;

- -                             // magenta to indicate transparent color.
- -                             color_array[3].r = color_array[2].r;
- -                             color_array[3].g = color_array[2].g;
- -                             color_array[3].b = color_array[2].b;
+                               // Set all components to 0 to match DXT specs.
+                               color_array[3].r = 0x00; // color_array[2].r;
+                               color_array[3].g = 0x00; // color_array[2].g;
+                               color_array[3].b = 0x00; // color_array[2].b;
                               color_array[3].a = 0x00;
                       }
               }
       };


- -     QDataStream & operator>> ( QDataStream & s, BlockDXT & c )
+       static QDataStream & operator>> ( QDataStream & s, BlockDXT & c )
       {
               return s >> c.col0 >> c.col1 >> c.row[0] >> c.row[1] >> c.row[2] >> c.row[3];
       }
@@ -419,7 +447,7 @@ namespace { // Private.
               ushort row[4];
       };

- -     QDataStream & operator>> ( QDataStream & s, BlockDXTAlphaExplicit & c )
+       static QDataStream & operator>> ( QDataStream & s, BlockDXTAlphaExplicit & c )
       {
               return s >> c.row[0] >> c.row[1] >> c.row[2] >> c.row[3];
       }
@@ -485,13 +513,13 @@ namespace {       // Private.
               }
       };

- -     QDataStream & operator>> ( QDataStream & s, BlockDXTAlphaLinear & c )
+       static QDataStream & operator>> ( QDataStream & s, BlockDXTAlphaLinear & c )
       {
               s >> c.alpha0 >> c.alpha1;
               return s >> c.bits[0] >> c.bits[1] >> c.bits[2] >> c.bits[3] >> c.bits[4] >> c.bits[5];
       }

- -     bool LoadDXT1( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadDXT1( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -530,7 +558,7 @@ namespace { // Private.
               return true;
       }

- -     bool LoadDXT3( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadDXT3( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -575,14 +603,14 @@ namespace {       // Private.
               return true;
       }

- -     bool LoadDXT2( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadDXT2( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               if( !LoadDXT3(s, header, img) ) return false;
               //UndoPremultiplyAlpha(img);
               return true;
       }

- -     bool LoadDXT5( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadDXT5( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               const uint w = header.width;
               const uint h = header.height;
@@ -630,19 +658,122 @@ namespace {      // Private.

               return true;
       }
- -
- -     bool LoadDXT4( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadDXT4( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               if( !LoadDXT5(s, header, img) ) return false;
               //UndoPremultiplyAlpha(img);
               return true;
       }

+       static bool LoadRXGB( QDataStream & s, const DDSHeader & header, QImage & img )
+       {
+               const uint w = header.width;
+               const uint h = header.height;
+
+               BlockDXT block;
+               BlockDXTAlphaLinear alpha;
+               QRgb * scanline[4];

- -     typedef bool (* TextureLoader)( QDataStream & s, const DDSHeader & header, QImage img );
+               for( uint y = 0; y < h; y += 4 ) {
+                       for( uint j = 0; j < 4; j++ ) {
+                               scanline[j] = (QRgb *) img.scanLine( y + j );
+                       }
+                       for( uint x = 0; x < w; x += 4 ) {
+
+                               // Read 128bit color block.
+                               s >> alpha;
+                               s >> block;
+
+                               // Decode color block.
+                               Color8888 color_array[4];
+                               block.GetColors(color_array);
+
+                               uchar alpha_array[8];
+                               alpha.GetAlphas(alpha_array);
+
+                               uchar bit_array[16];
+                               alpha.GetBits(bit_array);
+
+                               // bit masks = 00000011, 00001100, 00110000, 11000000
+                               const uint masks[4] = { 3, 3<<2, 3<<4, 3<<6 };
+                               const int shift[4] = { 0, 2, 4, 6 };
+
+                               // Write color block.
+                               for( uint j = 0; j < 4; j++ ) {
+                                       for( uint i = 0; i < 4; i++ ) {
+                                               if( img.valid( x+i, y+j ) ) {
+                                                       uint idx = (block.row[j] & masks[i]) >> shift[i];
+                                                       color_array[idx].a = alpha_array[bit_array[j*4+i]];
+                                                       scanline[j][x+i] = qRgb(color_array[idx].a, color_array[idx].g, color_array[idx].b);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return true;
+       }
+
+       static bool LoadATI2( QDataStream & s, const DDSHeader & header, QImage & img )
+       {
+               const uint w = header.width;
+               const uint h = header.height;
+
+               BlockDXTAlphaLinear xblock;
+               BlockDXTAlphaLinear yblock;
+               QRgb * scanline[4];
+
+               for( uint y = 0; y < h; y += 4 ) {
+                       for( uint j = 0; j < 4; j++ ) {
+                               scanline[j] = (QRgb *) img.scanLine( y + j );
+                       }
+                       for( uint x = 0; x < w; x += 4 ) {
+
+                               // Read 128bit color block.
+                               s >> xblock;
+                               s >> yblock;
+
+                               // Decode color block.
+                               uchar xblock_array[8];
+                               xblock.GetAlphas(xblock_array);
+
+                               uchar xbit_array[16];
+                               xblock.GetBits(xbit_array);
+
+                               uchar yblock_array[8];
+                               yblock.GetAlphas(yblock_array);
+
+                               uchar ybit_array[16];
+                               yblock.GetBits(ybit_array);
+
+                               // Write color block.
+                               for( uint j = 0; j < 4; j++ ) {
+                                       for( uint i = 0; i < 4; i++ ) {
+                                               if( img.valid( x+i, y+j ) ) {
+                                                       const uchar nx = xblock_array[xbit_array[j*4+i]];
+                                                       const uchar ny = yblock_array[ybit_array[j*4+i]];
+
+                                                       const float fx = float(nx) / 127.5f - 1.0f;
+                                                       const float fy = float(ny) / 127.5f - 1.0f;
+                                                       const float fz = sqrtf(1.0f - fx*fx - fy*fy);
+                                                       const uchar nz = uchar((fz + 1.0f) * 127.5f);
+
+                                                       scanline[j][x+i] = qRgb(nx, ny, nz);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return true;
+       }
+
+
+
+       typedef bool (* TextureLoader)( QDataStream & s, const DDSHeader & header, QImage & img );

       // Get an appropiate texture loader for the given type.
- -     TextureLoader GetTextureLoader( DDSType type ) {
+       static TextureLoader GetTextureLoader( DDSType type ) {
               switch( type ) {
                       case DDS_A8R8G8B8:
                               return LoadA8R8G8B8;
@@ -664,6 +795,10 @@ namespace {        // Private.
                               return LoadDXT4;
                       case DDS_DXT5:
                               return LoadDXT5;
+                       case DDS_RXGB:
+                               return LoadRXGB;
+                       case DDS_ATI2:
+                               return LoadATI2;
                       default:
                               return NULL;
               };
@@ -671,7 +806,7 @@ namespace { // Private.


       // Load a 2d texture.
- -     bool LoadTexture( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadTexture( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               // Create dst image.
               if( !img.create( header.width, header.height, 32 )) {
@@ -695,7 +830,7 @@ namespace { // Private.
       }


- -     int FaceOffset( const DDSHeader & header ) {
+       static int FaceOffset( const DDSHeader & header ) {

               DDSType type = GetType( header );

@@ -727,11 +862,11 @@ namespace {       // Private.
       }

#if CUBE_LAYOUT == HORIZONTAL
- -     int face_offset[6][2] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {3, 1} };
+       static int face_offset[6][2] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {3, 1} };
#elif CUBE_LAYOUT == VERTICAL
- -     int face_offset[6][2] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {1, 3} };
+       static int face_offset[6][2] = { {2, 1}, {0, 1}, {1, 0}, {1, 2}, {1, 1}, {1, 3} };
#endif
- -     int face_flags[6] = {
+       static int face_flags[6] = {
               DDSCAPS2_CUBEMAP_POSITIVEX,
               DDSCAPS2_CUBEMAP_NEGATIVEX,
               DDSCAPS2_CUBEMAP_POSITIVEY,
@@ -741,7 +876,7 @@ namespace { // Private.
       };

       // Load unwrapped cube map.
- -     bool LoadCubeMap( QDataStream & s, const DDSHeader & header, QImage img )
+       static bool LoadCubeMap( QDataStream & s, const DDSHeader & header, QImage & img )
       {
               // Create dst image.
#if CUBE_LAYOUT == HORIZONTAL
diff -u -3 -d -p -r1.3 -r1.3.2.1
- --- exr.cpp   9 Jun 2004 08:28:36 -0000       1.3
+++ exr.cpp     19 Apr 2005 11:11:09 -0000      1.3.2.1
@@ -136,6 +136,8 @@ void kimgio_exr_read( QImageIO *io )
        file.readPixels (dw.min.y, dw.max.y);

               QImage image(width, height, 32, 0, QImage::BigEndian);
+               if( image.isNull())
+                       return;

               // somehow copy pixels into image
               for ( int y=0; y < height; y++ ) {
diff -u -3 -d -p -r1.21 -r1.21.2.1
- --- ico.cpp   9 Jun 2004 08:28:36 -0000       1.21
+++ ico.cpp     19 Apr 2005 11:11:09 -0000      1.21.2.1
@@ -113,6 +113,8 @@ namespace
            // closest size match precedes everything else
            if ( std::abs( int( lhs.width - size ) ) <
                 std::abs( int( rhs.width - size ) ) ) return true;
+            else if ( std::abs( int( lhs.width - size ) ) >
+                 std::abs( int( rhs.width - size ) ) ) return false;
            else if ( colors == 0 )
            {
                // high/true color requested
@@ -144,17 +146,31 @@ namespace
               header.biBitCount != 8 && header.biBitCount != 24 &&
               header.biBitCount != 32 ) ) return false;

- -        unsigned colors = header.biBitCount >= 24 ?
- -                          0 : header.biClrUsed ?
- -                          header.biClrUsed : 1 << header.biBitCount;
+        unsigned paletteSize, paletteEntries;
+
+        if (header.biBitCount > 8)
+        {
+            paletteEntries = 0;
+            paletteSize    = 0;
+        }
+        else
+        {
+            paletteSize    = (1 << header.biBitCount);
+            paletteEntries = paletteSize;
+            if (header.biClrUsed && header.biClrUsed < paletteSize)
+                paletteEntries = header.biClrUsed;
+        }
+
        // Always create a 32-bit image to get the mask right
+        // Note: this is safe as rec.width, rec.height are bytes
        icon.create( rec.width, rec.height, 32 );
        if ( icon.isNull() ) return false;
        icon.setAlphaBuffer( true );

- -        QMemArray< QRgb > colorTable( 1 << header.biBitCount );
+        QMemArray< QRgb > colorTable( paletteSize );
+
        colorTable.fill( QRgb( 0 ) );
- -        for ( unsigned i = 0; i < colors; ++i )
+        for ( unsigned i = 0; i < paletteEntries; ++i )
        {
            unsigned char rgb[ 4 ];
            stream.readRawBytes( reinterpret_cast< char* >( &rgb ),
@@ -163,6 +179,7 @@ namespace
        }

        unsigned bpl = ( rec.width * header.biBitCount + 31 ) / 32 * 4;
+
        unsigned char* buf = new unsigned char[ bpl ];
        unsigned char** lines = icon.jumpTable();
        for ( unsigned y = rec.height; !stream.atEnd() && y--; )
@@ -265,11 +282,13 @@ extern "C" void kimgio_ico_read( QImageI
        stream >> rec;
        icons.push_back( rec );
    }
- -    IconList::const_iterator selected =
- -        requestedIndex >= 0 ?
- -        std::min( icons.begin() + requestedIndex, icons.end() ) :
- -        std::min_element( icons.begin(), icons.end(),
+    IconList::const_iterator selected;
+    if (requestedIndex >= 0) {
+        selected = std::min( icons.begin() + requestedIndex, icons.end() );
+    } else {
+        selected = std::min_element( icons.begin(), icons.end(),
                          LessDifference( requestedSize, requestedColors ) );
+    }
    if ( stream.atEnd() || selected == icons.end() ||
         offset + selected->offset > io->ioDevice()->size() )
        return;
diff -u -3 -d -p -r1.13 -r1.13.6.1
- --- jp2.cpp   30 Sep 2003 12:49:01 -0000      1.13
+++ jp2.cpp     19 Apr 2005 11:11:09 -0000      1.13.6.1
@@ -157,8 +157,9 @@ namespace {
       void
       draw_view_gray( gs_t& gs, QImage& qti )
       {
- -             qti.create( jas_image_width( gs.image ), jas_image_height( gs.image ),
- -                     8, 256 );
+               if( !qti.create( jas_image_width( gs.image ), jas_image_height( gs.image ),
+                       8, 256 ))
+                       return;
               for( int i = 0; i < 256; ++i )
                       qti.setColor( i, qRgb( i, i, i ) );

diff -u -3 -d -p -r1.11 -r1.11.6.1
- --- pcx.cpp   23 Oct 2003 13:17:27 -0000      1.11
+++ pcx.cpp     19 Apr 2005 11:11:09 -0000      1.11.6.1
@@ -1,5 +1,5 @@
/* This file is part of the KDE project
- -   Copyright (C) 2002-2003 Nadeem Hasan <[email protected]>
+   Copyright (C) 2002-2005 Nadeem Hasan <[email protected]>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -44,6 +44,11 @@ static QDataStream &operator>>( QDataStr
  s >> ph.HScreenSize;
  s >> ph.VScreenSize;

+  // Skip the rest of the header
+  Q_UINT8 byte;
+  while ( s.device()->at() < 128 )
+    s >> byte;
+
  return s;
}

@@ -85,25 +90,22 @@ static QDataStream &operator<<( QDataStr
  return s;
}

- -static PCXHEADER header;
- -static QImage img;
- -static Q_UINT16 w, h;
- -
- -void PCXHEADER::reset()
+PCXHEADER::PCXHEADER()
{
+  // Initialize all data to zero
  QByteArray dummy( 128 );
  dummy.fill( 0 );
  QDataStream s( dummy, IO_ReadOnly );
  s >> *this;
}

- -static void readLine( QDataStream &s, QByteArray &buf )
+static void readLine( QDataStream &s, QByteArray &buf, const PCXHEADER &header )
{
  Q_UINT32 i=0;
  Q_UINT32 size = buf.size();
  Q_UINT8 byte, count;

- -  if ( header.Encoding == 1 )
+  if ( header.isCompressed() )
  {
    // Uncompress the image data
    while ( i < size )
@@ -130,13 +132,14 @@ static void readLine( QDataStream &s, QB
  }
}

- -static void readImage1( QDataStream &s )
+static void readImage1( QImage &img, QDataStream &s, const PCXHEADER &header )
{
  QByteArray buf( header.BytesPerLine );

- -  img.create( w, h, 1, 2, QImage::BigEndian );
+  if(!img.create( header.width(), header.height(), 1, 2, QImage::BigEndian ))
+    return;

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    if ( s.atEnd() )
    {
@@ -144,10 +147,11 @@ static void readImage1( QDataStream &s )
      return;
    }

- -    readLine( s, buf );
- -
- -    for ( int x=0; x<header.BytesPerLine; ++x )
- -      *( img.scanLine( y )+x ) = buf[ x ];
+    readLine( s, buf, header );
+    uchar *p = img.scanLine( y );
+    unsigned int bpl = QMIN((header.width()+7)/8, header.BytesPerLine);
+    for ( unsigned int x=0; x< bpl; ++x )
+      p[ x ] = buf[x];
  }

  // Set the color palette
@@ -155,14 +159,15 @@ static void readImage1( QDataStream &s )
  img.setColor( 1, qRgb( 255, 255, 255 ) );
}

- -static void readImage4( QDataStream &s )
+static void readImage4( QImage &img, QDataStream &s, const PCXHEADER &header )
{
  QByteArray buf( header.BytesPerLine*4 );
- -  QByteArray pixbuf( w );
+  QByteArray pixbuf( header.width() );

- -  img.create( w, h, 8, 16, QImage::IgnoreEndian );
+  if(!img.create( header.width(), header.height(), 8, 16 ))
+    return;

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    if ( s.atEnd() )
    {
@@ -171,20 +176,19 @@ static void readImage4( QDataStream &s )
    }

    pixbuf.fill( 0 );
- -    readLine( s, buf );
+    readLine( s, buf, header );

    for ( int i=0; i<4; i++ )
    {
      Q_UINT32 offset = i*header.BytesPerLine;
- -      for ( int x=0; x<w; ++x )
+      for ( unsigned int x=0; x<header.width(); ++x )
        if ( buf[ offset + ( x/8 ) ] & ( 128 >> ( x%8 ) ) )
          pixbuf[ x ] += ( 1 << i );
    }

    uchar *p = img.scanLine( y );
- -
- -    for ( int x=0; x<w; ++x )
- -      *p++ = pixbuf[ x ];
+    for ( unsigned int x=0; x<header.width(); ++x )
+      p[ x ] = pixbuf[ x ];
  }

  // Read the palette
@@ -192,13 +196,14 @@ static void readImage4( QDataStream &s )
    img.setColor( i, header.ColorMap.color( i ) );
}

- -static void readImage8( QDataStream &s )
+static void readImage8( QImage &img, QDataStream &s, const PCXHEADER &header )
{
  QByteArray buf( header.BytesPerLine );

- -  img.create( w, h, 8, 256, QImage::IgnoreEndian );
+  if(!img.create( header.width(), header.height(), 8, 256 ))
+    return;

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    if ( s.atEnd() )
    {
@@ -206,19 +211,19 @@ static void readImage8( QDataStream &s )
      return;
    }

- -    readLine( s, buf );
+    readLine( s, buf, header );

    uchar *p = img.scanLine( y );
- -
- -    for ( int x=0; x<header.BytesPerLine; ++x )
- -      *p++ = buf[ x ];
+    unsigned int bpl = QMIN(header.BytesPerLine, header.width());
+    for ( unsigned int x=0; x<bpl; ++x )
+      p[ x ] = buf[ x ];
  }

  Q_UINT8 flag;
  s >> flag;
- -  kdDebug() << "Flag: " << flag << endl;
+  kdDebug( 399 ) << "Palette Flag: " << flag << endl;

- -  if ( flag == 12 && header.Version == 5 )
+  if ( flag == 12 && ( header.Version == 5 || header.Version == 2 ) )
  {
    // Read the palette
    Q_UINT8 r, g, b;
@@ -230,15 +235,16 @@ static void readImage8( QDataStream &s )
  }
}

- -static void readImage24( QDataStream &s )
+static void readImage24( QImage &img, QDataStream &s, const PCXHEADER &header )
{
  QByteArray r_buf( header.BytesPerLine );
  QByteArray g_buf( header.BytesPerLine );
  QByteArray b_buf( header.BytesPerLine );

- -  img.create( w, h, 32 );
+  if(!img.create( header.width(), header.height(), 32 ))
+    return;

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    if ( s.atEnd() )
    {
@@ -246,14 +252,13 @@ static void readImage24( QDataStream &s
      return;
    }

- -    readLine( s, r_buf );
- -    readLine( s, g_buf );
- -    readLine( s, b_buf );
+    readLine( s, r_buf, header );
+    readLine( s, g_buf, header );
+    readLine( s, b_buf, header );

    uint *p = ( uint * )img.scanLine( y );
- -
- -    for ( int x=0; x<header.BytesPerLine; ++x )
- -      *p++ = qRgb( r_buf[ x ], g_buf[ x ], b_buf[ x ] );
+    for ( unsigned int x=0; x<header.width(); ++x )
+      p[ x ] = qRgb( r_buf[ x ], g_buf[ x ], b_buf[ x ] );
  }
}

@@ -268,6 +273,8 @@ void kimgio_pcx_read( QImageIO *io )
    return;
  }

+  PCXHEADER header;
+
  s >> header;

  if ( header.Manufacturer != 10 || s.atEnd())
@@ -276,10 +283,8 @@ void kimgio_pcx_read( QImageIO *io )
    return;
  }

- -  w = ( header.XMax-header.XMin ) + 1;
- -  h = ( header.YMax-header.YMin ) + 1;
- -
- -  img.reset();
+  int w = header.width();
+  int h = header.height();

  kdDebug( 399 ) << "Manufacturer: " << header.Manufacturer << endl;
  kdDebug( 399 ) << "Version: " << header.Version << endl;
@@ -288,30 +293,27 @@ void kimgio_pcx_read( QImageIO *io )
  kdDebug( 399 ) << "Width: " << w << endl;
  kdDebug( 399 ) << "Height: " << h << endl;
  kdDebug( 399 ) << "Window: " << header.XMin << "," << header.XMax << ","
- -            << header.YMin << "," << header.YMax << endl;
+                 << header.YMin << "," << header.YMax << endl;
  kdDebug( 399 ) << "BytesPerLine: " << header.BytesPerLine << endl;
  kdDebug( 399 ) << "NPlanes: " << header.NPlanes << endl;

- -  // Skip the rest of the header
- -  Q_UINT8 byte;
- -  while ( s.device()->at() < 128 )
- -    s >> byte;
+  QImage img;

  if ( header.Bpp == 1 && header.NPlanes == 1 )
  {
- -    readImage1( s );
+    readImage1( img, s, header );
  }
  else if ( header.Bpp == 1 && header.NPlanes == 4 )
  {
- -    readImage4( s );
+    readImage4( img, s, header );
  }
  else if ( header.Bpp == 8 && header.NPlanes == 1 )
  {
- -    readImage8( s );
+    readImage8( img, s, header );
  }
  else if ( header.Bpp == 8 && header.NPlanes == 3 )
  {
- -    readImage24( s );
+    readImage24( img, s, header );
  }

  kdDebug( 399 ) << "Image Bytes: " << img.numBytes() << endl;
@@ -359,7 +361,7 @@ static void writeLine( QDataStream &s, Q
  }
}

- -static void writeImage1( QDataStream &s )
+static void writeImage1( QImage &img, QDataStream &s, PCXHEADER &header )
{
  img = img.convertBitOrder( QImage::BigEndian );

@@ -367,29 +369,27 @@ static void writeImage1( QDataStream &s
  header.NPlanes = 1;
  header.BytesPerLine = img.bytesPerLine();

- -  header.ColorMap.setColor( 0, qRgb( 0, 0, 0 ) );
- -  header.ColorMap.setColor( 1, qRgb( 255, 255, 255 ) );
- -
  s << header;

  QByteArray buf( header.BytesPerLine );

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    Q_UINT8 *p = img.scanLine( y );

+    // Invert as QImage uses reverse palette for monochrome images?
    for ( int i=0; i<header.BytesPerLine; ++i )
- -      buf[ i ] = p[ i ];
+      buf[ i ] = ~p[ i ];

    writeLine( s, buf );
  }
}

- -static void writeImage4( QDataStream &s )
+static void writeImage4( QImage &img, QDataStream &s, PCXHEADER &header )
{
  header.Bpp = 1;
  header.NPlanes = 4;
- -  header.BytesPerLine = w/8;
+  header.BytesPerLine = header.width()/8;

  for ( int i=0; i<16; ++i )
    header.ColorMap.setColor( i, img.color( i ) );
@@ -401,14 +401,14 @@ static void writeImage4( QDataStream &s
  for ( int i=0; i<4; ++i )
      buf[ i ].resize( header.BytesPerLine );

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    Q_UINT8 *p = img.scanLine( y );

    for ( int i=0; i<4; ++i )
      buf[ i ].fill( 0 );

- -    for ( int x=0; x<w; ++x )
+    for ( unsigned int x=0; x<header.width(); ++x )
    {
      for ( int i=0; i<4; ++i )
        if ( *( p+x ) & ( 1 << i ) )
@@ -420,7 +420,7 @@ static void writeImage4( QDataStream &s
  }
}

- -static void writeImage8( QDataStream &s )
+static void writeImage8( QImage &img, QDataStream &s, PCXHEADER &header )
{
  header.Bpp = 8;
  header.NPlanes = 1;
@@ -430,7 +430,7 @@ static void writeImage8( QDataStream &s

  QByteArray buf( header.BytesPerLine );

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    Q_UINT8 *p = img.scanLine( y );

@@ -449,23 +449,23 @@ static void writeImage8( QDataStream &s
    s << RGB( img.color( i ) );
}

- -static void writeImage24( QDataStream &s )
+static void writeImage24( QImage &img, QDataStream &s, PCXHEADER &header )
{
  header.Bpp = 8;
  header.NPlanes = 3;
- -  header.BytesPerLine = w;
+  header.BytesPerLine = header.width();

  s << header;

- -  QByteArray r_buf( w );
- -  QByteArray g_buf( w );
- -  QByteArray b_buf( w );
+  QByteArray r_buf( header.width() );
+  QByteArray g_buf( header.width() );
+  QByteArray b_buf( header.width() );

- -  for ( int y=0; y<h; ++y )
+  for ( int y=0; y<header.height(); ++y )
  {
    uint *p = ( uint * )img.scanLine( y );

- -    for ( int x=0; x<w; ++x )
+    for ( unsigned int x=0; x<header.width(); ++x )
    {
      QRgb rgb = *p++;
      r_buf[ x ] = qRed( rgb );
@@ -484,10 +484,10 @@ void kimgio_pcx_write( QImageIO *io )
  QDataStream s( io->ioDevice() );
  s.setByteOrder( QDataStream::LittleEndian );

- -  img = io->image();
+  QImage img = io->image();

- -  w = img.width();
- -  h = img.height();
+  int w = img.width();
+  int h = img.height();

  kdDebug( 399 ) << "Width: " << w << endl;
  kdDebug( 399 ) << "Height: " << h << endl;
@@ -495,6 +495,8 @@ void kimgio_pcx_write( QImageIO *io )
  kdDebug( 399 ) << "BytesPerLine: " << img.bytesPerLine() << endl;
  kdDebug( 399 ) << "Num Colors: " << img.numColors() << endl;

+  PCXHEADER header;
+
  header.Manufacturer = 10;
  header.Version = 5;
  header.Encoding = 1;
@@ -509,19 +511,19 @@ void kimgio_pcx_write( QImageIO *io )

  if ( img.depth() == 1 )
  {
- -    writeImage1( s );
+    writeImage1( img, s, header );
  }
  else if ( img.depth() == 8 && img.numColors() <= 16 )
  {
- -    writeImage4( s );
+    writeImage4( img, s, header );
  }
  else if ( img.depth() == 8 )
  {
- -    writeImage8( s );
+    writeImage8( img, s, header );
  }
  else if ( img.depth() == 32 )
  {
- -    writeImage24( s );
+    writeImage24( img, s, header );
  }

  io->setStatus( 0 );
Index: pcx.h
===================================================================
RCS file: /home/kde/kdelibs/kimgio/pcx.h,v
retrieving revision 1.4
retrieving revision 1.4.6.1
diff -u -3 -d -p -r1.4 -r1.4.6.1
- --- pcx.h     4 Jan 2003 00:48:25 -0000       1.4
+++ pcx.h       19 Apr 2005 11:11:09 -0000      1.4.6.1
@@ -49,7 +49,7 @@ class Palette
      rgb[ i ] = RGB( color );
    }

- -    QRgb color( int i )
+    QRgb color( int i ) const
    {
      return qRgb( rgb[ i ].r, rgb[ i ].g, rgb[ i ].b );
    }
@@ -60,12 +60,11 @@ class Palette
class PCXHEADER
{
  public:
- -    PCXHEADER()
- -    {
- -      reset();
- -    }
+    PCXHEADER();

- -    void reset();
+    inline int width() const { return ( XMax-XMin ) + 1; }
+    inline int height() const { return ( YMax-YMin ) + 1; }
+    inline bool isCompressed() const { return ( Encoding==1 ); }

    Q_UINT8  Manufacturer;    // Constant Flag, 10 = ZSoft .pcx
    Q_UINT8  Version;         // Version information�
@@ -99,7 +98,7 @@ class PCXHEADER
                              // found only in PB IV/IV Plus
    Q_UINT16 VScreenSize;     // Vertical screen size in pixels. New field
                              // found only in PB IV/IV Plus
- -};
+} KDE_PACKED;

#endif // PCX_H

diff -u -3 -d -p -r1.25 -r1.25.2.1
- --- rgb.cpp   9 Jun 2004 08:28:36 -0000       1.25
+++ rgb.cpp     19 Apr 2005 11:11:09 -0000      1.25.2.1
@@ -87,7 +87,9 @@ bool SGIImage::getRow(uchar *dest)
       int n, i;
       if (!m_rle) {
               for (i = 0; i < m_xsize; i++) {
- -                     *dest++ = uchar(*m_pos);
+                       if(m_pos >= m_data.end())
+                               return false;
+                       dest[i] = uchar(*m_pos);
                       m_pos += m_bpc;
               }
               return true;
@@ -120,7 +122,7 @@ bool SGIImage::readData(QImage& img)
{
       QRgb *c;
       Q_UINT32 *start = m_starttab;
- -     QCString lguard(m_xsize);
+       QByteArray lguard(m_xsize);
       uchar *line = (uchar *)lguard.data();
       unsigned x, y;

@@ -128,7 +130,7 @@ bool SGIImage::readData(QImage& img)
               m_pos = m_data.begin();

       for (y = 0; y < m_ysize; y++) {
- -             c = reinterpret_cast<QRgb *>(img.scanLine(m_ysize - y - 1));
+               c = (QRgb *) img.scanLine(m_ysize - y - 1);
               if (m_rle)
                       m_pos = m_data.begin() + *start++;
               if (!getRow(line))
@@ -166,11 +168,11 @@ bool SGIImage::readData(QImage& img)
       }

       for (y = 0; y < m_ysize; y++) {
- -             c = reinterpret_cast<QRgb *>(img.scanLine(m_ysize - y - 1));
               if (m_rle)
                       m_pos = m_data.begin() + *start++;
               if (!getRow(line))
                       return false;
+               c = (QRgb*) img.scanLine(m_ysize - y - 1);
               for (x = 0; x < m_xsize; x++, c++)
                       *c = qRgba(qRed(*c), qGreen(*c), qBlue(*c), line[x]);
       }
@@ -351,24 +353,32 @@ uchar SGIImage::intensity(uchar c)

uint SGIImage::compact(uchar *d, uchar *s)
{
- -     uchar *dest = d, *src = s, patt, *cnt;
- -     int n;
- -     while (src - s < m_xsize) {
- -             if (src - s + 1 == m_xsize) {           // last bit
- -                     *dest++ = 0x81;
- -                     *dest++ = *src;
+       uchar *dest = d, *src = s, patt, *t, *end = s + m_xsize;
+       int i, n;
+       while (src < end) {
+               for (n = 0, t = src; t + 2 < end && !(*t == t[1] && *t == t[2]); t++)
+                       n++;
+
+               while (n) {
+                       i = n > 126 ? 126 : n;
+                       n -= i;
+                       *dest++ = 0x80 | i;
+                       while (i--)
+                               *dest++ = *src++;
+               }
+
+               if (src == end)
                       break;
- -             } else if (*src == src[1]) {
- -                     patt = *src++;
- -                     for (n = 1; src - s < m_xsize && n < 126 && *src == patt; src++)
- -                             n++;
- -                     *dest++ = n;
+
+               patt = *src++;
+               for (n = 1; src < end && *src == patt; src++)
+                       n++;
+
+               while (n) {
+                       i = n > 126 ? 126 : n;
+                       n -= i;
+                       *dest++ = i;
                       *dest++ = patt;
- -             } else {
- -                     cnt = dest++;
- -                     for (n = 0; src - s < m_xsize && n < 126 && *src != src[1]; n++)
- -                             *dest++ = *src++;
- -                     *cnt = 0x80 | n;
               }
       }
       *dest++ = 0;
@@ -444,16 +454,12 @@ void SGIImage::writeHeader()
       kdDebug(399) << "Description: " << desc << endl;
       desc.truncate(79);

- -     char id[] = "KDE kimgio", *s = id;
       for (i = 0; i < desc.length(); i++)
               m_imagename[i] = desc.latin1()[i];
       for (; i < 80; i++)
               m_imagename[i] = '\0';
- -     if (desc.length() < 68)
- -             for (i = 69; *s; i++)
- -                     m_imagename[i] = *s++;
- -
       m_stream.writeRawBytes(m_imagename, 80);
+
       m_stream << m_colormap;
       for (i = 0; i < 404; i++)
               m_stream << Q_UINT8(0);
@@ -551,13 +557,6 @@ bool SGIImage::writeImage(QImage& img)

       m_numrows = m_ysize * m_zsize;

- -     // compressing a row with up to 11 pixels takes 11 or more bytes
- -     // (start/length table: 8, smallest possible RLE packet: 3)
- -     if (m_xsize <= 11) {
- -             writeVerbatim(img);
- -             return true;
- -     }
- -
       m_starttab = new Q_UINT32[m_numrows];
       m_rlemap.setBaseOffset(512 + m_numrows * 2 * sizeof(Q_UINT32));

@@ -579,7 +578,7 @@ bool SGIImage::writeImage(QImage& img)
       kdDebug(399) << "total savings: " << (verbatim_size - rle_size) << " bytes" << endl;
       kdDebug(399) << "compression: " << (rle_size * 100.0 / verbatim_size) << '%' << endl;

- -     if (verbatim_size <= rle_size)
+       if (verbatim_size <= rle_size || m_io->quality() > 50)
               writeVerbatim(img);
       else
               writeRle();
diff -u -3 -d -p -r1.7 -r1.7.2.1
- --- tga.cpp   1 Aug 2004 16:45:53 -0000       1.7
+++ tga.cpp     19 Apr 2005 11:11:09 -0000      1.7.2.1
@@ -1,5 +1,6 @@
/* This file is part of the KDE project
   Copyright (C) 2003 Dominik Seichter <[email protected]>
+   Copyright (C) 2004 Ignacio Casta�o <[email protected]>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the Lesser GNU General Public
@@ -9,213 +10,347 @@

/* this code supports:
 * reading:
- - *     run length encoded true color tga files
- - *     uncompressed true color tga files
+ *     uncompressed and run length encoded indexed, grey and color tga files.
+ *     image types 1, 2, 3, 9, 10 and 11.
+ *     only RGB color maps with no more than 256 colors.
+ *     pixel formats 8, 15, 24 and 32.
 * writing:
 *     uncompressed true color tga files
 */

#include "tga.h"

+#include <assert.h>
+
#include <qimage.h>
#include <qdatastream.h>

- -/*
- - * uncompressed TGA magic header
- - */
- -unsigned char targaMagic[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#include <kdebug.h>

- -/*
- - * compressed TGA magic header
- - */
- -unsigned char compMagic[12] = { 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+typedef Q_UINT32 uint;
+typedef Q_UINT16 ushort;
+typedef Q_UINT8 uchar;

- -/*
- - * the origin of the image (default is TOP_LEFT)
- - */
- -enum { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT };
+namespace {    // Private.

- -/*
- - * Read one pixel and return its color
- - */
- -int getData( QDataStream* s, int bpp )
- -{
- -    unsigned char* data = new unsigned char[bpp];
+       // Header format of saved files.
+       uchar targaMagic[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

- -    for( int d = 0; d < bpp; d++ )
- -        *s >> data[d];
+       enum TGAType {
+               TGA_TYPE_INDEXED                = 1,
+               TGA_TYPE_RGB                    = 2,
+               TGA_TYPE_GREY                   = 3,
+               TGA_TYPE_RLE_INDEXED    = 9,
+               TGA_TYPE_RLE_RGB                = 10,
+               TGA_TYPE_RLE_GREY               = 11
+       };

- -    int color = 0;
- -    if( bpp == 4 )
- -        color = qRgba( data[0], data[1], data[2], data[3] );
- -    else
- -        color = qRgb( data[0], data[1], data[2] );
+#define TGA_INTERLEAVE_MASK    0xc0
+#define TGA_INTERLEAVE_NONE    0x00
+#define TGA_INTERLEAVE_2WAY    0x40
+#define TGA_INTERLEAVE_4WAY    0x80

- -    delete [] data;
- -    return color;
- -}
+#define TGA_ORIGIN_MASK                0x30
+#define TGA_ORIGIN_LEFT                0x00
+#define TGA_ORIGIN_RIGHT       0x10
+#define TGA_ORIGIN_LOWER       0x00
+#define TGA_ORIGIN_UPPER       0x20

- -/*
- - * checks wether y is inside of the image
- - * when origin is of mode m
- - */
- -bool checky( int y, int h, int m )
- -{
- -    if( m == TOP_LEFT )
- -     return (y < h);
- -    else if( m == BOTTOM_LEFT || m == BOTTOM_RIGHT )
- -     return ( y >= 0 );
+       /** Tga Header. */
+       struct TgaHeader {
+               uchar id_length;
+               uchar colormap_type;
+               uchar image_type;
+               ushort colormap_index;
+               ushort colormap_length;
+               uchar colormap_size;
+               ushort x_origin;
+               ushort y_origin;
+               ushort width;
+               ushort height;
+               uchar pixel_size;
+               uchar flags;
+
+               enum { SIZE = 18 }; // const static int SIZE = 18;
+       };

- -    return false;
- -}
+       static QDataStream & operator>> ( QDataStream & s, TgaHeader & head )
+       {
+               s >> head.id_length;
+               s >> head.colormap_type;
+               s >> head.image_type;
+               s >> head.colormap_index;
+               s >> head.colormap_length;
+               s >> head.colormap_size;
+               s >> head.x_origin;
+               s >> head.y_origin;
+               s >> head.width;
+               s >> head.height;
+               s >> head.pixel_size;
+               s >> head.flags;
+               return s;
+       }

- -  /*
- -   * checks wether x is inside of the image
- -   * when origin is of mode m
- -   */
- -  bool checkx( int x, int w, int m )
- -  {
- -      if( m == TOP_LEFT || m == BOTTOM_LEFT )
- -       return (x < w);
- -      else if( m == BOTTOM_RIGHT )
- -       return ( x >= 0 );
+       static bool IsSupported( const TgaHeader & head )
+       {
+               if( head.image_type != TGA_TYPE_INDEXED &&
+                       head.image_type != TGA_TYPE_RGB &&
+                       head.image_type != TGA_TYPE_GREY &&
+                       head.image_type != TGA_TYPE_RLE_INDEXED &&
+                       head.image_type != TGA_TYPE_RLE_RGB &&
+                       head.image_type != TGA_TYPE_RLE_GREY )
+               {
+                       return false;
+               }
+               if( head.image_type == TGA_TYPE_INDEXED ||
+                       head.image_type == TGA_TYPE_RLE_INDEXED )
+               {
+                       if( head.colormap_length > 256 || head.colormap_size != 24 )
+                       {
+                               return false;
+                       }
+               }
+               if( head.width == 0 || head.height == 0 )
+               {
+                       return false;
+               }
+               if( head.pixel_size != 8 && head.pixel_size != 16 &&
+                       head.pixel_size != 24 && head.pixel_size != 32 )
+               {
+                       return false;
+               }
+               return true;
+       }

- -      return false;
- -  }
+       struct Color555 {
+               ushort b : 5;
+               ushort g : 5;
+               ushort r : 5;
+       };
+
+       static bool HasAlpha( const TgaHeader & tga )
+       {
+               return tga.pixel_size == 32;
+       }

- -  void kimgio_tga_read( QImageIO *io )
- -  {
- -      unsigned char header[6];
- -      bool compressed = false;
+       struct TgaHeaderInfo {
+               bool rle;
+               bool pal;
+               bool rgb;
+               bool grey;
+               bool supported;
+
+               TgaHeaderInfo( const TgaHeader & tga ) : rle(false), pal(false), rgb(false), grey(false), supported(true)
+               {
+                       switch( tga.image_type ) {
+                               case TGA_TYPE_RLE_INDEXED:
+                                       rle = true;
+                                       // no break is intended!
+                               case TGA_TYPE_INDEXED:
+                                       if( tga.colormap_type!=1 || tga.colormap_size!=24 || tga.colormap_length>256 ) {
+                                               supported = false;
+                                       }
+                                       pal = true;
+                                       break;
+
+                               case TGA_TYPE_RLE_RGB:
+                                       rle = true;
+                                       // no break is intended!
+                               case TGA_TYPE_RGB:
+                                       rgb = true;
+                                       break;
+
+                               case TGA_TYPE_RLE_GREY:
+                                       rle = true;
+                                       // no break is intended!
+                               case TGA_TYPE_GREY:
+                                       grey = true;
+                                       break;
+
+                               default:
+                                       // Error, unknown image type.
+                                       supported = false;
+                       }
+               }
+       };
+

- -      QDataStream s( io->ioDevice() );
- -      s.setByteOrder( QDataStream::LittleEndian );

- -      /*
- -       * check whether it is a targa file or not
- -       */
- -      for( int i = 0; i < 12; i++ ) {
- -       unsigned char a;
- -       s >> a;
- -       if( a != targaMagic[i] && a!= compMagic[i]) {
- -           io->setImage( 0 );
- -           io->setStatus( -1 );
- -           return;
- -       }
+       static bool LoadTGA( QDataStream & s, const TgaHeader & tga, QImage &img )
+       {
+               // Create image.
+               if( !img.create( tga.width, tga.height, 32 )) {
+                       return false;
+               }

- -       // check if it is a compressed targa file
- -       if( i == 2 && a == compMagic[i] )
- -           compressed = true;
- -      }
+               TgaHeaderInfo info(tga);
+               if( !info.supported ) {
+                       // File not supported.
+                       kdDebug(399) << "This TGA file is not supported." << endl;
+                       return false;
+               }
+
+               // Enable alpha buffer for transparent images.
+               if( HasAlpha( tga ) ) {
+                       img.setAlphaBuffer( true );
+               }

- -      for( int i = 0; i < 6; i++ )
- -       s >> header[i];
- -      if( s.atEnd()) {
- -       io->setImage( 0 );
- -       io->setStatus( -1 );
- -       return;
- -      }
+               uint pixel_size = (tga.pixel_size/8);
+               uint size = tga.width * tga.height * pixel_size;

- -      int width  = header[1] * 256 + header[0];
- -      int height = header[3] * 256 + header[2];
- -      int bpp = header[4];
- -      int bit = header[5];
- -      int bytesPerPixel = bpp / 8;
+
+               // Read palette.
+               char palette[768];
+               if( info.pal ) {
+                       // @todo Support palettes in other formats!
+                       s.readRawBytes( palette, 3 * tga.colormap_length );
+               }

- -    /* Bit values:
- -     * bit 0-3: number of alpha bits per fixel
- -     * bit 4-5: origin of image:
- -     *  - 0 0 bottom left
- -     *  - 1 0 bottom right
- -     *  - 0 1 top left // that's what we write
- -     *  - 1 1 top right
- -     */
+               // Allocate image.
+               uchar * const image = new uchar[size];

- -    int mode;
- -    if( (bit | 0)  == 0 )
- -     mode = BOTTOM_LEFT;
- -    else if( (bit & 8) == 8 )
- -     /*
- -      * should be BOTTOM_RIGHT,
- -      * but GIMP writes them this way.
- -      */
- -     mode = BOTTOM_LEFT;
- -    else if( (bit & 32) == 32 )
- -     mode = TOP_LEFT;
- -    else
- -     mode = TOP_LEFT;
+               if( info.rle ) {
+                       // Decode image.
+                       char * dst = (char *)image;
+                       int num = size;
+
+                       while (num > 0) {
+                               // Get packet header.
+                               uchar c;
+                               s >> c;
+
+                               uint count = (c & 0x7f) + 1;
+                               num -= count * pixel_size;
+
+                               if (c & 0x80) {
+                                       // RLE pixels.
+                                        assert(pixel_size <= 8);
+                                       char pixel[8];
+                                       s.readRawBytes( pixel, pixel_size );
+                                       do {
+                                               memcpy(dst, pixel, pixel_size);
+                                               dst += pixel_size;
+                                       } while (--count);
+                               }
+                               else {
+                                       // Raw pixels.
+                                       count *= pixel_size;
+                                       s.readRawBytes( dst, count );
+                                       dst += count;
+                               }
+                       }
+               }
+               else {
+                       // Read raw image.
+                       s.readRawBytes( (char *)image, size );
+               }

- -    if( bytesPerPixel != 3 &&  bytesPerPixel != 4 ) {
- -     io->setImage( 0 );
- -     io->setStatus( -1 );
- -     return;
- -    }
+               // Convert image to internal format.
+               int y_start, y_step, y_end;
+               if( tga.flags & TGA_ORIGIN_UPPER ) {
+                       y_start = 0;
+                       y_step = 1;
+                       y_end = tga.height - 1;
+               }
+               else {
+                       y_start = tga.height - 1;
+                       y_step = -1;
+                       y_end = 0;
+               }

- -    QImage img;
- -    if( !img.create( width, height, (bpp == 24 ? 32 : bpp) )) {
- -        io->setImage( 0 );
- -        io->setStatus( -1 );
- -        return;
- -    }
+               uchar * src = image;

- -    /*
- -     * Enable alpha buffer for transparent images
- -     */
- -    if( img.depth() == 32 )
- -     img.setAlphaBuffer( true );
+               for( int y = y_start; y != y_end; y += y_step ) {
+                       QRgb * scanline = (QRgb *) img.scanLine( y );
+
+                       if( info.pal ) {
+                               // Paletted.
+                               for( int x = 0; x < tga.width; x++ ) {
+                                       uchar idx = *src++;
+                                       scanline[x] = qRgb( palette[3*idx+2], palette[3*idx+1], palette[3*idx+0] );
+                               }
+                       }
+                       else if( info.grey ) {
+                               // Greyscale.
+                               for( int x = 0; x < tga.width; x++ ) {
+                                       scanline[x] = qRgb( *src, *src, *src );
+                                       src++;
+                               }
+                       }
+                       else {
+                               // True Color.
+                               if( tga.pixel_size == 16 ) {
+                                       for( int x = 0; x < tga.width; x++ ) {
+                                               Color555 c = *reinterpret_cast<Color555 *>(src);
+                                               scanline[x] = qRgb( (c.r << 3) | (c.r >> 2), (c.g << 3) | (c.g >> 2), (c.b << 3) | (c.b >> 2) );
+                                               src += 2;
+                                       }
+                               }
+                               else if( tga.pixel_size == 24 ) {
+                                       for( int x = 0; x < tga.width; x++ ) {
+                                               scanline[x] = qRgb( src[2], src[1], src[0] );
+                                               src += 3;
+                                       }
+                               }
+                               else if( tga.pixel_size == 32 ) {
+                                       for( int x = 0; x < tga.width; x++ ) {
+                                               scanline[x] = qRgba( src[2], src[1], src[0], src[3] );
+                                               src += 4;
+                                       }
+                               }
+                       }
+               }

+               // Free image.
+               delete [] image;
+
+               return true;
+       }
+
+} // namespace

- -    int x = 0;
- -    int y = 0;
- -    int addy = 1;
- -    int addx = 1;
- -    if( mode == BOTTOM_LEFT || mode == BOTTOM_RIGHT ) {
- -     y = height - 1;
- -     addy = -1;
- -    }

- -    if( mode == BOTTOM_RIGHT || mode == TOP_RIGHT ) {
- -     x = width - 1;
- -     addx = -1;
- -    }
+void kimgio_tga_read( QImageIO *io )
+{
+       //kdDebug(399) << "Loading TGA file!" << endl;
+
+       QDataStream s( io->ioDevice() );
+       s.setByteOrder( QDataStream::LittleEndian );
+
+
+       // Read image header.
+       TgaHeader tga;
+       s >> tga;
+       s.device()->at( TgaHeader::SIZE + tga.id_length );
+
+       // Check image file format.
+       if( s.atEnd() ) {
+               kdDebug(399) << "This TGA file is not valid." << endl;
+               io->setImage( 0 );
+               io->setStatus( -1 );
+               return;
+       }
+
+       // Check supported file types.
+       if( !IsSupported(tga) ) {
+               kdDebug(399) << "This TGA file is not supported." << endl;
+               io->setImage( 0 );
+               io->setStatus( -1 );
+               return;
+       }
+
+
+       QImage img;
+       bool result = LoadTGA(s, tga, img);
+
+       if( result == false ) {
+               kdDebug(399) << "Error loading TGA file." << endl;
+               io->setImage( 0 );
+               io->setStatus( -1 );
+               return;
+       }

- -    /*
- -     * we have to restore the value of x after each loop
- -     */
- -    int oldx = x;
- -    if( !compressed ) {
- -     for( ; !s.atEnd() && checky( y, height, mode ); y += addy )
- -         for( x = oldx; checkx( x, width, mode ); x += addx  ) {
- -             img.setPixel( x, y, getData( &s, bytesPerPixel ) );
- -         }
- -    } else {
- -        unsigned char cur;
- -        while( !s.atEnd() && checky( y, height, mode ) ) {
- -            while( checkx( x, width, mode ) ) {
- -                s >> cur;
- -                if( (cur & 128) == 128 ) {
- -                    // found a RLE chunk
- -                    int length = (cur & 127) + 1;
- -                    int color = getData( &s, bytesPerPixel );
- -                    for( int i = 0; i < length; i++ ) {
- -                        img.setPixel( x, y, color );
- -                        x += addx;
- -                    }
- -                } else {
- -                    int length = (cur & 127) + 1;
- -                    for( int i = 0; i < length; i++ ) {
- -                        img.setPixel( x, y, getData( &s, bytesPerPixel ) );
- -                        x += addx;
- -                   }
- -                }
- -            }
- -            y += addy;
- -            x = oldx;
- -        }
- -    }

- -    img = img.swapRGB();
- -
    io->setImage( img );
    io->setStatus( 0 );
}
diff -u -3 -d -p -r1.12 -r1.12.2.1
- --- tiffr.cpp 9 Jun 2004 08:28:36 -0000       1.12
+++ tiffr.cpp   19 Apr 2005 11:11:09 -0000      1.12.2.1
@@ -83,6 +83,10 @@ void kimgio_tiff_read( QImageIO *io )
            return;

       QImage image( width, height, 32 );
+       if( image.isNull()) {
+               TIFFClose( tiff );
+               return;
+       }
       data = (uint32 *)image.bits();

       //Sven: changed to %ld for 64bit machines
diff -u -3 -d -p -r1.10 -r1.10.6.1
- --- xview.cpp 6 Sep 2003 19:06:36 -0000       1.10
+++ xview.cpp   19 Apr 2005 11:11:09 -0000      1.10.6.1
@@ -7,12 +7,16 @@

#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <qimage.h>

#include "xview.h"

#define BUFSIZE 1024

+static const int b_255_3[]= {0,85,170,255},  // index*255/3
+           rg_255_7[]={0,36,72,109,145,182,218,255}; // index *255/7
+
void kimgio_xv_read( QImageIO *_imageio )
{
       int x=-1;
@@ -48,10 +52,14 @@ void kimgio_xv_read( QImageIO *_imageio
       sscanf(str, "%d %d %d", &x, &y, &maxval);

       if (maxval != 255) return;
+       int blocksize = x*y;
+        if(x < 0 || y < 0 || blocksize < x || blocksize < y)
+            return;

       // now follows a binary block of x*y bytes.
- -     int blocksize = x*y;
- -     char *block = new char[ blocksize ];
+       char *block = (char*) malloc(blocksize);
+        if(!block)
+            return;

       if (iodev->readBlock(block, blocksize) != blocksize )
       {
@@ -60,6 +68,10 @@ void kimgio_xv_read( QImageIO *_imageio

       // Create the image
       QImage image( x, y, 8, maxval + 1, QImage::BigEndian );
+       if( image.isNull()) {
+                free(block);
+               return;
+        }

       // how do the color handling? they are absolute 24bpp
       // or at least can be calculated as such.
@@ -67,29 +79,9 @@ void kimgio_xv_read( QImageIO *_imageio

       for ( int j = 0; j < 256; j++ )
       {
- -// ----------- OLIVER EIDEN
- -//   That is the old-code !
- -/*           r =  ((int) ((j >> 5) & 0x07)) << 5;
- -             g =  ((int) ((j >> 2) & 0x07)) << 5;
- -             b =  ((int) ((j >> 0) & 0x03)) << 6;*/
- -
- -
- -//   That is the code-how xv, decode 3-3-2 pixmaps, it is slighly different,
- -//   but yields much better visuals results
- -/*           r =  (((int) ((j >> 5) & 0x07)) *255) / 7;
- -             g =  (((int) ((j >> 2) & 0x07)) *255) / 7;
- -             b =  (((int) ((j >> 0) & 0x03)) *255) / 3;*/
- -
- -//   This is the same as xv, with multiplications/divisions replaced by indexing
- -
- -//      Look-up table to avoid multiplications and divisons
- -     static int b_255_3[]= {0,85,170,255},  // index*255/3
- -                rg_255_7[]={0,36,72,109,145,182,218,255}; // index *255/7
- -
               r =  rg_255_7[((j >> 5) & 0x07)];
               g =  rg_255_7[((j >> 2) & 0x07)];
               b =  b_255_3[((j >> 0) & 0x03)];
- -// ---------------
               image.setColor( j, qRgb( r, g, b ) );
       }

@@ -102,7 +94,7 @@ void kimgio_xv_read( QImageIO *_imageio
       _imageio->setImage( image );
       _imageio->setStatus( 0 );

- -     delete [] block;
+       free(block);
       return;
}

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)

iD8DBQFCerlJvsXr+iuy1UoRAt0SAJ9jaZQjDf8/OnA32Pk13yNjhaCTUwCfa/k5
v6XrOfrae8BRpThvgnRjFCM=
=O5/k
-----END PGP SIGNATURE-----