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 +#include // 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 + Copyright (C) 2002-2005 Nadeem Hasan 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> ( x%8 ) ) ) pixbuf[ x ] += ( 1 << i ); } uchar *p = img.scanLine( y ); - - for ( int x=0; x> 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> 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; yioDevice() ); 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(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(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]); } @@ -270,7 +272,7 @@ bool SGIImage::readImage(QImage& img) // sanity ckeck if (m_rle) for (uint o = 0; o < m_numrows; o++) - if (m_starttab[o] + m_lengthtab[o] > m_data.size()) { + if (m_starttab[o] + m_lengthtab[o] >= m_data.size()) { kdDebug(399) << "image corrupt (sanity check failed)" << endl; return false; } @@ -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 + Copyright (C) 2004 Ignacio Castaņo 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 + #include #include -/* - * uncompressed TGA magic header - */ -unsigned char targaMagic[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#include -/* - * 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(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 #include +#include #include #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; }