diff -Naur ImageMagick-6.3.9.orig/coders/Makefile.am ImageMagick-6.3.9/coders/Makefile.am --- ImageMagick-6.3.9.orig/coders/Makefile.am 2008-02-22 04:24:31.000000000 +0100 +++ ImageMagick-6.3.9/coders/Makefile.am 2008-02-25 22:07:53.000000000 +0100 @@ -79,6 +79,7 @@ coders/cmyk.c \ coders/cut.c \ coders/dcm.c \ + coders/dds.c \ coders/dib.c \ coders/dng.c \ coders/dot.c \ @@ -184,6 +185,7 @@ coders/cmyk.la \ coders/cut.la \ coders/dcm.la \ + coders/dds.la \ coders/dib.la \ coders/dng.la \ coders/dot.la \ @@ -351,6 +353,12 @@ coders_dcm_la_LDFLAGS = $(MODULECOMMONFLAGS) coders_dcm_la_LIBADD = $(LIBMAGICK) +# DDS coder module +coders_dds_la_SOURCES = coders/dds.c +coders_dds_la_CPPFLAGS = $(MODULE_EXTRA_CPPFLAGS) +coders_dds_la_LDFLAGS = $(MODULECOMMONFLAGS) +coders_dds_la_LIBADD = $(LIBMAGICK) + # DIB coder module coders_dib_la_SOURCES = coders/dib.c coders_dib_la_CPPFLAGS = $(MODULE_EXTRA_CPPFLAGS) diff -Naur ImageMagick-6.3.9.orig/coders/dds.c ImageMagick-6.3.9/coders/dds.c --- ImageMagick-6.3.9.orig/coders/dds.c 1970-01-01 01:00:00.000000000 +0100 +++ ImageMagick-6.3.9/coders/dds.c 2008-03-05 19:20:40.000000000 +0100 @@ -0,0 +1,968 @@ +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% DDDD DDDD SSSSS % +% D D D D SS % +% D D D D SSS % +% D D D D SS % +% DDDD DDDD SSSSS % +% % +% % +% Read Microsoft Direct Draw Surface Image Format. % +% % +% Software Design % +% Bianca van Schaik % +% March 2008 % +% % +% % +% Copyright 1999-2008 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. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% +*/ + +/* + Include declarations. +*/ +#include "magick/studio.h" +#include "magick/blob.h" +#include "magick/blob-private.h" +//#include "magick/color-private.h" +#include "magick/colorspace.h" +#include "magick/exception.h" +#include "magick/exception-private.h" +#include "magick/image.h" +#include "magick/image-private.h" +#include "magick/list.h" +#include "magick/log.h" +#include "magick/magick.h" +#include "magick/memory_.h" +#include "magick/monitor.h" +#include "magick/profile.h" +#include "magick/quantum-private.h" +#include "magick/static.h" +#include "magick/string_.h" +#include "magick/module.h" +#include "magick/transform.h" + +#include "magick/studio.h" +#include "magick/blob.h" +#include "magick/blob-private.h" +#include "magick/colorspace.h" +#include "magick/exception.h" +#include "magick/exception-private.h" +#include "magick/compress.h" +#include "magick/image.h" +#include "magick/image-private.h" +#include "magick/list.h" +#include "magick/magick.h" +#include "magick/memory_.h" +#include "magick/monitor.h" +#include "magick/quantum.h" +#include "magick/static.h" +#include "magick/string_.h" + +/* + 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 + +/* + Structure declarations. +*/ +typedef struct _DDSPixelFormat +{ + unsigned long + flags, + fourcc, + rgb_bitcount, + r_bitmask, + g_bitmask, + b_bitmask, + alpha_bitmask; +} DDSPixelFormat; + +typedef struct _DDSInfo +{ + unsigned long + 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 MagickBooleanType + DDSDecoder(Image *,DDSInfo *); + +/* + 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) + +/* + Forward declarations +*/ +static MagickBooleanType + ReadDDSInfo(Image *image, DDSInfo *dds_info); + +static void + CalculateColors(unsigned short c0, unsigned short c1, + DDSColors *c, MagickBooleanType ignoreAlpha); + +static MagickBooleanType + ReadDXT1(Image *image, DDSInfo *dds_info); + +static MagickBooleanType + ReadDXT3(Image *image, DDSInfo *dds_info); + +static MagickBooleanType + ReadDXT5(Image *image, DDSInfo *dds_info); + +static MagickBooleanType + ReadUncompressedRGB(Image *image, DDSInfo *dds_info); + +static MagickBooleanType + ReadUncompressedRGBA(Image *image, DDSInfo *dds_info); + +static void + SkipDXTMipmaps(Image *image, DDSInfo *dds_info, int texel_size); + +static void + SkipRGBMipmaps(Image *image, DDSInfo *dds_info, int pixel_size); + +static inline unsigned long Min(unsigned long one, unsigned long two) +{ + if (one < two) + return one; + return two; +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% 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, + matte; + + CompressionType + compression; + + DDSInfo + dds_info; + + DDSDecoder + *decoder; + + unsigned long + 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=AllocateImage(image_info); + 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; + + SeekBlob(image, 128, SEEK_SET); + + /* + Determine pixel format + */ + if (dds_info.pixelformat.flags & DDPF_RGB) + { + compression = NoCompression; + if (dds_info.pixelformat.flags & DDPF_ALPHAPIXELS) + { + matte = MagickTrue; + decoder = ReadUncompressedRGBA; + } + else + { + matte = MagickTrue; + decoder = ReadUncompressedRGB; + } + } + else if (dds_info.pixelformat.flags & DDPF_FOURCC) + { + switch (dds_info.pixelformat.fourcc) + { + case FOURCC_DXT1: + { + matte = MagickFalse; + compression = DXT1Compression; + decoder = ReadDXT1; + break; + } + + case FOURCC_DXT3: + { + matte = MagickTrue; + compression = DXT3Compression; + decoder = ReadDXT3; + break; + } + + case FOURCC_DXT5: + { + matte = MagickTrue; + 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 */ + AllocateNextImage(image_info,image); + if (GetNextImageInList(image) == (Image *) NULL) + { + image = DestroyImageList(image); + return((Image *) NULL); + } + image=SyncNextImageInList(image); + } + + image->matte = matte; + 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) + { + CloseBlob(image); + return(GetFirstImageInList(image)); + } + + if ((decoder)(image, &dds_info) != MagickTrue) + { + CloseBlob(image); + return(GetFirstImageInList(image)); + } + } + + if (EOFBlob(image) != MagickFalse) + ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", + image->filename); + + CloseBlob(image); + return(GetFirstImageInList(image)); +} + +static MagickBooleanType ReadDDSInfo(Image *image, DDSInfo *dds_info) +{ + unsigned long + hdr_size, + required; + + /* Seek to start of header */ + 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 = (DDSD_CAPS | 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); + + 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); + SeekBlob(image, 12, SEEK_CUR); /* 3 reserved DWORDs */ + + return MagickTrue; +} + +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 == MagickTrue || 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 MagickBooleanType ReadDXT1(Image *image, DDSInfo *dds_info) +{ + unsigned long + bits, + i, j, x, y; + + unsigned short + c0, + c1; + + unsigned char + code; + + DDSColors + colors; + + PixelPacket + *q; + + for (y = 0; y < dds_info->height; y += 4) + { + for (x = 0; x < dds_info->width; x += 4) + { + /* Get 4x4 patch of pixels to write on */ + q = SetImagePixels(image, x, y, Min(4, dds_info->width - x), + Min(4, dds_info->height - y)); + + if (q == (PixelPacket *) 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) < dds_info->width && (y + j) < dds_info->height) + { + code = (bits >> ((j*4+i)*2)) & 0x3; + q->red = ScaleCharToQuantum( colors.r[code] ); + q->green = ScaleCharToQuantum( colors.g[code] ); + q->blue = ScaleCharToQuantum( colors.b[code] ); + q->opacity = ScaleCharToQuantum( colors.a[code] ); + if (colors.a[code] && image->matte == MagickFalse) + /* Correct matte */ + image->matte = MagickTrue; + q++; + } + } + } + + if (SyncImagePixels(image) == MagickFalse) + return MagickFalse; + } + } + + SkipDXTMipmaps(image, dds_info, 8); + + return MagickTrue; +} + +static MagickBooleanType ReadDXT3(Image *image, DDSInfo *dds_info) +{ + unsigned long + a0, + a1, + bits, + code, + i, j, x, y; + + unsigned short + c0, + c1; + + unsigned char + alpha; + + DDSColors + colors; + + PixelPacket + *q; + + for (y = 0; y < dds_info->height; y += 4) + { + for (x = 0; x < dds_info->width; x += 4) + { + /* Get 4x4 patch of pixels to write on */ + q = SetImagePixels(image, x, y, Min(4, dds_info->width - x), + Min(4, dds_info->height - y)); + + if (q == (PixelPacket *) 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) < dds_info->width && (y + j) < dds_info->height) + { + code = (bits >> ((4*j+i)*2)) & 0x3; + q->red = ScaleCharToQuantum( colors.r[code] ); + q->green = ScaleCharToQuantum( colors.g[code] ); + q->blue = ScaleCharToQuantum( colors.b[code] ); + + /* + Extract alpha value: multiply 0..15 by 17 to get range 0..255 + */ + if (j < 2) + alpha = 17 * (unsigned char) ((a0 >> (4*(4*j+i))) & 0xf); + else + alpha = 17 * (unsigned char) ((a1 >> (4*(4*(j-2)+i))) & 0xf); + + q->opacity = ScaleCharToQuantum( 255 - alpha ); + + q++; + } + } + } + + if (SyncImagePixels(image) == MagickFalse) + return MagickFalse; + } + } + + SkipDXTMipmaps(image, dds_info, 16); + + return MagickTrue; +} + +static MagickBooleanType ReadDXT5(Image *image, DDSInfo *dds_info) +{ + unsigned long long + alpha_bits; + + unsigned long + bits, + code, + alpha_code, + i, j, x, y; + + unsigned short + c0, + c1; + + unsigned char + a0, + a1, + alpha; + + DDSColors + colors; + + PixelPacket + *q; + + for (y = 0; y < dds_info->height; y += 4) + { + for (x = 0; x < dds_info->width; x += 4) + { + /* Get 4x4 patch of pixels to write on */ + q = SetImagePixels(image, x, y, Min(4, dds_info->width - x), + Min(4, dds_info->height - y)); + + if (q == (PixelPacket *) NULL) + return MagickFalse; + + /* Read alpha values (8 bytes) */ + a0 = (unsigned char) ReadBlobByte(image); + a1 = (unsigned char) ReadBlobByte(image); + + alpha_bits = (unsigned long long)ReadBlobLSBLong(image) + | ((unsigned long long)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) < dds_info->width && (y + j) < dds_info->height) + { + code = (bits >> ((4*j+i)*2)) & 0x3; + q->red = ScaleCharToQuantum( colors.r[code] ); + q->green = ScaleCharToQuantum( colors.g[code] ); + q->blue = ScaleCharToQuantum( colors.b[code] ); + + /* Extract alpha value */ + alpha_code = (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 = alpha_code; + else if (alpha_code == 7) + alpha = 255; + else + alpha = ((6-alpha_code) * a0 + (alpha_code-1) * a1) / 5; + + q->opacity = ScaleCharToQuantum( 255 - alpha ); + + q++; + } + } + } + + if (SyncImagePixels(image) == MagickFalse) + return MagickFalse; + } + } + + SkipDXTMipmaps(image, dds_info, 16); + + return MagickTrue; +} + +static MagickBooleanType ReadUncompressedRGB(Image *image, DDSInfo *dds_info) +{ + unsigned long + x, y; + + PixelPacket + *q; + + for (y = 0; y < dds_info->height; y++) + { + q = SetImagePixels(image, 0, y, dds_info->width, 1); + + if (q == (PixelPacket *) NULL) + return MagickFalse; + + for (x = 0; x < dds_info->width; x++) + { + q->blue = ScaleCharToQuantum( ReadBlobByte(image) ); + q->green = ScaleCharToQuantum( ReadBlobByte(image) ); + q->red = ScaleCharToQuantum( ReadBlobByte(image) ); + q++; + } + + if (SyncImagePixels(image) == MagickFalse) + return MagickFalse; + } + + SkipRGBMipmaps(image, dds_info, 3); + + return MagickTrue; +} + +static MagickBooleanType ReadUncompressedRGBA(Image *image, DDSInfo *dds_info) +{ + unsigned long + x, y; + + PixelPacket + *q; + + for (y = 0; y < dds_info->height; y++) + { + q = SetImagePixels(image, 0, y, dds_info->width, 1); + + if (q == (PixelPacket *) NULL) + return MagickFalse; + + for (x = 0; x < dds_info->width; x++) + { + q->blue = ScaleCharToQuantum( ReadBlobByte(image) ); + q->green = ScaleCharToQuantum( ReadBlobByte(image) ); + q->red = ScaleCharToQuantum( ReadBlobByte(image) ); + q->opacity = ScaleCharToQuantum( 255 - ReadBlobByte(image) ); + q++; + } + + if (SyncImagePixels(image) == MagickFalse) + return MagickFalse; + } + + SkipRGBMipmaps(image, dds_info, 4); + + return MagickTrue; +} + +/* + Skip the mipmap images for compressed (DXTn) dds files +*/ +static void SkipDXTMipmaps(Image *image, DDSInfo *dds_info, int texel_size) +{ + unsigned long + w, + h, + i, + length; + + /* + 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 < dds_info->mipmapcount && w && h; i++) + { + length = ((w + 3) / 4) * ((h + 3) / 4) * texel_size; + SeekBlob(image, length, 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) +{ + unsigned long + w, + h, + i, + length; + + /* + 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 < dds_info->mipmapcount && w && h; i++) + { + length = w * h * pixel_size; + SeekBlob(image, length, SEEK_CUR); + + w = DIV2(w); + h = DIV2(h); + } + } +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% 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: This string is generally the first few bytes of an image file +% or blob. +% +% 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 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 unsigned long RegisterDDSImage(void) +{ + MagickInfo + *entry; + + entry = SetMagickInfo("DDS"); + entry->decoder = (DecodeImageHandler *) ReadDDSImage; + entry->magick = (IsImageFormatHandler *) IsDDS; + entry->description = ConstantString("Microsoft DirectDraw Surface"); + entry->module = ConstantString("DDS"); + (void) RegisterMagickInfo(entry); + return(MagickImageCoderSignature); +} + + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% 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"); +} + diff -Naur ImageMagick-6.3.9.orig/magick/compress.h ImageMagick-6.3.9/magick/compress.h --- ImageMagick-6.3.9.orig/magick/compress.h 2007-12-05 23:22:41.000000000 +0100 +++ ImageMagick-6.3.9/magick/compress.h 2008-03-03 17:17:50.000000000 +0100 @@ -27,6 +27,9 @@ UndefinedCompression, NoCompression, BZipCompression, + DXT1Compression, + DXT3Compression, + DXT5Compression, FaxCompression, Group4Compression, JPEGCompression, diff -Naur ImageMagick-6.3.9.orig/magick/methods.h ImageMagick-6.3.9/magick/methods.h --- ImageMagick-6.3.9.orig/magick/methods.h 2008-02-12 00:17:16.000000000 +0100 +++ ImageMagick-6.3.9/magick/methods.h 2008-02-26 21:13:59.000000000 +0100 @@ -725,6 +725,7 @@ #define RegisterCMYKImage PrependMagickMethod(RegisterCMYKImage) #define RegisterCUTImage PrependMagickMethod(RegisterCUTImage) #define RegisterDCMImage PrependMagickMethod(RegisterDCMImage) +#define RegisterDDSImage PrependMagickMethod(RegisterDDSImage) #define RegisterDIBImage PrependMagickMethod(RegisterDIBImage) #define RegisterDNGImage PrependMagickMethod(RegisterDNGImage) #define RegisterDPSImage PrependMagickMethod(RegisterDPSImage) @@ -1000,6 +1001,7 @@ #define UnregisterCMYKImage PrependMagickMethod(UnregisterCMYKImage) #define UnregisterCUTImage PrependMagickMethod(UnregisterCUTImage) #define UnregisterDCMImage PrependMagickMethod(UnregisterDCMImage) +#define UnregisterDDSImage PrependMagickMethod(UnregisterDDSImage) #define UnregisterDIBImage PrependMagickMethod(UnregisterDIBImage) #define UnregisterDNGImage PrependMagickMethod(UnregisterDNGImage) #define UnregisterDPSImage PrependMagickMethod(UnregisterDPSImage) diff -Naur ImageMagick-6.3.9.orig/magick/option.c ImageMagick-6.3.9/magick/option.c --- ImageMagick-6.3.9.orig/magick/option.c 2008-02-12 01:23:42.000000000 +0100 +++ ImageMagick-6.3.9/magick/option.c 2008-03-03 17:18:49.000000000 +0100 @@ -690,6 +690,9 @@ { { "Undefined", (long) UndefinedCompression }, { "BZip", (long) BZipCompression }, + { "DXT1", (long) DXT1Compression }, + { "DXT3", (long) DXT3Compression }, + { "DXT5", (long) DXT5Compression }, { "Fax", (long) FaxCompression }, { "Group4", (long) Group4Compression }, { "JPEG", (long) JPEGCompression }, diff -Naur ImageMagick-6.3.9.orig/magick/static.c ImageMagick-6.3.9/magick/static.c --- ImageMagick-6.3.9.orig/magick/static.c 2008-02-10 00:07:54.000000000 +0100 +++ ImageMagick-6.3.9/magick/static.c 2008-02-26 21:15:16.000000000 +0100 @@ -166,6 +166,7 @@ (void) RegisterCMYKImage(); (void) RegisterCUTImage(); (void) RegisterDCMImage(); + (void) RegisterDDSImage(); (void) RegisterDIBImage(); #if defined(MAGICKCORE_DJVU_DELEGATE) (void) RegisterDJVUImage(); @@ -325,6 +326,7 @@ UnregisterCMYKImage(); UnregisterCUTImage(); UnregisterDCMImage(); + UnregisterDDSImage(); UnregisterDIBImage(); #if defined(MAGICKCORE_DJVU_DELEGATE) UnregisterDJVUImage(); diff -Naur ImageMagick-6.3.9.orig/magick/static.h ImageMagick-6.3.9/magick/static.h --- ImageMagick-6.3.9.orig/magick/static.h 2008-01-17 20:56:43.000000000 +0100 +++ ImageMagick-6.3.9/magick/static.h 2008-02-26 21:14:47.000000000 +0100 @@ -37,6 +37,7 @@ RegisterCUTImage(void), RegisterDCMImage(void), RegisterDCXImage(void), + RegisterDDSImage(void), RegisterDIBImage(void), RegisterDJVUImage(void), RegisterDNGImage(void), @@ -179,6 +180,7 @@ UnregisterCUTImage(void), UnregisterDCMImage(void), UnregisterDCXImage(void), + UnregisterDDSImage(void), UnregisterDIBImage(void), UnregisterDJVUImage(void), UnregisterDNGImage(void),