Группа :: Графические оболочки/KDE
Пакет: kdelibs
Главная Изменения Спек Патчи Загрузить Bugs and FR
Патч: post-3.3.2-kdelibs-kimgio-fixed.diff
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 <nhasan@kde.org>
+ Copyright (C) 2002-2005 Nadeem Hasan <nhasan@kde.org>
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 <domseichter@web.de>
+ Copyright (C) 2004 Ignacio CastaЯo <castano@ludicon.com>
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;
}