[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    dds kimgio plugin updated
From:       Ignacio_Castaņo <castanyo () yahoo ! es>
Date:       2004-02-10 0:16:49
Message-ID: 402822F1.8070603 () yahoo ! es
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


I've updated my DDS plugin for kimgio with the following:

- faster image loading.
- support cube map images.
- several buf fixes.

I think it would be a good idea to add a new kimgio_plugins directory to 
kdegraphics to place there unusual image formats like dds and the 
recently added exr, that I think shouldn't be inside kdelibs.

The attached patch should be applied inside kdelibs/kimgio, though.

I've also attached a desktop file for the dds mime type.

Feel free to send comments and suggestions.

-- 
Ignacio Castaņo
castanyo@yahoo.es

["kimgio_dds-2004-02-10.patch" (text/x-patch)]

Index: dds.cpp
===================================================================
RCS file: N/A
diff -u /dev/null dds.cpp
--- /dev/null	2004-01-29 00:50:03.000000000 +0100
+++ dds.cpp	2004-02-10 00:18:56.000000000 +0100
@@ -0,0 +1,879 @@
+/* This file is part of the KDE project
+   Copyright (C) 2003 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
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   Almost all this code is based on nVidia's DDS-loading example
+   and the DevIl's source code by Denton Woods.
+*/
+
+/* this code supports:
+ * reading:
+ *     rgb and dxt dds files
+ *     cubemap dds files
+ *     volume dds files -- TODO
+ * writing:
+ *     rgb dds files only -- TODO
+ */
+
+#include "dds.h"
+
+#include <qimage.h>
+#include <qdatastream.h>
+
+
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+
+namespace {	// Private.
+
+#if !defined(MAKEFOURCC)
+#	define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+		(uint(uchar(ch0)) | (uint(uchar(ch1)) << 8) | \
+		(uint(uchar(ch2)) << 16) | (uint(uchar(ch3)) << 24 ))
+#endif
+
+#define max(a,b)	((a)>?(b))
+
+#define HORIZONTAL 1
+#define VERTICAL 2
+#define CUBE_LAYOUT	HORIZONTAL
+
+
+	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');
+
+	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;
+
+	const uint DDSCAPS_TEXTURE = 0x00001000l;
+	const uint DDSCAPS2_VOLUME = 0x00200000l;
+	const uint DDSCAPS2_CUBEMAP = 0x00000200l;
+
+	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;
+
+	enum DDSType {
+		DDS_A8R8G8B8 = 0,
+		DDS_A1R5G5B5 = 1,
+		DDS_A4R4G4B4 = 2,
+		DDS_R8G8B8 = 3,
+		DDS_R5G6B5 = 4,
+		DDS_DXT1 = 5,
+		DDS_DXT2 = 6,
+		DDS_DXT3 = 7,
+		DDS_DXT4 = 8,
+		DDS_DXT5 = 9,
+		DDS_UNKNOWN
+	};
+
+
+	struct DDSPixelFormat {
+		uint size;
+		uint flags;
+		uint fourcc;
+		uint bitcount;
+		uint rmask;
+		uint gmask;
+		uint bmask;
+		uint amask;
+	};
+
+	QDataStream & operator>> ( QDataStream & s, DDSPixelFormat & pf )
+	{
+		s >> pf.size;
+		s >> pf.flags;
+		s >> pf.fourcc;
+		s >> pf.bitcount;
+		s >> pf.rmask;
+		s >> pf.gmask;
+		s >> pf.bmask;
+		s >> pf.amask;
+		return s;
+	}
+
+	struct DDSCaps {
+		uint caps1;
+		uint caps2;
+		uint caps3;
+		uint caps4;
+	};
+
+	QDataStream & operator>> ( QDataStream & s, DDSCaps & caps )
+	{
+		s >> caps.caps1;
+		s >> caps.caps2;
+		s >> caps.caps3;
+		s >> caps.caps4;
+		return s;
+	}
+
+	struct DDSHeader {
+		uint size;
+		uint flags;
+		uint height;
+		uint width;
+		uint pitch;
+		uint depth;
+		uint mipmapcount;
+		uint reserved[11];
+		DDSPixelFormat pf;
+		DDSCaps caps;
+		uint notused;
+	};
+
+	QDataStream & operator>> ( QDataStream & s, DDSHeader & header )
+	{
+		s >> header.size;
+		s >> header.flags;
+		s >> header.height;
+		s >> header.width;
+		s >> header.pitch;
+		s >> header.depth;
+		s >> header.mipmapcount;
+		for( int i = 0; i < 11; i++ ) {
+			s >> header.reserved[i];
+		}
+		s >> header.pf;
+		s >> header.caps;
+		s >> header.notused;
+		return s;
+	}
+
+	bool IsValid( const DDSHeader & header )
+	{
+		if( header.size != 124 ) {
+			return false;
+		}
+		const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT);
+		if( (header.flags & required) != required ) {
+			return false;
+		}
+		if( header.pf.size != 32 ) {
+			return false;
+		}
+		if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
+			return false;
+		}
+		return true;
+	}
+
+
+	// Get supported type. We currently support 10 different types.
+	DDSType GetType( const DDSHeader & header )
+	{
+		if( header.pf.flags & DDPF_RGB ) {
+			if( header.pf.flags & DDPF_ALPHAPIXELS ) {
+				switch( header.pf.bitcount ) {
+					case 16:
+						return (header.pf.amask == 0x7000) ? DDS_A1R5G5B5 : DDS_A4R4G4B4;
+					case 32:
+						return DDS_A8R8G8B8;
+				}
+			}
+			else {
+				switch( header.pf.bitcount ) {
+					case 16:
+						return DDS_R5G6B5;
+					case 24:
+						return DDS_R8G8B8;
+				}
+			}
+		}
+		else if( header.pf.flags & DDPF_FOURCC ) {
+			switch( header.pf.fourcc ) {
+				case FOURCC_DXT1:
+					return DDS_DXT1;
+				case FOURCC_DXT2:
+					return DDS_DXT2;
+				case FOURCC_DXT3:
+					return DDS_DXT3;
+				case FOURCC_DXT4:
+					return DDS_DXT4;
+				case FOURCC_DXT5:
+					return DDS_DXT5;
+			}
+		}
+		return DDS_UNKNOWN;
+	}
+
+
+	bool HasAlpha( const DDSHeader & header )
+	{
+		return header.pf.flags & DDPF_ALPHAPIXELS;
+	}
+
+	bool IsCubeMap( const DDSHeader & header )
+	{
+		return header.caps.caps2 & DDSCAPS2_CUBEMAP;
+	}
+
+	bool IsSupported( const DDSHeader & header )
+	{
+		/*if( IsCubeMap(header) ) {
+			return false;
+		}*/
+		if( header.caps.caps2 & DDSCAPS2_VOLUME ) {
+			return false;
+		}
+		if( GetType(header) == DDS_UNKNOWN ) {
+			return false;
+		}
+		return true;
+	}
+
+
+	bool LoadA8R8G8B8( QDataStream & s, const DDSHeader & header, QImage img  )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		for( uint y = 0; y < h; y++ ) {
+			QRgb * scanline = (QRgb *) img.scanLine( y );
+			for( uint x = 0; x < w; x++ ) {
+				uchar r, g, b, a;
+				s >> b >> g >> r >> a;
+				scanline[x] = qRgba(r, g, b, a);
+			}
+		}
+
+		return true;
+	}
+
+	bool LoadR8G8B8( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		for( uint y = 0; y < h; y++ ) {
+			QRgb * scanline = (QRgb *) img.scanLine( y );
+			for( uint x = 0; x < w; x++ ) {
+				uchar r, g, b;
+				s >> b >> g >> r;
+				scanline[x] = qRgb(r, g, b);
+			}
+		}
+
+		return true;
+	}
+
+	bool LoadA1R5G5B5( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		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;
+				scanline[x] = qRgba(r, g, b, a);
+			}
+		}
+
+		return true;
+	}
+
+	bool LoadA4R4G4B4( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		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;
+				scanline[x] = qRgba(r, g, b, a);
+			}
+		}
+
+		return true;
+	}
+
+	bool LoadR5G6B5( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		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;
+				scanline[x] = qRgb(r, g, b);
+			}
+		}
+
+		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 )
+	{
+		return s >> c.u;
+	}
+
+
+	struct BlockDXT
+	{
+		Color565 col0;
+		Color565 col1;
+		uchar row[4];
+
+		void GetColors( Color8888 color_array[4] )
+		{
+			color_array[0].r = col0.c.r << 3;
+			color_array[0].g = col0.c.g << 2;
+			color_array[0].b = col0.c.b << 3;
+			color_array[0].a = 0xFF;
+
+			color_array[1].r = col1.c.r << 3;
+			color_array[1].g = col1.c.g << 2;
+			color_array[1].b = col1.c.b << 3;
+			color_array[1].a = 0xFF;
+
+			if( col0.u > col1.u ) {
+				// Four-color block: derive the other two colors.
+				color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
+				color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
+				color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
+				color_array[2].a = 0xFF;
+
+				color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
+				color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
+				color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
+				color_array[3].a = 0xFF;
+			}
+			else {
+				// Three-color block: derive the other color.
+				color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
+				color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
+				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;
+				color_array[3].a = 0x00;
+			}
+		}
+	};
+
+
+	QDataStream & operator>> ( QDataStream & s, BlockDXT & c )
+	{
+		return s >> c.col0 >> c.col1 >> c.row[0] >> c.row[1] >> c.row[2] >> c.row[3];
+	}
+
+	struct BlockDXTAlphaExplicit {
+		ushort row[4];
+	};
+
+	QDataStream & operator>> ( QDataStream & s, BlockDXTAlphaExplicit & c )
+	{
+		return s >> c.row[0] >> c.row[1] >> c.row[2] >> c.row[3];
+	}
+
+	struct BlockDXTAlphaLinear {
+		uchar alpha0;
+		uchar alpha1;
+		uchar bits[6];
+
+		void GetAlphas( uchar alpha_array[8] )
+		{
+			alpha_array[0] = alpha0;
+			alpha_array[1] = alpha1;
+
+			// 8-alpha or 6-alpha block?
+			if( alpha_array[0] > alpha_array[1] )
+			{
+				// 8-alpha block:  derive the other 6 alphas.
+				// 000 = alpha_0, 001 = alpha_1, others are interpolated
+
+				alpha_array[2] = ( 6 * alpha0 +     alpha1) / 7;	// bit code 010
+				alpha_array[3] = ( 5 * alpha0 + 2 * alpha1) / 7;	// Bit code 011
+				alpha_array[4] = ( 4 * alpha0 + 3 * alpha1) / 7;	// Bit code 100
+				alpha_array[5] = ( 3 * alpha0 + 4 * alpha1) / 7;	// Bit code 101
+				alpha_array[6] = ( 2 * alpha0 + 5 * alpha1) / 7;	// Bit code 110
+				alpha_array[7] = (     alpha0 + 6 * alpha1) / 7;	// Bit code 111
+			}
+			else
+			{
+				// 6-alpha block:  derive the other alphas.
+				// 000 = alpha_0, 001 = alpha_1, others are interpolated
+
+				alpha_array[2] = (4 * alpha0 +     alpha1) / 5;		// Bit code 010
+				alpha_array[3] = (3 * alpha0 + 2 * alpha1) / 5;		// Bit code 011
+				alpha_array[4] = (2 * alpha0 + 3 * alpha1) / 5;		// Bit code 100
+				alpha_array[5] = (    alpha0 + 4 * alpha1) / 5;		// Bit code 101
+				alpha_array[6] = 0x00;								// Bit code 110
+				alpha_array[7] = 0xFF;								// Bit code 111
+			}
+		}
+
+		void GetBits( uchar bit_array[16] )
+		{
+			uint b = (uint &) bits[0];
+			bit_array[0] = uchar(b & 0x07); b >>= 3;
+			bit_array[1] = uchar(b & 0x07); b >>= 3;
+			bit_array[2] = uchar(b & 0x07); b >>= 3;
+			bit_array[3] = uchar(b & 0x07); b >>= 3;
+			bit_array[4] = uchar(b & 0x07); b >>= 3;
+			bit_array[5] = uchar(b & 0x07); b >>= 3;
+			bit_array[6] = uchar(b & 0x07); b >>= 3;
+			bit_array[7] = uchar(b & 0x07); b >>= 3;
+
+			b = (uint &) bits[3];
+			bit_array[8] = uchar(b & 0x07); b >>= 3;
+			bit_array[9] = uchar(b & 0x07); b >>= 3;
+			bit_array[10] = uchar(b & 0x07); b >>= 3;
+			bit_array[11] = uchar(b & 0x07); b >>= 3;
+			bit_array[12] = uchar(b & 0x07); b >>= 3;
+			bit_array[13] = uchar(b & 0x07); b >>= 3;
+			bit_array[14] = uchar(b & 0x07); b >>= 3;
+			bit_array[15] = uchar(b & 0x07); b >>= 3;
+		}
+	};
+
+	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 )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		BlockDXT block;
+		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 64bit color block.
+				s >> block;
+
+				// Decode color block.
+				Color8888 color_array[4];
+				block.GetColors(color_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];
+							scanline[j][x+i] = qRgba(color_array[idx].r, color_array[idx].g, \
color_array[idx].b, color_array[idx].a); +						}
+					}
+				}
+			}
+		}
+		return true;
+	}
+
+	bool LoadDXT3( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		BlockDXT block;
+		BlockDXTAlphaExplicit alpha;
+		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 >> alpha;
+				s >> block;
+
+				// Decode color block.
+				Color8888 color_array[4];
+				block.GetColors(color_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++ ) {
+					ushort a = alpha.row[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 = a & 0x0f;
+							color_array[idx].a = color_array[idx].a | (color_array[idx].a << 4);
+							scanline[j][x+i] = qRgba(color_array[idx].r, color_array[idx].g, \
color_array[idx].b, color_array[idx].a); +						}
+						a >>= 4;
+					}
+				}
+			}
+		}
+		return true;
+	}
+
+	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 )
+	{
+		const uint w = header.width;
+		const uint h = header.height;
+
+		BlockDXT block;
+		BlockDXTAlphaLinear alpha;
+		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 >> 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] = qRgba(color_array[idx].r, color_array[idx].g, \
color_array[idx].b, color_array[idx].a); +						}
+					}
+				}
+			}
+		}
+
+		return true;
+	}
+	
+	bool LoadDXT4( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		if( !LoadDXT5(s, header, img) ) return false;
+		//UndoPremultiplyAlpha(img);
+		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 ) {
+		switch( type ) {
+			case DDS_A8R8G8B8:
+				return LoadA8R8G8B8;
+			case DDS_A1R5G5B5:
+				return LoadA1R5G5B5;
+			case DDS_A4R4G4B4:
+				return LoadA4R4G4B4;
+			case DDS_R8G8B8:
+				return LoadR8G8B8;
+			case DDS_R5G6B5:
+				return LoadR5G6B5;
+			case DDS_DXT1:
+				return LoadDXT1;
+			case DDS_DXT2:
+				return LoadDXT2;
+			case DDS_DXT3:
+				return LoadDXT3;
+			case DDS_DXT4:
+				return LoadDXT4;
+			case DDS_DXT5:
+				return LoadDXT5;
+			default:
+				return NULL;
+		};
+	}
+
+
+	// Load a 2d texture.
+	bool LoadTexture( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		// Create dst image.
+		if( !img.create( header.width, header.height, 32 )) {
+			return false;
+		}
+
+		// Read image.
+		DDSType type = GetType( header );
+
+		// Enable alpha buffer for transparent or DDS images.
+		if( HasAlpha( header ) || type >= DDS_DXT1 ) {
+			img.setAlphaBuffer( true );
+		}
+
+		TextureLoader loader = GetTextureLoader( type );
+		if( loader == NULL ) {
+			return false;
+		}
+
+		return loader( s, header, img );
+	}
+
+
+	int FaceOffset( const DDSHeader & header ) {
+
+		DDSType type = GetType( header );
+
+		int mipmap = max(header.mipmapcount, 1);
+		int size = 0;
+		int w = header.width;
+		int h = header.height;
+		
+		if( type >= DDS_DXT1 ) {
+			int multiplier = (type == DDS_DXT1) ? 8 : 16;
+			do {
+				int face_size = max(w/4,1) * max(h/4,1) * multiplier;
+				size += face_size;
+				w >>= 1;
+				h >>= 1;
+			} while( --mipmap );
+		}
+		else {
+			int multiplier = header.pf.bitcount / 8;
+			do {
+				int face_size = w * h * multiplier;
+				size += face_size;
+				w = max( w>>1, 1 );
+				h = max( h>>1, 1 );
+			} while( --mipmap );
+		}
+
+		return size;
+	}
+
+#if CUBE_LAYOUT == HORIZONTAL
+	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} };
+#endif
+	int face_flags[6] = {
+		DDSCAPS2_CUBEMAP_POSITIVEX,
+		DDSCAPS2_CUBEMAP_NEGATIVEX,
+		DDSCAPS2_CUBEMAP_POSITIVEY,
+		DDSCAPS2_CUBEMAP_NEGATIVEY,
+		DDSCAPS2_CUBEMAP_POSITIVEZ,
+		DDSCAPS2_CUBEMAP_NEGATIVEZ
+	};
+
+	// Load unwrapped cube map.
+	bool LoadCubeMap( QDataStream & s, const DDSHeader & header, QImage img )
+	{
+		// Create dst image.
+#if CUBE_LAYOUT == HORIZONTAL
+		if( !img.create( 4 * header.width, 3 * header.height, 32 )) {
+			return false;	// duplicate code for correct syntax coloring.
+		}
+#elif CUBE_LAYOUT == VERTICAL
+		if( !img.create( 3 * header.width, 4 * header.height, 32 )) {
+			return false;
+		}
+#endif
+
+		DDSType type = GetType( header );
+		
+		// Enable alpha buffer for transparent or DDS images.
+		if( HasAlpha( header ) || type >= DDS_DXT1 ) {
+			img.setAlphaBuffer( true );
+		}
+
+		// Select texture loader.
+		TextureLoader loader = GetTextureLoader( type );
+		if( loader == NULL ) {
+			return false;
+		}
+
+		// Clear background.
+		img.fill( 0 );
+
+		// Create face image.
+		QImage face;
+		if( !face.create( header.width, header.height, 32 )) {
+			return false;
+		}
+		
+		int offset = s.device()->at();
+		int size = FaceOffset( header );
+
+		for( int i = 0; i < 6; i++ ) {
+
+			if( !(header.caps.caps2 & face_flags[i]) ) {
+				// Skip face.
+				continue;
+			}
+
+			// Seek device.
+			s.device()->at( offset );
+			offset += size;
+
+			// Load face from stream.
+			if( !loader( s, header, face ) ) {
+				return false;
+			}
+
+#if CUBE_LAYOUT == VERTICAL
+			if( i == 5 ) {
+				face = face.mirror(true, true);
+			}
+#endif
+
+			// Compute face offsets.
+			int offset_x = face_offset[i][0] * header.width;
+			int offset_y = face_offset[i][1] * header.height;
+
+			// Copy face on the image.
+			for( uint y = 0; y < header.height; y++ ) {
+				QRgb * src = (QRgb *) face.scanLine( y );
+    			QRgb * dst = (QRgb *) img.scanLine( y + offset_y ) + offset_x;
+				memcpy( dst, src, sizeof(QRgb) * header.width );
+			}
+		}
+
+		return true;
+	}
+
+}
+
+
+void kimgio_dds_read( QImageIO *io )
+{
+	QDataStream s( io->ioDevice() );
+	s.setByteOrder( QDataStream::LittleEndian );
+
+	// Validate header.
+	uint fourcc;
+	s >> fourcc;
+	if( fourcc != FOURCC_DDS ) {
+		io->setImage( 0 );
+		io->setStatus( -1 );
+		return;
+	}
+
+	// Read image header.
+	DDSHeader header;
+	s >> header;
+
+	// Check image file format.
+	if( !IsValid( header ) ) {
+		io->setImage( 0 );
+		io->setStatus( -1 );
+		return;
+	}
+
+	// Determine image type, by now, we only support 2d textures.
+	if( !IsSupported( header ) ) {
+		io->setImage( 0 );
+		io->setStatus( -1 );
+		return;
+	}
+
+
+	QImage img;
+	bool result;
+
+	if( IsCubeMap( header ) ) {
+		result = LoadCubeMap( s, header, img );
+	}
+	else {
+		result = LoadTexture( s, header, img );
+	}
+
+	if( result == false ) {
+		io->setImage( 0 );
+		io->setStatus( -1 );
+		return;
+	}
+
+    io->setImage( img );
+    io->setStatus( 0 );
+}
+
+
+void kimgio_dds_write( QImageIO * )
+{
+	// TODO Stub!
+}
+
Index: dds.h
===================================================================
RCS file: N/A
diff -u /dev/null dds.h
--- /dev/null	2004-01-29 00:50:03.000000000 +0100
+++ dds.h	2004-02-10 00:54:07.000000000 +0100
@@ -0,0 +1,21 @@
+/* This file is part of the KDE project
+   Copyright (C) 2003 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
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+*/
+
+#ifndef KIMG_DDS_H
+#define KIMG_DDS_H
+
+class QImageIO;
+
+extern "C" {
+void kimgio_dds_read( QImageIO * );
+void kimgio_dds_write( QImageIO * );
+}
+
+#endif
+ 
Index: dds.kimgio
===================================================================
RCS file: N/A
diff -u /dev/null dds.kimgio
--- /dev/null	2004-01-29 00:50:03.000000000 +0100
+++ dds.kimgio	2004-02-09 14:27:58.000000000 +0100
@@ -0,0 +1,10 @@
+[Image Format]
+Type=DDS
+Header=^DDS 
+Name=Direct Draw Surface
+Read=true
+Write=false
+Suffices=dds,DDS
+Mimetype=image/x-dds
+Library=kimg_dds.la
+ 
Index: AUTHORS
===================================================================
RCS file: /home/kde/kdelibs/kimgio/AUTHORS,v
retrieving revision 1.7
diff -u -3 -p -r1.7 AUTHORS
--- AUTHORS	1 Mar 2003 18:28:37 -0000	1.7
+++ AUTHORS	9 Feb 2004 23:57:23 -0000
@@ -6,3 +6,4 @@ Antonio Larossa	<larossa@kde.org> -- ini
 Sven Wiegand <SWiegand@tfh-berlin.de> -- eps output filter (from KSnapshot)
 Dominik Seichter <domseichter@web.de> -- TGA format read/write support
 Nadeem Hasan <nhasan@kde.org> -- PCX format read/write support
+Ignacio Castaņo <castano@ludicon.com> -- DDS format reader.
Index: Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/kimgio/Makefile.am,v
retrieving revision 1.51
diff -u -3 -p -r1.51 Makefile.am
--- Makefile.am	1 Feb 2004 04:40:41 -0000	1.51
+++ Makefile.am	9 Feb 2004 23:57:23 -0000
@@ -17,7 +17,7 @@ endif
 
 kde_module_LTLIBRARIES= kimg_eps.la kimg_xview.la  \
 	         $(KIMGIO_TIFF_MODULES) kimg_ico.la $(KIMGIO_JP2_MODULES) \
-             kimg_pcx.la kimg_tga.la $(KIMGIO_EXR_MODULES)
+             kimg_pcx.la kimg_tga.la kimg_dds.la $(KIMGIO_EXR_MODULES)
 
 KIMGIO_PLUGIN = -avoid-version -export-symbols-regex 'kimgio_.*_(read|write)'
 
@@ -53,11 +53,15 @@ kimg_tga_la_SOURCES = tga.cpp
 kimg_tga_la_LDFLAGS = -module $(KIMGIO_PLUGIN) -no-undefined $(all_libraries)
 kimg_tga_la_LIBADD = $(LIB_QT) $(LIB_KDECORE)
 
+kimg_dds_la_SOURCES = dds.cpp
+kimg_dds_la_LDFLAGS = -module $(KIMGIO_PLUGIN) -no-undefined $(all_libraries)
+kimg_dds_la_LIBADD = $(LIB_QT) $(LIB_KDECORE)
+	
 kimg_exr_la_SOURCES = exr.cpp
 kimg_exr_la_LDFLAGS = -module $(KIMGIO_PLUGIN) -no-undefined $(all_libraries)
 kimg_exr_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_EXR)
 
-noinst_HEADERS= xview.h eps.h tiffr.h g3r.h ico.h jp2.h pcx.h tga.h exr.h
+noinst_HEADERS= xview.h eps.h tiffr.h g3r.h ico.h jp2.h pcx.h tga.h dds.h exr.h
 
 INCLUDES = -I$(top_srcdir)/kio -I$(top_srcdir)/dcop -I$(top_srcdir)/libltdl \
$(all_includes) -Drestrict= $(EXR_FLAGS)  
@@ -65,4 +69,4 @@ servicedir = $(kde_servicesdir)
 service_DATA = png.kimgio xpm.kimgio bmp.kimgio pbm.kimgio pgm.kimgio \
 	       ppm.kimgio xbm.kimgio jpeg.kimgio xv.kimgio eps.kimgio \
            $(KIMGIO_TIFF_DATAFILES) ico.kimgio $(KIMGIO_JP2_DATAFILES) \
-           gif.kimgio pcx.kimgio tga.kimgio $(KIMGIO_EXR_DATAFILES)
+           gif.kimgio pcx.kimgio tga.kimgio dds.kimgio $(KIMGIO_EXR_DATAFILES)
Index: README
===================================================================
RCS file: /home/kde/kdelibs/kimgio/README,v
retrieving revision 1.11
diff -u -3 -p -r1.11 README
--- README	8 Nov 2003 03:02:08 -0000	1.11
+++ README	9 Feb 2004 23:57:23 -0000
@@ -13,6 +13,7 @@ PNG	<read> <write, only with newer libra
 TIFF	<read>
 TGA	<read> <write>
 PCX <read> <write>
+DDS <read>
 
 To use these formats, you only need to:
 


["dds.desktop" (text/plain)]

[Desktop Entry]
Encoding=UTF-8
Type=MimeType
MimeType=image/dds
Icon=image
Patterns=*.dds;*.DDS;
Comment=DirectDraw Surface

["signature.asc" (application/pgp-signature)]

>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic