]> granicus.if.org Git - imagemagick/commitdiff
Newlines...
authordirk <dirk@git.imagemagick.org>
Mon, 7 Jul 2014 18:47:28 +0000 (18:47 +0000)
committerdirk <dirk@git.imagemagick.org>
Mon, 7 Jul 2014 18:47:28 +0000 (18:47 +0000)
coders/dds.c

index 4ee2929f465b48f659be020996c19aa69cb4af44..b0d7e7652b2ce0778955e70ea801ca92477ede99 100644 (file)
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%                            DDDD   DDDD   SSSSS                              %\r
-%                            D   D  D   D  SS                                 %\r
-%                            D   D  D   D   SSS                               %\r
-%                            D   D  D   D     SS                              %\r
-%                            DDDD   DDDD   SSSSS                              %\r
-%                                                                             %\r
-%                                                                             %\r
-%           Read/Write Microsoft Direct Draw Surface Image Format             %\r
-%                                                                             %\r
-%                              Software Design                                %\r
-%                             Bianca van Schaik                               %\r
-%                                March 2008                                   %\r
-%                               Dirk Lemstra                                  %\r
-%                              September 2013                                 %\r
-%                                                                             %\r
-%                                                                             %\r
-%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %\r
-%  dedicated to making software imaging solutions freely available.           %\r
-%                                                                             %\r
-%  You may not use this file except in compliance with the License.  You may  %\r
-%  obtain a copy of the License at                                            %\r
-%                                                                             %\r
-%    http://www.imagemagick.org/script/license.php                            %\r
-%                                                                             %\r
-%  Unless required by applicable law or agreed to in writing, software        %\r
-%  distributed under the License is distributed on an "AS IS" BASIS,          %\r
-%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %\r
-%  See the License for the specific language governing permissions and        %\r
-%  limitations under the License.                                             %\r
-%                                                                             %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-%\r
-*/\r
-\f\r
-/*\r
-  Include declarations.\r
-*/\r
-#include "MagickCore/studio.h"\r
-#include "MagickCore/blob.h"\r
-#include "MagickCore/blob-private.h"\r
-#include "MagickCore/cache.h"\r
-#include "MagickCore/colorspace.h"\r
-#include "MagickCore/exception.h"\r
-#include "MagickCore/exception-private.h"\r
-#include "MagickCore/image.h"\r
-#include "MagickCore/image-private.h"\r
-#include "MagickCore/list.h"\r
-#include "MagickCore/log.h"\r
-#include "MagickCore/magick.h"\r
-#include "MagickCore/memory_.h"\r
-#include "MagickCore/monitor.h"\r
-#include "MagickCore/monitor-private.h"\r
-#include "MagickCore/profile.h"\r
-#include "MagickCore/quantum-private.h"\r
-#include "MagickCore/static.h"\r
-#include "MagickCore/string_.h"\r
-#include "MagickCore/module.h"\r
-#include "MagickCore/transform.h"\r
-#include "MagickCore/studio.h"\r
-#include "MagickCore/blob.h"\r
-#include "MagickCore/blob-private.h"\r
-#include "MagickCore/colorspace.h"\r
-#include "MagickCore/colorspace-private.h"\r
-#include "MagickCore/exception.h"\r
-#include "MagickCore/exception-private.h"\r
-#include "MagickCore/compress.h"\r
-#include "MagickCore/image.h"\r
-#include "MagickCore/image-private.h"\r
-#include "MagickCore/list.h"\r
-#include "MagickCore/magick.h"\r
-#include "MagickCore/memory_.h"\r
-#include "MagickCore/monitor.h"\r
-#include "MagickCore/monitor-private.h"\r
-#include "MagickCore/option.h"\r
-#include "MagickCore/pixel-accessor.h"\r
-#include "MagickCore/quantum.h"\r
-#include "MagickCore/static.h"\r
-#include "MagickCore/string_.h"\r
-#include "MagickCore/string-private.h"\r
-\f\r
-/*\r
-  Definitions\r
-*/\r
-#define DDSD_CAPS         0x00000001\r
-#define DDSD_HEIGHT       0x00000002\r
-#define DDSD_WIDTH        0x00000004\r
-#define DDSD_PITCH        0x00000008\r
-#define DDSD_PIXELFORMAT  0x00001000\r
-#define DDSD_MIPMAPCOUNT  0x00020000\r
-#define DDSD_LINEARSIZE   0x00080000\r
-#define DDSD_DEPTH        0x00800000\r
-\r
-#define DDPF_ALPHAPIXELS  0x00000001\r
-#define DDPF_FOURCC       0x00000004\r
-#define DDPF_RGB          0x00000040\r
-\r
-#define FOURCC_DXT1       0x31545844\r
-#define FOURCC_DXT3       0x33545844\r
-#define FOURCC_DXT5       0x35545844\r
-\r
-#define DDSCAPS_COMPLEX   0x00000008\r
-#define DDSCAPS_TEXTURE   0x00001000\r
-#define DDSCAPS_MIPMAP    0x00400000\r
-\r
-#define DDSCAPS2_CUBEMAP  0x00000200\r
-#define DDSCAPS2_CUBEMAP_POSITIVEX  0x00000400\r
-#define DDSCAPS2_CUBEMAP_NEGATIVEX  0x00000800\r
-#define DDSCAPS2_CUBEMAP_POSITIVEY  0x00001000\r
-#define DDSCAPS2_CUBEMAP_NEGATIVEY  0x00002000\r
-#define DDSCAPS2_CUBEMAP_POSITIVEZ  0x00004000\r
-#define DDSCAPS2_CUBEMAP_NEGATIVEZ  0x00008000\r
-#define DDSCAPS2_VOLUME   0x00200000\r
-\r
-#ifndef SIZE_MAX\r
-#define SIZE_MAX ((size_t) -1)\r
-#endif\r
-\r
-/*\r
-  Structure declarations.\r
-*/\r
-typedef struct _DDSPixelFormat\r
-{\r
-  size_t\r
-    flags,\r
-    fourcc,\r
-    rgb_bitcount,\r
-    r_bitmask,\r
-    g_bitmask,\r
-    b_bitmask,\r
-    alpha_bitmask;\r
-} DDSPixelFormat;\r
-\r
-typedef struct _DDSInfo\r
-{\r
-  size_t\r
-    flags,\r
-    height,\r
-    width,\r
-    pitchOrLinearSize,\r
-    depth,\r
-    mipmapcount,\r
-    ddscaps1,\r
-    ddscaps2;\r
-  \r
-  DDSPixelFormat\r
-    pixelformat;\r
-} DDSInfo;\r
-\r
-typedef struct _DDSColors\r
-{\r
-  unsigned char\r
-    r[4],\r
-    g[4],\r
-    b[4],\r
-    a[4];\r
-} DDSColors;\r
-\r
-typedef struct _DDSVector4\r
-{\r
-  float\r
-    x,\r
-    y,\r
-    z,\r
-    w;\r
-} DDSVector4;\r
-\r
-typedef struct _DDSVector3\r
-{\r
-  float\r
-    x,\r
-    y,\r
-    z;\r
-} DDSVector3;\r
-\r
-typedef struct _DDSSourceBlock\r
-{\r
-  unsigned char\r
-    start,\r
-    end,\r
-    error;\r
-} DDSSourceBlock;\r
-\r
-typedef struct _DDSSingleColourLookup\r
-{\r
-  DDSSourceBlock sources[2];\r
-} DDSSingleColourLookup;\r
-\r
-typedef MagickBooleanType\r
-  DDSDecoder(Image *, DDSInfo *, ExceptionInfo *);\r
-\r
-static const DDSSingleColourLookup DDSLookup_5_4[] =\r
-{\r
-  { { { 0, 0, 0 }, { 0, 0, 0 } } },\r
-  { { { 0, 0, 1 }, { 0, 1, 1 } } },\r
-  { { { 0, 0, 2 }, { 0, 1, 0 } } },\r
-  { { { 0, 0, 3 }, { 0, 1, 1 } } },\r
-  { { { 0, 0, 4 }, { 0, 2, 1 } } },\r
-  { { { 1, 0, 3 }, { 0, 2, 0 } } },\r
-  { { { 1, 0, 2 }, { 0, 2, 1 } } },\r
-  { { { 1, 0, 1 }, { 0, 3, 1 } } },\r
-  { { { 1, 0, 0 }, { 0, 3, 0 } } },\r
-  { { { 1, 0, 1 }, { 1, 2, 1 } } },\r
-  { { { 1, 0, 2 }, { 1, 2, 0 } } },\r
-  { { { 1, 0, 3 }, { 0, 4, 0 } } },\r
-  { { { 1, 0, 4 }, { 0, 5, 1 } } },\r
-  { { { 2, 0, 3 }, { 0, 5, 0 } } },\r
-  { { { 2, 0, 2 }, { 0, 5, 1 } } },\r
-  { { { 2, 0, 1 }, { 0, 6, 1 } } },\r
-  { { { 2, 0, 0 }, { 0, 6, 0 } } },\r
-  { { { 2, 0, 1 }, { 2, 3, 1 } } },\r
-  { { { 2, 0, 2 }, { 2, 3, 0 } } },\r
-  { { { 2, 0, 3 }, { 0, 7, 0 } } },\r
-  { { { 2, 0, 4 }, { 1, 6, 1 } } },\r
-  { { { 3, 0, 3 }, { 1, 6, 0 } } },\r
-  { { { 3, 0, 2 }, { 0, 8, 0 } } },\r
-  { { { 3, 0, 1 }, { 0, 9, 1 } } },\r
-  { { { 3, 0, 0 }, { 0, 9, 0 } } },\r
-  { { { 3, 0, 1 }, { 0, 9, 1 } } },\r
-  { { { 3, 0, 2 }, { 0, 10, 1 } } },\r
-  { { { 3, 0, 3 }, { 0, 10, 0 } } },\r
-  { { { 3, 0, 4 }, { 2, 7, 1 } } },\r
-  { { { 4, 0, 4 }, { 2, 7, 0 } } },\r
-  { { { 4, 0, 3 }, { 0, 11, 0 } } },\r
-  { { { 4, 0, 2 }, { 1, 10, 1 } } },\r
-  { { { 4, 0, 1 }, { 1, 10, 0 } } },\r
-  { { { 4, 0, 0 }, { 0, 12, 0 } } },\r
-  { { { 4, 0, 1 }, { 0, 13, 1 } } },\r
-  { { { 4, 0, 2 }, { 0, 13, 0 } } },\r
-  { { { 4, 0, 3 }, { 0, 13, 1 } } },\r
-  { { { 4, 0, 4 }, { 0, 14, 1 } } },\r
-  { { { 5, 0, 3 }, { 0, 14, 0 } } },\r
-  { { { 5, 0, 2 }, { 2, 11, 1 } } },\r
-  { { { 5, 0, 1 }, { 2, 11, 0 } } },\r
-  { { { 5, 0, 0 }, { 0, 15, 0 } } },\r
-  { { { 5, 0, 1 }, { 1, 14, 1 } } },\r
-  { { { 5, 0, 2 }, { 1, 14, 0 } } },\r
-  { { { 5, 0, 3 }, { 0, 16, 0 } } },\r
-  { { { 5, 0, 4 }, { 0, 17, 1 } } },\r
-  { { { 6, 0, 3 }, { 0, 17, 0 } } },\r
-  { { { 6, 0, 2 }, { 0, 17, 1 } } },\r
-  { { { 6, 0, 1 }, { 0, 18, 1 } } },\r
-  { { { 6, 0, 0 }, { 0, 18, 0 } } },\r
-  { { { 6, 0, 1 }, { 2, 15, 1 } } },\r
-  { { { 6, 0, 2 }, { 2, 15, 0 } } },\r
-  { { { 6, 0, 3 }, { 0, 19, 0 } } },\r
-  { { { 6, 0, 4 }, { 1, 18, 1 } } },\r
-  { { { 7, 0, 3 }, { 1, 18, 0 } } },\r
-  { { { 7, 0, 2 }, { 0, 20, 0 } } },\r
-  { { { 7, 0, 1 }, { 0, 21, 1 } } },\r
-  { { { 7, 0, 0 }, { 0, 21, 0 } } },\r
-  { { { 7, 0, 1 }, { 0, 21, 1 } } },\r
-  { { { 7, 0, 2 }, { 0, 22, 1 } } },\r
-  { { { 7, 0, 3 }, { 0, 22, 0 } } },\r
-  { { { 7, 0, 4 }, { 2, 19, 1 } } },\r
-  { { { 8, 0, 4 }, { 2, 19, 0 } } },\r
-  { { { 8, 0, 3 }, { 0, 23, 0 } } },\r
-  { { { 8, 0, 2 }, { 1, 22, 1 } } },\r
-  { { { 8, 0, 1 }, { 1, 22, 0 } } },\r
-  { { { 8, 0, 0 }, { 0, 24, 0 } } },\r
-  { { { 8, 0, 1 }, { 0, 25, 1 } } },\r
-  { { { 8, 0, 2 }, { 0, 25, 0 } } },\r
-  { { { 8, 0, 3 }, { 0, 25, 1 } } },\r
-  { { { 8, 0, 4 }, { 0, 26, 1 } } },\r
-  { { { 9, 0, 3 }, { 0, 26, 0 } } },\r
-  { { { 9, 0, 2 }, { 2, 23, 1 } } },\r
-  { { { 9, 0, 1 }, { 2, 23, 0 } } },\r
-  { { { 9, 0, 0 }, { 0, 27, 0 } } },\r
-  { { { 9, 0, 1 }, { 1, 26, 1 } } },\r
-  { { { 9, 0, 2 }, { 1, 26, 0 } } },\r
-  { { { 9, 0, 3 }, { 0, 28, 0 } } },\r
-  { { { 9, 0, 4 }, { 0, 29, 1 } } },\r
-  { { { 10, 0, 3 }, { 0, 29, 0 } } },\r
-  { { { 10, 0, 2 }, { 0, 29, 1 } } },\r
-  { { { 10, 0, 1 }, { 0, 30, 1 } } },\r
-  { { { 10, 0, 0 }, { 0, 30, 0 } } },\r
-  { { { 10, 0, 1 }, { 2, 27, 1 } } },\r
-  { { { 10, 0, 2 }, { 2, 27, 0 } } },\r
-  { { { 10, 0, 3 }, { 0, 31, 0 } } },\r
-  { { { 10, 0, 4 }, { 1, 30, 1 } } },\r
-  { { { 11, 0, 3 }, { 1, 30, 0 } } },\r
-  { { { 11, 0, 2 }, { 4, 24, 0 } } },\r
-  { { { 11, 0, 1 }, { 1, 31, 1 } } },\r
-  { { { 11, 0, 0 }, { 1, 31, 0 } } },\r
-  { { { 11, 0, 1 }, { 1, 31, 1 } } },\r
-  { { { 11, 0, 2 }, { 2, 30, 1 } } },\r
-  { { { 11, 0, 3 }, { 2, 30, 0 } } },\r
-  { { { 11, 0, 4 }, { 2, 31, 1 } } },\r
-  { { { 12, 0, 4 }, { 2, 31, 0 } } },\r
-  { { { 12, 0, 3 }, { 4, 27, 0 } } },\r
-  { { { 12, 0, 2 }, { 3, 30, 1 } } },\r
-  { { { 12, 0, 1 }, { 3, 30, 0 } } },\r
-  { { { 12, 0, 0 }, { 4, 28, 0 } } },\r
-  { { { 12, 0, 1 }, { 3, 31, 1 } } },\r
-  { { { 12, 0, 2 }, { 3, 31, 0 } } },\r
-  { { { 12, 0, 3 }, { 3, 31, 1 } } },\r
-  { { { 12, 0, 4 }, { 4, 30, 1 } } },\r
-  { { { 13, 0, 3 }, { 4, 30, 0 } } },\r
-  { { { 13, 0, 2 }, { 6, 27, 1 } } },\r
-  { { { 13, 0, 1 }, { 6, 27, 0 } } },\r
-  { { { 13, 0, 0 }, { 4, 31, 0 } } },\r
-  { { { 13, 0, 1 }, { 5, 30, 1 } } },\r
-  { { { 13, 0, 2 }, { 5, 30, 0 } } },\r
-  { { { 13, 0, 3 }, { 8, 24, 0 } } },\r
-  { { { 13, 0, 4 }, { 5, 31, 1 } } },\r
-  { { { 14, 0, 3 }, { 5, 31, 0 } } },\r
-  { { { 14, 0, 2 }, { 5, 31, 1 } } },\r
-  { { { 14, 0, 1 }, { 6, 30, 1 } } },\r
-  { { { 14, 0, 0 }, { 6, 30, 0 } } },\r
-  { { { 14, 0, 1 }, { 6, 31, 1 } } },\r
-  { { { 14, 0, 2 }, { 6, 31, 0 } } },\r
-  { { { 14, 0, 3 }, { 8, 27, 0 } } },\r
-  { { { 14, 0, 4 }, { 7, 30, 1 } } },\r
-  { { { 15, 0, 3 }, { 7, 30, 0 } } },\r
-  { { { 15, 0, 2 }, { 8, 28, 0 } } },\r
-  { { { 15, 0, 1 }, { 7, 31, 1 } } },\r
-  { { { 15, 0, 0 }, { 7, 31, 0 } } },\r
-  { { { 15, 0, 1 }, { 7, 31, 1 } } },\r
-  { { { 15, 0, 2 }, { 8, 30, 1 } } },\r
-  { { { 15, 0, 3 }, { 8, 30, 0 } } },\r
-  { { { 15, 0, 4 }, { 10, 27, 1 } } },\r
-  { { { 16, 0, 4 }, { 10, 27, 0 } } },\r
-  { { { 16, 0, 3 }, { 8, 31, 0 } } },\r
-  { { { 16, 0, 2 }, { 9, 30, 1 } } },\r
-  { { { 16, 0, 1 }, { 9, 30, 0 } } },\r
-  { { { 16, 0, 0 }, { 12, 24, 0 } } },\r
-  { { { 16, 0, 1 }, { 9, 31, 1 } } },\r
-  { { { 16, 0, 2 }, { 9, 31, 0 } } },\r
-  { { { 16, 0, 3 }, { 9, 31, 1 } } },\r
-  { { { 16, 0, 4 }, { 10, 30, 1 } } },\r
-  { { { 17, 0, 3 }, { 10, 30, 0 } } },\r
-  { { { 17, 0, 2 }, { 10, 31, 1 } } },\r
-  { { { 17, 0, 1 }, { 10, 31, 0 } } },\r
-  { { { 17, 0, 0 }, { 12, 27, 0 } } },\r
-  { { { 17, 0, 1 }, { 11, 30, 1 } } },\r
-  { { { 17, 0, 2 }, { 11, 30, 0 } } },\r
-  { { { 17, 0, 3 }, { 12, 28, 0 } } },\r
-  { { { 17, 0, 4 }, { 11, 31, 1 } } },\r
-  { { { 18, 0, 3 }, { 11, 31, 0 } } },\r
-  { { { 18, 0, 2 }, { 11, 31, 1 } } },\r
-  { { { 18, 0, 1 }, { 12, 30, 1 } } },\r
-  { { { 18, 0, 0 }, { 12, 30, 0 } } },\r
-  { { { 18, 0, 1 }, { 14, 27, 1 } } },\r
-  { { { 18, 0, 2 }, { 14, 27, 0 } } },\r
-  { { { 18, 0, 3 }, { 12, 31, 0 } } },\r
-  { { { 18, 0, 4 }, { 13, 30, 1 } } },\r
-  { { { 19, 0, 3 }, { 13, 30, 0 } } },\r
-  { { { 19, 0, 2 }, { 16, 24, 0 } } },\r
-  { { { 19, 0, 1 }, { 13, 31, 1 } } },\r
-  { { { 19, 0, 0 }, { 13, 31, 0 } } },\r
-  { { { 19, 0, 1 }, { 13, 31, 1 } } },\r
-  { { { 19, 0, 2 }, { 14, 30, 1 } } },\r
-  { { { 19, 0, 3 }, { 14, 30, 0 } } },\r
-  { { { 19, 0, 4 }, { 14, 31, 1 } } },\r
-  { { { 20, 0, 4 }, { 14, 31, 0 } } },\r
-  { { { 20, 0, 3 }, { 16, 27, 0 } } },\r
-  { { { 20, 0, 2 }, { 15, 30, 1 } } },\r
-  { { { 20, 0, 1 }, { 15, 30, 0 } } },\r
-  { { { 20, 0, 0 }, { 16, 28, 0 } } },\r
-  { { { 20, 0, 1 }, { 15, 31, 1 } } },\r
-  { { { 20, 0, 2 }, { 15, 31, 0 } } },\r
-  { { { 20, 0, 3 }, { 15, 31, 1 } } },\r
-  { { { 20, 0, 4 }, { 16, 30, 1 } } },\r
-  { { { 21, 0, 3 }, { 16, 30, 0 } } },\r
-  { { { 21, 0, 2 }, { 18, 27, 1 } } },\r
-  { { { 21, 0, 1 }, { 18, 27, 0 } } },\r
-  { { { 21, 0, 0 }, { 16, 31, 0 } } },\r
-  { { { 21, 0, 1 }, { 17, 30, 1 } } },\r
-  { { { 21, 0, 2 }, { 17, 30, 0 } } },\r
-  { { { 21, 0, 3 }, { 20, 24, 0 } } },\r
-  { { { 21, 0, 4 }, { 17, 31, 1 } } },\r
-  { { { 22, 0, 3 }, { 17, 31, 0 } } },\r
-  { { { 22, 0, 2 }, { 17, 31, 1 } } },\r
-  { { { 22, 0, 1 }, { 18, 30, 1 } } },\r
-  { { { 22, 0, 0 }, { 18, 30, 0 } } },\r
-  { { { 22, 0, 1 }, { 18, 31, 1 } } },\r
-  { { { 22, 0, 2 }, { 18, 31, 0 } } },\r
-  { { { 22, 0, 3 }, { 20, 27, 0 } } },\r
-  { { { 22, 0, 4 }, { 19, 30, 1 } } },\r
-  { { { 23, 0, 3 }, { 19, 30, 0 } } },\r
-  { { { 23, 0, 2 }, { 20, 28, 0 } } },\r
-  { { { 23, 0, 1 }, { 19, 31, 1 } } },\r
-  { { { 23, 0, 0 }, { 19, 31, 0 } } },\r
-  { { { 23, 0, 1 }, { 19, 31, 1 } } },\r
-  { { { 23, 0, 2 }, { 20, 30, 1 } } },\r
-  { { { 23, 0, 3 }, { 20, 30, 0 } } },\r
-  { { { 23, 0, 4 }, { 22, 27, 1 } } },\r
-  { { { 24, 0, 4 }, { 22, 27, 0 } } },\r
-  { { { 24, 0, 3 }, { 20, 31, 0 } } },\r
-  { { { 24, 0, 2 }, { 21, 30, 1 } } },\r
-  { { { 24, 0, 1 }, { 21, 30, 0 } } },\r
-  { { { 24, 0, 0 }, { 24, 24, 0 } } },\r
-  { { { 24, 0, 1 }, { 21, 31, 1 } } },\r
-  { { { 24, 0, 2 }, { 21, 31, 0 } } },\r
-  { { { 24, 0, 3 }, { 21, 31, 1 } } },\r
-  { { { 24, 0, 4 }, { 22, 30, 1 } } },\r
-  { { { 25, 0, 3 }, { 22, 30, 0 } } },\r
-  { { { 25, 0, 2 }, { 22, 31, 1 } } },\r
-  { { { 25, 0, 1 }, { 22, 31, 0 } } },\r
-  { { { 25, 0, 0 }, { 24, 27, 0 } } },\r
-  { { { 25, 0, 1 }, { 23, 30, 1 } } },\r
-  { { { 25, 0, 2 }, { 23, 30, 0 } } },\r
-  { { { 25, 0, 3 }, { 24, 28, 0 } } },\r
-  { { { 25, 0, 4 }, { 23, 31, 1 } } },\r
-  { { { 26, 0, 3 }, { 23, 31, 0 } } },\r
-  { { { 26, 0, 2 }, { 23, 31, 1 } } },\r
-  { { { 26, 0, 1 }, { 24, 30, 1 } } },\r
-  { { { 26, 0, 0 }, { 24, 30, 0 } } },\r
-  { { { 26, 0, 1 }, { 26, 27, 1 } } },\r
-  { { { 26, 0, 2 }, { 26, 27, 0 } } },\r
-  { { { 26, 0, 3 }, { 24, 31, 0 } } },\r
-  { { { 26, 0, 4 }, { 25, 30, 1 } } },\r
-  { { { 27, 0, 3 }, { 25, 30, 0 } } },\r
-  { { { 27, 0, 2 }, { 28, 24, 0 } } },\r
-  { { { 27, 0, 1 }, { 25, 31, 1 } } },\r
-  { { { 27, 0, 0 }, { 25, 31, 0 } } },\r
-  { { { 27, 0, 1 }, { 25, 31, 1 } } },\r
-  { { { 27, 0, 2 }, { 26, 30, 1 } } },\r
-  { { { 27, 0, 3 }, { 26, 30, 0 } } },\r
-  { { { 27, 0, 4 }, { 26, 31, 1 } } },\r
-  { { { 28, 0, 4 }, { 26, 31, 0 } } },\r
-  { { { 28, 0, 3 }, { 28, 27, 0 } } },\r
-  { { { 28, 0, 2 }, { 27, 30, 1 } } },\r
-  { { { 28, 0, 1 }, { 27, 30, 0 } } },\r
-  { { { 28, 0, 0 }, { 28, 28, 0 } } },\r
-  { { { 28, 0, 1 }, { 27, 31, 1 } } },\r
-  { { { 28, 0, 2 }, { 27, 31, 0 } } },\r
-  { { { 28, 0, 3 }, { 27, 31, 1 } } },\r
-  { { { 28, 0, 4 }, { 28, 30, 1 } } },\r
-  { { { 29, 0, 3 }, { 28, 30, 0 } } },\r
-  { { { 29, 0, 2 }, { 30, 27, 1 } } },\r
-  { { { 29, 0, 1 }, { 30, 27, 0 } } },\r
-  { { { 29, 0, 0 }, { 28, 31, 0 } } },\r
-  { { { 29, 0, 1 }, { 29, 30, 1 } } },\r
-  { { { 29, 0, 2 }, { 29, 30, 0 } } },\r
-  { { { 29, 0, 3 }, { 29, 30, 1 } } },\r
-  { { { 29, 0, 4 }, { 29, 31, 1 } } },\r
-  { { { 30, 0, 3 }, { 29, 31, 0 } } },\r
-  { { { 30, 0, 2 }, { 29, 31, 1 } } },\r
-  { { { 30, 0, 1 }, { 30, 30, 1 } } },\r
-  { { { 30, 0, 0 }, { 30, 30, 0 } } },\r
-  { { { 30, 0, 1 }, { 30, 31, 1 } } },\r
-  { { { 30, 0, 2 }, { 30, 31, 0 } } },\r
-  { { { 30, 0, 3 }, { 30, 31, 1 } } },\r
-  { { { 30, 0, 4 }, { 31, 30, 1 } } },\r
-  { { { 31, 0, 3 }, { 31, 30, 0 } } },\r
-  { { { 31, 0, 2 }, { 31, 30, 1 } } },\r
-  { { { 31, 0, 1 }, { 31, 31, 1 } } },\r
-  { { { 31, 0, 0 }, { 31, 31, 0 } } }\r
-};\r
-\r
-static const DDSSingleColourLookup DDSLookup_6_4[] =\r
-{\r
-  { { { 0, 0, 0 }, { 0, 0, 0 } } },\r
-  { { { 0, 0, 1 }, { 0, 1, 0 } } },\r
-  { { { 0, 0, 2 }, { 0, 2, 0 } } },\r
-  { { { 1, 0, 1 }, { 0, 3, 1 } } },\r
-  { { { 1, 0, 0 }, { 0, 3, 0 } } },\r
-  { { { 1, 0, 1 }, { 0, 4, 0 } } },\r
-  { { { 1, 0, 2 }, { 0, 5, 0 } } },\r
-  { { { 2, 0, 1 }, { 0, 6, 1 } } },\r
-  { { { 2, 0, 0 }, { 0, 6, 0 } } },\r
-  { { { 2, 0, 1 }, { 0, 7, 0 } } },\r
-  { { { 2, 0, 2 }, { 0, 8, 0 } } },\r
-  { { { 3, 0, 1 }, { 0, 9, 1 } } },\r
-  { { { 3, 0, 0 }, { 0, 9, 0 } } },\r
-  { { { 3, 0, 1 }, { 0, 10, 0 } } },\r
-  { { { 3, 0, 2 }, { 0, 11, 0 } } },\r
-  { { { 4, 0, 1 }, { 0, 12, 1 } } },\r
-  { { { 4, 0, 0 }, { 0, 12, 0 } } },\r
-  { { { 4, 0, 1 }, { 0, 13, 0 } } },\r
-  { { { 4, 0, 2 }, { 0, 14, 0 } } },\r
-  { { { 5, 0, 1 }, { 0, 15, 1 } } },\r
-  { { { 5, 0, 0 }, { 0, 15, 0 } } },\r
-  { { { 5, 0, 1 }, { 0, 16, 0 } } },\r
-  { { { 5, 0, 2 }, { 1, 15, 0 } } },\r
-  { { { 6, 0, 1 }, { 0, 17, 0 } } },\r
-  { { { 6, 0, 0 }, { 0, 18, 0 } } },\r
-  { { { 6, 0, 1 }, { 0, 19, 0 } } },\r
-  { { { 6, 0, 2 }, { 3, 14, 0 } } },\r
-  { { { 7, 0, 1 }, { 0, 20, 0 } } },\r
-  { { { 7, 0, 0 }, { 0, 21, 0 } } },\r
-  { { { 7, 0, 1 }, { 0, 22, 0 } } },\r
-  { { { 7, 0, 2 }, { 4, 15, 0 } } },\r
-  { { { 8, 0, 1 }, { 0, 23, 0 } } },\r
-  { { { 8, 0, 0 }, { 0, 24, 0 } } },\r
-  { { { 8, 0, 1 }, { 0, 25, 0 } } },\r
-  { { { 8, 0, 2 }, { 6, 14, 0 } } },\r
-  { { { 9, 0, 1 }, { 0, 26, 0 } } },\r
-  { { { 9, 0, 0 }, { 0, 27, 0 } } },\r
-  { { { 9, 0, 1 }, { 0, 28, 0 } } },\r
-  { { { 9, 0, 2 }, { 7, 15, 0 } } },\r
-  { { { 10, 0, 1 }, { 0, 29, 0 } } },\r
-  { { { 10, 0, 0 }, { 0, 30, 0 } } },\r
-  { { { 10, 0, 1 }, { 0, 31, 0 } } },\r
-  { { { 10, 0, 2 }, { 9, 14, 0 } } },\r
-  { { { 11, 0, 1 }, { 0, 32, 0 } } },\r
-  { { { 11, 0, 0 }, { 0, 33, 0 } } },\r
-  { { { 11, 0, 1 }, { 2, 30, 0 } } },\r
-  { { { 11, 0, 2 }, { 0, 34, 0 } } },\r
-  { { { 12, 0, 1 }, { 0, 35, 0 } } },\r
-  { { { 12, 0, 0 }, { 0, 36, 0 } } },\r
-  { { { 12, 0, 1 }, { 3, 31, 0 } } },\r
-  { { { 12, 0, 2 }, { 0, 37, 0 } } },\r
-  { { { 13, 0, 1 }, { 0, 38, 0 } } },\r
-  { { { 13, 0, 0 }, { 0, 39, 0 } } },\r
-  { { { 13, 0, 1 }, { 5, 30, 0 } } },\r
-  { { { 13, 0, 2 }, { 0, 40, 0 } } },\r
-  { { { 14, 0, 1 }, { 0, 41, 0 } } },\r
-  { { { 14, 0, 0 }, { 0, 42, 0 } } },\r
-  { { { 14, 0, 1 }, { 6, 31, 0 } } },\r
-  { { { 14, 0, 2 }, { 0, 43, 0 } } },\r
-  { { { 15, 0, 1 }, { 0, 44, 0 } } },\r
-  { { { 15, 0, 0 }, { 0, 45, 0 } } },\r
-  { { { 15, 0, 1 }, { 8, 30, 0 } } },\r
-  { { { 15, 0, 2 }, { 0, 46, 0 } } },\r
-  { { { 16, 0, 2 }, { 0, 47, 0 } } },\r
-  { { { 16, 0, 1 }, { 1, 46, 0 } } },\r
-  { { { 16, 0, 0 }, { 0, 48, 0 } } },\r
-  { { { 16, 0, 1 }, { 0, 49, 0 } } },\r
-  { { { 16, 0, 2 }, { 0, 50, 0 } } },\r
-  { { { 17, 0, 1 }, { 2, 47, 0 } } },\r
-  { { { 17, 0, 0 }, { 0, 51, 0 } } },\r
-  { { { 17, 0, 1 }, { 0, 52, 0 } } },\r
-  { { { 17, 0, 2 }, { 0, 53, 0 } } },\r
-  { { { 18, 0, 1 }, { 4, 46, 0 } } },\r
-  { { { 18, 0, 0 }, { 0, 54, 0 } } },\r
-  { { { 18, 0, 1 }, { 0, 55, 0 } } },\r
-  { { { 18, 0, 2 }, { 0, 56, 0 } } },\r
-  { { { 19, 0, 1 }, { 5, 47, 0 } } },\r
-  { { { 19, 0, 0 }, { 0, 57, 0 } } },\r
-  { { { 19, 0, 1 }, { 0, 58, 0 } } },\r
-  { { { 19, 0, 2 }, { 0, 59, 0 } } },\r
-  { { { 20, 0, 1 }, { 7, 46, 0 } } },\r
-  { { { 20, 0, 0 }, { 0, 60, 0 } } },\r
-  { { { 20, 0, 1 }, { 0, 61, 0 } } },\r
-  { { { 20, 0, 2 }, { 0, 62, 0 } } },\r
-  { { { 21, 0, 1 }, { 8, 47, 0 } } },\r
-  { { { 21, 0, 0 }, { 0, 63, 0 } } },\r
-  { { { 21, 0, 1 }, { 1, 62, 0 } } },\r
-  { { { 21, 0, 2 }, { 1, 63, 0 } } },\r
-  { { { 22, 0, 1 }, { 10, 46, 0 } } },\r
-  { { { 22, 0, 0 }, { 2, 62, 0 } } },\r
-  { { { 22, 0, 1 }, { 2, 63, 0 } } },\r
-  { { { 22, 0, 2 }, { 3, 62, 0 } } },\r
-  { { { 23, 0, 1 }, { 11, 47, 0 } } },\r
-  { { { 23, 0, 0 }, { 3, 63, 0 } } },\r
-  { { { 23, 0, 1 }, { 4, 62, 0 } } },\r
-  { { { 23, 0, 2 }, { 4, 63, 0 } } },\r
-  { { { 24, 0, 1 }, { 13, 46, 0 } } },\r
-  { { { 24, 0, 0 }, { 5, 62, 0 } } },\r
-  { { { 24, 0, 1 }, { 5, 63, 0 } } },\r
-  { { { 24, 0, 2 }, { 6, 62, 0 } } },\r
-  { { { 25, 0, 1 }, { 14, 47, 0 } } },\r
-  { { { 25, 0, 0 }, { 6, 63, 0 } } },\r
-  { { { 25, 0, 1 }, { 7, 62, 0 } } },\r
-  { { { 25, 0, 2 }, { 7, 63, 0 } } },\r
-  { { { 26, 0, 1 }, { 16, 45, 0 } } },\r
-  { { { 26, 0, 0 }, { 8, 62, 0 } } },\r
-  { { { 26, 0, 1 }, { 8, 63, 0 } } },\r
-  { { { 26, 0, 2 }, { 9, 62, 0 } } },\r
-  { { { 27, 0, 1 }, { 16, 48, 0 } } },\r
-  { { { 27, 0, 0 }, { 9, 63, 0 } } },\r
-  { { { 27, 0, 1 }, { 10, 62, 0 } } },\r
-  { { { 27, 0, 2 }, { 10, 63, 0 } } },\r
-  { { { 28, 0, 1 }, { 16, 51, 0 } } },\r
-  { { { 28, 0, 0 }, { 11, 62, 0 } } },\r
-  { { { 28, 0, 1 }, { 11, 63, 0 } } },\r
-  { { { 28, 0, 2 }, { 12, 62, 0 } } },\r
-  { { { 29, 0, 1 }, { 16, 54, 0 } } },\r
-  { { { 29, 0, 0 }, { 12, 63, 0 } } },\r
-  { { { 29, 0, 1 }, { 13, 62, 0 } } },\r
-  { { { 29, 0, 2 }, { 13, 63, 0 } } },\r
-  { { { 30, 0, 1 }, { 16, 57, 0 } } },\r
-  { { { 30, 0, 0 }, { 14, 62, 0 } } },\r
-  { { { 30, 0, 1 }, { 14, 63, 0 } } },\r
-  { { { 30, 0, 2 }, { 15, 62, 0 } } },\r
-  { { { 31, 0, 1 }, { 16, 60, 0 } } },\r
-  { { { 31, 0, 0 }, { 15, 63, 0 } } },\r
-  { { { 31, 0, 1 }, { 24, 46, 0 } } },\r
-  { { { 31, 0, 2 }, { 16, 62, 0 } } },\r
-  { { { 32, 0, 2 }, { 16, 63, 0 } } },\r
-  { { { 32, 0, 1 }, { 17, 62, 0 } } },\r
-  { { { 32, 0, 0 }, { 25, 47, 0 } } },\r
-  { { { 32, 0, 1 }, { 17, 63, 0 } } },\r
-  { { { 32, 0, 2 }, { 18, 62, 0 } } },\r
-  { { { 33, 0, 1 }, { 18, 63, 0 } } },\r
-  { { { 33, 0, 0 }, { 27, 46, 0 } } },\r
-  { { { 33, 0, 1 }, { 19, 62, 0 } } },\r
-  { { { 33, 0, 2 }, { 19, 63, 0 } } },\r
-  { { { 34, 0, 1 }, { 20, 62, 0 } } },\r
-  { { { 34, 0, 0 }, { 28, 47, 0 } } },\r
-  { { { 34, 0, 1 }, { 20, 63, 0 } } },\r
-  { { { 34, 0, 2 }, { 21, 62, 0 } } },\r
-  { { { 35, 0, 1 }, { 21, 63, 0 } } },\r
-  { { { 35, 0, 0 }, { 30, 46, 0 } } },\r
-  { { { 35, 0, 1 }, { 22, 62, 0 } } },\r
-  { { { 35, 0, 2 }, { 22, 63, 0 } } },\r
-  { { { 36, 0, 1 }, { 23, 62, 0 } } },\r
-  { { { 36, 0, 0 }, { 31, 47, 0 } } },\r
-  { { { 36, 0, 1 }, { 23, 63, 0 } } },\r
-  { { { 36, 0, 2 }, { 24, 62, 0 } } },\r
-  { { { 37, 0, 1 }, { 24, 63, 0 } } },\r
-  { { { 37, 0, 0 }, { 32, 47, 0 } } },\r
-  { { { 37, 0, 1 }, { 25, 62, 0 } } },\r
-  { { { 37, 0, 2 }, { 25, 63, 0 } } },\r
-  { { { 38, 0, 1 }, { 26, 62, 0 } } },\r
-  { { { 38, 0, 0 }, { 32, 50, 0 } } },\r
-  { { { 38, 0, 1 }, { 26, 63, 0 } } },\r
-  { { { 38, 0, 2 }, { 27, 62, 0 } } },\r
-  { { { 39, 0, 1 }, { 27, 63, 0 } } },\r
-  { { { 39, 0, 0 }, { 32, 53, 0 } } },\r
-  { { { 39, 0, 1 }, { 28, 62, 0 } } },\r
-  { { { 39, 0, 2 }, { 28, 63, 0 } } },\r
-  { { { 40, 0, 1 }, { 29, 62, 0 } } },\r
-  { { { 40, 0, 0 }, { 32, 56, 0 } } },\r
-  { { { 40, 0, 1 }, { 29, 63, 0 } } },\r
-  { { { 40, 0, 2 }, { 30, 62, 0 } } },\r
-  { { { 41, 0, 1 }, { 30, 63, 0 } } },\r
-  { { { 41, 0, 0 }, { 32, 59, 0 } } },\r
-  { { { 41, 0, 1 }, { 31, 62, 0 } } },\r
-  { { { 41, 0, 2 }, { 31, 63, 0 } } },\r
-  { { { 42, 0, 1 }, { 32, 61, 0 } } },\r
-  { { { 42, 0, 0 }, { 32, 62, 0 } } },\r
-  { { { 42, 0, 1 }, { 32, 63, 0 } } },\r
-  { { { 42, 0, 2 }, { 41, 46, 0 } } },\r
-  { { { 43, 0, 1 }, { 33, 62, 0 } } },\r
-  { { { 43, 0, 0 }, { 33, 63, 0 } } },\r
-  { { { 43, 0, 1 }, { 34, 62, 0 } } },\r
-  { { { 43, 0, 2 }, { 42, 47, 0 } } },\r
-  { { { 44, 0, 1 }, { 34, 63, 0 } } },\r
-  { { { 44, 0, 0 }, { 35, 62, 0 } } },\r
-  { { { 44, 0, 1 }, { 35, 63, 0 } } },\r
-  { { { 44, 0, 2 }, { 44, 46, 0 } } },\r
-  { { { 45, 0, 1 }, { 36, 62, 0 } } },\r
-  { { { 45, 0, 0 }, { 36, 63, 0 } } },\r
-  { { { 45, 0, 1 }, { 37, 62, 0 } } },\r
-  { { { 45, 0, 2 }, { 45, 47, 0 } } },\r
-  { { { 46, 0, 1 }, { 37, 63, 0 } } },\r
-  { { { 46, 0, 0 }, { 38, 62, 0 } } },\r
-  { { { 46, 0, 1 }, { 38, 63, 0 } } },\r
-  { { { 46, 0, 2 }, { 47, 46, 0 } } },\r
-  { { { 47, 0, 1 }, { 39, 62, 0 } } },\r
-  { { { 47, 0, 0 }, { 39, 63, 0 } } },\r
-  { { { 47, 0, 1 }, { 40, 62, 0 } } },\r
-  { { { 47, 0, 2 }, { 48, 46, 0 } } },\r
-  { { { 48, 0, 2 }, { 40, 63, 0 } } },\r
-  { { { 48, 0, 1 }, { 41, 62, 0 } } },\r
-  { { { 48, 0, 0 }, { 41, 63, 0 } } },\r
-  { { { 48, 0, 1 }, { 48, 49, 0 } } },\r
-  { { { 48, 0, 2 }, { 42, 62, 0 } } },\r
-  { { { 49, 0, 1 }, { 42, 63, 0 } } },\r
-  { { { 49, 0, 0 }, { 43, 62, 0 } } },\r
-  { { { 49, 0, 1 }, { 48, 52, 0 } } },\r
-  { { { 49, 0, 2 }, { 43, 63, 0 } } },\r
-  { { { 50, 0, 1 }, { 44, 62, 0 } } },\r
-  { { { 50, 0, 0 }, { 44, 63, 0 } } },\r
-  { { { 50, 0, 1 }, { 48, 55, 0 } } },\r
-  { { { 50, 0, 2 }, { 45, 62, 0 } } },\r
-  { { { 51, 0, 1 }, { 45, 63, 0 } } },\r
-  { { { 51, 0, 0 }, { 46, 62, 0 } } },\r
-  { { { 51, 0, 1 }, { 48, 58, 0 } } },\r
-  { { { 51, 0, 2 }, { 46, 63, 0 } } },\r
-  { { { 52, 0, 1 }, { 47, 62, 0 } } },\r
-  { { { 52, 0, 0 }, { 47, 63, 0 } } },\r
-  { { { 52, 0, 1 }, { 48, 61, 0 } } },\r
-  { { { 52, 0, 2 }, { 48, 62, 0 } } },\r
-  { { { 53, 0, 1 }, { 56, 47, 0 } } },\r
-  { { { 53, 0, 0 }, { 48, 63, 0 } } },\r
-  { { { 53, 0, 1 }, { 49, 62, 0 } } },\r
-  { { { 53, 0, 2 }, { 49, 63, 0 } } },\r
-  { { { 54, 0, 1 }, { 58, 46, 0 } } },\r
-  { { { 54, 0, 0 }, { 50, 62, 0 } } },\r
-  { { { 54, 0, 1 }, { 50, 63, 0 } } },\r
-  { { { 54, 0, 2 }, { 51, 62, 0 } } },\r
-  { { { 55, 0, 1 }, { 59, 47, 0 } } },\r
-  { { { 55, 0, 0 }, { 51, 63, 0 } } },\r
-  { { { 55, 0, 1 }, { 52, 62, 0 } } },\r
-  { { { 55, 0, 2 }, { 52, 63, 0 } } },\r
-  { { { 56, 0, 1 }, { 61, 46, 0 } } },\r
-  { { { 56, 0, 0 }, { 53, 62, 0 } } },\r
-  { { { 56, 0, 1 }, { 53, 63, 0 } } },\r
-  { { { 56, 0, 2 }, { 54, 62, 0 } } },\r
-  { { { 57, 0, 1 }, { 62, 47, 0 } } },\r
-  { { { 57, 0, 0 }, { 54, 63, 0 } } },\r
-  { { { 57, 0, 1 }, { 55, 62, 0 } } },\r
-  { { { 57, 0, 2 }, { 55, 63, 0 } } },\r
-  { { { 58, 0, 1 }, { 56, 62, 1 } } },\r
-  { { { 58, 0, 0 }, { 56, 62, 0 } } },\r
-  { { { 58, 0, 1 }, { 56, 63, 0 } } },\r
-  { { { 58, 0, 2 }, { 57, 62, 0 } } },\r
-  { { { 59, 0, 1 }, { 57, 63, 1 } } },\r
-  { { { 59, 0, 0 }, { 57, 63, 0 } } },\r
-  { { { 59, 0, 1 }, { 58, 62, 0 } } },\r
-  { { { 59, 0, 2 }, { 58, 63, 0 } } },\r
-  { { { 60, 0, 1 }, { 59, 62, 1 } } },\r
-  { { { 60, 0, 0 }, { 59, 62, 0 } } },\r
-  { { { 60, 0, 1 }, { 59, 63, 0 } } },\r
-  { { { 60, 0, 2 }, { 60, 62, 0 } } },\r
-  { { { 61, 0, 1 }, { 60, 63, 1 } } },\r
-  { { { 61, 0, 0 }, { 60, 63, 0 } } },\r
-  { { { 61, 0, 1 }, { 61, 62, 0 } } },\r
-  { { { 61, 0, 2 }, { 61, 63, 0 } } },\r
-  { { { 62, 0, 1 }, { 62, 62, 1 } } },\r
-  { { { 62, 0, 0 }, { 62, 62, 0 } } },\r
-  { { { 62, 0, 1 }, { 62, 63, 0 } } },\r
-  { { { 62, 0, 2 }, { 63, 62, 0 } } },\r
-  { { { 63, 0, 1 }, { 63, 63, 1 } } },\r
-  { { { 63, 0, 0 }, { 63, 63, 0 } } }\r
-};\r
-\r
-static const DDSSingleColourLookup*\r
-  DDS_LOOKUP[] =\r
-{\r
-  DDSLookup_5_4,\r
-  DDSLookup_6_4,\r
-  DDSLookup_5_4\r
-};\r
-\r
-/*\r
-  Macros\r
-*/\r
-#define C565_r(x) (((x) & 0xF800) >> 11)\r
-#define C565_g(x) (((x) & 0x07E0) >> 5)\r
-#define C565_b(x)  ((x) & 0x001F)\r
-\r
-#define C565_red(x)   ( (C565_r(x) << 3 | C565_r(x) >> 2))\r
-#define C565_green(x) ( (C565_g(x) << 2 | C565_g(x) >> 4))\r
-#define C565_blue(x)  ( (C565_b(x) << 3 | C565_b(x) >> 2))\r
-\r
-#define DIV2(x)  ((x) > 1 ? ((x) >> 1) : 1)\r
-\r
-#define FixRange(min, max, steps) \\r
-if (min > max) \\r
-  min = max; \\r
-if (max - min < steps) \\r
-  max = Min(min + steps, 255); \\r
-if (max - min < steps) \\r
-  min = Max(min - steps, 0)\r
-\r
-#define Dot(left, right) (left.x*right.x) + (left.y*right.y) + (left.z*right.z)\r
-\r
-#define VectorInit(vector, value) vector.x = vector.y = vector.z = vector.w \\r
-  = value\r
-#define VectorInit3(vector, value) vector.x = vector.y = vector.z = value\r
-\r
-#define IsBitMask(mask, r, g, b, a) (mask.r_bitmask == r && mask.g_bitmask == \\r
-  g && mask.b_bitmask == b && mask.alpha_bitmask == a)\r
-\r
-/*\r
-  Forward declarations\r
-*/\r
-static MagickBooleanType\r
-  ConstructOrdering(const size_t, const DDSVector4 *, const DDSVector3,\r
-  DDSVector4 *, DDSVector4 *, unsigned char *, size_t);\r
-\r
-static MagickBooleanType\r
-  ReadDDSInfo(Image *, DDSInfo *);\r
-\r
-static void\r
-  CalculateColors(unsigned short, unsigned short,\r
-    DDSColors *, MagickBooleanType);\r
-\r
-static MagickBooleanType\r
-  ReadDXT1(Image *, DDSInfo *, ExceptionInfo *);\r
-\r
-static MagickBooleanType\r
-  ReadDXT3(Image *, DDSInfo *, ExceptionInfo *);\r
-\r
-static MagickBooleanType\r
-  ReadDXT5(Image *, DDSInfo *, ExceptionInfo *);\r
-\r
-static MagickBooleanType\r
-  ReadUncompressedRGB(Image *, DDSInfo *, ExceptionInfo *);\r
-\r
-static MagickBooleanType\r
-  ReadUncompressedRGBA(Image *, DDSInfo *, ExceptionInfo *);\r
-\r
-static void\r
-  RemapIndices(const ssize_t *, const unsigned char *, unsigned char *);\r
-\r
-static void\r
-  SkipDXTMipmaps(Image *, DDSInfo *, int);\r
-\r
-static void\r
-  SkipRGBMipmaps(Image *, DDSInfo *, int);\r
-\r
-static\r
-  MagickBooleanType WriteDDSImage(const ImageInfo *, Image *, ExceptionInfo *);\r
-\r
-static void\r
-  WriteDDSInfo(Image *, const size_t, const size_t, const size_t);\r
-\r
-static void\r
-  WriteFourCC(Image *, const size_t, const MagickBooleanType,\r
-    const MagickBooleanType, ExceptionInfo *);\r
-\r
-static void\r
-  WriteImageData(Image *, const size_t, const size_t, const MagickBooleanType,\r
-  const MagickBooleanType, ExceptionInfo *);\r
-\r
-static void\r
-  WriteIndices(Image *, const DDSVector3, const DDSVector3, unsigned char *);\r
-\r
-static MagickBooleanType\r
-  WriteMipmaps(Image *, const size_t, const size_t, const size_t,\r
-    const MagickBooleanType, const MagickBooleanType, ExceptionInfo *);\r
-\r
-static void\r
-  WriteSingleColorFit(Image *, const DDSVector4 *, const ssize_t *);\r
-\r
-static void\r
-  WriteUncompressed(Image *, ExceptionInfo *);\r
-\r
-static inline size_t Max(size_t one, size_t two)\r
-{\r
-  if (one > two)\r
-    return one;\r
-  return two;\r
-}\r
-\r
-static inline float MaxF(float one, float two)\r
-{\r
-  if (one > two)\r
-    return one;\r
-  return two;\r
-}\r
-\r
-static inline size_t Min(size_t one, size_t two)\r
-{\r
-  if (one < two)\r
-    return one;\r
-  return two;\r
-}\r
-\r
-static inline float MinF(float one, float two)\r
-{\r
-  if (one < two)\r
-    return one;\r
-  return two;\r
-}\r
-\r
-static inline void VectorAdd(const DDSVector4 left, const DDSVector4 right,\r
-  DDSVector4 *destination)\r
-{\r
-  destination->x = left.x + right.x;\r
-  destination->y = left.y + right.y;\r
-  destination->z = left.z + right.z;\r
-  destination->w = left.w + right.w;\r
-}\r
-\r
-static inline void VectorClamp(DDSVector4 *value)\r
-{\r
-  value->x = MinF(1.0f,MaxF(0.0f,value->x));\r
-  value->y = MinF(1.0f,MaxF(0.0f,value->y));\r
-  value->z = MinF(1.0f,MaxF(0.0f,value->z));\r
-  value->w = MinF(1.0f,MaxF(0.0f,value->w));\r
-}\r
-\r
-static inline void VectorClamp3(DDSVector3 *value)\r
-{\r
-  value->x = MinF(1.0f,MaxF(0.0f,value->x));\r
-  value->y = MinF(1.0f,MaxF(0.0f,value->y));\r
-  value->z = MinF(1.0f,MaxF(0.0f,value->z));\r
-}\r
-\r
-static inline void VectorCopy43(const DDSVector4 source,\r
-  DDSVector3 *destination)\r
-{\r
-  destination->x = source.x;\r
-  destination->y = source.y;\r
-  destination->z = source.z;\r
-}\r
-\r
-static inline void VectorCopy44(const DDSVector4 source,\r
-  DDSVector4 *destination)\r
-{\r
-  destination->x = source.x;\r
-  destination->y = source.y;\r
-  destination->z = source.z;\r
-  destination->w = source.w;\r
-}\r
-\r
-static inline void VectorNegativeMultiplySubtract(const DDSVector4 a,\r
-  const DDSVector4 b, const DDSVector4 c, DDSVector4 *destination)\r
-{\r
-  destination->x = c.x - (a.x * b.x);\r
-  destination->y = c.y - (a.y * b.y);\r
-  destination->z = c.z - (a.z * b.z);\r
-  destination->w = c.w - (a.w * b.w);\r
-}\r
-\r
-static inline void VectorMultiply(const DDSVector4 left,\r
-  const DDSVector4 right, DDSVector4 *destination)\r
-{\r
-  destination->x = left.x * right.x;\r
-  destination->y = left.y * right.y;\r
-  destination->z = left.z * right.z;\r
-  destination->w = left.w * right.w;\r
-}\r
-\r
-static inline void VectorMultiply3(const DDSVector3 left,\r
-  const DDSVector3 right, DDSVector3 *destination)\r
-{\r
-  destination->x = left.x * right.x;\r
-  destination->y = left.y * right.y;\r
-  destination->z = left.z * right.z;\r
-}\r
-\r
-static inline void VectorMultiplyAdd(const DDSVector4 a, const DDSVector4 b,\r
-  const DDSVector4 c, DDSVector4 *destination)\r
-{\r
-  destination->x = (a.x * b.x) + c.x;\r
-  destination->y = (a.y * b.y) + c.y;\r
-  destination->z = (a.z * b.z) + c.z;\r
-  destination->w = (a.w * b.w) + c.w;\r
-}\r
-\r
-static inline void VectorMultiplyAdd3(const DDSVector3 a, const DDSVector3 b,\r
-  const DDSVector3 c, DDSVector3 *destination)\r
-{\r
-  destination->x = (a.x * b.x) + c.x;\r
-  destination->y = (a.y * b.y) + c.y;\r
-  destination->z = (a.z * b.z) + c.z;\r
-}\r
-\r
-static inline void VectorReciprocal(const DDSVector4 value,\r
-  DDSVector4 *destination)\r
-{\r
-  destination->x = 1.0f / value.x;\r
-  destination->y = 1.0f / value.y;\r
-  destination->z = 1.0f / value.z;\r
-  destination->w = 1.0f / value.w;\r
-}\r
-\r
-static inline void VectorSubtract(const DDSVector4 left,\r
-  const DDSVector4 right, DDSVector4 *destination)\r
-{\r
-  destination->x = left.x - right.x;\r
-  destination->y = left.y - right.y;\r
-  destination->z = left.z - right.z;\r
-  destination->w = left.w - right.w;\r
-}\r
-\r
-static inline void VectorSubtract3(const DDSVector3 left,\r
-  const DDSVector3 right, DDSVector3 *destination)\r
-{\r
-  destination->x = left.x - right.x;\r
-  destination->y = left.y - right.y;\r
-  destination->z = left.z - right.z;\r
-}\r
-\r
-static inline void VectorTruncate(DDSVector4 *value)\r
-{\r
-  value->x = value->x > 0.0f ? floor(value->x) : ceil(value->x);\r
-  value->y = value->y > 0.0f ? floor(value->y) : ceil(value->y);\r
-  value->z = value->z > 0.0f ? floor(value->z) : ceil(value->z);\r
-  value->w = value->w > 0.0f ? floor(value->w) : ceil(value->w);\r
-}\r
-\r
-static inline void VectorTruncate3(DDSVector3 *value)\r
-{\r
-  value->x = value->x > 0.0f ? floor(value->x) : ceil(value->x);\r
-  value->y = value->y > 0.0f ? floor(value->y) : ceil(value->y);\r
-  value->z = value->z > 0.0f ? floor(value->z) : ceil(value->z);\r
-}\r
-\r
-static void CalculateColors(unsigned short c0, unsigned short c1,\r
-  DDSColors *c, MagickBooleanType ignoreAlpha)\r
-{\r
-  c->a[0] = c->a[1] = c->a[2] = c->a[3] = 0;\r
-\r
-  c->r[0] = (unsigned char) C565_red(c0);\r
-  c->g[0] = (unsigned char) C565_green(c0);\r
-  c->b[0] = (unsigned char) C565_blue(c0);\r
-\r
-  c->r[1] = (unsigned char) C565_red(c1);\r
-  c->g[1] = (unsigned char) C565_green(c1);\r
-  c->b[1] = (unsigned char) C565_blue(c1);\r
-\r
-  if (ignoreAlpha != MagickFalse || c0 > c1)\r
-    {\r
-      c->r[2] = (unsigned char) ((2 * c->r[0] + c->r[1]) / 3);\r
-      c->g[2] = (unsigned char) ((2 * c->g[0] + c->g[1]) / 3);\r
-      c->b[2] = (unsigned char) ((2 * c->b[0] + c->b[1]) / 3);\r
-\r
-      c->r[3] = (unsigned char) ((c->r[0] + 2 * c->r[1]) / 3);\r
-      c->g[3] = (unsigned char) ((c->g[0] + 2 * c->g[1]) / 3);\r
-      c->b[3] = (unsigned char) ((c->b[0] + 2 * c->b[1]) / 3);\r
-    }\r
-  else\r
-    {\r
-      c->r[2] = (unsigned char) ((c->r[0] + c->r[1]) / 2);\r
-      c->g[2] = (unsigned char) ((c->g[0] + c->g[1]) / 2);\r
-      c->b[2] = (unsigned char) ((c->b[0] + c->b[1]) / 2);\r
-\r
-      c->r[3] = c->g[3] = c->b[3] = 0;\r
-      c->a[3] = 255;\r
-    }\r
-}\r
-\r
-static size_t CompressAlpha(const size_t min, const size_t max,\r
-  const size_t steps, const ssize_t *alphas, unsigned char* indices)\r
-{\r
-  unsigned char\r
-    codes[8];\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    error,\r
-    index,\r
-    j,\r
-    least,\r
-    value;\r
-\r
-  codes[0] = (unsigned char) min;\r
-  codes[1] = (unsigned char) max;\r
-  codes[6] = 0;\r
-  codes[7] = 255;\r
-\r
-  for (i=1; i <  (ssize_t) steps; i++)\r
-    codes[i+1] = (unsigned char) (((steps-i)*min + i*max) / steps);\r
-\r
-  error = 0;\r
-  for (i=0; i<16; i++)\r
-  {\r
-    if (alphas[i] == -1)\r
-      {\r
-        indices[i] = 0;\r
-        continue;\r
-      }\r
-\r
-    value = alphas[i];\r
-    least = SIZE_MAX;\r
-    index = 0;\r
-    for (j=0; j<8; j++)\r
-    {\r
-      size_t\r
-        dist;\r
-\r
-      dist = value - (size_t)codes[j];\r
-      dist *= dist;\r
-\r
-      if (dist < least)\r
-        {\r
-          least = dist;\r
-          index = j;\r
-        }\r
-    }\r
-\r
-    indices[i] = (unsigned char)index;\r
-    error += least;\r
-  }\r
-\r
-  return error;\r
-}\r
-\r
-static void CompressClusterFit(const size_t count,\r
-  const DDSVector4 *points, const ssize_t *map, const DDSVector3 principle,\r
-  const DDSVector4 metric, DDSVector3 *start, DDSVector3* end,\r
-  unsigned char *indices)\r
-{\r
-  DDSVector3\r
-    axis;\r
-\r
-  DDSVector4\r
-    grid,\r
-    gridrcp,\r
-    half,\r
-    onethird_onethird2,\r
-    part0,\r
-    part1,\r
-    part2,\r
-    part3,\r
-    pointsWeights[16],\r
-    two,\r
-    twonineths,\r
-    twothirds_twothirds2,\r
-    xSumwSum;\r
-\r
-  float\r
-    bestError = 1e+37f;\r
-\r
-  size_t\r
-    bestIteration = 0,\r
-    besti = 0,\r
-    bestj = 0,\r
-    bestk = 0,\r
-    iterationIndex,\r
-    i,\r
-    j,\r
-    k,\r
-    kmin;\r
-\r
-  unsigned char\r
-    *o,\r
-    order[128],\r
-    unordered[16];\r
-\r
-  VectorInit(half,0.5f);\r
-  VectorInit(two,2.0f);\r
-\r
-  VectorInit(onethird_onethird2,1.0f/3.0f);\r
-  onethird_onethird2.w = 1.0f/9.0f;\r
-  VectorInit(twothirds_twothirds2,2.0f/3.0f);\r
-  twothirds_twothirds2.w = 4.0f/9.0f;\r
-  VectorInit(twonineths,2.0f/9.0f);\r
-\r
-  grid.x = 31.0f;\r
-  grid.y = 63.0f;\r
-  grid.z = 31.0f;\r
-  grid.w = 0.0f;\r
-\r
-  gridrcp.x = 1.0f/31.0f;\r
-  gridrcp.y = 1.0f/63.0f;\r
-  gridrcp.z = 1.0f/31.0f;\r
-  gridrcp.w = 0.0f;\r
-\r
-  xSumwSum.x = 0.0f;\r
-  xSumwSum.y = 0.0f;\r
-  xSumwSum.z = 0.0f;\r
-  xSumwSum.w = 0.0f;\r
-\r
-  ConstructOrdering(count,points,principle,pointsWeights,&xSumwSum,order,0);\r
-\r
-  for (iterationIndex = 0;;)\r
-  {\r
-    VectorInit(part0,0.0f);\r
-    for (i=0; i < count; i++)\r
-    {\r
-      VectorInit(part1,0.0f);\r
-      for (j=i;;)\r
-      {\r
-        if (j == 0)\r
-          {\r
-            VectorCopy44(pointsWeights[0],&part2);\r
-            kmin = 1;\r
-          }\r
-          else\r
-          {\r
-            VectorInit(part2,0.0f);\r
-            kmin = j;\r
-          }\r
-\r
-        for (k=kmin;;)\r
-        {\r
-          DDSVector4\r
-            a,\r
-            alpha2_sum,\r
-            alphax_sum,\r
-            alphabeta_sum,\r
-            b,\r
-            beta2_sum,\r
-            betax_sum,\r
-            e1,\r
-            e2,\r
-            factor;\r
-\r
-          float\r
-            error;\r
-\r
-          VectorSubtract(xSumwSum,part2,&part3);\r
-          VectorSubtract(part3,part1,&part3);\r
-          VectorSubtract(part3,part0,&part3);\r
-\r
-          VectorMultiplyAdd(part1,twothirds_twothirds2,part0,&alphax_sum);\r
-          VectorMultiplyAdd(part2,onethird_onethird2,alphax_sum,&alphax_sum);\r
-          VectorInit(alpha2_sum,alphax_sum.w);\r
-\r
-          VectorMultiplyAdd(part2,twothirds_twothirds2,part3,&betax_sum);\r
-          VectorMultiplyAdd(part1,onethird_onethird2,betax_sum,&betax_sum);\r
-          VectorInit(beta2_sum,betax_sum.w);\r
-\r
-          VectorAdd(part1,part2,&alphabeta_sum);\r
-          VectorInit(alphabeta_sum,alphabeta_sum.w);\r
-          VectorMultiply(twonineths,alphabeta_sum,&alphabeta_sum);\r
-\r
-          VectorMultiply(alpha2_sum,beta2_sum,&factor);\r
-          VectorNegativeMultiplySubtract(alphabeta_sum,alphabeta_sum,factor,\r
-            &factor);\r
-          VectorReciprocal(factor,&factor);\r
-\r
-          VectorMultiply(alphax_sum,beta2_sum,&a);\r
-          VectorNegativeMultiplySubtract(betax_sum,alphabeta_sum,a,&a);\r
-          VectorMultiply(a,factor,&a);\r
-\r
-          VectorMultiply(betax_sum,alpha2_sum,&b);\r
-          VectorNegativeMultiplySubtract(alphax_sum,alphabeta_sum,b,&b);\r
-          VectorMultiply(b,factor,&b);\r
-\r
-          VectorClamp(&a);\r
-          VectorMultiplyAdd(grid,a,half,&a);\r
-          VectorTruncate(&a);\r
-          VectorMultiply(a,gridrcp,&a);\r
-\r
-          VectorClamp(&b);\r
-          VectorMultiplyAdd(grid,b,half,&b);\r
-          VectorTruncate(&b);\r
-          VectorMultiply(b,gridrcp,&b);\r
-\r
-          VectorMultiply(b,b,&e1);\r
-          VectorMultiply(e1,beta2_sum,&e1);\r
-          VectorMultiply(a,a,&e2);\r
-          VectorMultiplyAdd(e2,alpha2_sum,e1,&e1);\r
-\r
-          VectorMultiply(a,b,&e2);\r
-          VectorMultiply(e2,alphabeta_sum,&e2);\r
-          VectorNegativeMultiplySubtract(a,alphax_sum,e2,&e2);\r
-          VectorNegativeMultiplySubtract(b,betax_sum,e2,&e2);\r
-          VectorMultiplyAdd(two,e2,e1,&e2);\r
-          VectorMultiply(e2,metric,&e2);\r
-\r
-          error = e2.x + e2.y + e2.z;\r
-\r
-          if (error < bestError)\r
-          {\r
-            VectorCopy43(a,start);\r
-            VectorCopy43(b,end);\r
-            bestError = error;\r
-            besti = i;\r
-            bestj = j;\r
-            bestk = k;\r
-            bestIteration = iterationIndex;\r
-          }\r
-\r
-          if (k == count)\r
-            break;\r
-\r
-          VectorAdd(pointsWeights[k],part2,&part2);\r
-          k++;\r
-        }\r
-\r
-        if (j == count)\r
-          break;\r
-\r
-        VectorAdd(pointsWeights[j],part1,&part1);\r
-        j++;\r
-      }\r
-\r
-      VectorAdd(pointsWeights[i],part0,&part0);\r
-    }\r
-\r
-    if (bestIteration != iterationIndex)\r
-      break;\r
-\r
-    iterationIndex++;\r
-    if (iterationIndex == 8)\r
-      break;\r
-\r
-    VectorSubtract3(*end,*start,&axis);\r
-    if (ConstructOrdering(count,points,axis,pointsWeights,&xSumwSum,order,\r
-      iterationIndex) == MagickFalse)\r
-      break;\r
-  }\r
-\r
-  o = order + (16*bestIteration);\r
-\r
-  for (i=0; i < besti; i++)\r
-    unordered[o[i]] = 0;\r
-  for (i=besti; i < bestj; i++)\r
-    unordered[o[i]] = 2;\r
-  for (i=bestj; i < bestk; i++)\r
-    unordered[o[i]] = 3;\r
-  for (i=bestk; i < count; i++)\r
-    unordered[o[i]] = 1;\r
-\r
-  RemapIndices(map,unordered,indices);\r
-}\r
-\r
-static void CompressRangeFit(const size_t count,\r
-  const DDSVector4* points, const ssize_t *map, const DDSVector3 principle,\r
-  const DDSVector4 metric, DDSVector3 *start, DDSVector3 *end,\r
-  unsigned char *indices)\r
-{\r
-  float\r
-    d,\r
-    bestDist,\r
-    max,\r
-    min,\r
-    val;\r
-\r
-  DDSVector3\r
-    codes[4],\r
-    grid,\r
-    gridrcp,\r
-    half,\r
-    dist;\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    bestj,\r
-    j;\r
-\r
-  unsigned char\r
-    closest[16];\r
-\r
-  VectorInit3(half,0.5f);\r
-\r
-  grid.x = 31.0f;\r
-  grid.y = 63.0f;\r
-  grid.z = 31.0f;\r
-\r
-  gridrcp.x = 1.0f/31.0f;\r
-  gridrcp.y = 1.0f/63.0f;\r
-  gridrcp.z = 1.0f/31.0f;\r
-\r
-  if (count > 0)\r
-    {\r
-      VectorCopy43(points[0],start);\r
-      VectorCopy43(points[0],end);\r
-\r
-      min = max = Dot(points[0],principle);\r
-      for (i=1; i < (ssize_t) count; i++)\r
-      {\r
-        val = Dot(points[i],principle);\r
-        if (val < min)\r
-        {\r
-          VectorCopy43(points[i],start);\r
-          min = val;\r
-        }\r
-        else if (val > max)\r
-        {\r
-          VectorCopy43(points[i],end);\r
-          max = val;\r
-        }\r
-      }\r
-    }\r
-\r
-  VectorClamp3(start);\r
-  VectorMultiplyAdd3(grid,*start,half,start);\r
-  VectorTruncate3(start);\r
-  VectorMultiply3(*start,gridrcp,start);\r
-\r
-  VectorClamp3(end);\r
-  VectorMultiplyAdd3(grid,*end,half,end);\r
-  VectorTruncate3(end);\r
-  VectorMultiply3(*end,gridrcp,end);\r
-\r
-  codes[0] = *start;\r
-  codes[1] = *end;\r
-  codes[2].x = (start->x * (2.0f/3.0f)) + (end->x * (1.0f/3.0f));\r
-  codes[2].y = (start->y * (2.0f/3.0f)) + (end->y * (1.0f/3.0f));\r
-  codes[2].z = (start->z * (2.0f/3.0f)) + (end->z * (1.0f/3.0f));\r
-  codes[3].x = (start->x * (1.0f/3.0f)) + (end->x * (2.0f/3.0f));\r
-  codes[3].y = (start->y * (1.0f/3.0f)) + (end->y * (2.0f/3.0f));\r
-  codes[3].z = (start->z * (1.0f/3.0f)) + (end->z * (2.0f/3.0f));\r
-\r
-  for (i=0; i < (ssize_t) count; i++)\r
-  {\r
-    bestDist = 1e+37f;\r
-    bestj = 0;\r
-    for (j=0; j < 4; j++)\r
-    {\r
-      dist.x = (points[i].x - codes[j].x) * metric.x;\r
-      dist.y = (points[i].y - codes[j].y) * metric.y;\r
-      dist.z = (points[i].z - codes[j].z) * metric.z;\r
-\r
-      d = Dot(dist,dist);\r
-      if (d < bestDist)\r
-        {\r
-          bestDist = d;\r
-          bestj = j;\r
-        }\r
-    }\r
-\r
-    closest[i] = (unsigned char) bestj;\r
-  }\r
-\r
-  RemapIndices(map, closest, indices);\r
-}\r
-\r
-static void ComputeEndPoints(const DDSSingleColourLookup *lookup[],\r
-  const unsigned char *color, DDSVector3 *start, DDSVector3 *end,\r
-  unsigned char *index)\r
-{\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    c,\r
-    maxError = SIZE_MAX;\r
-\r
-  for (i=0; i < 2; i++)\r
-  {\r
-    const DDSSourceBlock*\r
-      sources[3];\r
-\r
-      size_t\r
-        error = 0;\r
-\r
-    for (c=0; c < 3; c++)\r
-    {\r
-      sources[c] = &lookup[c][color[c]].sources[i];\r
-      error += ((size_t) sources[c]->error) * ((size_t) sources[c]->error);\r
-    }\r
-\r
-    if (error > maxError)\r
-      continue;\r
-\r
-    start->x = (float) sources[0]->start / 31.0f;\r
-    start->y = (float) sources[1]->start / 63.0f;\r
-    start->z = (float) sources[2]->start / 31.0f;\r
-\r
-    end->x = (float) sources[0]->end / 31.0f;\r
-    end->y = (float) sources[1]->end / 63.0f;\r
-    end->z = (float) sources[2]->end / 31.0f;\r
-\r
-    *index = (unsigned char) (2*i);\r
-    maxError = error;\r
-  }\r
-}\r
-\r
-static void ComputePrincipleComponent(const float *covariance,\r
-  DDSVector3 *principle)\r
-{\r
-  DDSVector4\r
-    row0,\r
-    row1,\r
-    row2,\r
-    v;\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  row0.x = covariance[0];\r
-  row0.y = covariance[1];\r
-  row0.z = covariance[2];\r
-  row0.w = 0.0f;\r
-\r
-  row1.x = covariance[1];\r
-  row1.y = covariance[3];\r
-  row1.z = covariance[4];\r
-  row1.w = 0.0f;\r
-\r
-  row2.x = covariance[2];\r
-  row2.y = covariance[4];\r
-  row2.z = covariance[5];\r
-  row2.w = 0.0f;\r
-\r
-  VectorInit(v,1.0f);\r
-\r
-  for (i=0; i < 8; i++)\r
-  {\r
-    DDSVector4\r
-      w;\r
-\r
-    float\r
-      a;\r
-\r
-    w.x = row0.x * v.x;\r
-    w.y = row0.y * v.x;\r
-    w.z = row0.z * v.x;\r
-    w.w = row0.w * v.x;\r
-\r
-    w.x = (row1.x * v.y) + w.x;\r
-    w.y = (row1.y * v.y) + w.y;\r
-    w.z = (row1.z * v.y) + w.z;\r
-    w.w = (row1.w * v.y) + w.w;\r
-\r
-    w.x = (row2.x * v.z) + w.x;\r
-    w.y = (row2.y * v.z) + w.y;\r
-    w.z = (row2.z * v.z) + w.z;\r
-    w.w = (row2.w * v.z) + w.w;\r
-\r
-    a = 1.0f / MaxF(w.x,MaxF(w.y,w.z));\r
-\r
-    v.x = w.x * a;\r
-    v.y = w.y * a;\r
-    v.z = w.z * a;\r
-    v.w = w.w * a;\r
-  }\r
-\r
-  VectorCopy43(v,principle);\r
-}\r
-\r
-static void ComputeWeightedCovariance(const size_t count,\r
-  const DDSVector4 *points, float *covariance)\r
-{\r
-  DDSVector3\r
-    centroid;\r
-\r
-  float\r
-    total;\r
-\r
-  size_t\r
-    i;\r
-\r
-  total = 0.0f;\r
-  VectorInit3(centroid,0.0f);\r
-\r
-  for (i=0; i < count; i++)\r
-  {\r
-    total += points[i].w;\r
-    centroid.x += (points[i].x * points[i].w);\r
-    centroid.y += (points[i].y * points[i].w);\r
-    centroid.z += (points[i].z * points[i].w);\r
-  }\r
-\r
-  if( total > 1.192092896e-07F)\r
-    {\r
-      centroid.x /= total;\r
-      centroid.y /= total;\r
-      centroid.z /= total;\r
-    }\r
-\r
-  for (i=0; i < 6; i++)\r
-    covariance[i] = 0.0f;\r
-\r
-  for (i = 0; i < count; i++)\r
-  {\r
-    DDSVector3\r
-      a,\r
-      b;\r
-\r
-    a.x = points[i].x - centroid.x;\r
-    a.y = points[i].y - centroid.y;\r
-    a.z = points[i].z - centroid.z;\r
-\r
-    b.x = points[i].w * a.x;\r
-    b.y = points[i].w * a.y;\r
-    b.z = points[i].w * a.z;\r
-\r
-    covariance[0] += a.x*b.x;\r
-    covariance[1] += a.x*b.y;\r
-    covariance[2] += a.x*b.z;\r
-    covariance[3] += a.y*b.y;\r
-    covariance[4] += a.y*b.z;\r
-    covariance[5] += a.z*b.z;\r
-  }\r
-}\r
-\r
-static MagickBooleanType ConstructOrdering(const size_t count,\r
-  const DDSVector4 *points, const DDSVector3 axis, DDSVector4 *pointsWeights,\r
-  DDSVector4 *xSumwSum, unsigned char *order, size_t iteration)\r
-{\r
-  float\r
-     dps[16],\r
-     f;\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    j;\r
-\r
-  unsigned char\r
-    c,\r
-    *o,\r
-    *p;\r
-\r
-  o = order + (16*iteration);\r
-\r
-  for (i=0; i < (ssize_t) count; i++)\r
-  {\r
-    dps[i] = Dot(points[i],axis);\r
-    o[i] = (unsigned char)i;\r
-  }\r
-\r
-  for (i=0; i < (ssize_t) count; i++)\r
-  {\r
-    for (j=i; j > 0 && dps[j] < dps[j - 1]; j--)\r
-    {\r
-      f = dps[j];\r
-      dps[j] = dps[j - 1];\r
-      dps[j - 1] = f;\r
-\r
-      c = o[j];\r
-      o[j] = o[j - 1];\r
-      o[j - 1] = c;\r
-    }\r
-  }\r
-\r
-  for (i=0; i < (ssize_t) iteration; i++)\r
-  {\r
-    MagickBooleanType\r
-      same;\r
-\r
-    p = order + (16*i);\r
-    same = MagickTrue;\r
-\r
-    for (j=0; j < count; j++)\r
-    {\r
-      if (o[j] != p[j])\r
-        {\r
-          same = MagickFalse;\r
-          break;\r
-        }\r
-    }\r
-\r
-    if (same != MagickFalse)\r
-      return MagickFalse;\r
-  }\r
-\r
-  xSumwSum->x = 0;\r
-  xSumwSum->y = 0;\r
-  xSumwSum->z = 0;\r
-  xSumwSum->w = 0;\r
-\r
-  for (i=0; i < (ssize_t) count; i++)\r
-  {\r
-    DDSVector4\r
-      v;\r
-\r
-    j = (size_t) o[i];\r
-\r
-    v.x = points[j].w * points[j].x;\r
-    v.y = points[j].w * points[j].y;\r
-    v.z = points[j].w * points[j].z;\r
-    v.w = points[j].w * 1.0f;\r
-\r
-    VectorCopy44(v,&pointsWeights[i]);\r
-    VectorAdd(*xSumwSum,v,xSumwSum);\r
-  }\r
-\r
-  return MagickTrue;\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%   I s D D S                                                                 %\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-%  IsDDS() returns MagickTrue if the image format type, identified by the\r
-%  magick string, is DDS.\r
-%\r
-%  The format of the IsDDS method is:\r
-%\r
-%      MagickBooleanType IsDDS(const unsigned char *magick,const size_t length)\r
-%\r
-%  A description of each parameter follows:\r
-%\r
-%    o magick: compare image format pattern against these bytes.\r
-%\r
-%    o length: Specifies the length of the magick string.\r
-%\r
-*/\r
-static MagickBooleanType IsDDS(const unsigned char *magick, const size_t length)\r
-{\r
-  if (length < 4)\r
-    return(MagickFalse);\r
-  if (LocaleNCompare((char *) magick,"DDS ", 4) == 0)\r
-    return(MagickTrue);\r
-  return(MagickFalse);\r
-}\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%   R e a d D D S I m a g e                                                   %\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-%  ReadDDSImage() reads a DirectDraw Surface image file and returns it.  It\r
-%  allocates the memory necessary for the new Image structure and returns a\r
-%  pointer to the new image.\r
-%\r
-%  The format of the ReadDDSImage method is:\r
-%\r
-%      Image *ReadDDSImage(const ImageInfo *image_info,ExceptionInfo *exception)\r
-%\r
-%  A description of each parameter follows:\r
-%\r
-%    o image_info: The image info.\r
-%\r
-%    o exception: return any errors or warnings in this structure.\r
-%\r
-*/\r
-\r
-static Image *ReadDDSImage(const ImageInfo *image_info,ExceptionInfo *exception)\r
-{\r
-  Image\r
-    *image;\r
-\r
-  MagickBooleanType\r
-    status,\r
-    cubemap = MagickFalse,\r
-    volume = MagickFalse;\r
-\r
-  CompressionType\r
-    compression;\r
-\r
-  DDSInfo\r
-    dds_info;\r
-  \r
-  DDSDecoder\r
-    *decoder;\r
-  \r
-  PixelTrait\r
-    alpha_trait;\r
-  \r
-  size_t\r
-    n,\r
-    num_images;\r
-\r
-  /*\r
-    Open image file.\r
-  */\r
-  assert(image_info != (const ImageInfo *) NULL);\r
-  assert(image_info->signature == MagickSignature);\r
-  if (image_info->debug != MagickFalse)\r
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",\r
-      image_info->filename);\r
-  assert(exception != (ExceptionInfo *) NULL);\r
-  assert(exception->signature == MagickSignature);\r
-  image=AcquireImage(image_info,exception);\r
-  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);\r
-  if (status == MagickFalse)\r
-    {\r
-      image=DestroyImageList(image);\r
-      return((Image *) NULL);\r
-    }\r
-  \r
-  /*\r
-    Initialize image structure.\r
-  */\r
-  if (ReadDDSInfo(image, &dds_info) != MagickTrue) {\r
-    ThrowReaderException(CorruptImageError,"ImproperImageHeader");\r
-  }\r
-  \r
-  if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP)\r
-    cubemap = MagickTrue;\r
-  \r
-  if (dds_info.ddscaps2 & DDSCAPS2_VOLUME && dds_info.depth > 0)\r
-    volume = MagickTrue;\r
-  \r
-  (void) SeekBlob(image, 128, SEEK_SET);\r
-\r
-  /*\r
-    Determine pixel format\r
-  */\r
-  if (dds_info.pixelformat.flags & DDPF_RGB)\r
-    {\r
-      compression = NoCompression;\r
-      if (dds_info.pixelformat.flags & DDPF_ALPHAPIXELS)\r
-        {\r
-          alpha_trait = BlendPixelTrait;\r
-          decoder = ReadUncompressedRGBA;\r
-        }\r
-      else\r
-        {\r
-          alpha_trait = UndefinedPixelTrait;\r
-          decoder = ReadUncompressedRGB;\r
-        }\r
-    }\r
-  else if (dds_info.pixelformat.flags & DDPF_FOURCC)\r
-    {\r
-      switch (dds_info.pixelformat.fourcc)\r
-      {\r
-        case FOURCC_DXT1:\r
-        {\r
-          alpha_trait = UndefinedPixelTrait;\r
-          compression = DXT1Compression;\r
-          decoder = ReadDXT1;\r
-          break;\r
-        }\r
-        \r
-        case FOURCC_DXT3:\r
-        {\r
-          alpha_trait = BlendPixelTrait;\r
-          compression = DXT3Compression;\r
-          decoder = ReadDXT3;\r
-          break;\r
-        }\r
-        \r
-        case FOURCC_DXT5:\r
-        {\r
-          alpha_trait = BlendPixelTrait;\r
-          compression = DXT5Compression;\r
-          decoder = ReadDXT5;\r
-          break;\r
-        }\r
-        \r
-        default:\r
-        {\r
-          /* Unknown FOURCC */\r
-          ThrowReaderException(CorruptImageError, "ImageTypeNotSupported");\r
-        }\r
-      }\r
-    }\r
-  else\r
-    {\r
-      /* Neither compressed nor uncompressed... thus unsupported */\r
-      ThrowReaderException(CorruptImageError, "ImageTypeNotSupported");\r
-    }\r
-  \r
-  num_images = 1;\r
-  if (cubemap)\r
-    {\r
-      /*\r
-        Determine number of faces defined in the cubemap\r
-      */\r
-      num_images = 0;\r
-      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) num_images++;\r
-      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) num_images++;\r
-      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEY) num_images++;\r
-      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) num_images++;\r
-      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) num_images++;\r
-      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) num_images++;\r
-    }\r
-  \r
-  if (volume)\r
-    num_images = dds_info.depth;\r
-  \r
-  for (n = 0; n < num_images; n++)\r
-  {\r
-    if (n != 0)\r
-      {\r
-        /* Start a new image */\r
-        AcquireNextImage(image_info,image,exception);\r
-        if (GetNextImageInList(image) == (Image *) NULL)\r
-          return(DestroyImageList(image));\r
-        image=SyncNextImageInList(image);\r
-      }\r
-    \r
-    image->alpha_trait=alpha_trait;\r
-    image->compression = compression;\r
-    image->columns = dds_info.width;\r
-    image->rows = dds_info.height;\r
-    image->storage_class = DirectClass;\r
-    image->endian = LSBEndian;\r
-    image->depth = 8;\r
-    if (image_info->ping != MagickFalse)\r
-      {\r
-        (void) CloseBlob(image);\r
-        return(GetFirstImageInList(image));\r
-      }\r
-    \r
-    if ((decoder)(image, &dds_info, exception) != MagickTrue)\r
-      {\r
-        (void) CloseBlob(image);\r
-        return(GetFirstImageInList(image));\r
-      }\r
-  }\r
-  \r
-  if (EOFBlob(image) != MagickFalse)\r
-    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",\r
-      image->filename);\r
-  \r
-  (void) CloseBlob(image);\r
-  return(GetFirstImageInList(image));\r
-}\r
-\r
-static MagickBooleanType ReadDDSInfo(Image *image, DDSInfo *dds_info)\r
-{\r
-  size_t\r
-    hdr_size,\r
-    required;\r
-  \r
-  /* Seek to start of header */\r
-  (void) SeekBlob(image, 4, SEEK_SET);\r
-  \r
-  /* Check header field */\r
-  hdr_size = ReadBlobLSBLong(image);\r
-  if (hdr_size != 124)\r
-    return MagickFalse;\r
-  \r
-  /* Fill in DDS info struct */\r
-  dds_info->flags = ReadBlobLSBLong(image);\r
-  \r
-  /* Check required flags */\r
-  required=(size_t) (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT);\r
-  if ((dds_info->flags & required) != required)\r
-    return MagickFalse;\r
-  \r
-  dds_info->height = ReadBlobLSBLong(image);\r
-  dds_info->width = ReadBlobLSBLong(image);\r
-  dds_info->pitchOrLinearSize = ReadBlobLSBLong(image);\r
-  dds_info->depth = ReadBlobLSBLong(image);\r
-  dds_info->mipmapcount = ReadBlobLSBLong(image);\r
-  \r
-  (void) SeekBlob(image, 44, SEEK_CUR);   /* reserved region of 11 DWORDs */\r
-  \r
-  /* Read pixel format structure */\r
-  hdr_size = ReadBlobLSBLong(image);\r
-  if (hdr_size != 32)\r
-    return MagickFalse;\r
-  \r
-  dds_info->pixelformat.flags = ReadBlobLSBLong(image);\r
-  dds_info->pixelformat.fourcc = ReadBlobLSBLong(image);\r
-  dds_info->pixelformat.rgb_bitcount = ReadBlobLSBLong(image);\r
-  dds_info->pixelformat.r_bitmask = ReadBlobLSBLong(image);\r
-  dds_info->pixelformat.g_bitmask = ReadBlobLSBLong(image);\r
-  dds_info->pixelformat.b_bitmask = ReadBlobLSBLong(image);\r
-  dds_info->pixelformat.alpha_bitmask = ReadBlobLSBLong(image);\r
-  \r
-  dds_info->ddscaps1 = ReadBlobLSBLong(image);\r
-  dds_info->ddscaps2 = ReadBlobLSBLong(image);\r
-  (void) SeekBlob(image, 12, SEEK_CUR); /* 3 reserved DWORDs */\r
-  \r
-  return MagickTrue;\r
-}\r
-\r
-static MagickBooleanType ReadDXT1(Image *image, DDSInfo *dds_info,\r
-  ExceptionInfo *exception)\r
-{\r
-  DDSColors\r
-    colors;\r
-\r
-  register Quantum\r
-    *q;\r
-  \r
-  register ssize_t\r
-    i,\r
-    x;\r
-  \r
-  size_t\r
-    bits;\r
-\r
-  ssize_t\r
-    j,\r
-    y;\r
-  \r
-  unsigned char\r
-    code;\r
-  \r
-  unsigned short\r
-    c0,\r
-    c1;\r
-  \r
-  for (y = 0; y < (ssize_t) dds_info->height; y += 4)\r
-  {\r
-    for (x = 0; x < (ssize_t) dds_info->width; x += 4)\r
-    {\r
-      /* Get 4x4 patch of pixels to write on */\r
-      q = QueueAuthenticPixels(image, x, y, Min(4, dds_info->width - x),\r
-        Min(4, dds_info->height - y),exception);\r
-      \r
-      if (q == (Quantum *) NULL)\r
-        return MagickFalse;\r
-      \r
-      /* Read 8 bytes of data from the image */\r
-      c0 = ReadBlobLSBShort(image);\r
-      c1 = ReadBlobLSBShort(image);\r
-      bits = ReadBlobLSBLong(image);\r
-      \r
-      CalculateColors(c0, c1, &colors, MagickFalse);\r
-      \r
-      /* Write the pixels */\r
-      for (j = 0; j < 4; j++)\r
-      {\r
-        for (i = 0; i < 4; i++)\r
-        {\r
-          if ((x + i) < (ssize_t) dds_info->width &&\r
-              (y + j) < (ssize_t) dds_info->height)\r
-            {\r
-              code = (unsigned char) ((bits >> ((j*4+i)*2)) & 0x3);\r
-              SetPixelRed(image,ScaleCharToQuantum(colors.r[code]),q);\r
-              SetPixelGreen(image,ScaleCharToQuantum(colors.g[code]),q);\r
-              SetPixelBlue(image,ScaleCharToQuantum(colors.b[code]),q);\r
-              SetPixelAlpha(image,ScaleCharToQuantum(colors.a[code]),q);\r
-              if (colors.a[code] && (image->alpha_trait != BlendPixelTrait))\r
-                image->alpha_trait=BlendPixelTrait;  /* Correct matte */\r
-              q+=GetPixelChannels(image);\r
-            }\r
-        }\r
-      }\r
-      \r
-      if (SyncAuthenticPixels(image,exception) == MagickFalse)\r
-        return MagickFalse;\r
-    }\r
-  }\r
-  \r
-  SkipDXTMipmaps(image, dds_info, 8);\r
-  \r
-  return MagickTrue;\r
-}\r
-\r
-static MagickBooleanType ReadDXT3(Image *image, DDSInfo *dds_info,\r
-  ExceptionInfo *exception)\r
-{\r
-  DDSColors\r
-    colors;\r
-  \r
-  register Quantum\r
-    *q;\r
-  \r
-  register ssize_t\r
-    i,\r
-    x;\r
-  \r
-  unsigned char\r
-    alpha;\r
-  \r
-  size_t\r
-    a0,\r
-    a1,\r
-    bits,\r
-    code;\r
-\r
-  ssize_t\r
-    j,\r
-    y;\r
-\r
-  unsigned short\r
-    c0,\r
-    c1;\r
-  \r
-  for (y = 0; y < (ssize_t) dds_info->height; y += 4)\r
-  {\r
-    for (x = 0; x < (ssize_t) dds_info->width; x += 4)\r
-    {\r
-      /* Get 4x4 patch of pixels to write on */\r
-      q = QueueAuthenticPixels(image, x, y, Min(4, dds_info->width - x),\r
-                         Min(4, dds_info->height - y),exception);\r
-      \r
-      if (q == (Quantum *) NULL)\r
-        return MagickFalse;\r
-      \r
-      /* Read alpha values (8 bytes) */\r
-      a0 = ReadBlobLSBLong(image);\r
-      a1 = ReadBlobLSBLong(image);\r
-      \r
-      /* Read 8 bytes of data from the image */\r
-      c0 = ReadBlobLSBShort(image);\r
-      c1 = ReadBlobLSBShort(image);\r
-      bits = ReadBlobLSBLong(image);\r
-      \r
-      CalculateColors(c0, c1, &colors, MagickTrue);\r
-      \r
-      /* Write the pixels */\r
-      for (j = 0; j < 4; j++)\r
-      {\r
-        for (i = 0; i < 4; i++)\r
-        {\r
-          if ((x + i) < (ssize_t) dds_info->width && (y + j) < (ssize_t) dds_info->height)\r
-            {\r
-              code = (bits >> ((4*j+i)*2)) & 0x3;\r
-              SetPixelRed(image,ScaleCharToQuantum(colors.r[code]),q);\r
-              SetPixelGreen(image,ScaleCharToQuantum(colors.g[code]),q);\r
-              SetPixelBlue(image,ScaleCharToQuantum(colors.b[code]),q);\r
-              /*\r
-                Extract alpha value: multiply 0..15 by 17 to get range 0..255\r
-              */\r
-              if (j < 2)\r
-                alpha = 17U * (unsigned char) ((a0 >> (4*(4*j+i))) & 0xf);\r
-              else\r
-                alpha = 17U * (unsigned char) ((a1 >> (4*(4*(j-2)+i))) & 0xf);\r
-              SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) alpha),q);\r
-              q+=GetPixelChannels(image);\r
-            }\r
-        }\r
-      }\r
-      \r
-      if (SyncAuthenticPixels(image,exception) == MagickFalse)\r
-        return MagickFalse;\r
-    }\r
-  }\r
-  \r
-  SkipDXTMipmaps(image, dds_info, 16);\r
-  \r
-  return MagickTrue;\r
-}\r
-\r
-static MagickBooleanType ReadDXT5(Image *image, DDSInfo *dds_info,\r
-  ExceptionInfo *exception)\r
-{\r
-  DDSColors\r
-    colors;\r
-  \r
-  MagickSizeType\r
-    alpha_bits;\r
-  \r
-  register Quantum\r
-    *q;\r
-  \r
-  register ssize_t\r
-    i,\r
-    x;\r
-\r
-  unsigned char\r
-    a0,\r
-    a1;\r
-  \r
-  size_t\r
-    alpha,\r
-    bits,\r
-    code,\r
-    alpha_code;\r
-\r
-  ssize_t\r
-    j,\r
-    y;\r
-\r
-  unsigned short\r
-    c0,\r
-    c1;\r
-  \r
-  for (y = 0; y < (ssize_t) dds_info->height; y += 4)\r
-  {\r
-    for (x = 0; x < (ssize_t) dds_info->width; x += 4)\r
-    {\r
-      /* Get 4x4 patch of pixels to write on */\r
-      q = QueueAuthenticPixels(image, x, y, Min(4, dds_info->width - x),\r
-                         Min(4, dds_info->height - y),exception);\r
-      \r
-      if (q == (Quantum *) NULL)\r
-        return MagickFalse;\r
-      \r
-      /* Read alpha values (8 bytes) */\r
-      a0 = (unsigned char) ReadBlobByte(image);\r
-      a1 = (unsigned char) ReadBlobByte(image);\r
-      \r
-      alpha_bits = (MagickSizeType)ReadBlobLSBLong(image);\r
-      alpha_bits = alpha_bits | ((MagickSizeType)ReadBlobLSBShort(image) << 32);\r
-      \r
-      /* Read 8 bytes of data from the image */\r
-      c0 = ReadBlobLSBShort(image);\r
-      c1 = ReadBlobLSBShort(image);\r
-      bits = ReadBlobLSBLong(image);\r
-      \r
-      CalculateColors(c0, c1, &colors, MagickTrue);\r
-      \r
-      /* Write the pixels */\r
-      for (j = 0; j < 4; j++)\r
-      {\r
-        for (i = 0; i < 4; i++)\r
-        {\r
-          if ((x + i) < (ssize_t) dds_info->width &&\r
-              (y + j) < (ssize_t) dds_info->height)\r
-            {\r
-              code = (bits >> ((4*j+i)*2)) & 0x3;\r
-              SetPixelRed(image,ScaleCharToQuantum(colors.r[code]),q);\r
-              SetPixelGreen(image,ScaleCharToQuantum(colors.g[code]),q);\r
-              SetPixelBlue(image,ScaleCharToQuantum(colors.b[code]),q);\r
-              /* Extract alpha value */\r
-              alpha_code = (size_t) (alpha_bits >> (3*(4*j+i))) & 0x7;\r
-              if (alpha_code == 0)\r
-                alpha = a0;\r
-              else if (alpha_code == 1)\r
-                alpha = a1;\r
-              else if (a0 > a1)\r
-                alpha = ((8-alpha_code) * a0 + (alpha_code-1) * a1) / 7;\r
-              else if (alpha_code == 6)\r
-                alpha = 0;\r
-              else if (alpha_code == 7)\r
-                alpha = 255;\r
-              else\r
-                alpha = (((6-alpha_code) * a0 + (alpha_code-1) * a1) / 5);\r
-              SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) alpha),q);\r
-              q+=GetPixelChannels(image);\r
-            }\r
-        }\r
-      }\r
-      \r
-      if (SyncAuthenticPixels(image,exception) == MagickFalse)\r
-        return MagickFalse;\r
-    }\r
-  }\r
-  \r
-  SkipDXTMipmaps(image, dds_info, 16);\r
-  \r
-  return MagickTrue;\r
-}\r
-\r
-static MagickBooleanType ReadUncompressedRGB(Image *image, DDSInfo *dds_info,\r
-  ExceptionInfo *exception)\r
-{\r
-  register Quantum\r
-    *q;\r
-\r
-  ssize_t\r
-    x, y;\r
-\r
-  unsigned short\r
-    color;\r
-\r
-  if (dds_info->pixelformat.rgb_bitcount == 16 && !IsBitMask(\r
-    dds_info->pixelformat,0xf800,0x07e0,0x001f,0x0000))\r
-    ThrowBinaryException(CorruptImageError,"ImageTypeNotSupported",\r
-      image->filename);\r
-\r
-  for (y = 0; y < (ssize_t) dds_info->height; y++)\r
-  {\r
-    q = QueueAuthenticPixels(image, 0, y, dds_info->width, 1,exception);\r
-    \r
-    if (q == (Quantum *) NULL)\r
-      return MagickFalse;\r
-    \r
-    for (x = 0; x < (ssize_t) dds_info->width; x++)\r
-    {\r
-\r
-      if (dds_info->pixelformat.rgb_bitcount == 16)\r
-        {\r
-           color=ReadBlobShort(image);\r
-           SetPixelRed(image,ScaleCharToQuantum((unsigned char)\r
-             (((color >> 11)/31.0)*255)),q);\r
-           SetPixelGreen(image,ScaleCharToQuantum((unsigned char)\r
-             ((((unsigned short)(color << 5) >> 10)/63.0)*255)),q);\r
-           SetPixelBlue(image,ScaleCharToQuantum((unsigned char)\r
-             ((((unsigned short)(color << 11) >> 11)/31.0)*255)),q);\r
-        }\r
-      else\r
-        {\r
-          SetPixelBlue(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-          SetPixelGreen(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-          SetPixelRed(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-          if (dds_info->pixelformat.rgb_bitcount == 32)\r
-            (void) ReadBlobByte(image);\r
-        }\r
-      q+=GetPixelChannels(image);\r
-    }\r
-    \r
-    if (SyncAuthenticPixels(image,exception) == MagickFalse)\r
-      return MagickFalse;\r
-  }\r
-  \r
-  SkipRGBMipmaps(image, dds_info, 3);\r
-  \r
-  return MagickTrue;\r
-}\r
-\r
-static MagickBooleanType ReadUncompressedRGBA(Image *image, DDSInfo *dds_info,\r
-  ExceptionInfo *exception)\r
-{\r
-  register Quantum\r
-    *q;\r
-\r
-  ssize_t\r
-    alphaBits,\r
-    x,\r
-    y;\r
-\r
-  unsigned short\r
-    color;\r
-\r
-  alphaBits=0;\r
-  if (dds_info->pixelformat.rgb_bitcount == 16)\r
-    {\r
-      if (IsBitMask(dds_info->pixelformat,0x7c00,0x03e0,0x001f,0x8000))\r
-        alphaBits=1;\r
-      else if (IsBitMask(dds_info->pixelformat,0x0f00,0x00f0,0x000f,0xf000))\r
-        alphaBits=4;\r
-      else\r
-        ThrowBinaryException(CorruptImageError,"ImageTypeNotSupported",\r
-          image->filename);\r
-    }\r
-\r
-  for (y = 0; y < (ssize_t) dds_info->height; y++)\r
-  {\r
-    q = QueueAuthenticPixels(image, 0, y, dds_info->width, 1,exception);\r
-    \r
-    if (q == (Quantum *) NULL)\r
-      return MagickFalse;\r
-    \r
-    for (x = 0; x < (ssize_t) dds_info->width; x++)\r
-    {\r
-      if (dds_info->pixelformat.rgb_bitcount == 16)\r
-        {\r
-           color=ReadBlobShort(image);\r
-           if (alphaBits == 1)\r
-             {\r
-               SetPixelAlpha(image,(color & (1 << 15)) ? QuantumRange : 0,q);\r
-               SetPixelRed(image,ScaleCharToQuantum((unsigned char)\r
-                 ((((unsigned short)(color << 1) >> 11)/31.0)*255)),q);\r
-               SetPixelGreen(image,ScaleCharToQuantum((unsigned char)\r
-                 ((((unsigned short)(color << 6) >> 11)/31.0)*255)),q);\r
-               SetPixelBlue(image,ScaleCharToQuantum((unsigned char)\r
-                 ((((unsigned short)(color << 11) >> 11)/31.0)*255)),q);\r
-             }\r
-          else\r
-            {\r
-               SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)\r
-                 (((color >> 12)/15.0)*255)),q);\r
-               SetPixelRed(image,ScaleCharToQuantum((unsigned char)\r
-                 ((((unsigned short)(color << 4) >> 12)/15.0)*255)),q);\r
-               SetPixelGreen(image,ScaleCharToQuantum((unsigned char)\r
-                 ((((unsigned short)(color << 8) >> 12)/15.0)*255)),q);\r
-               SetPixelBlue(image,ScaleCharToQuantum((unsigned char)\r
-                 ((((unsigned short)(color << 12) >> 12)/15.0)*255)),q);\r
-            }\r
-        }\r
-      else\r
-        {\r
-          SetPixelBlue(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-          SetPixelGreen(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-          SetPixelRed(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-          SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)\r
-            ReadBlobByte(image)),q);\r
-        }\r
-      q+=GetPixelChannels(image);\r
-    }\r
-    \r
-    if (SyncAuthenticPixels(image,exception) == MagickFalse)\r
-      return MagickFalse;\r
-  }\r
-  \r
-  SkipRGBMipmaps(image, dds_info, 4);\r
-  \r
-  return MagickTrue;\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%   R e g i s t e r D D S I m a g e                                           %\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-%  RegisterDDSImage() adds attributes for the DDS image format to\r
-%  the list of supported formats.  The attributes include the image format\r
-%  tag, a method to read and/or write the format, whether the format\r
-%  supports the saving of more than one frame to the same file or blob,\r
-%  whether the format supports native in-memory I/O, and a brief\r
-%  description of the format.\r
-%\r
-%  The format of the RegisterDDSImage method is:\r
-%\r
-%      RegisterDDSImage(void)\r
-%\r
-*/\r
-ModuleExport size_t RegisterDDSImage(void)\r
-{\r
-  MagickInfo\r
-    *entry;\r
-\r
-  entry = SetMagickInfo("DDS");\r
-  entry->decoder = (DecodeImageHandler *) ReadDDSImage;\r
-  entry->encoder = (EncodeImageHandler *) WriteDDSImage;\r
-  entry->magick = (IsImageFormatHandler *) IsDDS;\r
-  entry->seekable_stream=MagickTrue;\r
-  entry->description = ConstantString("Microsoft DirectDraw Surface");\r
-  entry->module = ConstantString("DDS");\r
-  (void) RegisterMagickInfo(entry);\r
-  entry = SetMagickInfo("DXT1");\r
-  entry->decoder = (DecodeImageHandler *) ReadDDSImage;\r
-  entry->encoder = (EncodeImageHandler *) WriteDDSImage;\r
-  entry->magick = (IsImageFormatHandler *) IsDDS;\r
-  entry->seekable_stream=MagickTrue;\r
-  entry->description = ConstantString("Microsoft DirectDraw Surface");\r
-  entry->module = ConstantString("DDS");\r
-  (void) RegisterMagickInfo(entry);\r
-  entry = SetMagickInfo("DXT5");\r
-  entry->decoder = (DecodeImageHandler *) ReadDDSImage;\r
-  entry->encoder = (EncodeImageHandler *) WriteDDSImage;\r
-  entry->magick = (IsImageFormatHandler *) IsDDS;\r
-  entry->seekable_stream=MagickTrue;\r
-  entry->description = ConstantString("Microsoft DirectDraw Surface");\r
-  entry->module = ConstantString("DDS");\r
-  (void) RegisterMagickInfo(entry);\r
-  return(MagickImageCoderSignature);\r
-}\r
-\r
-static void RemapIndices(const ssize_t *map, const unsigned char *source,\r
-  unsigned char *target)\r
-{\r
-  register ssize_t\r
-    i;\r
-\r
-  for (i = 0; i < 16; i++)\r
-  {\r
-    if (map[i] == -1)\r
-      target[i] = 3;\r
-    else\r
-      target[i] = source[map[i]];\r
-  }\r
-}\r
-\r
-/*\r
-  Skip the mipmap images for compressed (DXTn) dds files\r
-*/\r
-static void SkipDXTMipmaps(Image *image, DDSInfo *dds_info, int texel_size)\r
-{\r
-  MagickOffsetType\r
-    offset;\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    h,\r
-    w;\r
-  \r
-  /*\r
-    Only skip mipmaps for textures and cube maps\r
-  */\r
-  if (dds_info->ddscaps1 & DDSCAPS_MIPMAP\r
-      && (dds_info->ddscaps1 & DDSCAPS_TEXTURE\r
-          || dds_info->ddscaps2 & DDSCAPS2_CUBEMAP))\r
-    {\r
-      w = DIV2(dds_info->width);\r
-      h = DIV2(dds_info->height);\r
-      \r
-      /*\r
-        Mipmapcount includes the main image, so start from one\r
-      */\r
-      for (i = 1; (i < (ssize_t) dds_info->mipmapcount) && w && h; i++)\r
-      {\r
-        offset = (MagickOffsetType) ((w + 3) / 4) * ((h + 3) / 4) * texel_size;\r
-        (void) SeekBlob(image, offset, SEEK_CUR);\r
-        \r
-        w = DIV2(w);\r
-        h = DIV2(h);\r
-      }\r
-    }\r
-}\r
-\r
-/*\r
-  Skip the mipmap images for uncompressed (RGB or RGBA) dds files\r
-*/\r
-static void SkipRGBMipmaps(Image *image, DDSInfo *dds_info, int pixel_size)\r
-{\r
-  MagickOffsetType\r
-    offset;\r
-  \r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    h,\r
-    w;\r
-\r
-  /*\r
-    Only skip mipmaps for textures and cube maps\r
-  */\r
-  if (dds_info->ddscaps1 & DDSCAPS_MIPMAP\r
-      && (dds_info->ddscaps1 & DDSCAPS_TEXTURE\r
-          || dds_info->ddscaps2 & DDSCAPS2_CUBEMAP))\r
-    {\r
-      w = DIV2(dds_info->width);\r
-      h = DIV2(dds_info->height);\r
-      \r
-      /*\r
-        Mipmapcount includes the main image, so start from one\r
-      */\r
-      for (i=1; (i < (ssize_t) dds_info->mipmapcount) && w && h; i++)\r
-      {\r
-        offset = (MagickOffsetType) w * h * pixel_size;\r
-        (void) SeekBlob(image, offset, SEEK_CUR);\r
-        \r
-        w = DIV2(w);\r
-        h = DIV2(h);\r
-      }\r
-    }\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%   U n r e g i s t e r D D S I m a g e                                       %\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-%  UnregisterDDSImage() removes format registrations made by the\r
-%  DDS module from the list of supported formats.\r
-%\r
-%  The format of the UnregisterDDSImage method is:\r
-%\r
-%      UnregisterDDSImage(void)\r
-%\r
-*/\r
-ModuleExport void UnregisterDDSImage(void)\r
-{\r
-  (void) UnregisterMagickInfo("DDS");\r
-  (void) UnregisterMagickInfo("DXT1");\r
-  (void) UnregisterMagickInfo("DXT5");\r
-}\r
-\r
-static void WriteAlphas(Image *image, const ssize_t *alphas, size_t min5,\r
-  size_t max5, size_t min7, size_t max7)\r
-{\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    err5,\r
-    err7,\r
-    j;\r
-\r
-  unsigned char\r
-    indices5[16],\r
-    indices7[16];\r
-\r
-  FixRange(min5,max5,5);\r
-  err5 = CompressAlpha(min5,max5,5,alphas,indices5);\r
-\r
-  FixRange(min7,max7,7);\r
-  err7 = CompressAlpha(min7,max7,7,alphas,indices7);\r
-\r
-  if (err7 < err5)\r
-  {\r
-    for (i=0; i < 16; i++)\r
-    {\r
-      unsigned char\r
-        index;\r
-\r
-      index = indices7[i];\r
-      if( index == 0 )\r
-        indices5[i] = 1;\r
-      else if (index == 1)\r
-        indices5[i] = 0;\r
-      else\r
-        indices5[i] = 9 - index;\r
-    }\r
-\r
-    min5 = max7;\r
-    max5 = min7;\r
-  }\r
-  \r
-  (void) WriteBlobByte(image,(unsigned char) min5);\r
-  (void) WriteBlobByte(image,(unsigned char) max5);\r
-  \r
-  for(i=0; i < 2; i++)\r
-  {\r
-    size_t\r
-      value = 0;\r
-\r
-    for (j=0; j < 8; j++)\r
-    {\r
-      size_t index = (size_t) indices5[j + i*8];\r
-      value |= ( index << 3*j );\r
-    }\r
-\r
-    for (j=0; j < 3; j++)\r
-    {\r
-      size_t byte = (value >> 8*j) & 0xff;\r
-      (void) WriteBlobByte(image,(unsigned char) byte);\r
-    }\r
-  }\r
-}\r
-\r
-static void WriteCompressed(Image *image, const size_t count,\r
-  DDSVector4 *points, const ssize_t *map, const MagickBooleanType clusterFit)\r
-{\r
-  float\r
-    covariance[16];\r
-\r
-  DDSVector3\r
-    end,\r
-    principle,\r
-    start;\r
-\r
-  DDSVector4\r
-    metric;\r
-\r
-  unsigned char\r
-    indices[16];\r
-\r
-  VectorInit(metric,1.0f);\r
-  VectorInit3(start,0.0f);\r
-  VectorInit3(end,0.0f);\r
-\r
-  ComputeWeightedCovariance(count,points,covariance);\r
-  ComputePrincipleComponent(covariance,&principle);\r
-\r
-  if (clusterFit == MagickFalse || count == 0)\r
-    CompressRangeFit(count,points,map,principle,metric,&start,&end,indices);\r
-  else\r
-    CompressClusterFit(count,points,map,principle,metric,&start,&end,indices);\r
-\r
-  WriteIndices(image,start,end,indices);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%   W r i t e D D S I m a g e                                                 %\r
-%                                                                             %\r
-%                                                                             %\r
-%                                                                             %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-%  WriteDDSImage() writes a DirectDraw Surface image file in the DXT5 format.\r
-%\r
-%  The format of the WriteBMPImage method is:\r
-%\r
-%     MagickBooleanType WriteDDSImage(const ImageInfo *image_info,Image *image)\r
-%\r
-%  A description of each parameter follows.\r
-%\r
-%    o image_info: the image info.\r
-%\r
-%    o image:  The image.\r
-%\r
-*/\r
-static MagickBooleanType WriteDDSImage(const ImageInfo *image_info,\r
-  Image *image, ExceptionInfo *exception)\r
-{\r
-  const char\r
-    *option;\r
-\r
-  size_t\r
-    compression,\r
-    columns,\r
-    maxMipmaps,\r
-    mipmaps,\r
-    pixelFormat,\r
-    rows;\r
-\r
-  MagickBooleanType\r
-    clusterFit,\r
-    status,\r
-    weightByAlpha;\r
-\r
-  assert(image_info != (const ImageInfo *) NULL);\r
-  assert(image_info->signature == MagickSignature);\r
-  assert(image != (Image *) NULL);\r
-  assert(image->signature == MagickSignature);\r
-  if (image->debug != MagickFalse)\r
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);\r
-  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);\r
-  if (status == MagickFalse)\r
-    return(status);\r
-  (void) TransformImageColorspace(image,sRGBColorspace,exception);\r
-  pixelFormat=DDPF_FOURCC;\r
-  compression=FOURCC_DXT5;\r
-\r
-  if (image->alpha_trait != BlendPixelTrait)\r
-    compression=FOURCC_DXT1;\r
-\r
-  if (LocaleCompare(image_info->magick,"dxt1") == 0)\r
-    compression=FOURCC_DXT1;\r
-\r
-  option=GetImageOption(image_info,"dds:compression");\r
-  if (option != (char *) NULL)\r
-    {\r
-       if (LocaleCompare(option,"dxt1") == 0)\r
-         compression=FOURCC_DXT1;\r
-       if (LocaleCompare(option,"none") == 0)\r
-         pixelFormat=DDPF_RGB;\r
-    }\r
-\r
-  clusterFit=MagickFalse;\r
-  weightByAlpha=MagickFalse;\r
-\r
-  if (pixelFormat == DDPF_FOURCC)\r
-    {\r
-      option=GetImageOption(image_info,"dds:cluster-fit");\r
-      if (option != (char *) NULL && LocaleCompare(option,"true") == 0)\r
-        {\r
-          clusterFit=MagickTrue;\r
-          if (compression != FOURCC_DXT1)\r
-            {\r
-              option=GetImageOption(image_info,"dds:weight-by-alpha");\r
-              if (option != (char *) NULL && LocaleCompare(option,"true") == 0)\r
-                weightByAlpha=MagickTrue;\r
-            }\r
-        }\r
-    }\r
-\r
-  maxMipmaps=SIZE_MAX;\r
-  mipmaps=0;\r
-  if ((image->columns & (image->columns - 1)) == 0 &&\r
-      (image->rows & (image->rows - 1)) == 0)\r
-    {\r
-      option=GetImageOption(image_info,"dds:mipmaps");\r
-      if (option != (char *) NULL)\r
-        maxMipmaps=StringToUnsignedLong(option);\r
-\r
-      if (maxMipmaps != 0)\r
-        {\r
-          columns=image->columns;\r
-          rows=image->rows;\r
-          while (columns != 1 && rows != 1 && mipmaps != maxMipmaps)\r
-          {\r
-            columns=DIV2(columns);\r
-            rows=DIV2(rows);\r
-            mipmaps++;\r
-          }\r
-        }\r
-    }\r
-\r
-  WriteDDSInfo(image,pixelFormat,compression,mipmaps);\r
-\r
-  WriteImageData(image,pixelFormat,compression,clusterFit,weightByAlpha,\r
-    exception);\r
-\r
-  if (mipmaps > 0 && WriteMipmaps(image,pixelFormat,compression,mipmaps,\r
-        clusterFit,weightByAlpha,exception) == MagickFalse)\r
-    return(MagickFalse);\r
-\r
-  (void) CloseBlob(image);\r
-  return(MagickTrue);\r
-}\r
-\r
-static void WriteDDSInfo(Image *image, const size_t pixelFormat,\r
-  const size_t compression, const size_t mipmaps)\r
-{\r
-  char\r
-    software[MaxTextExtent];\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  unsigned int\r
-    format,\r
-    caps,\r
-    flags;\r
-\r
-  flags=(unsigned int) (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT |\r
-    DDSD_PIXELFORMAT | DDSD_LINEARSIZE);\r
-  caps=(unsigned int) DDSCAPS_TEXTURE;\r
-  format=(unsigned int) pixelFormat;\r
-\r
-  if (mipmaps > 0)\r
-    {\r
-      flags=flags | (unsigned int) DDSD_MIPMAPCOUNT;\r
-      caps=caps | (unsigned int) (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX);\r
-    }\r
-\r
-  if (format != DDPF_FOURCC && image->alpha_trait == BlendPixelTrait)\r
-    format=format | DDPF_ALPHAPIXELS;\r
-\r
-  (void) WriteBlob(image,4,(unsigned char *) "DDS ");\r
-  (void) WriteBlobLSBLong(image,124);\r
-  (void) WriteBlobLSBLong(image,flags);\r
-  (void) WriteBlobLSBLong(image,image->rows);\r
-  (void) WriteBlobLSBLong(image,image->columns);\r
-\r
-  if (compression == FOURCC_DXT1)\r
-    (void) WriteBlobLSBLong(image,\r
-             (unsigned int) (Max(1,(image->columns+3)/4) * 8));\r
-  else\r
-    (void) WriteBlobLSBLong(image,\r
-             (unsigned int) (Max(1,(image->columns+3)/4) * 16));\r
-\r
-  (void) WriteBlobLSBLong(image,0x00);\r
-  (void) WriteBlobLSBLong(image,(unsigned int) mipmaps+1);\r
-  (void) ResetMagickMemory(software,0,sizeof(software));\r
-  (void) strcpy(software,"IMAGEMAGICK");\r
-  (void) WriteBlob(image,44,(unsigned char *) software);\r
-\r
-  (void) WriteBlobLSBLong(image,32);\r
-  (void) WriteBlobLSBLong(image,format);\r
-\r
-  if (pixelFormat == DDPF_FOURCC)\r
-    {\r
-      (void) WriteBlobLSBLong(image,(unsigned int) compression);\r
-      for(i=0;i < 5;i++) // bitcount / masks\r
-        (void) WriteBlobLSBLong(image,0x00);\r
-    }\r
-  else\r
-    {\r
-      (void) WriteBlobLSBLong(image,0x00);\r
-      if (image->alpha_trait == BlendPixelTrait)\r
-        {\r
-          (void) WriteBlobLSBLong(image,32);\r
-          (void) WriteBlobLSBLong(image,0xff0000);\r
-          (void) WriteBlobLSBLong(image,0xff00);\r
-          (void) WriteBlobLSBLong(image,0xff);\r
-          (void) WriteBlobLSBLong(image,0xff000000);\r
-        }\r
-      else\r
-        {\r
-          (void) WriteBlobLSBLong(image,24);\r
-          (void) WriteBlobLSBLong(image,0xff);\r
-          (void) WriteBlobLSBLong(image,0x00);\r
-          (void) WriteBlobLSBLong(image,0x00);\r
-          (void) WriteBlobLSBLong(image,0x00);\r
-        }\r
-    }\r
-  \r
-  (void) WriteBlobLSBLong(image,caps);\r
-  for(i=0;i < 4;i++) // ddscaps2 + reserved region\r
-    (void) WriteBlobLSBLong(image,0x00);\r
-}\r
-\r
-static void WriteFourCC(Image *image, const size_t compression,\r
-  const MagickBooleanType clusterFit, const MagickBooleanType weightByAlpha,\r
-  ExceptionInfo *exception)\r
-{\r
-  register ssize_t\r
-    x;\r
-\r
-  ssize_t\r
-    i,\r
-    y,\r
-    bx,\r
-    by;\r
-\r
-  register const Quantum\r
-    *p;\r
-\r
-  for (y=0; y < (ssize_t) image->rows; y+=4)\r
-  {\r
-    for (x=0; x < (ssize_t) image->columns; x+=4)\r
-    {\r
-      MagickBooleanType\r
-        match;\r
-\r
-      DDSVector4\r
-        point,\r
-        points[16];\r
-\r
-      size_t\r
-        count = 0,\r
-        max5 = 0,\r
-        max7 = 0,\r
-        min5 = 255,\r
-        min7 = 255,\r
-        columns = 4,\r
-        rows = 4;\r
-\r
-      ssize_t\r
-        alphas[16],\r
-        map[16];\r
-\r
-      unsigned char\r
-        alpha;\r
-\r
-      if (x + columns >= image->columns)\r
-        columns = image->columns - x;\r
-\r
-      if (y + rows >= image->rows)\r
-        rows = image->rows - y;\r
-\r
-      p=GetVirtualPixels(image,x,y,columns,rows,exception);\r
-      if (p == (const Quantum *) NULL)\r
-        break;\r
-\r
-      for (i=0; i<16; i++)\r
-      {\r
-        map[i] = -1;\r
-        alphas[i] = -1;\r
-      }\r
-\r
-      for (by=0; by <  (ssize_t) rows; by++)\r
-      {\r
-        for (bx=0; bx <  (ssize_t) columns; bx++)\r
-        {\r
-          if (compression == FOURCC_DXT5)\r
-            alpha = ScaleQuantumToChar(GetPixelAlpha(image,p));\r
-          else\r
-            alpha = 255;\r
-\r
-          alphas[4*by + bx] = (size_t)alpha;\r
-\r
-          point.x = (float)ScaleQuantumToChar(GetPixelRed(image,p)) / 255.0f;\r
-          point.y = (float)ScaleQuantumToChar(GetPixelGreen(image,p)) / 255.0f;\r
-          point.z = (float)ScaleQuantumToChar(GetPixelBlue(image,p)) / 255.0f;\r
-          point.w = weightByAlpha ? (float)(alpha + 1) / 256.0f : 1.0f;\r
-          p+=GetPixelChannels(image);\r
-\r
-          match = MagickFalse;\r
-          for (i=0; i <  (ssize_t) count; i++)\r
-          {\r
-            if ((points[i].x == point.x) &&\r
-                (points[i].y == point.y) &&\r
-                (points[i].z == point.z) &&\r
-                (alpha       >= 128 || compression == FOURCC_DXT5))\r
-              {\r
-                points[i].w += point.w;\r
-                map[4*by + bx] = i;\r
-                match = MagickTrue;\r
-                break;\r
-              }\r
-            }\r
-\r
-            if (match != MagickFalse)\r
-              continue;\r
-\r
-            points[count].x = point.x;\r
-            points[count].y = point.y;\r
-            points[count].z = point.z;\r
-            points[count].w = point.w;\r
-            map[4*by + bx] = count;\r
-            count++;\r
-\r
-            if (compression == FOURCC_DXT5)\r
-              {\r
-                if (alpha < min7)\r
-                  min7 = alpha;\r
-                if (alpha > max7)\r
-                  max7 = alpha;\r
-                if (alpha != 0 && alpha < min5)\r
-                  min5 = alpha;\r
-                if (alpha != 255 && alpha > max5)\r
-                  max5 = alpha;\r
-              }\r
-          }\r
-        }\r
-\r
-      for (i=0; i <  (ssize_t) count; i++)\r
-        points[i].w = sqrt(points[i].w);\r
-\r
-      if (compression == FOURCC_DXT5)\r
-        WriteAlphas(image,alphas,min5,max5,min7,max7);\r
-\r
-      if (count == 1)\r
-        WriteSingleColorFit(image,points,map);\r
-      else\r
-        WriteCompressed(image,count,points,map,clusterFit);\r
-    }\r
-  }\r
-}\r
-\r
-static void WriteImageData(Image *image, const size_t pixelFormat,\r
-  const size_t compression,const MagickBooleanType clusterFit,\r
-  const MagickBooleanType weightByAlpha, ExceptionInfo *exception)\r
-{\r
-  if (pixelFormat == DDPF_FOURCC)\r
-    WriteFourCC(image,compression,clusterFit,weightByAlpha,exception);\r
-  else\r
-    WriteUncompressed(image,exception);\r
-}\r
-\r
-static inline size_t ClampToLimit(const float value, const size_t limit)\r
-{\r
-  size_t\r
-    result = (int) (value + 0.5f);\r
-\r
-  if (result < 0.0f)\r
-    return(0);\r
-  if (result > limit)\r
-    return(limit);\r
-  return result;\r
-}\r
-\r
-static inline size_t ColorTo565(const DDSVector3 point)\r
-{\r
-  size_t r = ClampToLimit(31.0f*point.x,31);\r
-  size_t g = ClampToLimit(63.0f*point.y,63);\r
-  size_t b = ClampToLimit(31.0f*point.z,31);\r
-\r
-  return (r << 11) | (g << 5) | b;\r
-}\r
-\r
-static void WriteIndices(Image *image, const DDSVector3 start,\r
-  const DDSVector3 end, unsigned char *indices)\r
-{\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    a,\r
-    b;\r
-\r
-  unsigned char\r
-    remapped[16];\r
-\r
-  const unsigned char\r
-    *ind;\r
-\r
-  a = ColorTo565(start);\r
-  b = ColorTo565(end);\r
-\r
-  for (i=0; i<16; i++)\r
-  {\r
-    if( a < b )\r
-      remapped[i] = (indices[i] ^ 0x1) & 0x3;\r
-    else if( a == b )\r
-      remapped[i] = 0;\r
-    else\r
-      remapped[i] = indices[i];\r
-  }\r
-\r
-  if( a < b )\r
-    Swap(a,b);\r
-\r
-  (void) WriteBlobByte(image,(unsigned char) (a & 0xff));\r
-  (void) WriteBlobByte(image,(unsigned char) (a >> 8));\r
-  (void) WriteBlobByte(image,(unsigned char) (b & 0xff));\r
-  (void) WriteBlobByte(image,(unsigned char) (b >> 8));\r
-\r
-  for (i=0; i<4; i++)\r
-  {\r
-     ind = remapped + 4*i;\r
-     (void) WriteBlobByte(image,ind[0] | (ind[1] << 2) | (ind[2] << 4) |\r
-       (ind[3] << 6));\r
-  }\r
-}\r
-\r
-static MagickBooleanType WriteMipmaps(Image *image, const size_t pixelFormat,\r
-  const size_t compression, const size_t mipmaps,\r
-  const MagickBooleanType clusterFit, const MagickBooleanType weightByAlpha,\r
-  ExceptionInfo *exception)\r
-{\r
-  Image*\r
-    resize_image;\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  size_t\r
-    columns,\r
-    rows;\r
-\r
-  columns = image->columns;\r
-  rows = image->rows;\r
-\r
-  for (i=0; i< (ssize_t) mipmaps; i++)\r
-  {\r
-    resize_image = ResizeImage(image,columns/2,rows/2,TriangleFilter,\r
-      exception);\r
-\r
-    if (resize_image == (Image *) NULL)\r
-      return(MagickFalse);\r
-\r
-    DestroyBlob(resize_image);\r
-    resize_image->blob=ReferenceBlob(image->blob);\r
-\r
-    WriteImageData(resize_image,pixelFormat,compression,weightByAlpha,\r
-      clusterFit,exception);\r
-\r
-    resize_image=DestroyImage(resize_image);\r
-\r
-    columns = DIV2(columns);\r
-    rows = DIV2(rows);\r
-  }\r
-\r
-  return(MagickTrue);\r
-}\r
-\r
-static void WriteSingleColorFit(Image *image, const DDSVector4 *points,\r
-  const ssize_t *map)\r
-{\r
-  DDSVector3\r
-    start,\r
-    end;\r
-\r
-  register ssize_t\r
-    i;\r
-\r
-  unsigned char\r
-    color[3],\r
-    index,\r
-    indexes[16],\r
-    indices[16];\r
-\r
-  color[0] = (unsigned char) ClampToLimit(255.0f*points->x,255);\r
-  color[1] = (unsigned char) ClampToLimit(255.0f*points->y,255);\r
-  color[2] = (unsigned char) ClampToLimit(255.0f*points->z,255);\r
-\r
-  index=0;\r
-  ComputeEndPoints(DDS_LOOKUP,color,&start,&end,&index);\r
-\r
-  for (i=0; i< 16; i++)\r
-    indexes[i]=index;\r
-  RemapIndices(map,indexes,indices);\r
-  WriteIndices(image,start,end,indices);\r
-}\r
-\r
-static void WriteUncompressed(Image *image, ExceptionInfo *exception)\r
-{\r
-  register const Quantum\r
-    *p;\r
-\r
-  register ssize_t\r
-    x;\r
-\r
-  ssize_t\r
-    y;\r
-\r
-  for (y=0; y < (ssize_t) image->rows; y++)\r
-  {\r
-    p=GetVirtualPixels(image,0,y,image->columns,1,exception);\r
-    if (p == (const Quantum *) NULL)\r
-      break;\r
-\r
-    for (x=0; x < (ssize_t) image->columns; x++)\r
-    {\r
-      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelBlue(image,p)));\r
-      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelGreen(image,p)));\r
-      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelRed(image,p)));\r
-      if (image->alpha_trait == BlendPixelTrait)\r
-        (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelAlpha(image,p)));\r
-      p+=GetPixelChannels(image);\r
-    }\r
-  }\r
-}\r
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%                            DDDD   DDDD   SSSSS                              %
+%                            D   D  D   D  SS                                 %
+%                            D   D  D   D   SSS                               %
+%                            D   D  D   D     SS                              %
+%                            DDDD   DDDD   SSSSS                              %
+%                                                                             %
+%                                                                             %
+%           Read/Write Microsoft Direct Draw Surface Image Format             %
+%                                                                             %
+%                              Software Design                                %
+%                             Bianca van Schaik                               %
+%                                March 2008                                   %
+%                               Dirk Lemstra                                  %
+%                              September 2013                                 %
+%                                                                             %
+%                                                                             %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
+%  dedicated to making software imaging solutions freely available.           %
+%                                                                             %
+%  You may not use this file except in compliance with the License.  You may  %
+%  obtain a copy of the License at                                            %
+%                                                                             %
+%    http://www.imagemagick.org/script/license.php                            %
+%                                                                             %
+%  Unless required by applicable law or agreed to in writing, software        %
+%  distributed under the License is distributed on an "AS IS" BASIS,          %
+%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
+%  See the License for the specific language governing permissions and        %
+%  limitations under the License.                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+*/
+\f
+/*
+  Include declarations.
+*/
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/log.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/profile.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/module.h"
+#include "MagickCore/transform.h"
+#include "MagickCore/studio.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/compress.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/option.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/quantum.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
+\f
+/*
+  Definitions
+*/
+#define DDSD_CAPS         0x00000001
+#define DDSD_HEIGHT       0x00000002
+#define DDSD_WIDTH        0x00000004
+#define DDSD_PITCH        0x00000008
+#define DDSD_PIXELFORMAT  0x00001000
+#define DDSD_MIPMAPCOUNT  0x00020000
+#define DDSD_LINEARSIZE   0x00080000
+#define DDSD_DEPTH        0x00800000
+
+#define DDPF_ALPHAPIXELS  0x00000001
+#define DDPF_FOURCC       0x00000004
+#define DDPF_RGB          0x00000040
+
+#define FOURCC_DXT1       0x31545844
+#define FOURCC_DXT3       0x33545844
+#define FOURCC_DXT5       0x35545844
+
+#define DDSCAPS_COMPLEX   0x00000008
+#define DDSCAPS_TEXTURE   0x00001000
+#define DDSCAPS_MIPMAP    0x00400000
+
+#define DDSCAPS2_CUBEMAP  0x00000200
+#define DDSCAPS2_CUBEMAP_POSITIVEX  0x00000400
+#define DDSCAPS2_CUBEMAP_NEGATIVEX  0x00000800
+#define DDSCAPS2_CUBEMAP_POSITIVEY  0x00001000
+#define DDSCAPS2_CUBEMAP_NEGATIVEY  0x00002000
+#define DDSCAPS2_CUBEMAP_POSITIVEZ  0x00004000
+#define DDSCAPS2_CUBEMAP_NEGATIVEZ  0x00008000
+#define DDSCAPS2_VOLUME   0x00200000
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
+/*
+  Structure declarations.
+*/
+typedef struct _DDSPixelFormat
+{
+  size_t
+    flags,
+    fourcc,
+    rgb_bitcount,
+    r_bitmask,
+    g_bitmask,
+    b_bitmask,
+    alpha_bitmask;
+} DDSPixelFormat;
+
+typedef struct _DDSInfo
+{
+  size_t
+    flags,
+    height,
+    width,
+    pitchOrLinearSize,
+    depth,
+    mipmapcount,
+    ddscaps1,
+    ddscaps2;
+  
+  DDSPixelFormat
+    pixelformat;
+} DDSInfo;
+
+typedef struct _DDSColors
+{
+  unsigned char
+    r[4],
+    g[4],
+    b[4],
+    a[4];
+} DDSColors;
+
+typedef struct _DDSVector4
+{
+  float
+    x,
+    y,
+    z,
+    w;
+} DDSVector4;
+
+typedef struct _DDSVector3
+{
+  float
+    x,
+    y,
+    z;
+} DDSVector3;
+
+typedef struct _DDSSourceBlock
+{
+  unsigned char
+    start,
+    end,
+    error;
+} DDSSourceBlock;
+
+typedef struct _DDSSingleColourLookup
+{
+  DDSSourceBlock sources[2];
+} DDSSingleColourLookup;
+
+typedef MagickBooleanType
+  DDSDecoder(Image *, DDSInfo *, ExceptionInfo *);
+
+static const DDSSingleColourLookup DDSLookup_5_4[] =
+{
+  { { { 0, 0, 0 }, { 0, 0, 0 } } },
+  { { { 0, 0, 1 }, { 0, 1, 1 } } },
+  { { { 0, 0, 2 }, { 0, 1, 0 } } },
+  { { { 0, 0, 3 }, { 0, 1, 1 } } },
+  { { { 0, 0, 4 }, { 0, 2, 1 } } },
+  { { { 1, 0, 3 }, { 0, 2, 0 } } },
+  { { { 1, 0, 2 }, { 0, 2, 1 } } },
+  { { { 1, 0, 1 }, { 0, 3, 1 } } },
+  { { { 1, 0, 0 }, { 0, 3, 0 } } },
+  { { { 1, 0, 1 }, { 1, 2, 1 } } },
+  { { { 1, 0, 2 }, { 1, 2, 0 } } },
+  { { { 1, 0, 3 }, { 0, 4, 0 } } },
+  { { { 1, 0, 4 }, { 0, 5, 1 } } },
+  { { { 2, 0, 3 }, { 0, 5, 0 } } },
+  { { { 2, 0, 2 }, { 0, 5, 1 } } },
+  { { { 2, 0, 1 }, { 0, 6, 1 } } },
+  { { { 2, 0, 0 }, { 0, 6, 0 } } },
+  { { { 2, 0, 1 }, { 2, 3, 1 } } },
+  { { { 2, 0, 2 }, { 2, 3, 0 } } },
+  { { { 2, 0, 3 }, { 0, 7, 0 } } },
+  { { { 2, 0, 4 }, { 1, 6, 1 } } },
+  { { { 3, 0, 3 }, { 1, 6, 0 } } },
+  { { { 3, 0, 2 }, { 0, 8, 0 } } },
+  { { { 3, 0, 1 }, { 0, 9, 1 } } },
+  { { { 3, 0, 0 }, { 0, 9, 0 } } },
+  { { { 3, 0, 1 }, { 0, 9, 1 } } },
+  { { { 3, 0, 2 }, { 0, 10, 1 } } },
+  { { { 3, 0, 3 }, { 0, 10, 0 } } },
+  { { { 3, 0, 4 }, { 2, 7, 1 } } },
+  { { { 4, 0, 4 }, { 2, 7, 0 } } },
+  { { { 4, 0, 3 }, { 0, 11, 0 } } },
+  { { { 4, 0, 2 }, { 1, 10, 1 } } },
+  { { { 4, 0, 1 }, { 1, 10, 0 } } },
+  { { { 4, 0, 0 }, { 0, 12, 0 } } },
+  { { { 4, 0, 1 }, { 0, 13, 1 } } },
+  { { { 4, 0, 2 }, { 0, 13, 0 } } },
+  { { { 4, 0, 3 }, { 0, 13, 1 } } },
+  { { { 4, 0, 4 }, { 0, 14, 1 } } },
+  { { { 5, 0, 3 }, { 0, 14, 0 } } },
+  { { { 5, 0, 2 }, { 2, 11, 1 } } },
+  { { { 5, 0, 1 }, { 2, 11, 0 } } },
+  { { { 5, 0, 0 }, { 0, 15, 0 } } },
+  { { { 5, 0, 1 }, { 1, 14, 1 } } },
+  { { { 5, 0, 2 }, { 1, 14, 0 } } },
+  { { { 5, 0, 3 }, { 0, 16, 0 } } },
+  { { { 5, 0, 4 }, { 0, 17, 1 } } },
+  { { { 6, 0, 3 }, { 0, 17, 0 } } },
+  { { { 6, 0, 2 }, { 0, 17, 1 } } },
+  { { { 6, 0, 1 }, { 0, 18, 1 } } },
+  { { { 6, 0, 0 }, { 0, 18, 0 } } },
+  { { { 6, 0, 1 }, { 2, 15, 1 } } },
+  { { { 6, 0, 2 }, { 2, 15, 0 } } },
+  { { { 6, 0, 3 }, { 0, 19, 0 } } },
+  { { { 6, 0, 4 }, { 1, 18, 1 } } },
+  { { { 7, 0, 3 }, { 1, 18, 0 } } },
+  { { { 7, 0, 2 }, { 0, 20, 0 } } },
+  { { { 7, 0, 1 }, { 0, 21, 1 } } },
+  { { { 7, 0, 0 }, { 0, 21, 0 } } },
+  { { { 7, 0, 1 }, { 0, 21, 1 } } },
+  { { { 7, 0, 2 }, { 0, 22, 1 } } },
+  { { { 7, 0, 3 }, { 0, 22, 0 } } },
+  { { { 7, 0, 4 }, { 2, 19, 1 } } },
+  { { { 8, 0, 4 }, { 2, 19, 0 } } },
+  { { { 8, 0, 3 }, { 0, 23, 0 } } },
+  { { { 8, 0, 2 }, { 1, 22, 1 } } },
+  { { { 8, 0, 1 }, { 1, 22, 0 } } },
+  { { { 8, 0, 0 }, { 0, 24, 0 } } },
+  { { { 8, 0, 1 }, { 0, 25, 1 } } },
+  { { { 8, 0, 2 }, { 0, 25, 0 } } },
+  { { { 8, 0, 3 }, { 0, 25, 1 } } },
+  { { { 8, 0, 4 }, { 0, 26, 1 } } },
+  { { { 9, 0, 3 }, { 0, 26, 0 } } },
+  { { { 9, 0, 2 }, { 2, 23, 1 } } },
+  { { { 9, 0, 1 }, { 2, 23, 0 } } },
+  { { { 9, 0, 0 }, { 0, 27, 0 } } },
+  { { { 9, 0, 1 }, { 1, 26, 1 } } },
+  { { { 9, 0, 2 }, { 1, 26, 0 } } },
+  { { { 9, 0, 3 }, { 0, 28, 0 } } },
+  { { { 9, 0, 4 }, { 0, 29, 1 } } },
+  { { { 10, 0, 3 }, { 0, 29, 0 } } },
+  { { { 10, 0, 2 }, { 0, 29, 1 } } },
+  { { { 10, 0, 1 }, { 0, 30, 1 } } },
+  { { { 10, 0, 0 }, { 0, 30, 0 } } },
+  { { { 10, 0, 1 }, { 2, 27, 1 } } },
+  { { { 10, 0, 2 }, { 2, 27, 0 } } },
+  { { { 10, 0, 3 }, { 0, 31, 0 } } },
+  { { { 10, 0, 4 }, { 1, 30, 1 } } },
+  { { { 11, 0, 3 }, { 1, 30, 0 } } },
+  { { { 11, 0, 2 }, { 4, 24, 0 } } },
+  { { { 11, 0, 1 }, { 1, 31, 1 } } },
+  { { { 11, 0, 0 }, { 1, 31, 0 } } },
+  { { { 11, 0, 1 }, { 1, 31, 1 } } },
+  { { { 11, 0, 2 }, { 2, 30, 1 } } },
+  { { { 11, 0, 3 }, { 2, 30, 0 } } },
+  { { { 11, 0, 4 }, { 2, 31, 1 } } },
+  { { { 12, 0, 4 }, { 2, 31, 0 } } },
+  { { { 12, 0, 3 }, { 4, 27, 0 } } },
+  { { { 12, 0, 2 }, { 3, 30, 1 } } },
+  { { { 12, 0, 1 }, { 3, 30, 0 } } },
+  { { { 12, 0, 0 }, { 4, 28, 0 } } },
+  { { { 12, 0, 1 }, { 3, 31, 1 } } },
+  { { { 12, 0, 2 }, { 3, 31, 0 } } },
+  { { { 12, 0, 3 }, { 3, 31, 1 } } },
+  { { { 12, 0, 4 }, { 4, 30, 1 } } },
+  { { { 13, 0, 3 }, { 4, 30, 0 } } },
+  { { { 13, 0, 2 }, { 6, 27, 1 } } },
+  { { { 13, 0, 1 }, { 6, 27, 0 } } },
+  { { { 13, 0, 0 }, { 4, 31, 0 } } },
+  { { { 13, 0, 1 }, { 5, 30, 1 } } },
+  { { { 13, 0, 2 }, { 5, 30, 0 } } },
+  { { { 13, 0, 3 }, { 8, 24, 0 } } },
+  { { { 13, 0, 4 }, { 5, 31, 1 } } },
+  { { { 14, 0, 3 }, { 5, 31, 0 } } },
+  { { { 14, 0, 2 }, { 5, 31, 1 } } },
+  { { { 14, 0, 1 }, { 6, 30, 1 } } },
+  { { { 14, 0, 0 }, { 6, 30, 0 } } },
+  { { { 14, 0, 1 }, { 6, 31, 1 } } },
+  { { { 14, 0, 2 }, { 6, 31, 0 } } },
+  { { { 14, 0, 3 }, { 8, 27, 0 } } },
+  { { { 14, 0, 4 }, { 7, 30, 1 } } },
+  { { { 15, 0, 3 }, { 7, 30, 0 } } },
+  { { { 15, 0, 2 }, { 8, 28, 0 } } },
+  { { { 15, 0, 1 }, { 7, 31, 1 } } },
+  { { { 15, 0, 0 }, { 7, 31, 0 } } },
+  { { { 15, 0, 1 }, { 7, 31, 1 } } },
+  { { { 15, 0, 2 }, { 8, 30, 1 } } },
+  { { { 15, 0, 3 }, { 8, 30, 0 } } },
+  { { { 15, 0, 4 }, { 10, 27, 1 } } },
+  { { { 16, 0, 4 }, { 10, 27, 0 } } },
+  { { { 16, 0, 3 }, { 8, 31, 0 } } },
+  { { { 16, 0, 2 }, { 9, 30, 1 } } },
+  { { { 16, 0, 1 }, { 9, 30, 0 } } },
+  { { { 16, 0, 0 }, { 12, 24, 0 } } },
+  { { { 16, 0, 1 }, { 9, 31, 1 } } },
+  { { { 16, 0, 2 }, { 9, 31, 0 } } },
+  { { { 16, 0, 3 }, { 9, 31, 1 } } },
+  { { { 16, 0, 4 }, { 10, 30, 1 } } },
+  { { { 17, 0, 3 }, { 10, 30, 0 } } },
+  { { { 17, 0, 2 }, { 10, 31, 1 } } },
+  { { { 17, 0, 1 }, { 10, 31, 0 } } },
+  { { { 17, 0, 0 }, { 12, 27, 0 } } },
+  { { { 17, 0, 1 }, { 11, 30, 1 } } },
+  { { { 17, 0, 2 }, { 11, 30, 0 } } },
+  { { { 17, 0, 3 }, { 12, 28, 0 } } },
+  { { { 17, 0, 4 }, { 11, 31, 1 } } },
+  { { { 18, 0, 3 }, { 11, 31, 0 } } },
+  { { { 18, 0, 2 }, { 11, 31, 1 } } },
+  { { { 18, 0, 1 }, { 12, 30, 1 } } },
+  { { { 18, 0, 0 }, { 12, 30, 0 } } },
+  { { { 18, 0, 1 }, { 14, 27, 1 } } },
+  { { { 18, 0, 2 }, { 14, 27, 0 } } },
+  { { { 18, 0, 3 }, { 12, 31, 0 } } },
+  { { { 18, 0, 4 }, { 13, 30, 1 } } },
+  { { { 19, 0, 3 }, { 13, 30, 0 } } },
+  { { { 19, 0, 2 }, { 16, 24, 0 } } },
+  { { { 19, 0, 1 }, { 13, 31, 1 } } },
+  { { { 19, 0, 0 }, { 13, 31, 0 } } },
+  { { { 19, 0, 1 }, { 13, 31, 1 } } },
+  { { { 19, 0, 2 }, { 14, 30, 1 } } },
+  { { { 19, 0, 3 }, { 14, 30, 0 } } },
+  { { { 19, 0, 4 }, { 14, 31, 1 } } },
+  { { { 20, 0, 4 }, { 14, 31, 0 } } },
+  { { { 20, 0, 3 }, { 16, 27, 0 } } },
+  { { { 20, 0, 2 }, { 15, 30, 1 } } },
+  { { { 20, 0, 1 }, { 15, 30, 0 } } },
+  { { { 20, 0, 0 }, { 16, 28, 0 } } },
+  { { { 20, 0, 1 }, { 15, 31, 1 } } },
+  { { { 20, 0, 2 }, { 15, 31, 0 } } },
+  { { { 20, 0, 3 }, { 15, 31, 1 } } },
+  { { { 20, 0, 4 }, { 16, 30, 1 } } },
+  { { { 21, 0, 3 }, { 16, 30, 0 } } },
+  { { { 21, 0, 2 }, { 18, 27, 1 } } },
+  { { { 21, 0, 1 }, { 18, 27, 0 } } },
+  { { { 21, 0, 0 }, { 16, 31, 0 } } },
+  { { { 21, 0, 1 }, { 17, 30, 1 } } },
+  { { { 21, 0, 2 }, { 17, 30, 0 } } },
+  { { { 21, 0, 3 }, { 20, 24, 0 } } },
+  { { { 21, 0, 4 }, { 17, 31, 1 } } },
+  { { { 22, 0, 3 }, { 17, 31, 0 } } },
+  { { { 22, 0, 2 }, { 17, 31, 1 } } },
+  { { { 22, 0, 1 }, { 18, 30, 1 } } },
+  { { { 22, 0, 0 }, { 18, 30, 0 } } },
+  { { { 22, 0, 1 }, { 18, 31, 1 } } },
+  { { { 22, 0, 2 }, { 18, 31, 0 } } },
+  { { { 22, 0, 3 }, { 20, 27, 0 } } },
+  { { { 22, 0, 4 }, { 19, 30, 1 } } },
+  { { { 23, 0, 3 }, { 19, 30, 0 } } },
+  { { { 23, 0, 2 }, { 20, 28, 0 } } },
+  { { { 23, 0, 1 }, { 19, 31, 1 } } },
+  { { { 23, 0, 0 }, { 19, 31, 0 } } },
+  { { { 23, 0, 1 }, { 19, 31, 1 } } },
+  { { { 23, 0, 2 }, { 20, 30, 1 } } },
+  { { { 23, 0, 3 }, { 20, 30, 0 } } },
+  { { { 23, 0, 4 }, { 22, 27, 1 } } },
+  { { { 24, 0, 4 }, { 22, 27, 0 } } },
+  { { { 24, 0, 3 }, { 20, 31, 0 } } },
+  { { { 24, 0, 2 }, { 21, 30, 1 } } },
+  { { { 24, 0, 1 }, { 21, 30, 0 } } },
+  { { { 24, 0, 0 }, { 24, 24, 0 } } },
+  { { { 24, 0, 1 }, { 21, 31, 1 } } },
+  { { { 24, 0, 2 }, { 21, 31, 0 } } },
+  { { { 24, 0, 3 }, { 21, 31, 1 } } },
+  { { { 24, 0, 4 }, { 22, 30, 1 } } },
+  { { { 25, 0, 3 }, { 22, 30, 0 } } },
+  { { { 25, 0, 2 }, { 22, 31, 1 } } },
+  { { { 25, 0, 1 }, { 22, 31, 0 } } },
+  { { { 25, 0, 0 }, { 24, 27, 0 } } },
+  { { { 25, 0, 1 }, { 23, 30, 1 } } },
+  { { { 25, 0, 2 }, { 23, 30, 0 } } },
+  { { { 25, 0, 3 }, { 24, 28, 0 } } },
+  { { { 25, 0, 4 }, { 23, 31, 1 } } },
+  { { { 26, 0, 3 }, { 23, 31, 0 } } },
+  { { { 26, 0, 2 }, { 23, 31, 1 } } },
+  { { { 26, 0, 1 }, { 24, 30, 1 } } },
+  { { { 26, 0, 0 }, { 24, 30, 0 } } },
+  { { { 26, 0, 1 }, { 26, 27, 1 } } },
+  { { { 26, 0, 2 }, { 26, 27, 0 } } },
+  { { { 26, 0, 3 }, { 24, 31, 0 } } },
+  { { { 26, 0, 4 }, { 25, 30, 1 } } },
+  { { { 27, 0, 3 }, { 25, 30, 0 } } },
+  { { { 27, 0, 2 }, { 28, 24, 0 } } },
+  { { { 27, 0, 1 }, { 25, 31, 1 } } },
+  { { { 27, 0, 0 }, { 25, 31, 0 } } },
+  { { { 27, 0, 1 }, { 25, 31, 1 } } },
+  { { { 27, 0, 2 }, { 26, 30, 1 } } },
+  { { { 27, 0, 3 }, { 26, 30, 0 } } },
+  { { { 27, 0, 4 }, { 26, 31, 1 } } },
+  { { { 28, 0, 4 }, { 26, 31, 0 } } },
+  { { { 28, 0, 3 }, { 28, 27, 0 } } },
+  { { { 28, 0, 2 }, { 27, 30, 1 } } },
+  { { { 28, 0, 1 }, { 27, 30, 0 } } },
+  { { { 28, 0, 0 }, { 28, 28, 0 } } },
+  { { { 28, 0, 1 }, { 27, 31, 1 } } },
+  { { { 28, 0, 2 }, { 27, 31, 0 } } },
+  { { { 28, 0, 3 }, { 27, 31, 1 } } },
+  { { { 28, 0, 4 }, { 28, 30, 1 } } },
+  { { { 29, 0, 3 }, { 28, 30, 0 } } },
+  { { { 29, 0, 2 }, { 30, 27, 1 } } },
+  { { { 29, 0, 1 }, { 30, 27, 0 } } },
+  { { { 29, 0, 0 }, { 28, 31, 0 } } },
+  { { { 29, 0, 1 }, { 29, 30, 1 } } },
+  { { { 29, 0, 2 }, { 29, 30, 0 } } },
+  { { { 29, 0, 3 }, { 29, 30, 1 } } },
+  { { { 29, 0, 4 }, { 29, 31, 1 } } },
+  { { { 30, 0, 3 }, { 29, 31, 0 } } },
+  { { { 30, 0, 2 }, { 29, 31, 1 } } },
+  { { { 30, 0, 1 }, { 30, 30, 1 } } },
+  { { { 30, 0, 0 }, { 30, 30, 0 } } },
+  { { { 30, 0, 1 }, { 30, 31, 1 } } },
+  { { { 30, 0, 2 }, { 30, 31, 0 } } },
+  { { { 30, 0, 3 }, { 30, 31, 1 } } },
+  { { { 30, 0, 4 }, { 31, 30, 1 } } },
+  { { { 31, 0, 3 }, { 31, 30, 0 } } },
+  { { { 31, 0, 2 }, { 31, 30, 1 } } },
+  { { { 31, 0, 1 }, { 31, 31, 1 } } },
+  { { { 31, 0, 0 }, { 31, 31, 0 } } }
+};
+
+static const DDSSingleColourLookup DDSLookup_6_4[] =
+{
+  { { { 0, 0, 0 }, { 0, 0, 0 } } },
+  { { { 0, 0, 1 }, { 0, 1, 0 } } },
+  { { { 0, 0, 2 }, { 0, 2, 0 } } },
+  { { { 1, 0, 1 }, { 0, 3, 1 } } },
+  { { { 1, 0, 0 }, { 0, 3, 0 } } },
+  { { { 1, 0, 1 }, { 0, 4, 0 } } },
+  { { { 1, 0, 2 }, { 0, 5, 0 } } },
+  { { { 2, 0, 1 }, { 0, 6, 1 } } },
+  { { { 2, 0, 0 }, { 0, 6, 0 } } },
+  { { { 2, 0, 1 }, { 0, 7, 0 } } },
+  { { { 2, 0, 2 }, { 0, 8, 0 } } },
+  { { { 3, 0, 1 }, { 0, 9, 1 } } },
+  { { { 3, 0, 0 }, { 0, 9, 0 } } },
+  { { { 3, 0, 1 }, { 0, 10, 0 } } },
+  { { { 3, 0, 2 }, { 0, 11, 0 } } },
+  { { { 4, 0, 1 }, { 0, 12, 1 } } },
+  { { { 4, 0, 0 }, { 0, 12, 0 } } },
+  { { { 4, 0, 1 }, { 0, 13, 0 } } },
+  { { { 4, 0, 2 }, { 0, 14, 0 } } },
+  { { { 5, 0, 1 }, { 0, 15, 1 } } },
+  { { { 5, 0, 0 }, { 0, 15, 0 } } },
+  { { { 5, 0, 1 }, { 0, 16, 0 } } },
+  { { { 5, 0, 2 }, { 1, 15, 0 } } },
+  { { { 6, 0, 1 }, { 0, 17, 0 } } },
+  { { { 6, 0, 0 }, { 0, 18, 0 } } },
+  { { { 6, 0, 1 }, { 0, 19, 0 } } },
+  { { { 6, 0, 2 }, { 3, 14, 0 } } },
+  { { { 7, 0, 1 }, { 0, 20, 0 } } },
+  { { { 7, 0, 0 }, { 0, 21, 0 } } },
+  { { { 7, 0, 1 }, { 0, 22, 0 } } },
+  { { { 7, 0, 2 }, { 4, 15, 0 } } },
+  { { { 8, 0, 1 }, { 0, 23, 0 } } },
+  { { { 8, 0, 0 }, { 0, 24, 0 } } },
+  { { { 8, 0, 1 }, { 0, 25, 0 } } },
+  { { { 8, 0, 2 }, { 6, 14, 0 } } },
+  { { { 9, 0, 1 }, { 0, 26, 0 } } },
+  { { { 9, 0, 0 }, { 0, 27, 0 } } },
+  { { { 9, 0, 1 }, { 0, 28, 0 } } },
+  { { { 9, 0, 2 }, { 7, 15, 0 } } },
+  { { { 10, 0, 1 }, { 0, 29, 0 } } },
+  { { { 10, 0, 0 }, { 0, 30, 0 } } },
+  { { { 10, 0, 1 }, { 0, 31, 0 } } },
+  { { { 10, 0, 2 }, { 9, 14, 0 } } },
+  { { { 11, 0, 1 }, { 0, 32, 0 } } },
+  { { { 11, 0, 0 }, { 0, 33, 0 } } },
+  { { { 11, 0, 1 }, { 2, 30, 0 } } },
+  { { { 11, 0, 2 }, { 0, 34, 0 } } },
+  { { { 12, 0, 1 }, { 0, 35, 0 } } },
+  { { { 12, 0, 0 }, { 0, 36, 0 } } },
+  { { { 12, 0, 1 }, { 3, 31, 0 } } },
+  { { { 12, 0, 2 }, { 0, 37, 0 } } },
+  { { { 13, 0, 1 }, { 0, 38, 0 } } },
+  { { { 13, 0, 0 }, { 0, 39, 0 } } },
+  { { { 13, 0, 1 }, { 5, 30, 0 } } },
+  { { { 13, 0, 2 }, { 0, 40, 0 } } },
+  { { { 14, 0, 1 }, { 0, 41, 0 } } },
+  { { { 14, 0, 0 }, { 0, 42, 0 } } },
+  { { { 14, 0, 1 }, { 6, 31, 0 } } },
+  { { { 14, 0, 2 }, { 0, 43, 0 } } },
+  { { { 15, 0, 1 }, { 0, 44, 0 } } },
+  { { { 15, 0, 0 }, { 0, 45, 0 } } },
+  { { { 15, 0, 1 }, { 8, 30, 0 } } },
+  { { { 15, 0, 2 }, { 0, 46, 0 } } },
+  { { { 16, 0, 2 }, { 0, 47, 0 } } },
+  { { { 16, 0, 1 }, { 1, 46, 0 } } },
+  { { { 16, 0, 0 }, { 0, 48, 0 } } },
+  { { { 16, 0, 1 }, { 0, 49, 0 } } },
+  { { { 16, 0, 2 }, { 0, 50, 0 } } },
+  { { { 17, 0, 1 }, { 2, 47, 0 } } },
+  { { { 17, 0, 0 }, { 0, 51, 0 } } },
+  { { { 17, 0, 1 }, { 0, 52, 0 } } },
+  { { { 17, 0, 2 }, { 0, 53, 0 } } },
+  { { { 18, 0, 1 }, { 4, 46, 0 } } },
+  { { { 18, 0, 0 }, { 0, 54, 0 } } },
+  { { { 18, 0, 1 }, { 0, 55, 0 } } },
+  { { { 18, 0, 2 }, { 0, 56, 0 } } },
+  { { { 19, 0, 1 }, { 5, 47, 0 } } },
+  { { { 19, 0, 0 }, { 0, 57, 0 } } },
+  { { { 19, 0, 1 }, { 0, 58, 0 } } },
+  { { { 19, 0, 2 }, { 0, 59, 0 } } },
+  { { { 20, 0, 1 }, { 7, 46, 0 } } },
+  { { { 20, 0, 0 }, { 0, 60, 0 } } },
+  { { { 20, 0, 1 }, { 0, 61, 0 } } },
+  { { { 20, 0, 2 }, { 0, 62, 0 } } },
+  { { { 21, 0, 1 }, { 8, 47, 0 } } },
+  { { { 21, 0, 0 }, { 0, 63, 0 } } },
+  { { { 21, 0, 1 }, { 1, 62, 0 } } },
+  { { { 21, 0, 2 }, { 1, 63, 0 } } },
+  { { { 22, 0, 1 }, { 10, 46, 0 } } },
+  { { { 22, 0, 0 }, { 2, 62, 0 } } },
+  { { { 22, 0, 1 }, { 2, 63, 0 } } },
+  { { { 22, 0, 2 }, { 3, 62, 0 } } },
+  { { { 23, 0, 1 }, { 11, 47, 0 } } },
+  { { { 23, 0, 0 }, { 3, 63, 0 } } },
+  { { { 23, 0, 1 }, { 4, 62, 0 } } },
+  { { { 23, 0, 2 }, { 4, 63, 0 } } },
+  { { { 24, 0, 1 }, { 13, 46, 0 } } },
+  { { { 24, 0, 0 }, { 5, 62, 0 } } },
+  { { { 24, 0, 1 }, { 5, 63, 0 } } },
+  { { { 24, 0, 2 }, { 6, 62, 0 } } },
+  { { { 25, 0, 1 }, { 14, 47, 0 } } },
+  { { { 25, 0, 0 }, { 6, 63, 0 } } },
+  { { { 25, 0, 1 }, { 7, 62, 0 } } },
+  { { { 25, 0, 2 }, { 7, 63, 0 } } },
+  { { { 26, 0, 1 }, { 16, 45, 0 } } },
+  { { { 26, 0, 0 }, { 8, 62, 0 } } },
+  { { { 26, 0, 1 }, { 8, 63, 0 } } },
+  { { { 26, 0, 2 }, { 9, 62, 0 } } },
+  { { { 27, 0, 1 }, { 16, 48, 0 } } },
+  { { { 27, 0, 0 }, { 9, 63, 0 } } },
+  { { { 27, 0, 1 }, { 10, 62, 0 } } },
+  { { { 27, 0, 2 }, { 10, 63, 0 } } },
+  { { { 28, 0, 1 }, { 16, 51, 0 } } },
+  { { { 28, 0, 0 }, { 11, 62, 0 } } },
+  { { { 28, 0, 1 }, { 11, 63, 0 } } },
+  { { { 28, 0, 2 }, { 12, 62, 0 } } },
+  { { { 29, 0, 1 }, { 16, 54, 0 } } },
+  { { { 29, 0, 0 }, { 12, 63, 0 } } },
+  { { { 29, 0, 1 }, { 13, 62, 0 } } },
+  { { { 29, 0, 2 }, { 13, 63, 0 } } },
+  { { { 30, 0, 1 }, { 16, 57, 0 } } },
+  { { { 30, 0, 0 }, { 14, 62, 0 } } },
+  { { { 30, 0, 1 }, { 14, 63, 0 } } },
+  { { { 30, 0, 2 }, { 15, 62, 0 } } },
+  { { { 31, 0, 1 }, { 16, 60, 0 } } },
+  { { { 31, 0, 0 }, { 15, 63, 0 } } },
+  { { { 31, 0, 1 }, { 24, 46, 0 } } },
+  { { { 31, 0, 2 }, { 16, 62, 0 } } },
+  { { { 32, 0, 2 }, { 16, 63, 0 } } },
+  { { { 32, 0, 1 }, { 17, 62, 0 } } },
+  { { { 32, 0, 0 }, { 25, 47, 0 } } },
+  { { { 32, 0, 1 }, { 17, 63, 0 } } },
+  { { { 32, 0, 2 }, { 18, 62, 0 } } },
+  { { { 33, 0, 1 }, { 18, 63, 0 } } },
+  { { { 33, 0, 0 }, { 27, 46, 0 } } },
+  { { { 33, 0, 1 }, { 19, 62, 0 } } },
+  { { { 33, 0, 2 }, { 19, 63, 0 } } },
+  { { { 34, 0, 1 }, { 20, 62, 0 } } },
+  { { { 34, 0, 0 }, { 28, 47, 0 } } },
+  { { { 34, 0, 1 }, { 20, 63, 0 } } },
+  { { { 34, 0, 2 }, { 21, 62, 0 } } },
+  { { { 35, 0, 1 }, { 21, 63, 0 } } },
+  { { { 35, 0, 0 }, { 30, 46, 0 } } },
+  { { { 35, 0, 1 }, { 22, 62, 0 } } },
+  { { { 35, 0, 2 }, { 22, 63, 0 } } },
+  { { { 36, 0, 1 }, { 23, 62, 0 } } },
+  { { { 36, 0, 0 }, { 31, 47, 0 } } },
+  { { { 36, 0, 1 }, { 23, 63, 0 } } },
+  { { { 36, 0, 2 }, { 24, 62, 0 } } },
+  { { { 37, 0, 1 }, { 24, 63, 0 } } },
+  { { { 37, 0, 0 }, { 32, 47, 0 } } },
+  { { { 37, 0, 1 }, { 25, 62, 0 } } },
+  { { { 37, 0, 2 }, { 25, 63, 0 } } },
+  { { { 38, 0, 1 }, { 26, 62, 0 } } },
+  { { { 38, 0, 0 }, { 32, 50, 0 } } },
+  { { { 38, 0, 1 }, { 26, 63, 0 } } },
+  { { { 38, 0, 2 }, { 27, 62, 0 } } },
+  { { { 39, 0, 1 }, { 27, 63, 0 } } },
+  { { { 39, 0, 0 }, { 32, 53, 0 } } },
+  { { { 39, 0, 1 }, { 28, 62, 0 } } },
+  { { { 39, 0, 2 }, { 28, 63, 0 } } },
+  { { { 40, 0, 1 }, { 29, 62, 0 } } },
+  { { { 40, 0, 0 }, { 32, 56, 0 } } },
+  { { { 40, 0, 1 }, { 29, 63, 0 } } },
+  { { { 40, 0, 2 }, { 30, 62, 0 } } },
+  { { { 41, 0, 1 }, { 30, 63, 0 } } },
+  { { { 41, 0, 0 }, { 32, 59, 0 } } },
+  { { { 41, 0, 1 }, { 31, 62, 0 } } },
+  { { { 41, 0, 2 }, { 31, 63, 0 } } },
+  { { { 42, 0, 1 }, { 32, 61, 0 } } },
+  { { { 42, 0, 0 }, { 32, 62, 0 } } },
+  { { { 42, 0, 1 }, { 32, 63, 0 } } },
+  { { { 42, 0, 2 }, { 41, 46, 0 } } },
+  { { { 43, 0, 1 }, { 33, 62, 0 } } },
+  { { { 43, 0, 0 }, { 33, 63, 0 } } },
+  { { { 43, 0, 1 }, { 34, 62, 0 } } },
+  { { { 43, 0, 2 }, { 42, 47, 0 } } },
+  { { { 44, 0, 1 }, { 34, 63, 0 } } },
+  { { { 44, 0, 0 }, { 35, 62, 0 } } },
+  { { { 44, 0, 1 }, { 35, 63, 0 } } },
+  { { { 44, 0, 2 }, { 44, 46, 0 } } },
+  { { { 45, 0, 1 }, { 36, 62, 0 } } },
+  { { { 45, 0, 0 }, { 36, 63, 0 } } },
+  { { { 45, 0, 1 }, { 37, 62, 0 } } },
+  { { { 45, 0, 2 }, { 45, 47, 0 } } },
+  { { { 46, 0, 1 }, { 37, 63, 0 } } },
+  { { { 46, 0, 0 }, { 38, 62, 0 } } },
+  { { { 46, 0, 1 }, { 38, 63, 0 } } },
+  { { { 46, 0, 2 }, { 47, 46, 0 } } },
+  { { { 47, 0, 1 }, { 39, 62, 0 } } },
+  { { { 47, 0, 0 }, { 39, 63, 0 } } },
+  { { { 47, 0, 1 }, { 40, 62, 0 } } },
+  { { { 47, 0, 2 }, { 48, 46, 0 } } },
+  { { { 48, 0, 2 }, { 40, 63, 0 } } },
+  { { { 48, 0, 1 }, { 41, 62, 0 } } },
+  { { { 48, 0, 0 }, { 41, 63, 0 } } },
+  { { { 48, 0, 1 }, { 48, 49, 0 } } },
+  { { { 48, 0, 2 }, { 42, 62, 0 } } },
+  { { { 49, 0, 1 }, { 42, 63, 0 } } },
+  { { { 49, 0, 0 }, { 43, 62, 0 } } },
+  { { { 49, 0, 1 }, { 48, 52, 0 } } },
+  { { { 49, 0, 2 }, { 43, 63, 0 } } },
+  { { { 50, 0, 1 }, { 44, 62, 0 } } },
+  { { { 50, 0, 0 }, { 44, 63, 0 } } },
+  { { { 50, 0, 1 }, { 48, 55, 0 } } },
+  { { { 50, 0, 2 }, { 45, 62, 0 } } },
+  { { { 51, 0, 1 }, { 45, 63, 0 } } },
+  { { { 51, 0, 0 }, { 46, 62, 0 } } },
+  { { { 51, 0, 1 }, { 48, 58, 0 } } },
+  { { { 51, 0, 2 }, { 46, 63, 0 } } },
+  { { { 52, 0, 1 }, { 47, 62, 0 } } },
+  { { { 52, 0, 0 }, { 47, 63, 0 } } },
+  { { { 52, 0, 1 }, { 48, 61, 0 } } },
+  { { { 52, 0, 2 }, { 48, 62, 0 } } },
+  { { { 53, 0, 1 }, { 56, 47, 0 } } },
+  { { { 53, 0, 0 }, { 48, 63, 0 } } },
+  { { { 53, 0, 1 }, { 49, 62, 0 } } },
+  { { { 53, 0, 2 }, { 49, 63, 0 } } },
+  { { { 54, 0, 1 }, { 58, 46, 0 } } },
+  { { { 54, 0, 0 }, { 50, 62, 0 } } },
+  { { { 54, 0, 1 }, { 50, 63, 0 } } },
+  { { { 54, 0, 2 }, { 51, 62, 0 } } },
+  { { { 55, 0, 1 }, { 59, 47, 0 } } },
+  { { { 55, 0, 0 }, { 51, 63, 0 } } },
+  { { { 55, 0, 1 }, { 52, 62, 0 } } },
+  { { { 55, 0, 2 }, { 52, 63, 0 } } },
+  { { { 56, 0, 1 }, { 61, 46, 0 } } },
+  { { { 56, 0, 0 }, { 53, 62, 0 } } },
+  { { { 56, 0, 1 }, { 53, 63, 0 } } },
+  { { { 56, 0, 2 }, { 54, 62, 0 } } },
+  { { { 57, 0, 1 }, { 62, 47, 0 } } },
+  { { { 57, 0, 0 }, { 54, 63, 0 } } },
+  { { { 57, 0, 1 }, { 55, 62, 0 } } },
+  { { { 57, 0, 2 }, { 55, 63, 0 } } },
+  { { { 58, 0, 1 }, { 56, 62, 1 } } },
+  { { { 58, 0, 0 }, { 56, 62, 0 } } },
+  { { { 58, 0, 1 }, { 56, 63, 0 } } },
+  { { { 58, 0, 2 }, { 57, 62, 0 } } },
+  { { { 59, 0, 1 }, { 57, 63, 1 } } },
+  { { { 59, 0, 0 }, { 57, 63, 0 } } },
+  { { { 59, 0, 1 }, { 58, 62, 0 } } },
+  { { { 59, 0, 2 }, { 58, 63, 0 } } },
+  { { { 60, 0, 1 }, { 59, 62, 1 } } },
+  { { { 60, 0, 0 }, { 59, 62, 0 } } },
+  { { { 60, 0, 1 }, { 59, 63, 0 } } },
+  { { { 60, 0, 2 }, { 60, 62, 0 } } },
+  { { { 61, 0, 1 }, { 60, 63, 1 } } },
+  { { { 61, 0, 0 }, { 60, 63, 0 } } },
+  { { { 61, 0, 1 }, { 61, 62, 0 } } },
+  { { { 61, 0, 2 }, { 61, 63, 0 } } },
+  { { { 62, 0, 1 }, { 62, 62, 1 } } },
+  { { { 62, 0, 0 }, { 62, 62, 0 } } },
+  { { { 62, 0, 1 }, { 62, 63, 0 } } },
+  { { { 62, 0, 2 }, { 63, 62, 0 } } },
+  { { { 63, 0, 1 }, { 63, 63, 1 } } },
+  { { { 63, 0, 0 }, { 63, 63, 0 } } }
+};
+
+static const DDSSingleColourLookup*
+  DDS_LOOKUP[] =
+{
+  DDSLookup_5_4,
+  DDSLookup_6_4,
+  DDSLookup_5_4
+};
+
+/*
+  Macros
+*/
+#define C565_r(x) (((x) & 0xF800) >> 11)
+#define C565_g(x) (((x) & 0x07E0) >> 5)
+#define C565_b(x)  ((x) & 0x001F)
+
+#define C565_red(x)   ( (C565_r(x) << 3 | C565_r(x) >> 2))
+#define C565_green(x) ( (C565_g(x) << 2 | C565_g(x) >> 4))
+#define C565_blue(x)  ( (C565_b(x) << 3 | C565_b(x) >> 2))
+
+#define DIV2(x)  ((x) > 1 ? ((x) >> 1) : 1)
+
+#define FixRange(min, max, steps) \
+if (min > max) \
+  min = max; \
+if (max - min < steps) \
+  max = Min(min + steps, 255); \
+if (max - min < steps) \
+  min = Max(min - steps, 0)
+
+#define Dot(left, right) (left.x*right.x) + (left.y*right.y) + (left.z*right.z)
+
+#define VectorInit(vector, value) vector.x = vector.y = vector.z = vector.w \
+  = value
+#define VectorInit3(vector, value) vector.x = vector.y = vector.z = value
+
+#define IsBitMask(mask, r, g, b, a) (mask.r_bitmask == r && mask.g_bitmask == \
+  g && mask.b_bitmask == b && mask.alpha_bitmask == a)
+
+/*
+  Forward declarations
+*/
+static MagickBooleanType
+  ConstructOrdering(const size_t, const DDSVector4 *, const DDSVector3,
+  DDSVector4 *, DDSVector4 *, unsigned char *, size_t);
+
+static MagickBooleanType
+  ReadDDSInfo(Image *, DDSInfo *);
+
+static void
+  CalculateColors(unsigned short, unsigned short,
+    DDSColors *, MagickBooleanType);
+
+static MagickBooleanType
+  ReadDXT1(Image *, DDSInfo *, ExceptionInfo *);
+
+static MagickBooleanType
+  ReadDXT3(Image *, DDSInfo *, ExceptionInfo *);
+
+static MagickBooleanType
+  ReadDXT5(Image *, DDSInfo *, ExceptionInfo *);
+
+static MagickBooleanType
+  ReadUncompressedRGB(Image *, DDSInfo *, ExceptionInfo *);
+
+static MagickBooleanType
+  ReadUncompressedRGBA(Image *, DDSInfo *, ExceptionInfo *);
+
+static void
+  RemapIndices(const ssize_t *, const unsigned char *, unsigned char *);
+
+static void
+  SkipDXTMipmaps(Image *, DDSInfo *, int);
+
+static void
+  SkipRGBMipmaps(Image *, DDSInfo *, int);
+
+static
+  MagickBooleanType WriteDDSImage(const ImageInfo *, Image *, ExceptionInfo *);
+
+static void
+  WriteDDSInfo(Image *, const size_t, const size_t, const size_t);
+
+static void
+  WriteFourCC(Image *, const size_t, const MagickBooleanType,
+    const MagickBooleanType, ExceptionInfo *);
+
+static void
+  WriteImageData(Image *, const size_t, const size_t, const MagickBooleanType,
+  const MagickBooleanType, ExceptionInfo *);
+
+static void
+  WriteIndices(Image *, const DDSVector3, const DDSVector3, unsigned char *);
+
+static MagickBooleanType
+  WriteMipmaps(Image *, const size_t, const size_t, const size_t,
+    const MagickBooleanType, const MagickBooleanType, ExceptionInfo *);
+
+static void
+  WriteSingleColorFit(Image *, const DDSVector4 *, const ssize_t *);
+
+static void
+  WriteUncompressed(Image *, ExceptionInfo *);
+
+static inline size_t Max(size_t one, size_t two)
+{
+  if (one > two)
+    return one;
+  return two;
+}
+
+static inline float MaxF(float one, float two)
+{
+  if (one > two)
+    return one;
+  return two;
+}
+
+static inline size_t Min(size_t one, size_t two)
+{
+  if (one < two)
+    return one;
+  return two;
+}
+
+static inline float MinF(float one, float two)
+{
+  if (one < two)
+    return one;
+  return two;
+}
+
+static inline void VectorAdd(const DDSVector4 left, const DDSVector4 right,
+  DDSVector4 *destination)
+{
+  destination->x = left.x + right.x;
+  destination->y = left.y + right.y;
+  destination->z = left.z + right.z;
+  destination->w = left.w + right.w;
+}
+
+static inline void VectorClamp(DDSVector4 *value)
+{
+  value->x = MinF(1.0f,MaxF(0.0f,value->x));
+  value->y = MinF(1.0f,MaxF(0.0f,value->y));
+  value->z = MinF(1.0f,MaxF(0.0f,value->z));
+  value->w = MinF(1.0f,MaxF(0.0f,value->w));
+}
+
+static inline void VectorClamp3(DDSVector3 *value)
+{
+  value->x = MinF(1.0f,MaxF(0.0f,value->x));
+  value->y = MinF(1.0f,MaxF(0.0f,value->y));
+  value->z = MinF(1.0f,MaxF(0.0f,value->z));
+}
+
+static inline void VectorCopy43(const DDSVector4 source,
+  DDSVector3 *destination)
+{
+  destination->x = source.x;
+  destination->y = source.y;
+  destination->z = source.z;
+}
+
+static inline void VectorCopy44(const DDSVector4 source,
+  DDSVector4 *destination)
+{
+  destination->x = source.x;
+  destination->y = source.y;
+  destination->z = source.z;
+  destination->w = source.w;
+}
+
+static inline void VectorNegativeMultiplySubtract(const DDSVector4 a,
+  const DDSVector4 b, const DDSVector4 c, DDSVector4 *destination)
+{
+  destination->x = c.x - (a.x * b.x);
+  destination->y = c.y - (a.y * b.y);
+  destination->z = c.z - (a.z * b.z);
+  destination->w = c.w - (a.w * b.w);
+}
+
+static inline void VectorMultiply(const DDSVector4 left,
+  const DDSVector4 right, DDSVector4 *destination)
+{
+  destination->x = left.x * right.x;
+  destination->y = left.y * right.y;
+  destination->z = left.z * right.z;
+  destination->w = left.w * right.w;
+}
+
+static inline void VectorMultiply3(const DDSVector3 left,
+  const DDSVector3 right, DDSVector3 *destination)
+{
+  destination->x = left.x * right.x;
+  destination->y = left.y * right.y;
+  destination->z = left.z * right.z;
+}
+
+static inline void VectorMultiplyAdd(const DDSVector4 a, const DDSVector4 b,
+  const DDSVector4 c, DDSVector4 *destination)
+{
+  destination->x = (a.x * b.x) + c.x;
+  destination->y = (a.y * b.y) + c.y;
+  destination->z = (a.z * b.z) + c.z;
+  destination->w = (a.w * b.w) + c.w;
+}
+
+static inline void VectorMultiplyAdd3(const DDSVector3 a, const DDSVector3 b,
+  const DDSVector3 c, DDSVector3 *destination)
+{
+  destination->x = (a.x * b.x) + c.x;
+  destination->y = (a.y * b.y) + c.y;
+  destination->z = (a.z * b.z) + c.z;
+}
+
+static inline void VectorReciprocal(const DDSVector4 value,
+  DDSVector4 *destination)
+{
+  destination->x = 1.0f / value.x;
+  destination->y = 1.0f / value.y;
+  destination->z = 1.0f / value.z;
+  destination->w = 1.0f / value.w;
+}
+
+static inline void VectorSubtract(const DDSVector4 left,
+  const DDSVector4 right, DDSVector4 *destination)
+{
+  destination->x = left.x - right.x;
+  destination->y = left.y - right.y;
+  destination->z = left.z - right.z;
+  destination->w = left.w - right.w;
+}
+
+static inline void VectorSubtract3(const DDSVector3 left,
+  const DDSVector3 right, DDSVector3 *destination)
+{
+  destination->x = left.x - right.x;
+  destination->y = left.y - right.y;
+  destination->z = left.z - right.z;
+}
+
+static inline void VectorTruncate(DDSVector4 *value)
+{
+  value->x = value->x > 0.0f ? floor(value->x) : ceil(value->x);
+  value->y = value->y > 0.0f ? floor(value->y) : ceil(value->y);
+  value->z = value->z > 0.0f ? floor(value->z) : ceil(value->z);
+  value->w = value->w > 0.0f ? floor(value->w) : ceil(value->w);
+}
+
+static inline void VectorTruncate3(DDSVector3 *value)
+{
+  value->x = value->x > 0.0f ? floor(value->x) : ceil(value->x);
+  value->y = value->y > 0.0f ? floor(value->y) : ceil(value->y);
+  value->z = value->z > 0.0f ? floor(value->z) : ceil(value->z);
+}
+
+static void CalculateColors(unsigned short c0, unsigned short c1,
+  DDSColors *c, MagickBooleanType ignoreAlpha)
+{
+  c->a[0] = c->a[1] = c->a[2] = c->a[3] = 0;
+
+  c->r[0] = (unsigned char) C565_red(c0);
+  c->g[0] = (unsigned char) C565_green(c0);
+  c->b[0] = (unsigned char) C565_blue(c0);
+
+  c->r[1] = (unsigned char) C565_red(c1);
+  c->g[1] = (unsigned char) C565_green(c1);
+  c->b[1] = (unsigned char) C565_blue(c1);
+
+  if (ignoreAlpha != MagickFalse || c0 > c1)
+    {
+      c->r[2] = (unsigned char) ((2 * c->r[0] + c->r[1]) / 3);
+      c->g[2] = (unsigned char) ((2 * c->g[0] + c->g[1]) / 3);
+      c->b[2] = (unsigned char) ((2 * c->b[0] + c->b[1]) / 3);
+
+      c->r[3] = (unsigned char) ((c->r[0] + 2 * c->r[1]) / 3);
+      c->g[3] = (unsigned char) ((c->g[0] + 2 * c->g[1]) / 3);
+      c->b[3] = (unsigned char) ((c->b[0] + 2 * c->b[1]) / 3);
+    }
+  else
+    {
+      c->r[2] = (unsigned char) ((c->r[0] + c->r[1]) / 2);
+      c->g[2] = (unsigned char) ((c->g[0] + c->g[1]) / 2);
+      c->b[2] = (unsigned char) ((c->b[0] + c->b[1]) / 2);
+
+      c->r[3] = c->g[3] = c->b[3] = 0;
+      c->a[3] = 255;
+    }
+}
+
+static size_t CompressAlpha(const size_t min, const size_t max,
+  const size_t steps, const ssize_t *alphas, unsigned char* indices)
+{
+  unsigned char
+    codes[8];
+
+  register ssize_t
+    i;
+
+  size_t
+    error,
+    index,
+    j,
+    least,
+    value;
+
+  codes[0] = (unsigned char) min;
+  codes[1] = (unsigned char) max;
+  codes[6] = 0;
+  codes[7] = 255;
+
+  for (i=1; i <  (ssize_t) steps; i++)
+    codes[i+1] = (unsigned char) (((steps-i)*min + i*max) / steps);
+
+  error = 0;
+  for (i=0; i<16; i++)
+  {
+    if (alphas[i] == -1)
+      {
+        indices[i] = 0;
+        continue;
+      }
+
+    value = alphas[i];
+    least = SIZE_MAX;
+    index = 0;
+    for (j=0; j<8; j++)
+    {
+      size_t
+        dist;
+
+      dist = value - (size_t)codes[j];
+      dist *= dist;
+
+      if (dist < least)
+        {
+          least = dist;
+          index = j;
+        }
+    }
+
+    indices[i] = (unsigned char)index;
+    error += least;
+  }
+
+  return error;
+}
+
+static void CompressClusterFit(const size_t count,
+  const DDSVector4 *points, const ssize_t *map, const DDSVector3 principle,
+  const DDSVector4 metric, DDSVector3 *start, DDSVector3* end,
+  unsigned char *indices)
+{
+  DDSVector3
+    axis;
+
+  DDSVector4
+    grid,
+    gridrcp,
+    half,
+    onethird_onethird2,
+    part0,
+    part1,
+    part2,
+    part3,
+    pointsWeights[16],
+    two,
+    twonineths,
+    twothirds_twothirds2,
+    xSumwSum;
+
+  float
+    bestError = 1e+37f;
+
+  size_t
+    bestIteration = 0,
+    besti = 0,
+    bestj = 0,
+    bestk = 0,
+    iterationIndex,
+    i,
+    j,
+    k,
+    kmin;
+
+  unsigned char
+    *o,
+    order[128],
+    unordered[16];
+
+  VectorInit(half,0.5f);
+  VectorInit(two,2.0f);
+
+  VectorInit(onethird_onethird2,1.0f/3.0f);
+  onethird_onethird2.w = 1.0f/9.0f;
+  VectorInit(twothirds_twothirds2,2.0f/3.0f);
+  twothirds_twothirds2.w = 4.0f/9.0f;
+  VectorInit(twonineths,2.0f/9.0f);
+
+  grid.x = 31.0f;
+  grid.y = 63.0f;
+  grid.z = 31.0f;
+  grid.w = 0.0f;
+
+  gridrcp.x = 1.0f/31.0f;
+  gridrcp.y = 1.0f/63.0f;
+  gridrcp.z = 1.0f/31.0f;
+  gridrcp.w = 0.0f;
+
+  xSumwSum.x = 0.0f;
+  xSumwSum.y = 0.0f;
+  xSumwSum.z = 0.0f;
+  xSumwSum.w = 0.0f;
+
+  ConstructOrdering(count,points,principle,pointsWeights,&xSumwSum,order,0);
+
+  for (iterationIndex = 0;;)
+  {
+    VectorInit(part0,0.0f);
+    for (i=0; i < count; i++)
+    {
+      VectorInit(part1,0.0f);
+      for (j=i;;)
+      {
+        if (j == 0)
+          {
+            VectorCopy44(pointsWeights[0],&part2);
+            kmin = 1;
+          }
+          else
+          {
+            VectorInit(part2,0.0f);
+            kmin = j;
+          }
+
+        for (k=kmin;;)
+        {
+          DDSVector4
+            a,
+            alpha2_sum,
+            alphax_sum,
+            alphabeta_sum,
+            b,
+            beta2_sum,
+            betax_sum,
+            e1,
+            e2,
+            factor;
+
+          float
+            error;
+
+          VectorSubtract(xSumwSum,part2,&part3);
+          VectorSubtract(part3,part1,&part3);
+          VectorSubtract(part3,part0,&part3);
+
+          VectorMultiplyAdd(part1,twothirds_twothirds2,part0,&alphax_sum);
+          VectorMultiplyAdd(part2,onethird_onethird2,alphax_sum,&alphax_sum);
+          VectorInit(alpha2_sum,alphax_sum.w);
+
+          VectorMultiplyAdd(part2,twothirds_twothirds2,part3,&betax_sum);
+          VectorMultiplyAdd(part1,onethird_onethird2,betax_sum,&betax_sum);
+          VectorInit(beta2_sum,betax_sum.w);
+
+          VectorAdd(part1,part2,&alphabeta_sum);
+          VectorInit(alphabeta_sum,alphabeta_sum.w);
+          VectorMultiply(twonineths,alphabeta_sum,&alphabeta_sum);
+
+          VectorMultiply(alpha2_sum,beta2_sum,&factor);
+          VectorNegativeMultiplySubtract(alphabeta_sum,alphabeta_sum,factor,
+            &factor);
+          VectorReciprocal(factor,&factor);
+
+          VectorMultiply(alphax_sum,beta2_sum,&a);
+          VectorNegativeMultiplySubtract(betax_sum,alphabeta_sum,a,&a);
+          VectorMultiply(a,factor,&a);
+
+          VectorMultiply(betax_sum,alpha2_sum,&b);
+          VectorNegativeMultiplySubtract(alphax_sum,alphabeta_sum,b,&b);
+          VectorMultiply(b,factor,&b);
+
+          VectorClamp(&a);
+          VectorMultiplyAdd(grid,a,half,&a);
+          VectorTruncate(&a);
+          VectorMultiply(a,gridrcp,&a);
+
+          VectorClamp(&b);
+          VectorMultiplyAdd(grid,b,half,&b);
+          VectorTruncate(&b);
+          VectorMultiply(b,gridrcp,&b);
+
+          VectorMultiply(b,b,&e1);
+          VectorMultiply(e1,beta2_sum,&e1);
+          VectorMultiply(a,a,&e2);
+          VectorMultiplyAdd(e2,alpha2_sum,e1,&e1);
+
+          VectorMultiply(a,b,&e2);
+          VectorMultiply(e2,alphabeta_sum,&e2);
+          VectorNegativeMultiplySubtract(a,alphax_sum,e2,&e2);
+          VectorNegativeMultiplySubtract(b,betax_sum,e2,&e2);
+          VectorMultiplyAdd(two,e2,e1,&e2);
+          VectorMultiply(e2,metric,&e2);
+
+          error = e2.x + e2.y + e2.z;
+
+          if (error < bestError)
+          {
+            VectorCopy43(a,start);
+            VectorCopy43(b,end);
+            bestError = error;
+            besti = i;
+            bestj = j;
+            bestk = k;
+            bestIteration = iterationIndex;
+          }
+
+          if (k == count)
+            break;
+
+          VectorAdd(pointsWeights[k],part2,&part2);
+          k++;
+        }
+
+        if (j == count)
+          break;
+
+        VectorAdd(pointsWeights[j],part1,&part1);
+        j++;
+      }
+
+      VectorAdd(pointsWeights[i],part0,&part0);
+    }
+
+    if (bestIteration != iterationIndex)
+      break;
+
+    iterationIndex++;
+    if (iterationIndex == 8)
+      break;
+
+    VectorSubtract3(*end,*start,&axis);
+    if (ConstructOrdering(count,points,axis,pointsWeights,&xSumwSum,order,
+      iterationIndex) == MagickFalse)
+      break;
+  }
+
+  o = order + (16*bestIteration);
+
+  for (i=0; i < besti; i++)
+    unordered[o[i]] = 0;
+  for (i=besti; i < bestj; i++)
+    unordered[o[i]] = 2;
+  for (i=bestj; i < bestk; i++)
+    unordered[o[i]] = 3;
+  for (i=bestk; i < count; i++)
+    unordered[o[i]] = 1;
+
+  RemapIndices(map,unordered,indices);
+}
+
+static void CompressRangeFit(const size_t count,
+  const DDSVector4* points, const ssize_t *map, const DDSVector3 principle,
+  const DDSVector4 metric, DDSVector3 *start, DDSVector3 *end,
+  unsigned char *indices)
+{
+  float
+    d,
+    bestDist,
+    max,
+    min,
+    val;
+
+  DDSVector3
+    codes[4],
+    grid,
+    gridrcp,
+    half,
+    dist;
+
+  register ssize_t
+    i;
+
+  size_t
+    bestj,
+    j;
+
+  unsigned char
+    closest[16];
+
+  VectorInit3(half,0.5f);
+
+  grid.x = 31.0f;
+  grid.y = 63.0f;
+  grid.z = 31.0f;
+
+  gridrcp.x = 1.0f/31.0f;
+  gridrcp.y = 1.0f/63.0f;
+  gridrcp.z = 1.0f/31.0f;
+
+  if (count > 0)
+    {
+      VectorCopy43(points[0],start);
+      VectorCopy43(points[0],end);
+
+      min = max = Dot(points[0],principle);
+      for (i=1; i < (ssize_t) count; i++)
+      {
+        val = Dot(points[i],principle);
+        if (val < min)
+        {
+          VectorCopy43(points[i],start);
+          min = val;
+        }
+        else if (val > max)
+        {
+          VectorCopy43(points[i],end);
+          max = val;
+        }
+      }
+    }
+
+  VectorClamp3(start);
+  VectorMultiplyAdd3(grid,*start,half,start);
+  VectorTruncate3(start);
+  VectorMultiply3(*start,gridrcp,start);
+
+  VectorClamp3(end);
+  VectorMultiplyAdd3(grid,*end,half,end);
+  VectorTruncate3(end);
+  VectorMultiply3(*end,gridrcp,end);
+
+  codes[0] = *start;
+  codes[1] = *end;
+  codes[2].x = (start->x * (2.0f/3.0f)) + (end->x * (1.0f/3.0f));
+  codes[2].y = (start->y * (2.0f/3.0f)) + (end->y * (1.0f/3.0f));
+  codes[2].z = (start->z * (2.0f/3.0f)) + (end->z * (1.0f/3.0f));
+  codes[3].x = (start->x * (1.0f/3.0f)) + (end->x * (2.0f/3.0f));
+  codes[3].y = (start->y * (1.0f/3.0f)) + (end->y * (2.0f/3.0f));
+  codes[3].z = (start->z * (1.0f/3.0f)) + (end->z * (2.0f/3.0f));
+
+  for (i=0; i < (ssize_t) count; i++)
+  {
+    bestDist = 1e+37f;
+    bestj = 0;
+    for (j=0; j < 4; j++)
+    {
+      dist.x = (points[i].x - codes[j].x) * metric.x;
+      dist.y = (points[i].y - codes[j].y) * metric.y;
+      dist.z = (points[i].z - codes[j].z) * metric.z;
+
+      d = Dot(dist,dist);
+      if (d < bestDist)
+        {
+          bestDist = d;
+          bestj = j;
+        }
+    }
+
+    closest[i] = (unsigned char) bestj;
+  }
+
+  RemapIndices(map, closest, indices);
+}
+
+static void ComputeEndPoints(const DDSSingleColourLookup *lookup[],
+  const unsigned char *color, DDSVector3 *start, DDSVector3 *end,
+  unsigned char *index)
+{
+  register ssize_t
+    i;
+
+  size_t
+    c,
+    maxError = SIZE_MAX;
+
+  for (i=0; i < 2; i++)
+  {
+    const DDSSourceBlock*
+      sources[3];
+
+      size_t
+        error = 0;
+
+    for (c=0; c < 3; c++)
+    {
+      sources[c] = &lookup[c][color[c]].sources[i];
+      error += ((size_t) sources[c]->error) * ((size_t) sources[c]->error);
+    }
+
+    if (error > maxError)
+      continue;
+
+    start->x = (float) sources[0]->start / 31.0f;
+    start->y = (float) sources[1]->start / 63.0f;
+    start->z = (float) sources[2]->start / 31.0f;
+
+    end->x = (float) sources[0]->end / 31.0f;
+    end->y = (float) sources[1]->end / 63.0f;
+    end->z = (float) sources[2]->end / 31.0f;
+
+    *index = (unsigned char) (2*i);
+    maxError = error;
+  }
+}
+
+static void ComputePrincipleComponent(const float *covariance,
+  DDSVector3 *principle)
+{
+  DDSVector4
+    row0,
+    row1,
+    row2,
+    v;
+
+  register ssize_t
+    i;
+
+  row0.x = covariance[0];
+  row0.y = covariance[1];
+  row0.z = covariance[2];
+  row0.w = 0.0f;
+
+  row1.x = covariance[1];
+  row1.y = covariance[3];
+  row1.z = covariance[4];
+  row1.w = 0.0f;
+
+  row2.x = covariance[2];
+  row2.y = covariance[4];
+  row2.z = covariance[5];
+  row2.w = 0.0f;
+
+  VectorInit(v,1.0f);
+
+  for (i=0; i < 8; i++)
+  {
+    DDSVector4
+      w;
+
+    float
+      a;
+
+    w.x = row0.x * v.x;
+    w.y = row0.y * v.x;
+    w.z = row0.z * v.x;
+    w.w = row0.w * v.x;
+
+    w.x = (row1.x * v.y) + w.x;
+    w.y = (row1.y * v.y) + w.y;
+    w.z = (row1.z * v.y) + w.z;
+    w.w = (row1.w * v.y) + w.w;
+
+    w.x = (row2.x * v.z) + w.x;
+    w.y = (row2.y * v.z) + w.y;
+    w.z = (row2.z * v.z) + w.z;
+    w.w = (row2.w * v.z) + w.w;
+
+    a = 1.0f / MaxF(w.x,MaxF(w.y,w.z));
+
+    v.x = w.x * a;
+    v.y = w.y * a;
+    v.z = w.z * a;
+    v.w = w.w * a;
+  }
+
+  VectorCopy43(v,principle);
+}
+
+static void ComputeWeightedCovariance(const size_t count,
+  const DDSVector4 *points, float *covariance)
+{
+  DDSVector3
+    centroid;
+
+  float
+    total;
+
+  size_t
+    i;
+
+  total = 0.0f;
+  VectorInit3(centroid,0.0f);
+
+  for (i=0; i < count; i++)
+  {
+    total += points[i].w;
+    centroid.x += (points[i].x * points[i].w);
+    centroid.y += (points[i].y * points[i].w);
+    centroid.z += (points[i].z * points[i].w);
+  }
+
+  if( total > 1.192092896e-07F)
+    {
+      centroid.x /= total;
+      centroid.y /= total;
+      centroid.z /= total;
+    }
+
+  for (i=0; i < 6; i++)
+    covariance[i] = 0.0f;
+
+  for (i = 0; i < count; i++)
+  {
+    DDSVector3
+      a,
+      b;
+
+    a.x = points[i].x - centroid.x;
+    a.y = points[i].y - centroid.y;
+    a.z = points[i].z - centroid.z;
+
+    b.x = points[i].w * a.x;
+    b.y = points[i].w * a.y;
+    b.z = points[i].w * a.z;
+
+    covariance[0] += a.x*b.x;
+    covariance[1] += a.x*b.y;
+    covariance[2] += a.x*b.z;
+    covariance[3] += a.y*b.y;
+    covariance[4] += a.y*b.z;
+    covariance[5] += a.z*b.z;
+  }
+}
+
+static MagickBooleanType ConstructOrdering(const size_t count,
+  const DDSVector4 *points, const DDSVector3 axis, DDSVector4 *pointsWeights,
+  DDSVector4 *xSumwSum, unsigned char *order, size_t iteration)
+{
+  float
+     dps[16],
+     f;
+
+  register ssize_t
+    i;
+
+  size_t
+    j;
+
+  unsigned char
+    c,
+    *o,
+    *p;
+
+  o = order + (16*iteration);
+
+  for (i=0; i < (ssize_t) count; i++)
+  {
+    dps[i] = Dot(points[i],axis);
+    o[i] = (unsigned char)i;
+  }
+
+  for (i=0; i < (ssize_t) count; i++)
+  {
+    for (j=i; j > 0 && dps[j] < dps[j - 1]; j--)
+    {
+      f = dps[j];
+      dps[j] = dps[j - 1];
+      dps[j - 1] = f;
+
+      c = o[j];
+      o[j] = o[j - 1];
+      o[j - 1] = c;
+    }
+  }
+
+  for (i=0; i < (ssize_t) iteration; i++)
+  {
+    MagickBooleanType
+      same;
+
+    p = order + (16*i);
+    same = MagickTrue;
+
+    for (j=0; j < count; j++)
+    {
+      if (o[j] != p[j])
+        {
+          same = MagickFalse;
+          break;
+        }
+    }
+
+    if (same != MagickFalse)
+      return MagickFalse;
+  }
+
+  xSumwSum->x = 0;
+  xSumwSum->y = 0;
+  xSumwSum->z = 0;
+  xSumwSum->w = 0;
+
+  for (i=0; i < (ssize_t) count; i++)
+  {
+    DDSVector4
+      v;
+
+    j = (size_t) o[i];
+
+    v.x = points[j].w * points[j].x;
+    v.y = points[j].w * points[j].y;
+    v.z = points[j].w * points[j].z;
+    v.w = points[j].w * 1.0f;
+
+    VectorCopy44(v,&pointsWeights[i]);
+    VectorAdd(*xSumwSum,v,xSumwSum);
+  }
+
+  return MagickTrue;
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   I s D D S                                                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  IsDDS() returns MagickTrue if the image format type, identified by the
+%  magick string, is DDS.
+%
+%  The format of the IsDDS method is:
+%
+%      MagickBooleanType IsDDS(const unsigned char *magick,const size_t length)
+%
+%  A description of each parameter follows:
+%
+%    o magick: compare image format pattern against these bytes.
+%
+%    o length: Specifies the length of the magick string.
+%
+*/
+static MagickBooleanType IsDDS(const unsigned char *magick, const size_t length)
+{
+  if (length < 4)
+    return(MagickFalse);
+  if (LocaleNCompare((char *) magick,"DDS ", 4) == 0)
+    return(MagickTrue);
+  return(MagickFalse);
+}
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e a d D D S I m a g e                                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ReadDDSImage() reads a DirectDraw Surface image file and returns it.  It
+%  allocates the memory necessary for the new Image structure and returns a
+%  pointer to the new image.
+%
+%  The format of the ReadDDSImage method is:
+%
+%      Image *ReadDDSImage(const ImageInfo *image_info,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image_info: The image info.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+static Image *ReadDDSImage(const ImageInfo *image_info,ExceptionInfo *exception)
+{
+  Image
+    *image;
+
+  MagickBooleanType
+    status,
+    cubemap = MagickFalse,
+    volume = MagickFalse;
+
+  CompressionType
+    compression;
+
+  DDSInfo
+    dds_info;
+  
+  DDSDecoder
+    *decoder;
+  
+  PixelTrait
+    alpha_trait;
+  
+  size_t
+    n,
+    num_images;
+
+  /*
+    Open image file.
+  */
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickSignature);
+  if (image_info->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
+      image_info->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  image=AcquireImage(image_info,exception);
+  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
+  if (status == MagickFalse)
+    {
+      image=DestroyImageList(image);
+      return((Image *) NULL);
+    }
+  
+  /*
+    Initialize image structure.
+  */
+  if (ReadDDSInfo(image, &dds_info) != MagickTrue) {
+    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+  }
+  
+  if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP)
+    cubemap = MagickTrue;
+  
+  if (dds_info.ddscaps2 & DDSCAPS2_VOLUME && dds_info.depth > 0)
+    volume = MagickTrue;
+  
+  (void) SeekBlob(image, 128, SEEK_SET);
+
+  /*
+    Determine pixel format
+  */
+  if (dds_info.pixelformat.flags & DDPF_RGB)
+    {
+      compression = NoCompression;
+      if (dds_info.pixelformat.flags & DDPF_ALPHAPIXELS)
+        {
+          alpha_trait = BlendPixelTrait;
+          decoder = ReadUncompressedRGBA;
+        }
+      else
+        {
+          alpha_trait = UndefinedPixelTrait;
+          decoder = ReadUncompressedRGB;
+        }
+    }
+  else if (dds_info.pixelformat.flags & DDPF_FOURCC)
+    {
+      switch (dds_info.pixelformat.fourcc)
+      {
+        case FOURCC_DXT1:
+        {
+          alpha_trait = UndefinedPixelTrait;
+          compression = DXT1Compression;
+          decoder = ReadDXT1;
+          break;
+        }
+        
+        case FOURCC_DXT3:
+        {
+          alpha_trait = BlendPixelTrait;
+          compression = DXT3Compression;
+          decoder = ReadDXT3;
+          break;
+        }
+        
+        case FOURCC_DXT5:
+        {
+          alpha_trait = BlendPixelTrait;
+          compression = DXT5Compression;
+          decoder = ReadDXT5;
+          break;
+        }
+        
+        default:
+        {
+          /* Unknown FOURCC */
+          ThrowReaderException(CorruptImageError, "ImageTypeNotSupported");
+        }
+      }
+    }
+  else
+    {
+      /* Neither compressed nor uncompressed... thus unsupported */
+      ThrowReaderException(CorruptImageError, "ImageTypeNotSupported");
+    }
+  
+  num_images = 1;
+  if (cubemap)
+    {
+      /*
+        Determine number of faces defined in the cubemap
+      */
+      num_images = 0;
+      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) num_images++;
+      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) num_images++;
+      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEY) num_images++;
+      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) num_images++;
+      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) num_images++;
+      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) num_images++;
+    }
+  
+  if (volume)
+    num_images = dds_info.depth;
+  
+  for (n = 0; n < num_images; n++)
+  {
+    if (n != 0)
+      {
+        /* Start a new image */
+        AcquireNextImage(image_info,image,exception);
+        if (GetNextImageInList(image) == (Image *) NULL)
+          return(DestroyImageList(image));
+        image=SyncNextImageInList(image);
+      }
+    
+    image->alpha_trait=alpha_trait;
+    image->compression = compression;
+    image->columns = dds_info.width;
+    image->rows = dds_info.height;
+    image->storage_class = DirectClass;
+    image->endian = LSBEndian;
+    image->depth = 8;
+    if (image_info->ping != MagickFalse)
+      {
+        (void) CloseBlob(image);
+        return(GetFirstImageInList(image));
+      }
+    
+    if ((decoder)(image, &dds_info, exception) != MagickTrue)
+      {
+        (void) CloseBlob(image);
+        return(GetFirstImageInList(image));
+      }
+  }
+  
+  if (EOFBlob(image) != MagickFalse)
+    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
+      image->filename);
+  
+  (void) CloseBlob(image);
+  return(GetFirstImageInList(image));
+}
+
+static MagickBooleanType ReadDDSInfo(Image *image, DDSInfo *dds_info)
+{
+  size_t
+    hdr_size,
+    required;
+  
+  /* Seek to start of header */
+  (void) SeekBlob(image, 4, SEEK_SET);
+  
+  /* Check header field */
+  hdr_size = ReadBlobLSBLong(image);
+  if (hdr_size != 124)
+    return MagickFalse;
+  
+  /* Fill in DDS info struct */
+  dds_info->flags = ReadBlobLSBLong(image);
+  
+  /* Check required flags */
+  required=(size_t) (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT);
+  if ((dds_info->flags & required) != required)
+    return MagickFalse;
+  
+  dds_info->height = ReadBlobLSBLong(image);
+  dds_info->width = ReadBlobLSBLong(image);
+  dds_info->pitchOrLinearSize = ReadBlobLSBLong(image);
+  dds_info->depth = ReadBlobLSBLong(image);
+  dds_info->mipmapcount = ReadBlobLSBLong(image);
+  
+  (void) SeekBlob(image, 44, SEEK_CUR);   /* reserved region of 11 DWORDs */
+  
+  /* Read pixel format structure */
+  hdr_size = ReadBlobLSBLong(image);
+  if (hdr_size != 32)
+    return MagickFalse;
+  
+  dds_info->pixelformat.flags = ReadBlobLSBLong(image);
+  dds_info->pixelformat.fourcc = ReadBlobLSBLong(image);
+  dds_info->pixelformat.rgb_bitcount = ReadBlobLSBLong(image);
+  dds_info->pixelformat.r_bitmask = ReadBlobLSBLong(image);
+  dds_info->pixelformat.g_bitmask = ReadBlobLSBLong(image);
+  dds_info->pixelformat.b_bitmask = ReadBlobLSBLong(image);
+  dds_info->pixelformat.alpha_bitmask = ReadBlobLSBLong(image);
+  
+  dds_info->ddscaps1 = ReadBlobLSBLong(image);
+  dds_info->ddscaps2 = ReadBlobLSBLong(image);
+  (void) SeekBlob(image, 12, SEEK_CUR); /* 3 reserved DWORDs */
+  
+  return MagickTrue;
+}
+
+static MagickBooleanType ReadDXT1(Image *image, DDSInfo *dds_info,
+  ExceptionInfo *exception)
+{
+  DDSColors
+    colors;
+
+  register Quantum
+    *q;
+  
+  register ssize_t
+    i,
+    x;
+  
+  size_t
+    bits;
+
+  ssize_t
+    j,
+    y;
+  
+  unsigned char
+    code;
+  
+  unsigned short
+    c0,
+    c1;
+  
+  for (y = 0; y < (ssize_t) dds_info->height; y += 4)
+  {
+    for (x = 0; x < (ssize_t) dds_info->width; x += 4)
+    {
+      /* Get 4x4 patch of pixels to write on */
+      q = QueueAuthenticPixels(image, x, y, Min(4, dds_info->width - x),
+        Min(4, dds_info->height - y),exception);
+      
+      if (q == (Quantum *) NULL)
+        return MagickFalse;
+      
+      /* Read 8 bytes of data from the image */
+      c0 = ReadBlobLSBShort(image);
+      c1 = ReadBlobLSBShort(image);
+      bits = ReadBlobLSBLong(image);
+      
+      CalculateColors(c0, c1, &colors, MagickFalse);
+      
+      /* Write the pixels */
+      for (j = 0; j < 4; j++)
+      {
+        for (i = 0; i < 4; i++)
+        {
+          if ((x + i) < (ssize_t) dds_info->width &&
+              (y + j) < (ssize_t) dds_info->height)
+            {
+              code = (unsigned char) ((bits >> ((j*4+i)*2)) & 0x3);
+              SetPixelRed(image,ScaleCharToQuantum(colors.r[code]),q);
+              SetPixelGreen(image,ScaleCharToQuantum(colors.g[code]),q);
+              SetPixelBlue(image,ScaleCharToQuantum(colors.b[code]),q);
+              SetPixelAlpha(image,ScaleCharToQuantum(colors.a[code]),q);
+              if (colors.a[code] && (image->alpha_trait != BlendPixelTrait))
+                image->alpha_trait=BlendPixelTrait;  /* Correct matte */
+              q+=GetPixelChannels(image);
+            }
+        }
+      }
+      
+      if (SyncAuthenticPixels(image,exception) == MagickFalse)
+        return MagickFalse;
+    }
+  }
+  
+  SkipDXTMipmaps(image, dds_info, 8);
+  
+  return MagickTrue;
+}
+
+static MagickBooleanType ReadDXT3(Image *image, DDSInfo *dds_info,
+  ExceptionInfo *exception)
+{
+  DDSColors
+    colors;
+  
+  register Quantum
+    *q;
+  
+  register ssize_t
+    i,
+    x;
+  
+  unsigned char
+    alpha;
+  
+  size_t
+    a0,
+    a1,
+    bits,
+    code;
+
+  ssize_t
+    j,
+    y;
+
+  unsigned short
+    c0,
+    c1;
+  
+  for (y = 0; y < (ssize_t) dds_info->height; y += 4)
+  {
+    for (x = 0; x < (ssize_t) dds_info->width; x += 4)
+    {
+      /* Get 4x4 patch of pixels to write on */
+      q = QueueAuthenticPixels(image, x, y, Min(4, dds_info->width - x),
+                         Min(4, dds_info->height - y),exception);
+      
+      if (q == (Quantum *) NULL)
+        return MagickFalse;
+      
+      /* Read alpha values (8 bytes) */
+      a0 = ReadBlobLSBLong(image);
+      a1 = ReadBlobLSBLong(image);
+      
+      /* Read 8 bytes of data from the image */
+      c0 = ReadBlobLSBShort(image);
+      c1 = ReadBlobLSBShort(image);
+      bits = ReadBlobLSBLong(image);
+      
+      CalculateColors(c0, c1, &colors, MagickTrue);
+      
+      /* Write the pixels */
+      for (j = 0; j < 4; j++)
+      {
+        for (i = 0; i < 4; i++)
+        {
+          if ((x + i) < (ssize_t) dds_info->width && (y + j) < (ssize_t) dds_info->height)
+            {
+              code = (bits >> ((4*j+i)*2)) & 0x3;
+              SetPixelRed(image,ScaleCharToQuantum(colors.r[code]),q);
+              SetPixelGreen(image,ScaleCharToQuantum(colors.g[code]),q);
+              SetPixelBlue(image,ScaleCharToQuantum(colors.b[code]),q);
+              /*
+                Extract alpha value: multiply 0..15 by 17 to get range 0..255
+              */
+              if (j < 2)
+                alpha = 17U * (unsigned char) ((a0 >> (4*(4*j+i))) & 0xf);
+              else
+                alpha = 17U * (unsigned char) ((a1 >> (4*(4*(j-2)+i))) & 0xf);
+              SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) alpha),q);
+              q+=GetPixelChannels(image);
+            }
+        }
+      }
+      
+      if (SyncAuthenticPixels(image,exception) == MagickFalse)
+        return MagickFalse;
+    }
+  }
+  
+  SkipDXTMipmaps(image, dds_info, 16);
+  
+  return MagickTrue;
+}
+
+static MagickBooleanType ReadDXT5(Image *image, DDSInfo *dds_info,
+  ExceptionInfo *exception)
+{
+  DDSColors
+    colors;
+  
+  MagickSizeType
+    alpha_bits;
+  
+  register Quantum
+    *q;
+  
+  register ssize_t
+    i,
+    x;
+
+  unsigned char
+    a0,
+    a1;
+  
+  size_t
+    alpha,
+    bits,
+    code,
+    alpha_code;
+
+  ssize_t
+    j,
+    y;
+
+  unsigned short
+    c0,
+    c1;
+  
+  for (y = 0; y < (ssize_t) dds_info->height; y += 4)
+  {
+    for (x = 0; x < (ssize_t) dds_info->width; x += 4)
+    {
+      /* Get 4x4 patch of pixels to write on */
+      q = QueueAuthenticPixels(image, x, y, Min(4, dds_info->width - x),
+                         Min(4, dds_info->height - y),exception);
+      
+      if (q == (Quantum *) NULL)
+        return MagickFalse;
+      
+      /* Read alpha values (8 bytes) */
+      a0 = (unsigned char) ReadBlobByte(image);
+      a1 = (unsigned char) ReadBlobByte(image);
+      
+      alpha_bits = (MagickSizeType)ReadBlobLSBLong(image);
+      alpha_bits = alpha_bits | ((MagickSizeType)ReadBlobLSBShort(image) << 32);
+      
+      /* Read 8 bytes of data from the image */
+      c0 = ReadBlobLSBShort(image);
+      c1 = ReadBlobLSBShort(image);
+      bits = ReadBlobLSBLong(image);
+      
+      CalculateColors(c0, c1, &colors, MagickTrue);
+      
+      /* Write the pixels */
+      for (j = 0; j < 4; j++)
+      {
+        for (i = 0; i < 4; i++)
+        {
+          if ((x + i) < (ssize_t) dds_info->width &&
+              (y + j) < (ssize_t) dds_info->height)
+            {
+              code = (bits >> ((4*j+i)*2)) & 0x3;
+              SetPixelRed(image,ScaleCharToQuantum(colors.r[code]),q);
+              SetPixelGreen(image,ScaleCharToQuantum(colors.g[code]),q);
+              SetPixelBlue(image,ScaleCharToQuantum(colors.b[code]),q);
+              /* Extract alpha value */
+              alpha_code = (size_t) (alpha_bits >> (3*(4*j+i))) & 0x7;
+              if (alpha_code == 0)
+                alpha = a0;
+              else if (alpha_code == 1)
+                alpha = a1;
+              else if (a0 > a1)
+                alpha = ((8-alpha_code) * a0 + (alpha_code-1) * a1) / 7;
+              else if (alpha_code == 6)
+                alpha = 0;
+              else if (alpha_code == 7)
+                alpha = 255;
+              else
+                alpha = (((6-alpha_code) * a0 + (alpha_code-1) * a1) / 5);
+              SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) alpha),q);
+              q+=GetPixelChannels(image);
+            }
+        }
+      }
+      
+      if (SyncAuthenticPixels(image,exception) == MagickFalse)
+        return MagickFalse;
+    }
+  }
+  
+  SkipDXTMipmaps(image, dds_info, 16);
+  
+  return MagickTrue;
+}
+
+static MagickBooleanType ReadUncompressedRGB(Image *image, DDSInfo *dds_info,
+  ExceptionInfo *exception)
+{
+  register Quantum
+    *q;
+
+  ssize_t
+    x, y;
+
+  unsigned short
+    color;
+
+  if (dds_info->pixelformat.rgb_bitcount == 16 && !IsBitMask(
+    dds_info->pixelformat,0xf800,0x07e0,0x001f,0x0000))
+    ThrowBinaryException(CorruptImageError,"ImageTypeNotSupported",
+      image->filename);
+
+  for (y = 0; y < (ssize_t) dds_info->height; y++)
+  {
+    q = QueueAuthenticPixels(image, 0, y, dds_info->width, 1,exception);
+    
+    if (q == (Quantum *) NULL)
+      return MagickFalse;
+    
+    for (x = 0; x < (ssize_t) dds_info->width; x++)
+    {
+
+      if (dds_info->pixelformat.rgb_bitcount == 16)
+        {
+           color=ReadBlobShort(image);
+           SetPixelRed(image,ScaleCharToQuantum((unsigned char)
+             (((color >> 11)/31.0)*255)),q);
+           SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
+             ((((unsigned short)(color << 5) >> 10)/63.0)*255)),q);
+           SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
+             ((((unsigned short)(color << 11) >> 11)/31.0)*255)),q);
+        }
+      else
+        {
+          SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+          SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+          SetPixelRed(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+          if (dds_info->pixelformat.rgb_bitcount == 32)
+            (void) ReadBlobByte(image);
+        }
+      q+=GetPixelChannels(image);
+    }
+    
+    if (SyncAuthenticPixels(image,exception) == MagickFalse)
+      return MagickFalse;
+  }
+  
+  SkipRGBMipmaps(image, dds_info, 3);
+  
+  return MagickTrue;
+}
+
+static MagickBooleanType ReadUncompressedRGBA(Image *image, DDSInfo *dds_info,
+  ExceptionInfo *exception)
+{
+  register Quantum
+    *q;
+
+  ssize_t
+    alphaBits,
+    x,
+    y;
+
+  unsigned short
+    color;
+
+  alphaBits=0;
+  if (dds_info->pixelformat.rgb_bitcount == 16)
+    {
+      if (IsBitMask(dds_info->pixelformat,0x7c00,0x03e0,0x001f,0x8000))
+        alphaBits=1;
+      else if (IsBitMask(dds_info->pixelformat,0x0f00,0x00f0,0x000f,0xf000))
+        alphaBits=4;
+      else
+        ThrowBinaryException(CorruptImageError,"ImageTypeNotSupported",
+          image->filename);
+    }
+
+  for (y = 0; y < (ssize_t) dds_info->height; y++)
+  {
+    q = QueueAuthenticPixels(image, 0, y, dds_info->width, 1,exception);
+    
+    if (q == (Quantum *) NULL)
+      return MagickFalse;
+    
+    for (x = 0; x < (ssize_t) dds_info->width; x++)
+    {
+      if (dds_info->pixelformat.rgb_bitcount == 16)
+        {
+           color=ReadBlobShort(image);
+           if (alphaBits == 1)
+             {
+               SetPixelAlpha(image,(color & (1 << 15)) ? QuantumRange : 0,q);
+               SetPixelRed(image,ScaleCharToQuantum((unsigned char)
+                 ((((unsigned short)(color << 1) >> 11)/31.0)*255)),q);
+               SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
+                 ((((unsigned short)(color << 6) >> 11)/31.0)*255)),q);
+               SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
+                 ((((unsigned short)(color << 11) >> 11)/31.0)*255)),q);
+             }
+          else
+            {
+               SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
+                 (((color >> 12)/15.0)*255)),q);
+               SetPixelRed(image,ScaleCharToQuantum((unsigned char)
+                 ((((unsigned short)(color << 4) >> 12)/15.0)*255)),q);
+               SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
+                 ((((unsigned short)(color << 8) >> 12)/15.0)*255)),q);
+               SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
+                 ((((unsigned short)(color << 12) >> 12)/15.0)*255)),q);
+            }
+        }
+      else
+        {
+          SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+          SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+          SetPixelRed(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+          SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
+            ReadBlobByte(image)),q);
+        }
+      q+=GetPixelChannels(image);
+    }
+    
+    if (SyncAuthenticPixels(image,exception) == MagickFalse)
+      return MagickFalse;
+  }
+  
+  SkipRGBMipmaps(image, dds_info, 4);
+  
+  return MagickTrue;
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e g i s t e r D D S I m a g e                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  RegisterDDSImage() adds attributes for the DDS image format to
+%  the list of supported formats.  The attributes include the image format
+%  tag, a method to read and/or write the format, whether the format
+%  supports the saving of more than one frame to the same file or blob,
+%  whether the format supports native in-memory I/O, and a brief
+%  description of the format.
+%
+%  The format of the RegisterDDSImage method is:
+%
+%      RegisterDDSImage(void)
+%
+*/
+ModuleExport size_t RegisterDDSImage(void)
+{
+  MagickInfo
+    *entry;
+
+  entry = SetMagickInfo("DDS");
+  entry->decoder = (DecodeImageHandler *) ReadDDSImage;
+  entry->encoder = (EncodeImageHandler *) WriteDDSImage;
+  entry->magick = (IsImageFormatHandler *) IsDDS;
+  entry->seekable_stream=MagickTrue;
+  entry->description = ConstantString("Microsoft DirectDraw Surface");
+  entry->module = ConstantString("DDS");
+  (void) RegisterMagickInfo(entry);
+  entry = SetMagickInfo("DXT1");
+  entry->decoder = (DecodeImageHandler *) ReadDDSImage;
+  entry->encoder = (EncodeImageHandler *) WriteDDSImage;
+  entry->magick = (IsImageFormatHandler *) IsDDS;
+  entry->seekable_stream=MagickTrue;
+  entry->description = ConstantString("Microsoft DirectDraw Surface");
+  entry->module = ConstantString("DDS");
+  (void) RegisterMagickInfo(entry);
+  entry = SetMagickInfo("DXT5");
+  entry->decoder = (DecodeImageHandler *) ReadDDSImage;
+  entry->encoder = (EncodeImageHandler *) WriteDDSImage;
+  entry->magick = (IsImageFormatHandler *) IsDDS;
+  entry->seekable_stream=MagickTrue;
+  entry->description = ConstantString("Microsoft DirectDraw Surface");
+  entry->module = ConstantString("DDS");
+  (void) RegisterMagickInfo(entry);
+  return(MagickImageCoderSignature);
+}
+
+static void RemapIndices(const ssize_t *map, const unsigned char *source,
+  unsigned char *target)
+{
+  register ssize_t
+    i;
+
+  for (i = 0; i < 16; i++)
+  {
+    if (map[i] == -1)
+      target[i] = 3;
+    else
+      target[i] = source[map[i]];
+  }
+}
+
+/*
+  Skip the mipmap images for compressed (DXTn) dds files
+*/
+static void SkipDXTMipmaps(Image *image, DDSInfo *dds_info, int texel_size)
+{
+  MagickOffsetType
+    offset;
+
+  register ssize_t
+    i;
+
+  size_t
+    h,
+    w;
+  
+  /*
+    Only skip mipmaps for textures and cube maps
+  */
+  if (dds_info->ddscaps1 & DDSCAPS_MIPMAP
+      && (dds_info->ddscaps1 & DDSCAPS_TEXTURE
+          || dds_info->ddscaps2 & DDSCAPS2_CUBEMAP))
+    {
+      w = DIV2(dds_info->width);
+      h = DIV2(dds_info->height);
+      
+      /*
+        Mipmapcount includes the main image, so start from one
+      */
+      for (i = 1; (i < (ssize_t) dds_info->mipmapcount) && w && h; i++)
+      {
+        offset = (MagickOffsetType) ((w + 3) / 4) * ((h + 3) / 4) * texel_size;
+        (void) SeekBlob(image, offset, SEEK_CUR);
+        
+        w = DIV2(w);
+        h = DIV2(h);
+      }
+    }
+}
+
+/*
+  Skip the mipmap images for uncompressed (RGB or RGBA) dds files
+*/
+static void SkipRGBMipmaps(Image *image, DDSInfo *dds_info, int pixel_size)
+{
+  MagickOffsetType
+    offset;
+  
+  register ssize_t
+    i;
+
+  size_t
+    h,
+    w;
+
+  /*
+    Only skip mipmaps for textures and cube maps
+  */
+  if (dds_info->ddscaps1 & DDSCAPS_MIPMAP
+      && (dds_info->ddscaps1 & DDSCAPS_TEXTURE
+          || dds_info->ddscaps2 & DDSCAPS2_CUBEMAP))
+    {
+      w = DIV2(dds_info->width);
+      h = DIV2(dds_info->height);
+      
+      /*
+        Mipmapcount includes the main image, so start from one
+      */
+      for (i=1; (i < (ssize_t) dds_info->mipmapcount) && w && h; i++)
+      {
+        offset = (MagickOffsetType) w * h * pixel_size;
+        (void) SeekBlob(image, offset, SEEK_CUR);
+        
+        w = DIV2(w);
+        h = DIV2(h);
+      }
+    }
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   U n r e g i s t e r D D S I m a g e                                       %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  UnregisterDDSImage() removes format registrations made by the
+%  DDS module from the list of supported formats.
+%
+%  The format of the UnregisterDDSImage method is:
+%
+%      UnregisterDDSImage(void)
+%
+*/
+ModuleExport void UnregisterDDSImage(void)
+{
+  (void) UnregisterMagickInfo("DDS");
+  (void) UnregisterMagickInfo("DXT1");
+  (void) UnregisterMagickInfo("DXT5");
+}
+
+static void WriteAlphas(Image *image, const ssize_t *alphas, size_t min5,
+  size_t max5, size_t min7, size_t max7)
+{
+  register ssize_t
+    i;
+
+  size_t
+    err5,
+    err7,
+    j;
+
+  unsigned char
+    indices5[16],
+    indices7[16];
+
+  FixRange(min5,max5,5);
+  err5 = CompressAlpha(min5,max5,5,alphas,indices5);
+
+  FixRange(min7,max7,7);
+  err7 = CompressAlpha(min7,max7,7,alphas,indices7);
+
+  if (err7 < err5)
+  {
+    for (i=0; i < 16; i++)
+    {
+      unsigned char
+        index;
+
+      index = indices7[i];
+      if( index == 0 )
+        indices5[i] = 1;
+      else if (index == 1)
+        indices5[i] = 0;
+      else
+        indices5[i] = 9 - index;
+    }
+
+    min5 = max7;
+    max5 = min7;
+  }
+  
+  (void) WriteBlobByte(image,(unsigned char) min5);
+  (void) WriteBlobByte(image,(unsigned char) max5);
+  
+  for(i=0; i < 2; i++)
+  {
+    size_t
+      value = 0;
+
+    for (j=0; j < 8; j++)
+    {
+      size_t index = (size_t) indices5[j + i*8];
+      value |= ( index << 3*j );
+    }
+
+    for (j=0; j < 3; j++)
+    {
+      size_t byte = (value >> 8*j) & 0xff;
+      (void) WriteBlobByte(image,(unsigned char) byte);
+    }
+  }
+}
+
+static void WriteCompressed(Image *image, const size_t count,
+  DDSVector4 *points, const ssize_t *map, const MagickBooleanType clusterFit)
+{
+  float
+    covariance[16];
+
+  DDSVector3
+    end,
+    principle,
+    start;
+
+  DDSVector4
+    metric;
+
+  unsigned char
+    indices[16];
+
+  VectorInit(metric,1.0f);
+  VectorInit3(start,0.0f);
+  VectorInit3(end,0.0f);
+
+  ComputeWeightedCovariance(count,points,covariance);
+  ComputePrincipleComponent(covariance,&principle);
+
+  if (clusterFit == MagickFalse || count == 0)
+    CompressRangeFit(count,points,map,principle,metric,&start,&end,indices);
+  else
+    CompressClusterFit(count,points,map,principle,metric,&start,&end,indices);
+
+  WriteIndices(image,start,end,indices);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   W r i t e D D S I m a g e                                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  WriteDDSImage() writes a DirectDraw Surface image file in the DXT5 format.
+%
+%  The format of the WriteBMPImage method is:
+%
+%     MagickBooleanType WriteDDSImage(const ImageInfo *image_info,Image *image)
+%
+%  A description of each parameter follows.
+%
+%    o image_info: the image info.
+%
+%    o image:  The image.
+%
+*/
+static MagickBooleanType WriteDDSImage(const ImageInfo *image_info,
+  Image *image, ExceptionInfo *exception)
+{
+  const char
+    *option;
+
+  size_t
+    compression,
+    columns,
+    maxMipmaps,
+    mipmaps,
+    pixelFormat,
+    rows;
+
+  MagickBooleanType
+    clusterFit,
+    status,
+    weightByAlpha;
+
+  assert(image_info != (const ImageInfo *) NULL);
+  assert(image_info->signature == MagickSignature);
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
+  if (status == MagickFalse)
+    return(status);
+  (void) TransformImageColorspace(image,sRGBColorspace,exception);
+  pixelFormat=DDPF_FOURCC;
+  compression=FOURCC_DXT5;
+
+  if (image->alpha_trait != BlendPixelTrait)
+    compression=FOURCC_DXT1;
+
+  if (LocaleCompare(image_info->magick,"dxt1") == 0)
+    compression=FOURCC_DXT1;
+
+  option=GetImageOption(image_info,"dds:compression");
+  if (option != (char *) NULL)
+    {
+       if (LocaleCompare(option,"dxt1") == 0)
+         compression=FOURCC_DXT1;
+       if (LocaleCompare(option,"none") == 0)
+         pixelFormat=DDPF_RGB;
+    }
+
+  clusterFit=MagickFalse;
+  weightByAlpha=MagickFalse;
+
+  if (pixelFormat == DDPF_FOURCC)
+    {
+      option=GetImageOption(image_info,"dds:cluster-fit");
+      if (option != (char *) NULL && LocaleCompare(option,"true") == 0)
+        {
+          clusterFit=MagickTrue;
+          if (compression != FOURCC_DXT1)
+            {
+              option=GetImageOption(image_info,"dds:weight-by-alpha");
+              if (option != (char *) NULL && LocaleCompare(option,"true") == 0)
+                weightByAlpha=MagickTrue;
+            }
+        }
+    }
+
+  maxMipmaps=SIZE_MAX;
+  mipmaps=0;
+  if ((image->columns & (image->columns - 1)) == 0 &&
+      (image->rows & (image->rows - 1)) == 0)
+    {
+      option=GetImageOption(image_info,"dds:mipmaps");
+      if (option != (char *) NULL)
+        maxMipmaps=StringToUnsignedLong(option);
+
+      if (maxMipmaps != 0)
+        {
+          columns=image->columns;
+          rows=image->rows;
+          while (columns != 1 && rows != 1 && mipmaps != maxMipmaps)
+          {
+            columns=DIV2(columns);
+            rows=DIV2(rows);
+            mipmaps++;
+          }
+        }
+    }
+
+  WriteDDSInfo(image,pixelFormat,compression,mipmaps);
+
+  WriteImageData(image,pixelFormat,compression,clusterFit,weightByAlpha,
+    exception);
+
+  if (mipmaps > 0 && WriteMipmaps(image,pixelFormat,compression,mipmaps,
+        clusterFit,weightByAlpha,exception) == MagickFalse)
+    return(MagickFalse);
+
+  (void) CloseBlob(image);
+  return(MagickTrue);
+}
+
+static void WriteDDSInfo(Image *image, const size_t pixelFormat,
+  const size_t compression, const size_t mipmaps)
+{
+  char
+    software[MaxTextExtent];
+
+  register ssize_t
+    i;
+
+  unsigned int
+    format,
+    caps,
+    flags;
+
+  flags=(unsigned int) (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT |
+    DDSD_PIXELFORMAT | DDSD_LINEARSIZE);
+  caps=(unsigned int) DDSCAPS_TEXTURE;
+  format=(unsigned int) pixelFormat;
+
+  if (mipmaps > 0)
+    {
+      flags=flags | (unsigned int) DDSD_MIPMAPCOUNT;
+      caps=caps | (unsigned int) (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX);
+    }
+
+  if (format != DDPF_FOURCC && image->alpha_trait == BlendPixelTrait)
+    format=format | DDPF_ALPHAPIXELS;
+
+  (void) WriteBlob(image,4,(unsigned char *) "DDS ");
+  (void) WriteBlobLSBLong(image,124);
+  (void) WriteBlobLSBLong(image,flags);
+  (void) WriteBlobLSBLong(image,image->rows);
+  (void) WriteBlobLSBLong(image,image->columns);
+
+  if (compression == FOURCC_DXT1)
+    (void) WriteBlobLSBLong(image,
+             (unsigned int) (Max(1,(image->columns+3)/4) * 8));
+  else
+    (void) WriteBlobLSBLong(image,
+             (unsigned int) (Max(1,(image->columns+3)/4) * 16));
+
+  (void) WriteBlobLSBLong(image,0x00);
+  (void) WriteBlobLSBLong(image,(unsigned int) mipmaps+1);
+  (void) ResetMagickMemory(software,0,sizeof(software));
+  (void) strcpy(software,"IMAGEMAGICK");
+  (void) WriteBlob(image,44,(unsigned char *) software);
+
+  (void) WriteBlobLSBLong(image,32);
+  (void) WriteBlobLSBLong(image,format);
+
+  if (pixelFormat == DDPF_FOURCC)
+    {
+      (void) WriteBlobLSBLong(image,(unsigned int) compression);
+      for(i=0;i < 5;i++) // bitcount / masks
+        (void) WriteBlobLSBLong(image,0x00);
+    }
+  else
+    {
+      (void) WriteBlobLSBLong(image,0x00);
+      if (image->alpha_trait == BlendPixelTrait)
+        {
+          (void) WriteBlobLSBLong(image,32);
+          (void) WriteBlobLSBLong(image,0xff0000);
+          (void) WriteBlobLSBLong(image,0xff00);
+          (void) WriteBlobLSBLong(image,0xff);
+          (void) WriteBlobLSBLong(image,0xff000000);
+        }
+      else
+        {
+          (void) WriteBlobLSBLong(image,24);
+          (void) WriteBlobLSBLong(image,0xff);
+          (void) WriteBlobLSBLong(image,0x00);
+          (void) WriteBlobLSBLong(image,0x00);
+          (void) WriteBlobLSBLong(image,0x00);
+        }
+    }
+  
+  (void) WriteBlobLSBLong(image,caps);
+  for(i=0;i < 4;i++) // ddscaps2 + reserved region
+    (void) WriteBlobLSBLong(image,0x00);
+}
+
+static void WriteFourCC(Image *image, const size_t compression,
+  const MagickBooleanType clusterFit, const MagickBooleanType weightByAlpha,
+  ExceptionInfo *exception)
+{
+  register ssize_t
+    x;
+
+  ssize_t
+    i,
+    y,
+    bx,
+    by;
+
+  register const Quantum
+    *p;
+
+  for (y=0; y < (ssize_t) image->rows; y+=4)
+  {
+    for (x=0; x < (ssize_t) image->columns; x+=4)
+    {
+      MagickBooleanType
+        match;
+
+      DDSVector4
+        point,
+        points[16];
+
+      size_t
+        count = 0,
+        max5 = 0,
+        max7 = 0,
+        min5 = 255,
+        min7 = 255,
+        columns = 4,
+        rows = 4;
+
+      ssize_t
+        alphas[16],
+        map[16];
+
+      unsigned char
+        alpha;
+
+      if (x + columns >= image->columns)
+        columns = image->columns - x;
+
+      if (y + rows >= image->rows)
+        rows = image->rows - y;
+
+      p=GetVirtualPixels(image,x,y,columns,rows,exception);
+      if (p == (const Quantum *) NULL)
+        break;
+
+      for (i=0; i<16; i++)
+      {
+        map[i] = -1;
+        alphas[i] = -1;
+      }
+
+      for (by=0; by <  (ssize_t) rows; by++)
+      {
+        for (bx=0; bx <  (ssize_t) columns; bx++)
+        {
+          if (compression == FOURCC_DXT5)
+            alpha = ScaleQuantumToChar(GetPixelAlpha(image,p));
+          else
+            alpha = 255;
+
+          alphas[4*by + bx] = (size_t)alpha;
+
+          point.x = (float)ScaleQuantumToChar(GetPixelRed(image,p)) / 255.0f;
+          point.y = (float)ScaleQuantumToChar(GetPixelGreen(image,p)) / 255.0f;
+          point.z = (float)ScaleQuantumToChar(GetPixelBlue(image,p)) / 255.0f;
+          point.w = weightByAlpha ? (float)(alpha + 1) / 256.0f : 1.0f;
+          p+=GetPixelChannels(image);
+
+          match = MagickFalse;
+          for (i=0; i <  (ssize_t) count; i++)
+          {
+            if ((points[i].x == point.x) &&
+                (points[i].y == point.y) &&
+                (points[i].z == point.z) &&
+                (alpha       >= 128 || compression == FOURCC_DXT5))
+              {
+                points[i].w += point.w;
+                map[4*by + bx] = i;
+                match = MagickTrue;
+                break;
+              }
+            }
+
+            if (match != MagickFalse)
+              continue;
+
+            points[count].x = point.x;
+            points[count].y = point.y;
+            points[count].z = point.z;
+            points[count].w = point.w;
+            map[4*by + bx] = count;
+            count++;
+
+            if (compression == FOURCC_DXT5)
+              {
+                if (alpha < min7)
+                  min7 = alpha;
+                if (alpha > max7)
+                  max7 = alpha;
+                if (alpha != 0 && alpha < min5)
+                  min5 = alpha;
+                if (alpha != 255 && alpha > max5)
+                  max5 = alpha;
+              }
+          }
+        }
+
+      for (i=0; i <  (ssize_t) count; i++)
+        points[i].w = sqrt(points[i].w);
+
+      if (compression == FOURCC_DXT5)
+        WriteAlphas(image,alphas,min5,max5,min7,max7);
+
+      if (count == 1)
+        WriteSingleColorFit(image,points,map);
+      else
+        WriteCompressed(image,count,points,map,clusterFit);
+    }
+  }
+}
+
+static void WriteImageData(Image *image, const size_t pixelFormat,
+  const size_t compression,const MagickBooleanType clusterFit,
+  const MagickBooleanType weightByAlpha, ExceptionInfo *exception)
+{
+  if (pixelFormat == DDPF_FOURCC)
+    WriteFourCC(image,compression,clusterFit,weightByAlpha,exception);
+  else
+    WriteUncompressed(image,exception);
+}
+
+static inline size_t ClampToLimit(const float value, const size_t limit)
+{
+  size_t
+    result = (int) (value + 0.5f);
+
+  if (result < 0.0f)
+    return(0);
+  if (result > limit)
+    return(limit);
+  return result;
+}
+
+static inline size_t ColorTo565(const DDSVector3 point)
+{
+  size_t r = ClampToLimit(31.0f*point.x,31);
+  size_t g = ClampToLimit(63.0f*point.y,63);
+  size_t b = ClampToLimit(31.0f*point.z,31);
+
+  return (r << 11) | (g << 5) | b;
+}
+
+static void WriteIndices(Image *image, const DDSVector3 start,
+  const DDSVector3 end, unsigned char *indices)
+{
+  register ssize_t
+    i;
+
+  size_t
+    a,
+    b;
+
+  unsigned char
+    remapped[16];
+
+  const unsigned char
+    *ind;
+
+  a = ColorTo565(start);
+  b = ColorTo565(end);
+
+  for (i=0; i<16; i++)
+  {
+    if( a < b )
+      remapped[i] = (indices[i] ^ 0x1) & 0x3;
+    else if( a == b )
+      remapped[i] = 0;
+    else
+      remapped[i] = indices[i];
+  }
+
+  if( a < b )
+    Swap(a,b);
+
+  (void) WriteBlobByte(image,(unsigned char) (a & 0xff));
+  (void) WriteBlobByte(image,(unsigned char) (a >> 8));
+  (void) WriteBlobByte(image,(unsigned char) (b & 0xff));
+  (void) WriteBlobByte(image,(unsigned char) (b >> 8));
+
+  for (i=0; i<4; i++)
+  {
+     ind = remapped + 4*i;
+     (void) WriteBlobByte(image,ind[0] | (ind[1] << 2) | (ind[2] << 4) |
+       (ind[3] << 6));
+  }
+}
+
+static MagickBooleanType WriteMipmaps(Image *image, const size_t pixelFormat,
+  const size_t compression, const size_t mipmaps,
+  const MagickBooleanType clusterFit, const MagickBooleanType weightByAlpha,
+  ExceptionInfo *exception)
+{
+  Image*
+    resize_image;
+
+  register ssize_t
+    i;
+
+  size_t
+    columns,
+    rows;
+
+  columns = image->columns;
+  rows = image->rows;
+
+  for (i=0; i< (ssize_t) mipmaps; i++)
+  {
+    resize_image = ResizeImage(image,columns/2,rows/2,TriangleFilter,
+      exception);
+
+    if (resize_image == (Image *) NULL)
+      return(MagickFalse);
+
+    DestroyBlob(resize_image);
+    resize_image->blob=ReferenceBlob(image->blob);
+
+    WriteImageData(resize_image,pixelFormat,compression,weightByAlpha,
+      clusterFit,exception);
+
+    resize_image=DestroyImage(resize_image);
+
+    columns = DIV2(columns);
+    rows = DIV2(rows);
+  }
+
+  return(MagickTrue);
+}
+
+static void WriteSingleColorFit(Image *image, const DDSVector4 *points,
+  const ssize_t *map)
+{
+  DDSVector3
+    start,
+    end;
+
+  register ssize_t
+    i;
+
+  unsigned char
+    color[3],
+    index,
+    indexes[16],
+    indices[16];
+
+  color[0] = (unsigned char) ClampToLimit(255.0f*points->x,255);
+  color[1] = (unsigned char) ClampToLimit(255.0f*points->y,255);
+  color[2] = (unsigned char) ClampToLimit(255.0f*points->z,255);
+
+  index=0;
+  ComputeEndPoints(DDS_LOOKUP,color,&start,&end,&index);
+
+  for (i=0; i< 16; i++)
+    indexes[i]=index;
+  RemapIndices(map,indexes,indices);
+  WriteIndices(image,start,end,indices);
+}
+
+static void WriteUncompressed(Image *image, ExceptionInfo *exception)
+{
+  register const Quantum
+    *p;
+
+  register ssize_t
+    x;
+
+  ssize_t
+    y;
+
+  for (y=0; y < (ssize_t) image->rows; y++)
+  {
+    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+    if (p == (const Quantum *) NULL)
+      break;
+
+    for (x=0; x < (ssize_t) image->columns; x++)
+    {
+      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelBlue(image,p)));
+      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelGreen(image,p)));
+      (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelRed(image,p)));
+      if (image->alpha_trait == BlendPixelTrait)
+        (void) WriteBlobByte(image,ScaleQuantumToChar(GetPixelAlpha(image,p)));
+      p+=GetPixelChannels(image);
+    }
+  }
+}