Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Mein <mein@cs.umn.edu>2007-06-25 23:50:25 +0400
committerKent Mein <mein@cs.umn.edu>2007-06-25 23:50:25 +0400
commit613646b33e5fde13158a8d8644df8c97bdde2fbb (patch)
tree9b50512d8f6052e28daa54704e4aff112a4ca102 /source/blender/imbuf/intern
parentddc68225c24bc0754d7b81434b06f509d1f0e106 (diff)
This commit is a modified version of patch #6860
It adds read only dds support. (Writing will come later) Kent
Diffstat (limited to 'source/blender/imbuf/intern')
-rw-r--r--source/blender/imbuf/intern/Makefile5
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.cpp523
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.h227
-rw-r--r--source/blender/imbuf/intern/dds/Color.h99
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.cpp310
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.h115
-rw-r--r--source/blender/imbuf/intern/dds/Common.h44
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp828
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.h162
-rw-r--r--source/blender/imbuf/intern/dds/Image.cpp132
-rw-r--r--source/blender/imbuf/intern/dds/Image.h103
-rw-r--r--source/blender/imbuf/intern/dds/Makefile67
-rw-r--r--source/blender/imbuf/intern/dds/SConscript18
-rw-r--r--source/blender/imbuf/intern/dds/Stream.cpp88
-rw-r--r--source/blender/imbuf/intern/dds/Stream.h48
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp120
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.h43
-rw-r--r--source/blender/imbuf/intern/readimage.c9
-rw-r--r--source/blender/imbuf/intern/util.c15
-rw-r--r--source/blender/imbuf/intern/writeimage.c10
20 files changed, 2965 insertions, 1 deletions
diff --git a/source/blender/imbuf/intern/Makefile b/source/blender/imbuf/intern/Makefile
index f51844aad96..29332747a31 100644
--- a/source/blender/imbuf/intern/Makefile
+++ b/source/blender/imbuf/intern/Makefile
@@ -46,6 +46,10 @@ ifeq ($(WITH_OPENEXR), true)
CFLAGS += -DWITH_OPENEXR
endif
+ifeq ($(WITH_DDS), true)
+ DIRS += dds
+ CPPFLAGS += -DWITH_DDS
+endif
ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
CFLAGS += -funsigned-char
@@ -80,4 +84,3 @@ ifeq ($(WITH_FFMPEG), true)
CPPFLAGS += -DWITH_FFMPEG
CPPFLAGS += $(NAN_FFMPEGCFLAGS)
endif
-
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp
new file mode 100644
index 00000000000..5290a677678
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp
@@ -0,0 +1,523 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#include <Common.h>
+#include <Stream.h>
+#include <ColorBlock.h>
+#include <BlockDXT.h>
+
+/*----------------------------------------------------------------------------
+ BlockDXT1
+----------------------------------------------------------------------------*/
+
+unsigned int BlockDXT1::evaluatePalette(Color32 color_array[4]) const
+{
+ // Does bit expansion before interpolation.
+ color_array[0].b = (col0.b << 3) | (col0.b >> 2);
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (col0.r << 3) | (col0.r >> 2);
+ color_array[0].a = 0xFF;
+
+ // @@ Same as above, but faster?
+// Color32 c;
+// c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000);
+// c.u |= (c.u >> 5) & 0x070007;
+// c.u |= (c.u >> 6) & 0x000300;
+// color_array[0].u = c.u;
+
+ color_array[1].r = (col1.r << 3) | (col1.r >> 2);
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (col1.b << 3) | (col1.b >> 2);
+ color_array[1].a = 0xFF;
+
+ // @@ Same as above, but faster?
+// c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000);
+// c.u |= (c.u >> 5) & 0x070007;
+// c.u |= (c.u >> 6) & 0x000300;
+// color_array[1].u = c.u;
+
+ 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;
+
+ return 4;
+ }
+ 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;
+
+ // 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;
+
+ return 3;
+ }
+}
+
+// Evaluate palette assuming 3 color block.
+void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const
+{
+ color_array[0].b = (col0.b << 3) | (col0.b >> 2);
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (col0.r << 3) | (col0.r >> 2);
+ color_array[0].a = 0xFF;
+
+ color_array[1].r = (col1.r << 3) | (col1.r >> 2);
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (col1.b << 3) | (col1.b >> 2);
+ color_array[1].a = 0xFF;
+
+ // 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;
+
+ // 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;
+}
+
+// Evaluate palette assuming 4 color block.
+void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const
+{
+ color_array[0].b = (col0.b << 3) | (col0.b >> 2);
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (col0.r << 3) | (col0.r >> 2);
+ color_array[0].a = 0xFF;
+
+ color_array[1].r = (col1.r << 3) | (col1.r >> 2);
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (col1.b << 3) | (col1.b >> 2);
+ color_array[1].a = 0xFF;
+
+ // 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;
+}
+
+void BlockDXT1::decodeBlock(ColorBlock * block) const
+{
+ // Decode color block.
+ Color32 color_array[4];
+ evaluatePalette(color_array);
+
+ // Write color block.
+ for( unsigned int j = 0; j < 4; j++ ) {
+ for( unsigned int i = 0; i < 4; i++ ) {
+ unsigned int idx = (row[j] >> (2 * i)) & 3;
+ block->color(i, j) = color_array[idx];
+ }
+ }
+}
+
+void BlockDXT1::setIndices(int * idx)
+{
+ indices = 0;
+ for(unsigned int i = 0; i < 16; i++) {
+ indices |= (idx[i] & 3) << (2 * i);
+ }
+}
+
+
+/// Flip DXT1 block vertically.
+inline void BlockDXT1::flip4()
+{
+ unsigned char tmp;
+ swap(row[0], row[3], tmp);
+ swap(row[1], row[2], tmp);
+}
+
+/// Flip half DXT1 block vertically.
+inline void BlockDXT1::flip2()
+{
+ unsigned char tmp;
+ swap(row[0], row[1], tmp);
+}
+
+
+/*----------------------------------------------------------------------------
+ BlockDXT3
+----------------------------------------------------------------------------*/
+
+void BlockDXT3::decodeBlock(ColorBlock * block) const
+{
+ // Decode color.
+ color.decodeBlock(block);
+
+ // Decode alpha.
+ alpha.decodeBlock(block);
+}
+
+void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const
+{
+ block->color(0x0).a = (alpha0 << 4) | alpha0;
+ block->color(0x1).a = (alpha1 << 4) | alpha1;
+ block->color(0x2).a = (alpha2 << 4) | alpha2;
+ block->color(0x3).a = (alpha3 << 4) | alpha3;
+ block->color(0x4).a = (alpha4 << 4) | alpha4;
+ block->color(0x5).a = (alpha5 << 4) | alpha5;
+ block->color(0x6).a = (alpha6 << 4) | alpha6;
+ block->color(0x7).a = (alpha7 << 4) | alpha7;
+ block->color(0x8).a = (alpha8 << 4) | alpha8;
+ block->color(0x9).a = (alpha9 << 4) | alpha9;
+ block->color(0xA).a = (alphaA << 4) | alphaA;
+ block->color(0xB).a = (alphaB << 4) | alphaB;
+ block->color(0xC).a = (alphaC << 4) | alphaC;
+ block->color(0xD).a = (alphaD << 4) | alphaD;
+ block->color(0xE).a = (alphaE << 4) | alphaE;
+ block->color(0xF).a = (alphaF << 4) | alphaF;
+}
+
+/// Flip DXT3 alpha block vertically.
+void AlphaBlockDXT3::flip4()
+{
+ unsigned short tmp;
+ swap(row[0], row[3], tmp);
+ swap(row[1], row[2], tmp);
+}
+
+/// Flip half DXT3 alpha block vertically.
+void AlphaBlockDXT3::flip2()
+{
+ unsigned short tmp;
+ swap(row[0], row[1], tmp);
+}
+
+/// Flip DXT3 block vertically.
+void BlockDXT3::flip4()
+{
+ alpha.flip4();
+ color.flip4();
+}
+
+/// Flip half DXT3 block vertically.
+void BlockDXT3::flip2()
+{
+ alpha.flip2();
+ color.flip2();
+}
+
+
+/*----------------------------------------------------------------------------
+ BlockDXT5
+----------------------------------------------------------------------------*/
+
+void AlphaBlockDXT5::evaluatePalette(unsigned char alpha[8]) const
+{
+ if (alpha0 > alpha1) {
+ evaluatePalette8(alpha);
+ }
+ else {
+ evaluatePalette6(alpha);
+ }
+}
+
+void AlphaBlockDXT5::evaluatePalette8(unsigned char alpha[8]) const
+{
+ // 8-alpha block: derive the other six alphas.
+ // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
+ alpha[0] = alpha0;
+ alpha[1] = alpha1;
+ alpha[2] = (6 * alpha0 + 1 * alpha1) / 7; // bit code 010
+ alpha[3] = (5 * alpha0 + 2 * alpha1) / 7; // bit code 011
+ alpha[4] = (4 * alpha0 + 3 * alpha1) / 7; // bit code 100
+ alpha[5] = (3 * alpha0 + 4 * alpha1) / 7; // bit code 101
+ alpha[6] = (2 * alpha0 + 5 * alpha1) / 7; // bit code 110
+ alpha[7] = (1 * alpha0 + 6 * alpha1) / 7; // bit code 111
+}
+
+void AlphaBlockDXT5::evaluatePalette6(unsigned char alpha[8]) const
+{
+ // 6-alpha block.
+ // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
+ alpha[0] = alpha0;
+ alpha[1] = alpha1;
+ alpha[2] = (4 * alpha0 + 1 * alpha1) / 5; // Bit code 010
+ alpha[3] = (3 * alpha0 + 2 * alpha1) / 5; // Bit code 011
+ alpha[4] = (2 * alpha0 + 3 * alpha1) / 5; // Bit code 100
+ alpha[5] = (1 * alpha0 + 4 * alpha1) / 5; // Bit code 101
+ alpha[6] = 0x00; // Bit code 110
+ alpha[7] = 0xFF; // Bit code 111
+}
+
+void AlphaBlockDXT5::indices(unsigned char index_array[16]) const
+{
+ index_array[0x0] = bits0;
+ index_array[0x1] = bits1;
+ index_array[0x2] = bits2;
+ index_array[0x3] = bits3;
+ index_array[0x4] = bits4;
+ index_array[0x5] = bits5;
+ index_array[0x6] = bits6;
+ index_array[0x7] = bits7;
+ index_array[0x8] = bits8;
+ index_array[0x9] = bits9;
+ index_array[0xA] = bitsA;
+ index_array[0xB] = bitsB;
+ index_array[0xC] = bitsC;
+ index_array[0xD] = bitsD;
+ index_array[0xE] = bitsE;
+ index_array[0xF] = bitsF;
+}
+
+unsigned int AlphaBlockDXT5::index(unsigned int index) const
+{
+ int offset = (3 * index + 16);
+ return (this->u >> offset) & 0x7;
+}
+
+void AlphaBlockDXT5::setIndex(unsigned int index, unsigned int value)
+{
+ int offset = (3 * index + 16);
+ unsigned long long mask = ((unsigned long long)(0x7)) << offset;
+ this->u = (this->u & ~mask) | (((unsigned long long)(value)) << offset);
+}
+
+void AlphaBlockDXT5::decodeBlock(ColorBlock * block) const
+{
+ unsigned char alpha_array[8];
+ evaluatePalette(alpha_array);
+
+ unsigned char index_array[16];
+ indices(index_array);
+
+ for(unsigned int i = 0; i < 16; i++) {
+ block->color(i).a = alpha_array[index_array[i]];
+ }
+}
+
+void AlphaBlockDXT5::flip4()
+{
+ unsigned long long * b = (unsigned long long *)this;
+
+ // @@ The masks might have to be byte swapped.
+ unsigned long long tmp = (*b & (unsigned long long)(0x000000000000FFFFLL));
+ tmp |= (*b & (unsigned long long)(0x000000000FFF0000LL)) << 36;
+ tmp |= (*b & (unsigned long long)(0x000000FFF0000000LL)) << 12;
+ tmp |= (*b & (unsigned long long)(0x000FFF0000000000LL)) >> 12;
+ tmp |= (*b & (unsigned long long)(0xFFF0000000000000LL)) >> 36;
+
+ *b = tmp;
+}
+
+void AlphaBlockDXT5::flip2()
+{
+ unsigned int * b = (unsigned int *)this;
+
+ // @@ The masks might have to be byte swapped.
+ unsigned int tmp = (*b & 0xFF000000);
+ tmp |= (*b & 0x00000FFF) << 12;
+ tmp |= (*b & 0x00FFF000) >> 12;
+
+ *b = tmp;
+}
+
+void BlockDXT5::decodeBlock(ColorBlock * block) const
+{
+ // Decode color.
+ color.decodeBlock(block);
+
+ // Decode alpha.
+ alpha.decodeBlock(block);
+}
+
+/// Flip DXT5 block vertically.
+void BlockDXT5::flip4()
+{
+ alpha.flip4();
+ color.flip4();
+}
+
+/// Flip half DXT5 block vertically.
+void BlockDXT5::flip2()
+{
+ alpha.flip2();
+ color.flip2();
+}
+
+
+/// Decode ATI1 block.
+void BlockATI1::decodeBlock(ColorBlock * block) const
+{
+ unsigned char alpha_array[8];
+ alpha.evaluatePalette(alpha_array);
+
+ unsigned char index_array[16];
+ alpha.indices(index_array);
+
+ for(unsigned int i = 0; i < 16; i++) {
+ Color32 & c = block->color(i);
+ c.b = c.g = c.r = alpha_array[index_array[i]];
+ c.a = 255;
+ }
+}
+
+/// Flip ATI1 block vertically.
+void BlockATI1::flip4()
+{
+ alpha.flip4();
+}
+
+/// Flip half ATI1 block vertically.
+void BlockATI1::flip2()
+{
+ alpha.flip2();
+}
+
+
+/// Decode ATI2 block.
+void BlockATI2::decodeBlock(ColorBlock * block) const
+{
+ unsigned char alpha_array[8];
+ unsigned char index_array[16];
+
+ x.evaluatePalette(alpha_array);
+ x.indices(index_array);
+
+ for(unsigned int i = 0; i < 16; i++) {
+ Color32 & c = block->color(i);
+ c.r = alpha_array[index_array[i]];
+ }
+
+ y.evaluatePalette(alpha_array);
+ y.indices(index_array);
+
+ for(unsigned int i = 0; i < 16; i++) {
+ Color32 & c = block->color(i);
+ c.g = alpha_array[index_array[i]];
+ c.b = 0;
+ c.a = 255;
+ }
+}
+
+/// Flip ATI2 block vertically.
+void BlockATI2::flip4()
+{
+ x.flip4();
+ y.flip4();
+}
+
+/// Flip half ATI2 block vertically.
+void BlockATI2::flip2()
+{
+ x.flip2();
+ y.flip2();
+}
+
+void mem_read(Stream & mem, BlockDXT1 & block)
+{
+ mem_read(mem, block.col0.u);
+ mem_read(mem, block.col1.u);
+ mem_read(mem, block.indices);
+}
+
+void mem_read(Stream & mem, AlphaBlockDXT3 & block)
+{
+ for (unsigned int i = 0; i < 4; i++) mem_read(mem, block.row[i]);
+}
+
+void mem_read(Stream & mem, BlockDXT3 & block)
+{
+ mem_read(mem, block.alpha);
+ mem_read(mem, block.color);
+}
+
+void mem_read(Stream & mem, AlphaBlockDXT5 & block)
+{
+ mem_read(mem, block.u);
+}
+
+void mem_read(Stream & mem, BlockDXT5 & block)
+{
+ mem_read(mem, block.alpha);
+ mem_read(mem, block.color);
+}
+
+void mem_read(Stream & mem, BlockATI1 & block)
+{
+ mem_read(mem, block.alpha);
+}
+
+void mem_read(Stream & mem, BlockATI2 & block)
+{
+ mem_read(mem, block.x);
+ mem_read(mem, block.y);
+}
+
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h
new file mode 100644
index 00000000000..fde1bceac0d
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/BlockDXT.h
@@ -0,0 +1,227 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef _DDS_BLOCKDXT_H
+#define _DDS_BLOCKDXT_H
+
+#include <Color.h>
+#include <ColorBlock.h>
+#include <Stream.h>
+
+/// DXT1 block.
+struct BlockDXT1
+{
+ Color16 col0;
+ Color16 col1;
+ union {
+ unsigned char row[4];
+ unsigned int indices;
+ };
+
+ bool isFourColorMode() const;
+
+ unsigned int evaluatePalette(Color32 color_array[4]) const;
+ unsigned int evaluatePaletteFast(Color32 color_array[4]) const;
+ void evaluatePalette3(Color32 color_array[4]) const;
+ void evaluatePalette4(Color32 color_array[4]) const;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void setIndices(int * idx);
+
+ void flip4();
+ void flip2();
+};
+
+/// Return true if the block uses four color mode, false otherwise.
+inline bool BlockDXT1::isFourColorMode() const
+{
+ return col0.u >= col1.u; // @@ > or >= ?
+}
+
+
+/// DXT3 alpha block with explicit alpha.
+struct AlphaBlockDXT3
+{
+ union {
+ struct {
+ unsigned int alpha0 : 4;
+ unsigned int alpha1 : 4;
+ unsigned int alpha2 : 4;
+ unsigned int alpha3 : 4;
+ unsigned int alpha4 : 4;
+ unsigned int alpha5 : 4;
+ unsigned int alpha6 : 4;
+ unsigned int alpha7 : 4;
+ unsigned int alpha8 : 4;
+ unsigned int alpha9 : 4;
+ unsigned int alphaA : 4;
+ unsigned int alphaB : 4;
+ unsigned int alphaC : 4;
+ unsigned int alphaD : 4;
+ unsigned int alphaE : 4;
+ unsigned int alphaF : 4;
+ };
+ unsigned short row[4];
+ };
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+
+/// DXT3 block.
+struct BlockDXT3
+{
+ AlphaBlockDXT3 alpha;
+ BlockDXT1 color;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+
+/// DXT5 alpha block.
+struct AlphaBlockDXT5
+{
+ union {
+ struct {
+ unsigned long long alpha0 : 8; // 8
+ unsigned long long alpha1 : 8; // 16
+ unsigned long long bits0 : 3; // 3 - 19
+ unsigned long long bits1 : 3; // 6 - 22
+ unsigned long long bits2 : 3; // 9 - 25
+ unsigned long long bits3 : 3; // 12 - 28
+ unsigned long long bits4 : 3; // 15 - 31
+ unsigned long long bits5 : 3; // 18 - 34
+ unsigned long long bits6 : 3; // 21 - 37
+ unsigned long long bits7 : 3; // 24 - 40
+ unsigned long long bits8 : 3; // 27 - 43
+ unsigned long long bits9 : 3; // 30 - 46
+ unsigned long long bitsA : 3; // 33 - 49
+ unsigned long long bitsB : 3; // 36 - 52
+ unsigned long long bitsC : 3; // 39 - 55
+ unsigned long long bitsD : 3; // 42 - 58
+ unsigned long long bitsE : 3; // 45 - 61
+ unsigned long long bitsF : 3; // 48 - 64
+ };
+ unsigned long long u;
+ };
+
+ void evaluatePalette(unsigned char alpha[8]) const;
+ void evaluatePalette8(unsigned char alpha[8]) const;
+ void evaluatePalette6(unsigned char alpha[8]) const;
+ void indices(unsigned char index_array[16]) const;
+
+ unsigned int index(unsigned int index) const;
+ void setIndex(unsigned int index, unsigned int value);
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+
+/// DXT5 block.
+struct BlockDXT5
+{
+ AlphaBlockDXT5 alpha;
+ BlockDXT1 color;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+/// ATI1 block.
+struct BlockATI1
+{
+ AlphaBlockDXT5 alpha;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+/// ATI2 block.
+struct BlockATI2
+{
+ AlphaBlockDXT5 x;
+ AlphaBlockDXT5 y;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+void mem_read(Stream & mem, BlockDXT1 & block);
+void mem_read(Stream & mem, AlphaBlockDXT3 & block);
+void mem_read(Stream & mem, BlockDXT3 & block);
+void mem_read(Stream & mem, AlphaBlockDXT5 & block);
+void mem_read(Stream & mem, BlockDXT5 & block);
+void mem_read(Stream & mem, BlockATI1 & block);
+void mem_read(Stream & mem, BlockATI2 & block);
+
+#endif // _DDS_BLOCKDXT_H
diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h
new file mode 100644
index 00000000000..f8055afdfc9
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Color.h
@@ -0,0 +1,99 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#ifndef _DDS_COLOR_H
+#define _DDS_COLOR_H
+
+/// 32 bit color stored as BGRA.
+class Color32
+{
+public:
+ Color32() { }
+ Color32(const Color32 & c) : u(c.u) { }
+ Color32(unsigned char R, unsigned char G, unsigned char B) { setRGBA(R, G, B, 0xFF); }
+ Color32(unsigned char R, unsigned char G, unsigned char B, unsigned char A) { setRGBA( R, G, B, A); }
+ //Color32(unsigned char c[4]) { setRGBA(c[0], c[1], c[2], c[3]); }
+ //Color32(float R, float G, float B) { setRGBA(uint(R*255), uint(G*255), uint(B*255), 0xFF); }
+ //Color32(float R, float G, float B, float A) { setRGBA(uint(R*255), uint(G*255), uint(B*255), uint(A*255)); }
+ Color32(unsigned int U) : u(U) { }
+
+ void setRGBA(unsigned char R, unsigned char G, unsigned char B, unsigned char A)
+ {
+ r = R;
+ g = G;
+ b = B;
+ a = A;
+ }
+
+ void setBGRA(unsigned char B, unsigned char G, unsigned char R, unsigned char A = 0xFF)
+ {
+ r = R;
+ g = G;
+ b = B;
+ a = A;
+ }
+
+ operator unsigned int () const {
+ return u;
+ }
+
+ union {
+ struct {
+ unsigned char b, g, r, a;
+ };
+ unsigned int u;
+ };
+};
+
+/// 16 bit 565 BGR color.
+class Color16
+{
+public:
+ Color16() { }
+ Color16(const Color16 & c) : u(c.u) { }
+ explicit Color16(unsigned short U) : u(U) { }
+
+ union {
+ struct {
+ unsigned short b : 5;
+ unsigned short g : 6;
+ unsigned short r : 5;
+ };
+ unsigned short u;
+ };
+};
+
+#endif // _DDS_COLOR_H
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp
new file mode 100644
index 00000000000..63997f93c8c
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp
@@ -0,0 +1,310 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#include <ColorBlock.h>
+#include <Image.h>
+#include <Common.h>
+
+ // Get approximate luminance.
+ inline static unsigned int colorLuminance(Color32 c)
+ {
+ return c.r + c.g + c.b;
+ }
+
+ // Get the euclidean distance between the given colors.
+ inline static unsigned int colorDistance(Color32 c0, Color32 c1)
+ {
+ return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b);
+ }
+
+
+/// Default constructor.
+ColorBlock::ColorBlock()
+{
+}
+
+/// Init the color block with the contents of the given block.
+ColorBlock::ColorBlock(const ColorBlock & block)
+{
+ for(unsigned int i = 0; i < 16; i++) {
+ color(i) = block.color(i);
+ }
+}
+
+
+/// Initialize this color block.
+ColorBlock::ColorBlock(const Image * img, unsigned int x, unsigned int y)
+{
+ init(img, x, y);
+}
+
+void ColorBlock::init(const Image * img, unsigned int x, unsigned int y)
+{
+ const unsigned int bw = min(img->width() - x, 4U);
+ const unsigned int bh = min(img->height() - y, 4U);
+
+ static int remainder[] = {
+ 0, 0, 0, 0,
+ 0, 1, 0, 1,
+ 0, 1, 2, 0,
+ 0, 1, 2, 3,
+ };
+
+ // Blocks that are smaller than 4x4 are handled by repeating the pixels.
+ // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+
+ for(unsigned int i = 0; i < 4; i++) {
+ //const int by = i % bh;
+ const int by = remainder[(bh - 1) * 4 + i];
+ for(unsigned int e = 0; e < 4; e++) {
+ //const int bx = e % bw;
+ const int bx = remainder[(bw - 1) * 4 + e];
+ color(e, i) = img->pixel(x + bx, y + by);
+ }
+ }
+}
+
+
+void ColorBlock::swizzleDXT5n()
+{
+ for(int i = 0; i < 16; i++)
+ {
+ Color32 c = m_color[i];
+ m_color[i] = Color32(0, c.g, 0, c.r);
+ }
+}
+
+void ColorBlock::splatX()
+{
+ for(int i = 0; i < 16; i++)
+ {
+ unsigned char x = m_color[i].r;
+ m_color[i] = Color32(x, x, x, x);
+ }
+}
+
+void ColorBlock::splatY()
+{
+ for(int i = 0; i < 16; i++)
+ {
+ unsigned char y = m_color[i].g;
+ m_color[i] = Color32(y, y, y, y);
+ }
+}
+
+
+/// Count number of unique colors in this color block.
+unsigned int ColorBlock::countUniqueColors() const
+{
+ unsigned int count = 0;
+
+ // @@ This does not have to be o(n^2)
+ for(int i = 0; i < 16; i++)
+ {
+ bool unique = true;
+ for(int j = 0; j < i; j++) {
+ if( m_color[i] != m_color[j] ) {
+ unique = false;
+ }
+ }
+
+ if( unique ) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+/// Get average color of the block.
+Color32 ColorBlock::averageColor() const
+{
+ unsigned int r, g, b, a;
+ r = g = b = a = 0;
+
+ for(unsigned int i = 0; i < 16; i++) {
+ r += m_color[i].r;
+ g += m_color[i].g;
+ b += m_color[i].b;
+ a += m_color[i].a;
+ }
+
+ return Color32((unsigned char)(r / 16), (unsigned char)(g / 16), (unsigned char)(b / 16), (unsigned char)(a / 16));
+}
+
+
+/// Get diameter color range.
+void ColorBlock::diameterRange(Color32 * start, Color32 * end) const
+{
+ Color32 c0, c1;
+ unsigned int best_dist = 0;
+
+ for(int i = 0; i < 16; i++) {
+ for (int j = i+1; j < 16; j++) {
+ unsigned int dist = colorDistance(m_color[i], m_color[j]);
+ if( dist > best_dist ) {
+ best_dist = dist;
+ c0 = m_color[i];
+ c1 = m_color[j];
+ }
+ }
+ }
+
+ *start = c0;
+ *end = c1;
+}
+
+/// Get luminance color range.
+void ColorBlock::luminanceRange(Color32 * start, Color32 * end) const
+{
+ Color32 minColor, maxColor;
+ unsigned int minLuminance, maxLuminance;
+
+ maxLuminance = minLuminance = colorLuminance(m_color[0]);
+
+ for(unsigned int i = 1; i < 16; i++)
+ {
+ unsigned int luminance = colorLuminance(m_color[i]);
+
+ if (luminance > maxLuminance) {
+ maxLuminance = luminance;
+ maxColor = m_color[i];
+ }
+ else if (luminance < minLuminance) {
+ minLuminance = luminance;
+ minColor = m_color[i];
+ }
+ }
+
+ *start = minColor;
+ *end = maxColor;
+}
+
+/// Get color range based on the bounding box.
+void ColorBlock::boundsRange(Color32 * start, Color32 * end) const
+{
+ Color32 minColor(255, 255, 255);
+ Color32 maxColor(0, 0, 0);
+
+ for(unsigned int i = 0; i < 16; i++)
+ {
+ if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; }
+ if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; }
+ if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; }
+ if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; }
+ if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; }
+ if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; }
+ }
+
+ // Offset range by 1/16 of the extents
+ Color32 inset;
+ inset.r = (maxColor.r - minColor.r) >> 4;
+ inset.g = (maxColor.g - minColor.g) >> 4;
+ inset.b = (maxColor.b - minColor.b) >> 4;
+
+ minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255;
+ minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255;
+ minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255;
+
+ maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0;
+ maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0;
+ maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0;
+
+ *start = minColor;
+ *end = maxColor;
+}
+
+/// Get color range based on the bounding box.
+void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const
+{
+ Color32 minColor(255, 255, 255, 255);
+ Color32 maxColor(0, 0, 0, 0);
+
+ for(unsigned int i = 0; i < 16; i++)
+ {
+ if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; }
+ if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; }
+ if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; }
+ if (m_color[i].a < minColor.a) { minColor.a = m_color[i].a; }
+ if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; }
+ if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; }
+ if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; }
+ if (m_color[i].a > maxColor.a) { maxColor.a = m_color[i].a; }
+ }
+
+ // Offset range by 1/16 of the extents
+ Color32 inset;
+ inset.r = (maxColor.r - minColor.r) >> 4;
+ inset.g = (maxColor.g - minColor.g) >> 4;
+ inset.b = (maxColor.b - minColor.b) >> 4;
+ inset.a = (maxColor.a - minColor.a) >> 4;
+
+ minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255;
+ minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255;
+ minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255;
+ minColor.a = (minColor.a + inset.a <= 255) ? minColor.a + inset.a : 255;
+
+ maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0;
+ maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0;
+ maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0;
+ maxColor.a = (maxColor.a >= inset.a) ? maxColor.a - inset.a : 0;
+
+ *start = minColor;
+ *end = maxColor;
+}
+
+/// Sort colors by abosolute value in their 16 bit representation.
+void ColorBlock::sortColorsByAbsoluteValue()
+{
+ // Dummy selection sort.
+ for( unsigned int a = 0; a < 16; a++ ) {
+ unsigned int max = a;
+ Color16 cmax(m_color[a]);
+
+ for( unsigned int b = a+1; b < 16; b++ ) {
+ Color16 cb(m_color[b]);
+
+ if( cb.u > cmax.u ) {
+ max = b;
+ cmax = cb;
+ }
+ }
+ Color32 tmp;
+ swap( m_color[a], m_color[max], tmp );
+ }
+}
+
+
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h
new file mode 100644
index 00000000000..eba372768ad
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/ColorBlock.h
@@ -0,0 +1,115 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#ifndef _DDS_COLORBLOCK_H
+#define _DDS_COLORBLOCK_H
+
+#include <Color.h>
+#include <Image.h>
+
+/// Uncompressed 4x4 color block.
+struct ColorBlock
+{
+ ColorBlock();
+ ColorBlock(const ColorBlock & block);
+ ColorBlock(const Image * img, unsigned int x, unsigned int y);
+
+ void init(const Image * img, unsigned int x, unsigned int y);
+
+ void swizzleDXT5n();
+ void splatX();
+ void splatY();
+
+ unsigned int countUniqueColors() const;
+ Color32 averageColor() const;
+
+ void diameterRange(Color32 * start, Color32 * end) const;
+ void luminanceRange(Color32 * start, Color32 * end) const;
+ void boundsRange(Color32 * start, Color32 * end) const;
+ void boundsRangeAlpha(Color32 * start, Color32 * end) const;
+ void bestFitRange(Color32 * start, Color32 * end) const;
+
+ void sortColorsByAbsoluteValue();
+
+ float volume() const;
+
+ // Accessors
+ const Color32 * colors() const;
+
+ Color32 color(unsigned int i) const;
+ Color32 & color(unsigned int i);
+
+ Color32 color(unsigned int x, unsigned int y) const;
+ Color32 & color(unsigned int x, unsigned int y);
+
+private:
+
+ Color32 m_color[4*4];
+
+};
+
+
+/// Get pointer to block colors.
+inline const Color32 * ColorBlock::colors() const
+{
+ return m_color;
+}
+
+/// Get block color.
+inline Color32 ColorBlock::color(unsigned int i) const
+{
+ return m_color[i];
+}
+
+/// Get block color.
+inline Color32 & ColorBlock::color(unsigned int i)
+{
+ return m_color[i];
+}
+
+/// Get block color.
+inline Color32 ColorBlock::color(unsigned int x, unsigned int y) const
+{
+ return m_color[y * 4 + x];
+}
+
+/// Get block color.
+inline Color32 & ColorBlock::color(unsigned int x, unsigned int y)
+{
+ return m_color[y * 4 + x];
+}
+
+#endif // _DDS_COLORBLOCK_H
diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h
new file mode 100644
index 00000000000..5aa8972e437
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Common.h
@@ -0,0 +1,44 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef _DDS_COMMON_H
+#define _DDS_COMMON_H
+
+#ifndef min
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+#endif
+#ifndef clamp
+#define clamp(x,a,b) min(max((x), (a)), (b))
+#endif
+#ifndef swap
+#define swap(a,b,tmp) tmp=a; a=b; b=tmp;
+#endif
+
+#endif
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
new file mode 100644
index 00000000000..6937840334d
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -0,0 +1,828 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#include <Common.h>
+#include <DirectDrawSurface.h>
+#include <BlockDXT.h>
+
+#include <stdio.h> // printf
+#include <math.h> // sqrt
+
+/*** declarations ***/
+
+#if !defined(MAKEFOURCC)
+# define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((unsigned int)((unsigned char)(ch0)) | \
+ ((unsigned int)((unsigned char)(ch1)) << 8) | \
+ ((unsigned int)((unsigned char)(ch2)) << 16) | \
+ ((unsigned int)((unsigned char)(ch3)) << 24 ))
+#endif
+
+static const unsigned int FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
+static const unsigned int FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
+static const unsigned int FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
+static const unsigned int FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
+static const unsigned int FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
+static const unsigned int FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
+static const unsigned int FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
+static const unsigned int FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
+static const unsigned int FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
+
+// RGB formats.
+static const unsigned int D3DFMT_R8G8B8 = 20;
+static const unsigned int D3DFMT_A8R8G8B8 = 21;
+static const unsigned int D3DFMT_X8R8G8B8 = 22;
+static const unsigned int D3DFMT_R5G6B5 = 23;
+static const unsigned int D3DFMT_X1R5G5B5 = 24;
+static const unsigned int D3DFMT_A1R5G5B5 = 25;
+static const unsigned int D3DFMT_A4R4G4B4 = 26;
+static const unsigned int D3DFMT_R3G3B2 = 27;
+static const unsigned int D3DFMT_A8 = 28;
+static const unsigned int D3DFMT_A8R3G3B2 = 29;
+static const unsigned int D3DFMT_X4R4G4B4 = 30;
+static const unsigned int D3DFMT_A2B10G10R10 = 31;
+static const unsigned int D3DFMT_A8B8G8R8 = 32;
+static const unsigned int D3DFMT_X8B8G8R8 = 33;
+static const unsigned int D3DFMT_G16R16 = 34;
+static const unsigned int D3DFMT_A2R10G10B10 = 35;
+static const unsigned int D3DFMT_A16B16G16R16 = 36;
+
+// Palette formats.
+static const unsigned int D3DFMT_A8P8 = 40;
+static const unsigned int D3DFMT_P8 = 41;
+
+// Luminance formats.
+static const unsigned int D3DFMT_L8 = 50;
+static const unsigned int D3DFMT_A8L8 = 51;
+static const unsigned int D3DFMT_A4L4 = 52;
+
+// Floating point formats
+static const unsigned int D3DFMT_R16F = 111;
+static const unsigned int D3DFMT_G16R16F = 112;
+static const unsigned int D3DFMT_A16B16G16R16F = 113;
+static const unsigned int D3DFMT_R32F = 114;
+static const unsigned int D3DFMT_G32R32F = 115;
+static const unsigned int D3DFMT_A32B32G32R32F = 116;
+
+static const unsigned int DDSD_CAPS = 0x00000001U;
+static const unsigned int DDSD_PIXELFORMAT = 0x00001000U;
+static const unsigned int DDSD_WIDTH = 0x00000004U;
+static const unsigned int DDSD_HEIGHT = 0x00000002U;
+static const unsigned int DDSD_PITCH = 0x00000008U;
+static const unsigned int DDSD_MIPMAPCOUNT = 0x00020000U;
+static const unsigned int DDSD_LINEARSIZE = 0x00080000U;
+static const unsigned int DDSD_DEPTH = 0x00800000U;
+
+static const unsigned int DDSCAPS_COMPLEX = 0x00000008U;
+static const unsigned int DDSCAPS_TEXTURE = 0x00001000U;
+static const unsigned int DDSCAPS_MIPMAP = 0x00400000U;
+static const unsigned int DDSCAPS2_VOLUME = 0x00200000U;
+static const unsigned int DDSCAPS2_CUBEMAP = 0x00000200U;
+
+static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
+static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
+static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
+static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
+static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
+static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
+static const unsigned int DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U;
+
+static const unsigned int DDPF_ALPHAPIXELS = 0x00000001U;
+static const unsigned int DDPF_ALPHA = 0x00000002U;
+static const unsigned int DDPF_FOURCC = 0x00000004U;
+static const unsigned int DDPF_RGB = 0x00000040U;
+static const unsigned int DDPF_PALETTEINDEXED1 = 0x00000800U;
+static const unsigned int DDPF_PALETTEINDEXED2 = 0x00001000U;
+static const unsigned int DDPF_PALETTEINDEXED4 = 0x00000008U;
+static const unsigned int DDPF_PALETTEINDEXED8 = 0x00000020U;
+static const unsigned int DDPF_LUMINANCE = 0x00020000U;
+static const unsigned int DDPF_ALPHAPREMULT = 0x00008000U;
+static const unsigned int DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag.
+
+/*** implementation ***/
+
+void mem_read(Stream & mem, DDSPixelFormat & pf)
+{
+ mem_read(mem, pf.size);
+ mem_read(mem, pf.flags);
+ mem_read(mem, pf.fourcc);
+ mem_read(mem, pf.bitcount);
+ mem_read(mem, pf.rmask);
+ mem_read(mem, pf.gmask);
+ mem_read(mem, pf.bmask);
+ mem_read(mem, pf.amask);
+}
+
+void mem_read(Stream & mem, DDSCaps & caps)
+{
+ mem_read(mem, caps.caps1);
+ mem_read(mem, caps.caps2);
+ mem_read(mem, caps.caps3);
+ mem_read(mem, caps.caps4);
+}
+
+void mem_read(Stream & mem, DDSHeader & header)
+{
+ mem_read(mem, header.fourcc);
+ mem_read(mem, header.size);
+ mem_read(mem, header.flags);
+ mem_read(mem, header.height);
+ mem_read(mem, header.width);
+ mem_read(mem, header.pitch);
+ mem_read(mem, header.depth);
+ mem_read(mem, header.mipmapcount);
+ for (unsigned int i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
+ mem_read(mem, header.pf);
+ mem_read(mem, header.caps);
+ mem_read(mem, header.notused);
+}
+
+DDSHeader::DDSHeader()
+{
+ this->fourcc = FOURCC_DDS;
+ this->size = 124;
+ this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT);
+ this->height = 0;
+ this->width = 0;
+ this->pitch = 0;
+ this->depth = 0;
+ this->mipmapcount = 0;
+ for (unsigned int i = 0; i < 11; i++) this->reserved[i] = 0;
+
+ // Store version information on the reserved header attributes.
+ this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
+ this->reserved[10] = (0 << 16) | (9 << 8) | (3); // major.minor.revision
+
+ this->pf.size = 32;
+ this->pf.flags = 0;
+ this->pf.fourcc = 0;
+ this->pf.bitcount = 0;
+ this->pf.rmask = 0;
+ this->pf.gmask = 0;
+ this->pf.bmask = 0;
+ this->pf.amask = 0;
+ this->caps.caps1 = DDSCAPS_TEXTURE;
+ this->caps.caps2 = 0;
+ this->caps.caps3 = 0;
+ this->caps.caps4 = 0;
+ this->notused = 0;
+}
+
+void DDSHeader::setWidth(unsigned int w)
+{
+ this->flags |= DDSD_WIDTH;
+ this->width = w;
+}
+
+void DDSHeader::setHeight(unsigned int h)
+{
+ this->flags |= DDSD_HEIGHT;
+ this->height = h;
+}
+
+void DDSHeader::setDepth(unsigned int d)
+{
+ this->flags |= DDSD_DEPTH;
+ this->height = d;
+}
+
+void DDSHeader::setMipmapCount(unsigned int count)
+{
+ if (count == 0)
+ {
+ this->flags &= ~DDSD_MIPMAPCOUNT;
+ this->mipmapcount = 0;
+
+ if (this->caps.caps2 == 0) {
+ this->caps.caps1 = DDSCAPS_TEXTURE;
+ }
+ else {
+ this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
+ }
+ }
+ else
+ {
+ this->flags |= DDSD_MIPMAPCOUNT;
+ this->mipmapcount = count;
+
+ this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
+ }
+}
+
+void DDSHeader::setTexture2D()
+{
+ // nothing to do here.
+}
+
+void DDSHeader::setTexture3D()
+{
+ this->caps.caps2 = DDSCAPS2_VOLUME;
+}
+
+void DDSHeader::setTextureCube()
+{
+ this->caps.caps1 |= DDSCAPS_COMPLEX;
+ this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
+}
+
+void DDSHeader::setLinearSize(unsigned int size)
+{
+ this->flags &= ~DDSD_PITCH;
+ this->flags |= DDSD_LINEARSIZE;
+ this->pitch = size;
+}
+
+void DDSHeader::setPitch(unsigned int pitch)
+{
+ this->flags &= ~DDSD_LINEARSIZE;
+ this->flags |= DDSD_PITCH;
+ this->pitch = pitch;
+}
+
+void DDSHeader::setFourCC(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3)
+{
+ // set fourcc pixel format.
+ this->pf.flags = DDPF_FOURCC;
+ this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
+ this->pf.bitcount = 0;
+ this->pf.rmask = 0;
+ this->pf.gmask = 0;
+ this->pf.bmask = 0;
+ this->pf.amask = 0;
+}
+
+void DDSHeader::setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask)
+{
+ // Make sure the masks are correct.
+ if ((rmask & gmask) || \
+ (rmask & bmask) || \
+ (rmask & amask) || \
+ (gmask & bmask) || \
+ (gmask & amask) || \
+ (bmask & amask)) {
+ printf("DDS: bad RGBA masks, pixel format not set\n");
+ return;
+ }
+
+ this->pf.flags = DDPF_RGB;
+
+ if (amask != 0) {
+ this->pf.flags |= DDPF_ALPHAPIXELS;
+ }
+
+ if (bitcount == 0)
+ {
+ // Compute bit count from the masks.
+ unsigned int total = rmask | gmask | bmask | amask;
+ while(total != 0) {
+ bitcount++;
+ total >>= 1;
+ }
+ // @@ Align to 8?
+ }
+
+ this->pf.fourcc = 0;
+ this->pf.bitcount = bitcount;
+ this->pf.rmask = rmask;
+ this->pf.gmask = gmask;
+ this->pf.bmask = bmask;
+ this->pf.amask = amask;
+}
+
+void DDSHeader::setNormalFlag(bool b)
+{
+ if (b) this->pf.flags |= DDPF_NORMAL;
+ else this->pf.flags &= ~DDPF_NORMAL;
+}
+
+/*
+void DDSHeader::swapBytes()
+{
+ this->fourcc = POSH_LittleU32(this->fourcc);
+ this->size = POSH_LittleU32(this->size);
+ this->flags = POSH_LittleU32(this->flags);
+ this->height = POSH_LittleU32(this->height);
+ this->width = POSH_LittleU32(this->width);
+ this->pitch = POSH_LittleU32(this->pitch);
+ this->depth = POSH_LittleU32(this->depth);
+ this->mipmapcount = POSH_LittleU32(this->mipmapcount);
+
+ for(int i = 0; i < 11; i++) {
+ this->reserved[i] = POSH_LittleU32(this->reserved[i]);
+ }
+
+ this->pf.size = POSH_LittleU32(this->pf.size);
+ this->pf.flags = POSH_LittleU32(this->pf.flags);
+ this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
+ this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
+ this->pf.rmask = POSH_LittleU32(this->pf.rmask);
+ this->pf.gmask = POSH_LittleU32(this->pf.gmask);
+ this->pf.bmask = POSH_LittleU32(this->pf.bmask);
+ this->pf.amask = POSH_LittleU32(this->pf.amask);
+ this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
+ this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
+ this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
+ this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
+ this->notused = POSH_LittleU32(this->notused);
+}
+*/
+
+
+DirectDrawSurface::DirectDrawSurface(unsigned char *mem, unsigned int size) : stream(mem, size), header()
+{
+ mem_read(stream, header);
+}
+
+DirectDrawSurface::~DirectDrawSurface()
+{
+}
+
+bool DirectDrawSurface::isValid() const
+{
+ if (header.fourcc != FOURCC_DDS || header.size != 124)
+ {
+ return false;
+ }
+
+ const unsigned int required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT);
+ if( (header.flags & required) != required ) {
+ return false;
+ }
+
+ if (header.pf.size != 32) {
+ return false;
+ }
+
+ /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
+ /*
+ if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
+ return false;
+ }
+ */
+
+ return true;
+}
+
+bool DirectDrawSurface::isSupported() const
+{
+ if (header.pf.flags & DDPF_FOURCC)
+ {
+ if (header.pf.fourcc != FOURCC_DXT1 &&
+ header.pf.fourcc != FOURCC_DXT2 &&
+ header.pf.fourcc != FOURCC_DXT3 &&
+ header.pf.fourcc != FOURCC_DXT4 &&
+ header.pf.fourcc != FOURCC_DXT5 &&
+ header.pf.fourcc != FOURCC_RXGB &&
+ header.pf.fourcc != FOURCC_ATI1 &&
+ header.pf.fourcc != FOURCC_ATI2)
+ {
+ // Unknown fourcc code.
+ return false;
+ }
+ }
+ /*
+ else if (header.pf.flags & DDPF_RGB)
+ {
+ if (header.pf.bitcount == 24)
+ {
+ return false;
+ }
+ else if (header.pf.bitcount == 32)
+ {
+ return false;
+ }
+ else
+ {
+ // Unsupported pixel format.
+ return false;
+ }
+ }
+ */
+ else
+ {
+ return false;
+ }
+
+ if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
+ {
+ // Cubemaps must contain all faces.
+ return false;
+ }
+
+ if (isTexture3D())
+ {
+ // @@ 3D textures not supported yet.
+ return false;
+ }
+
+ return true;
+}
+
+
+unsigned int DirectDrawSurface::mipmapCount() const
+{
+ if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
+ else return 0;
+}
+
+
+unsigned int DirectDrawSurface::width() const
+{
+ if (header.flags & DDSD_WIDTH) return header.width;
+ else return 1;
+}
+
+unsigned int DirectDrawSurface::height() const
+{
+ if (header.flags & DDSD_HEIGHT) return header.height;
+ else return 1;
+}
+
+unsigned int DirectDrawSurface::depth() const
+{
+ if (header.flags & DDSD_DEPTH) return header.depth;
+ else return 1;
+}
+
+bool DirectDrawSurface::hasAlpha() const
+{
+ if (header.pf.fourcc == FOURCC_DXT1) return false;
+ else return true;
+}
+
+bool DirectDrawSurface::isTexture2D() const
+{
+ return !isTexture3D() && !isTextureCube();
+}
+
+bool DirectDrawSurface::isTexture3D() const
+{
+ return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
+}
+
+bool DirectDrawSurface::isTextureCube() const
+{
+ return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
+}
+
+void DirectDrawSurface::mipmap(Image * img, unsigned int face, unsigned int mipmap)
+{
+ stream.seek(offset(face, mipmap));
+
+ unsigned int w = width();
+ unsigned int h = height();
+
+ // Compute width and height.
+ for (unsigned int m = 0; m < mipmap; m++)
+ {
+ w = max(w/2, 1U);
+ h = max(h/2, 1U);
+ }
+
+ img->allocate(w, h);
+
+ if (header.pf.flags & DDPF_RGB)
+ {
+ readLinearImage(img);
+ }
+ else if (header.pf.flags & DDPF_FOURCC)
+ {
+ readBlockImage(img);
+ }
+}
+
+void DirectDrawSurface::readLinearImage(Image * img)
+{
+ // @@ Read linear RGB images.
+ printf("DDS: linear RGB images not supported\n");
+}
+
+void DirectDrawSurface::readBlockImage(Image * img)
+{
+ const unsigned int w = img->width();
+ const unsigned int h = img->height();
+
+ const unsigned int bw = (w + 3) / 4;
+ const unsigned int bh = (h + 3) / 4;
+
+ for (unsigned int by = 0; by < bh; by++)
+ {
+ for (unsigned int bx = 0; bx < bw; bx++)
+ {
+ ColorBlock block;
+
+ // Read color block.
+ readBlock(&block);
+
+ // Write color block.
+ for (unsigned int y = 0; y < min(4U, h-4*by); y++)
+ {
+ for (unsigned int x = 0; x < min(4U, w-4*bx); x++)
+ {
+ img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
+ }
+ }
+ }
+ }
+}
+
+static Color32 buildNormal(unsigned char x, unsigned char y)
+{
+ float nx = 2 * (x / 255) - 1;
+ float ny = 2 * (x / 255) - 1;
+ float nz = sqrt(1 - nx*nx - ny*ny);
+ unsigned char z = clamp(int(255 * (nz + 1) / 2), 0, 255);
+
+ return Color32(x, y, z);
+}
+
+
+void DirectDrawSurface::readBlock(ColorBlock * rgba)
+{
+ if (header.pf.fourcc == FOURCC_DXT1)
+ {
+ BlockDXT1 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+ else if (header.pf.fourcc == FOURCC_DXT2 ||
+ header.pf.fourcc == FOURCC_DXT3)
+ {
+ BlockDXT3 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+ else if (header.pf.fourcc == FOURCC_DXT4 ||
+ header.pf.fourcc == FOURCC_DXT5 ||
+ header.pf.fourcc == FOURCC_RXGB)
+ {
+ BlockDXT5 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+
+ if (header.pf.fourcc == FOURCC_RXGB)
+ {
+ // Swap R & A.
+ for (int i = 0; i < 16; i++)
+ {
+ Color32 & c = rgba->color(i);
+ unsigned int tmp = c.r;
+ c.r = c.a;
+ c.a = tmp;
+ }
+ }
+ }
+ else if (header.pf.fourcc == FOURCC_ATI1)
+ {
+ BlockATI1 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+ else if (header.pf.fourcc == FOURCC_ATI2)
+ {
+ BlockATI2 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+
+ // If normal flag set, convert to normal.
+ if (header.pf.flags & DDPF_NORMAL)
+ {
+ if (header.pf.fourcc == FOURCC_ATI2)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ Color32 & c = rgba->color(i);
+ c = buildNormal(c.r, c.g);
+ }
+ }
+ else if (header.pf.fourcc == FOURCC_DXT5)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ Color32 & c = rgba->color(i);
+ c = buildNormal(c.g, c.a);
+ }
+ }
+ }
+}
+
+
+unsigned int DirectDrawSurface::blockSize() const
+{
+ switch(header.pf.fourcc)
+ {
+ case FOURCC_DXT1:
+ case FOURCC_ATI1:
+ return 8;
+ case FOURCC_DXT2:
+ case FOURCC_DXT3:
+ case FOURCC_DXT4:
+ case FOURCC_DXT5:
+ case FOURCC_RXGB:
+ case FOURCC_ATI2:
+ return 16;
+ };
+
+ // Not a block image.
+ return 0;
+}
+
+unsigned int DirectDrawSurface::mipmapSize(unsigned int mipmap) const
+{
+ unsigned int w = width();
+ unsigned int h = height();
+ unsigned int d = depth();
+
+ for (unsigned int m = 0; m < mipmap; m++)
+ {
+ w = max(1U, w / 2);
+ h = max(1U, h / 2);
+ d = max(1U, d / 2);
+ }
+
+ if (header.pf.flags & DDPF_FOURCC)
+ {
+ // @@ How are 3D textures aligned?
+ w = (w + 3) / 4;
+ h = (h + 3) / 4;
+ return blockSize() * w * h;
+ }
+ else if (header.pf.flags & DDPF_RGB)
+ {
+ // Align pixels to bytes.
+ unsigned int byteCount = (header.pf.bitcount + 7) / 8;
+
+ // Align pitch to 4 bytes.
+ unsigned int pitch = 4 * ((w * byteCount + 3) / 4);
+
+ return pitch * h * d;
+ }
+ else {
+ printf("DDS: mipmap format not supported\n");
+ return(0);
+ };
+}
+
+unsigned int DirectDrawSurface::faceSize() const
+{
+ const unsigned int count = mipmapCount();
+ unsigned int size = 0;
+
+ for (unsigned int m = 0; m < count; m++)
+ {
+ size += mipmapSize(m);
+ }
+
+ return size;
+}
+
+unsigned int DirectDrawSurface::offset(const unsigned int face, const unsigned int mipmap)
+{
+ unsigned int size = sizeof(DDSHeader);
+
+ if (face != 0)
+ {
+ size += face * faceSize();
+ }
+
+ for (unsigned int m = 0; m < mipmap; m++)
+ {
+ size += mipmapSize(m);
+ }
+
+ return size;
+}
+
+
+void DirectDrawSurface::printInfo() const
+{
+ /* printf("FOURCC: %c%c%c%c\n", ((unsigned char *)&header.fourcc)[0], ((unsigned char *)&header.fourcc)[1], ((unsigned char *)&header.fourcc)[2], ((unsigned char *)&header.fourcc)[3]); */
+ printf("Flags: 0x%.8X\n", header.flags);
+ if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
+ if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
+ if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
+ if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
+ if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
+ if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
+ if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
+ if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
+
+ printf("Height: %d\n", header.height);
+ printf("Width: %d\n", header.width);
+ printf("Depth: %d\n", header.depth);
+ if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch);
+ else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch);
+ printf("Mipmap count: %d\n", header.mipmapcount);
+
+ printf("Pixel Format:\n");
+ /* printf("\tSize: %d\n", header.pf.size); */
+ printf("\tFlags: 0x%.8X\n", header.pf.flags);
+ if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
+ if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
+ if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
+ if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
+ if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
+ if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
+
+ printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF));
+ printf("\tBit count: %d\n", header.pf.bitcount);
+ printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
+ printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
+ printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
+ printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
+
+ printf("Caps:\n");
+ printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
+ if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
+ if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
+ if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
+
+ printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
+ if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
+ else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
+ {
+ printf("\t\tDDSCAPS2_CUBEMAP\n");
+ if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
+ else {
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
+ }
+ }
+
+ printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
+ printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
+
+ if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T'))
+ {
+ int major = (header.reserved[10] >> 16) & 0xFF;
+ int minor = (header.reserved[10] >> 8) & 0xFF;
+ int revision= header.reserved[10] & 0xFF;
+
+ printf("Version:\n");
+ printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
+ }
+}
+
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
new file mode 100644
index 00000000000..2b3319d05a1
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
@@ -0,0 +1,162 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef _DDS_DIRECTDRAWSURFACE_H
+#define _DDS_DIRECTDRAWSURFACE_H
+
+#include <Stream.h>
+#include <ColorBlock.h>
+#include <Image.h>
+
+struct DDSPixelFormat {
+ unsigned int size;
+ unsigned int flags;
+ unsigned int fourcc;
+ unsigned int bitcount;
+ unsigned int rmask;
+ unsigned int gmask;
+ unsigned int bmask;
+ unsigned int amask;
+};
+
+struct DDSCaps {
+ unsigned int caps1;
+ unsigned int caps2;
+ unsigned int caps3;
+ unsigned int caps4;
+};
+
+/// DDS file header.
+struct DDSHeader {
+ unsigned int fourcc;
+ unsigned int size;
+ unsigned int flags;
+ unsigned int height;
+ unsigned int width;
+ unsigned int pitch;
+ unsigned int depth;
+ unsigned int mipmapcount;
+ unsigned int reserved[11];
+ DDSPixelFormat pf;
+ DDSCaps caps;
+ unsigned int notused;
+
+ // Helper methods.
+ DDSHeader();
+
+ void setWidth(unsigned int w);
+ void setHeight(unsigned int h);
+ void setDepth(unsigned int d);
+ void setMipmapCount(unsigned int count);
+ void setTexture2D();
+ void setTexture3D();
+ void setTextureCube();
+ void setLinearSize(unsigned int size);
+ void setPitch(unsigned int pitch);
+ void setFourCC(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3);
+ void setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask);
+ void setNormalFlag(bool b);
+
+ /* void swapBytes(); */
+};
+
+/// DirectDraw Surface. (DDS)
+class DirectDrawSurface
+{
+public:
+ DirectDrawSurface(unsigned char *mem, unsigned int size);
+ ~DirectDrawSurface();
+
+ bool isValid() const;
+ bool isSupported() const;
+
+ unsigned int mipmapCount() const;
+ unsigned int width() const;
+ unsigned int height() const;
+ unsigned int depth() const;
+ bool isTexture2D() const;
+ bool isTexture3D() const;
+ bool isTextureCube() const;
+ bool hasAlpha() const; /* false for DXT1, true for all others */
+
+ void mipmap(Image * img, unsigned int f, unsigned int m);
+
+ void printInfo() const;
+
+private:
+
+ unsigned int blockSize() const;
+ unsigned int faceSize() const;
+ unsigned int mipmapSize(unsigned int m) const;
+
+ unsigned int offset(unsigned int f, unsigned int m);
+
+ void readLinearImage(Image * img);
+ void readBlockImage(Image * img);
+ void readBlock(ColorBlock * rgba);
+
+
+private:
+ Stream stream; // memory where DDS file resides
+ DDSHeader header;
+};
+
+void mem_read(Stream & mem, DDSPixelFormat & pf);
+void mem_read(Stream & mem, DDSCaps & caps);
+void mem_read(Stream & mem, DDSHeader & header);
+
+#endif // _DDS_DIRECTDRAWSURFACE_H
diff --git a/source/blender/imbuf/intern/dds/Image.cpp b/source/blender/imbuf/intern/dds/Image.cpp
new file mode 100644
index 00000000000..f3e6fa38955
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Image.cpp
@@ -0,0 +1,132 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#include <Color.h>
+#include <Image.h>
+
+#include <stdio.h> // printf
+
+Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(0)
+{
+}
+
+Image::~Image()
+{
+ free();
+}
+
+void Image::allocate(unsigned int w, unsigned int h)
+{
+ free();
+ m_width = w;
+ m_height = h;
+ m_data = new Color32[w * h];
+}
+
+void Image::free()
+{
+ if (m_data) delete [] m_data;
+ m_data = 0;
+}
+
+
+unsigned int Image::width() const
+{
+ return m_width;
+}
+
+unsigned int Image::height() const
+{
+ return m_height;
+}
+
+const Color32 * Image::scanline(unsigned int h) const
+{
+ if (h >= m_height) {
+ printf("DDS: scanline beyond dimensions of image");
+ return m_data;
+ }
+ return m_data + h * m_width;
+}
+
+Color32 * Image::scanline(unsigned int h)
+{
+ if (h >= m_height) {
+ printf("DDS: scanline beyond dimensions of image");
+ return m_data;
+ }
+ return m_data + h * m_width;
+}
+
+const Color32 * Image::pixels() const
+{
+ return m_data;
+}
+
+Color32 * Image::pixels()
+{
+ return m_data;
+}
+
+const Color32 & Image::pixel(unsigned int idx) const
+{
+ if (idx >= m_width * m_height) {
+ printf("DDS: pixel beyond dimensions of image");
+ return m_data[0];
+ }
+ return m_data[idx];
+}
+
+Color32 & Image::pixel(unsigned int idx)
+{
+ if (idx >= m_width * m_height) {
+ printf("DDS: pixel beyond dimensions of image");
+ return m_data[0];
+ }
+ return m_data[idx];
+}
+
+
+Image::Format Image::format() const
+{
+ return m_format;
+}
+
+void Image::setFormat(Image::Format f)
+{
+ m_format = f;
+}
+
diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h
new file mode 100644
index 00000000000..10356774777
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Image.h
@@ -0,0 +1,103 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#ifndef _DDS_IMAGE_H
+#define _DDS_IMAGE_H
+
+#include <Color.h>
+
+/// 32 bit RGBA image.
+class Image
+{
+public:
+
+ enum Format
+ {
+ Format_RGB,
+ Format_ARGB,
+ };
+
+ Image();
+ ~Image();
+
+ void allocate(unsigned int w, unsigned int h);
+ /*
+ bool load(const char * name);
+
+ void wrap(void * data, unsigned int w, unsigned int h);
+ void unwrap();
+ */
+
+ unsigned int width() const;
+ unsigned int height() const;
+
+ const Color32 * scanline(unsigned int h) const;
+ Color32 * scanline(unsigned int h);
+
+ const Color32 * pixels() const;
+ Color32 * pixels();
+
+ const Color32 & pixel(unsigned int idx) const;
+ Color32 & pixel(unsigned int idx);
+
+ const Color32 & pixel(unsigned int x, unsigned int y) const;
+ Color32 & pixel(unsigned int x, unsigned int y);
+
+ Format format() const;
+ void setFormat(Format f);
+
+private:
+ void free();
+
+private:
+ unsigned int m_width;
+ unsigned int m_height;
+ Format m_format;
+ Color32 * m_data;
+};
+
+
+inline const Color32 & Image::pixel(unsigned int x, unsigned int y) const
+{
+ return pixel(y * width() + x);
+}
+
+inline Color32 & Image::pixel(unsigned int x, unsigned int y)
+{
+ return pixel(y * width() + x);
+}
+
+#endif // _DDS_IMAGE_H
diff --git a/source/blender/imbuf/intern/dds/Makefile b/source/blender/imbuf/intern/dds/Makefile
new file mode 100644
index 00000000000..2bab1de1fc4
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Makefile
@@ -0,0 +1,67 @@
+#
+# $Id: Makefile 7037 2006-03-12 14:11:23Z ton $
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = dds
+DIR = $(OCGDIR)/blender/imbuf/dds
+SOURCEDIR = source/blender/imbuf/intern/dds
+
+include nan_compile.mk
+include nan_definitions.mk
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ CFLAGS += -funsigned-char
+endif
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_JPEG)/include
+CPPFLAGS += -I$(NAN_PNG)/include
+CPPFLAGS += -I$(NAN_ZLIB)/include
+CPPFLAGS += -I$(NAN_TIFF)/include
+CPPFLAGS += -I../../../include
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../avi
+CPPFLAGS += -I../../../quicktime
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+# This is not really needed, but until /include is cleaned, it must be
+# there for proper compilation.
+# - No, it is also needed in antialias, for listbase (nzc)
+CPPFLAGS += -I../../../makesdna
+# external interface of this module
+CPPFLAGS += -I../..
+CPPFLAGS += -I..
+CPPFLAGS += -I.
+CPPFLAGS += -DWITH_DDS
diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript
new file mode 100644
index 00000000000..0618e32b3c6
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/SConscript
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+Import ('env')
+
+source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp']
+
+incs = ['.',
+ '../../',
+ '..',
+ '../../../makesdna',
+ '../../../blenkernel',
+ '../../../blenlib',
+ 'intern/include',
+ '#/intern/guardedalloc']
+
+
+defs = []
+
+env.BlenderLib ('bf_dds', source_files, incs, defs, libtype=['core','player'], priority = [90, 200])
diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp
new file mode 100644
index 00000000000..a181ec74476
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Stream.cpp
@@ -0,0 +1,88 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <Stream.h>
+
+#include <stdio.h> // printf
+#include <string.h> // memcpy
+
+unsigned int Stream::seek(unsigned int p)
+{
+ if (p > size) {
+ printf("DDS: trying to seek beyond end of stream (corrupt file?)");
+ }
+ else {
+ pos = p;
+ }
+
+ return pos;
+}
+
+unsigned int mem_read(Stream & mem, unsigned long long & i)
+{
+ if (mem.pos + 8 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
+ mem.pos += 8;
+ return(8);
+}
+
+unsigned int mem_read(Stream & mem, unsigned int & i)
+{
+ if (mem.pos + 4 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
+ mem.pos += 4;
+ return(4);
+}
+
+unsigned int mem_read(Stream & mem, unsigned short & i)
+{
+ if (mem.pos + 2 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
+ mem.pos += 2;
+ return(2);
+}
+
+unsigned int mem_read(Stream & mem, unsigned char & i)
+{
+ if (mem.pos + 1 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ i = (mem.mem + mem.pos)[0];
+ mem.pos += 1;
+ return(1);
+}
+
diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h
new file mode 100644
index 00000000000..1e7d3c6b536
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Stream.h
@@ -0,0 +1,48 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* simple memory stream functions with buffer overflow check */
+
+#ifndef _STREAM_H
+#define _STREAM_H
+
+struct Stream
+{
+ unsigned char *mem; // location in memory
+ unsigned int size; // size
+ unsigned int pos; // current position
+ Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {};
+ unsigned int seek(unsigned int p);
+};
+
+unsigned int mem_read(Stream & mem, unsigned long long & i);
+unsigned int mem_read(Stream & mem, unsigned int & i);
+unsigned int mem_read(Stream & mem, unsigned short & i);
+unsigned int mem_read(Stream & mem, unsigned char & i);
+
+#endif // _STREAM_H
+
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
new file mode 100644
index 00000000000..0e06fd3e50b
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -0,0 +1,120 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <dds_api.h>
+#include <Stream.h>
+#include <DirectDrawSurface.h>
+
+#include <stdio.h> // printf
+
+extern "C" {
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_allocimbuf.h"
+
+/* not supported yet
+short imb_save_dds(struct ImBuf * ibuf, char *name, int flags)
+{
+ return(0);
+}
+*/
+
+int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
+{
+ /* heuristic check to see if mem contains a DDS file */
+ /* header.fourcc == FOURCC_DDS */
+ if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) return(0);
+ /* header.size == 124 */
+ if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) return(0);
+ return(1);
+}
+
+struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags)
+{
+ struct ImBuf * ibuf = 0;
+ DirectDrawSurface dds(mem, size); /* reads header */
+ unsigned char bytes_per_pixel;
+ unsigned int *rect;
+ Image img;
+ unsigned int numpixels = 0;
+ int col;
+ unsigned char *cp = (unsigned char *) &col;
+ Color32 pixel;
+ Color32 *pixels = 0;
+
+ /* check if DDS is valid and supported */
+ if (!dds.isValid()) {
+ printf("DDS: not valid; header follows\n");
+ dds.printInfo();
+ return(0);
+ }
+ if (!dds.isSupported()) {
+ printf("DDS: format not supported\n");
+ return(0);
+ }
+ if ((dds.width() > 65535) || (dds.height() > 65535)) {
+ printf("DDS: dimensions too large\n");
+ return(0);
+ }
+
+ /* convert DDS into ImBuf */
+ if (dds.hasAlpha()) bytes_per_pixel = 32;
+ else bytes_per_pixel = 24;
+ ibuf = IMB_allocImBuf(dds.width(), dds.height(), bytes_per_pixel, 0, 0);
+ if (ibuf == 0) return(0); /* memory allocation failed */
+
+ ibuf->ftype = DDS;
+
+ if ((flags & IB_test) == 0) {
+ if (!imb_addrectImBuf(ibuf)) return(ibuf);
+ if (ibuf->rect == 0) return(ibuf);
+
+ rect = ibuf->rect;
+ dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
+ pixels = img.pixels();
+ numpixels = dds.width() * dds.height();
+ cp[3] = 0xff; /* default alpha if alpha channel is not present */
+
+ for (unsigned int i = 0; i < numpixels; i++) {
+ pixel = pixels[i];
+ cp[0] = pixel.r; /* set R component of col */
+ cp[1] = pixel.g; /* set G component of col */
+ cp[2] = pixel.b; /* set B component of col */
+ if (bytes_per_pixel == 32)
+ cp[3] = pixel.a; /* set A component of col */
+ rect[i] = col;
+ }
+ IMB_flipy(ibuf);
+ }
+
+ return(ibuf);
+}
+
+} // extern "C"
diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h
new file mode 100644
index 00000000000..8a0f966dd68
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/dds_api.h
@@ -0,0 +1,43 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef _DDS_API_H
+#define _DDS_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+short imb_save_dds(struct ImBuf *ibuf, char *name, int flags);
+int imb_is_a_dds(unsigned char *mem); /* use only first 32 bytes of mem */
+struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DDS_API_H */
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index bfa6200d23b..c5901ccad90 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -59,6 +59,10 @@
#include "openexr/openexr_api.h"
#endif
+#ifdef WITH_DDS
+#include "dds/dds_api.h"
+#endif
+
#ifdef WITH_QUICKTIME
#if defined(_WIN32) || defined (__APPLE__)
#include "quicktime_import.h"
@@ -153,6 +157,11 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) {
ibuf = imb_load_openexr((uchar *)mem, size, flags);
if (ibuf) return (ibuf);
#endif
+
+#ifdef WITH_DDS
+ ibuf = imb_load_dds((uchar *)mem, size, flags);
+ if (ibuf) return (ibuf);
+#endif
#ifdef WITH_QUICKTIME
#if defined(_WIN32) || defined (__APPLE__)
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 69390951a25..4c7b5fec2c4 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -44,6 +44,11 @@
#include "IMB_targa.h"
#include "IMB_png.h"
+
+#ifdef WITH_DDS
+#include "dds/dds_api.h"
+#endif
+
#include "IMB_bmp.h"
#include "IMB_tiff.h"
#include "IMB_radiance_hdr.h"
@@ -113,6 +118,9 @@ static int IMB_ispic_name(char *name)
}
if (imb_is_a_png(buf)) return(PNG);
+#ifdef WITH_DDS
+ if (imb_is_a_dds((uchar *)buf)) return(DDS);
+#endif
if (imb_is_a_targa(buf)) return(TGA);
#ifdef WITH_OPENEXR
if (imb_is_a_openexr((uchar *)buf)) return(OPENEXR);
@@ -162,6 +170,9 @@ int IMB_ispic(char *filename)
|| BLI_testextensie(filename, ".rgb")
|| BLI_testextensie(filename, ".bmp")
|| BLI_testextensie(filename, ".png")
+#ifdef WITH_DDS
+ || BLI_testextensie(filename, ".dds")
+#endif
|| BLI_testextensie(filename, ".iff")
|| BLI_testextensie(filename, ".lbm")
|| BLI_testextensie(filename, ".gif")
@@ -188,6 +199,9 @@ int IMB_ispic(char *filename)
|| BLI_testextensie(filename, ".bmp")
|| BLI_testextensie(filename, ".png")
|| BLI_testextensie(filename, ".cin")
+#ifdef WITH_DDS
+ || BLI_testextensie(filename, ".dds")
+#endif
#ifdef WITH_BF_OPENEXR
|| BLI_testextensie(filename, ".exr")
#endif
@@ -251,6 +265,7 @@ static int isffmpeg (char *filename) {
if( BLI_testextensie(filename, ".swf") ||
BLI_testextensie(filename, ".jpg") ||
BLI_testextensie(filename, ".png") ||
+ BLI_testextensie(filename, ".dds") ||
BLI_testextensie(filename, ".tga") ||
BLI_testextensie(filename, ".bmp") ||
BLI_testextensie(filename, ".exr") ||
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index 2e922c65827..ccca8e9f859 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -61,6 +61,9 @@
#ifdef WITH_OPENEXR
#include "openexr/openexr_api.h"
#endif
+#ifdef WITH_DDS
+#include "dds/dds_api.h"
+#endif
#include "IMB_iff.h"
#include "IMB_bitplanes.h"
@@ -115,6 +118,13 @@ short IMB_saveiff(struct ImBuf *ibuf, char *name, int flags)
return imb_save_openexr(ibuf, name, flags);
}
#endif
+/* not supported yet
+#ifdef WITH_DDS
+ if (IS_dds(ibuf)) {
+ return imb_save_dds(ibuf, name, flags);
+ }
+#endif
+*/
if (IS_cineon(ibuf)) {
return imb_savecineon(ibuf, name, flags);