root / ImageMagick / trunk / coders / dds.c

Revision 11742, 27.9 kB (checked in by cristy, 2 months ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                            DDDD   DDDD   SSSSS                              %
7%                            D   D  D   D  SS                                 %
8%                            D   D  D   D   SSS                               %
9%                            D   D  D   D     SS                              %
10%                            DDDD   DDDD   SSSSS                              %
11%                                                                             %
12%                                                                             %
13%              Read Microsoft Direct Draw Surface Image Format.               %
14%                                                                             %
15%                              Software Design                                %
16%                             Bianca van Schaik                               %
17%                                March 2008                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/colorspace.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/image.h"
49#include "magick/image-private.h"
50#include "magick/list.h"
51#include "magick/log.h"
52#include "magick/magick.h"
53#include "magick/memory_.h"
54#include "magick/monitor.h"
55#include "magick/monitor-private.h"
56#include "magick/profile.h"
57#include "magick/quantum-private.h"
58#include "magick/static.h"
59#include "magick/string_.h"
60#include "magick/module.h"
61#include "magick/transform.h"
62#include "magick/studio.h"
63#include "magick/blob.h"
64#include "magick/blob-private.h"
65#include "magick/colorspace.h"
66#include "magick/exception.h"
67#include "magick/exception-private.h"
68#include "magick/compress.h"
69#include "magick/image.h"
70#include "magick/image-private.h"
71#include "magick/list.h"
72#include "magick/magick.h"
73#include "magick/memory_.h"
74#include "magick/monitor.h"
75#include "magick/monitor-private.h"
76#include "magick/quantum.h"
77#include "magick/static.h"
78#include "magick/string_.h"
79
80/*
81  Definitions
82*/
83#define DDSD_CAPS         0x00000001
84#define DDSD_HEIGHT       0x00000002
85#define DDSD_WIDTH        0x00000004
86#define DDSD_PITCH        0x00000008
87#define DDSD_PIXELFORMAT  0x00001000
88#define DDSD_MIPMAPCOUNT  0x00020000
89#define DDSD_LINEARSIZE   0x00080000
90#define DDSD_DEPTH        0x00800000
91
92#define DDPF_ALPHAPIXELS  0x00000001
93#define DDPF_FOURCC       0x00000004
94#define DDPF_RGB          0x00000040
95
96#define FOURCC_DXT1       0x31545844
97#define FOURCC_DXT3       0x33545844
98#define FOURCC_DXT5       0x35545844
99
100#define DDSCAPS_COMPLEX   0x00000008
101#define DDSCAPS_TEXTURE   0x00001000
102#define DDSCAPS_MIPMAP    0x00400000
103
104#define DDSCAPS2_CUBEMAP  0x00000200
105#define DDSCAPS2_CUBEMAP_POSITIVEX  0x00000400
106#define DDSCAPS2_CUBEMAP_NEGATIVEX  0x00000800
107#define DDSCAPS2_CUBEMAP_POSITIVEY  0x00001000
108#define DDSCAPS2_CUBEMAP_NEGATIVEY  0x00002000
109#define DDSCAPS2_CUBEMAP_POSITIVEZ  0x00004000
110#define DDSCAPS2_CUBEMAP_NEGATIVEZ  0x00008000
111#define DDSCAPS2_VOLUME   0x00200000
112
113/*
114  Structure declarations.
115*/
116typedef struct _DDSPixelFormat
117{
118  unsigned long
119    flags,
120    fourcc,
121    rgb_bitcount,
122    r_bitmask,
123    g_bitmask,
124    b_bitmask,
125    alpha_bitmask;
126} DDSPixelFormat;
127
128typedef struct _DDSInfo
129{
130        unsigned long
131                flags,
132                height,
133                width,
134                pitchOrLinearSize,
135                depth,
136                mipmapcount,
137    ddscaps1,
138    ddscaps2;
139 
140  DDSPixelFormat
141    pixelformat;
142} DDSInfo;
143
144typedef struct _DDSColors
145{
146  unsigned char
147    r[4],
148    g[4],
149    b[4],
150    a[4];
151} DDSColors;
152
153typedef MagickBooleanType
154  DDSDecoder(Image *,DDSInfo *);
155
156/*
157  Macros
158*/
159#define C565_r(x) (((x) & 0xF800) >> 11)
160#define C565_g(x) (((x) & 0x07E0) >> 5)
161#define C565_b(x)  ((x) & 0x001F)
162
163#define C565_red(x)   ( (C565_r(x) << 3 | C565_r(x) >> 2))
164#define C565_green(x) ( (C565_g(x) << 2 | C565_g(x) >> 4))
165#define C565_blue(x)  ( (C565_b(x) << 3 | C565_b(x) >> 2))
166
167#define DIV2(x)  ((x) > 1 ? ((x) >> 1) : 1)
168
169/*
170  Forward declarations
171*/
172static MagickBooleanType
173  ReadDDSInfo(Image *image, DDSInfo *dds_info);
174
175static void
176  CalculateColors(unsigned short c0, unsigned short c1,
177    DDSColors *c, MagickBooleanType ignoreAlpha);
178
179static MagickBooleanType
180  ReadDXT1(Image *image, DDSInfo *dds_info);
181
182static MagickBooleanType
183  ReadDXT3(Image *image, DDSInfo *dds_info);
184
185static MagickBooleanType
186  ReadDXT5(Image *image, DDSInfo *dds_info);
187
188static MagickBooleanType
189  ReadUncompressedRGB(Image *image, DDSInfo *dds_info);
190
191static MagickBooleanType
192  ReadUncompressedRGBA(Image *image, DDSInfo *dds_info);
193
194static void
195  SkipDXTMipmaps(Image *image, DDSInfo *dds_info, int texel_size);
196
197static void
198  SkipRGBMipmaps(Image *image, DDSInfo *dds_info, int pixel_size);
199
200/*
201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202%                                                                             %
203%                                                                             %
204%                                                                             %
205%   R e a d D D S I m a g e                                                   %
206%                                                                             %
207%                                                                             %
208%                                                                             %
209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210%
211%  ReadDDSImage() reads a DirectDraw Surface image file and returns it.  It
212%  allocates the memory necessary for the new Image structure and returns a
213%  pointer to the new image.
214%
215%  The format of the ReadDDSImage method is:
216%
217%      Image *ReadDDSImage(const ImageInfo *image_info,ExceptionInfo *exception)
218%
219%  A description of each parameter follows:
220%
221%    o image_info: The image info.
222%
223%    o exception: return any errors or warnings in this structure.
224%
225*/
226
227static inline unsigned long Min(unsigned long one, unsigned long two)
228{
229  if (one < two)
230    return one;
231  return two;
232}
233
234static Image *ReadDDSImage(const ImageInfo *image_info,ExceptionInfo *exception)
235{
236  Image
237    *image;
238
239  MagickBooleanType
240    status,
241    cubemap = MagickFalse,
242    volume = MagickFalse,
243    matte;
244 
245  CompressionType
246    compression;
247
248  DDSInfo
249        dds_info;
250 
251  DDSDecoder
252    *decoder;
253 
254  unsigned long
255    n, num_images;
256 
257  /*
258    Open image file.
259  */
260  assert(image_info != (const ImageInfo *) NULL);
261  assert(image_info->signature == MagickSignature);
262  if (image_info->debug != MagickFalse)
263    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
264      image_info->filename);
265  assert(exception != (ExceptionInfo *) NULL);
266  assert(exception->signature == MagickSignature);
267  image=AcquireImage(image_info);
268  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
269  if (status == MagickFalse)
270    {
271      image=DestroyImageList(image);
272      return((Image *) NULL);
273    }
274 
275  /*
276    Initialize image structure.
277  */
278  if (ReadDDSInfo(image, &dds_info) != MagickTrue) {
279          ThrowReaderException(CorruptImageError,"ImproperImageHeader");
280  }
281 
282  if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP)
283    cubemap = MagickTrue;
284 
285  if (dds_info.ddscaps2 & DDSCAPS2_VOLUME && dds_info.depth > 0)
286    volume = MagickTrue;
287 
288  (void) SeekBlob(image, 128, SEEK_SET);
289
290  /*
291    Determine pixel format
292  */
293  if (dds_info.pixelformat.flags & DDPF_RGB)
294    {
295      compression = NoCompression;
296      if (dds_info.pixelformat.flags & DDPF_ALPHAPIXELS)
297        {
298          matte = MagickTrue;
299          decoder = ReadUncompressedRGBA;
300        }
301      else
302        {
303          matte = MagickTrue;
304          decoder = ReadUncompressedRGB;
305        }
306    }
307  else if (dds_info.pixelformat.flags & DDPF_FOURCC)
308    {
309      switch (dds_info.pixelformat.fourcc)
310      {
311        case FOURCC_DXT1:
312        {
313          matte = MagickFalse;
314          compression = DXT1Compression;
315          decoder = ReadDXT1;
316          break;
317        }
318       
319        case FOURCC_DXT3:
320        {
321          matte = MagickTrue;
322          compression = DXT3Compression;
323          decoder = ReadDXT3;
324          break;
325        }
326       
327        case FOURCC_DXT5:
328        {
329          matte = MagickTrue;
330          compression = DXT5Compression;
331          decoder = ReadDXT5;
332          break;
333        }
334       
335        default:
336        {
337          /* Unknown FOURCC */
338          ThrowReaderException(CorruptImageError, "ImageTypeNotSupported");
339        }
340      }
341    }
342  else
343    {
344      /* Neither compressed nor uncompressed... thus unsupported */
345      ThrowReaderException(CorruptImageError, "ImageTypeNotSupported");
346    }
347 
348  num_images = 1;
349  if (cubemap)
350    {
351      /*
352        Determine number of faces defined in the cubemap
353      */
354      num_images = 0;
355      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) num_images++;
356      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) num_images++;
357      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEY) num_images++;
358      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) num_images++;
359      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) num_images++;
360      if (dds_info.ddscaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) num_images++;
361    }
362 
363  if (volume)
364    num_images = dds_info.depth;
365 
366  for (n = 0; n < num_images; n++)
367  {
368    if (n != 0)
369      {
370        /* Start a new image */
371        AcquireNextImage(image_info,image);
372        if (GetNextImageInList(image) == (Image *) NULL)
373          {
374            image = DestroyImageList(image);
375            return((Image *) NULL);
376          }
377        image=SyncNextImageInList(image);
378      }
379   
380    image->matte = matte;
381    image->compression = compression;
382    image->columns = dds_info.width;
383    image->rows = dds_info.height;
384    image->storage_class = DirectClass;
385    image->endian = LSBEndian;
386    image->depth = 8;
387    if (image_info->ping != MagickFalse)
388      {
389        (void) CloseBlob(image);
390        return(GetFirstImageInList(image));
391      }
392   
393    if ((decoder)(image, &dds_info) != MagickTrue)
394      {
395        (void) CloseBlob(image);
396        return(GetFirstImageInList(image));
397      }
398  }
399 
400  if (EOFBlob(image) != MagickFalse)
401    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
402      image->filename);
403 
404  (void) CloseBlob(image);
405  return(GetFirstImageInList(image));
406}
407
408static MagickBooleanType ReadDDSInfo(Image *image, DDSInfo *dds_info)
409{
410        unsigned long
411    hdr_size,
412    required;
413       
414        /* Seek to start of header */
415        (void) SeekBlob(image, 4, SEEK_SET);
416       
417        /* Check header field */
418        hdr_size = ReadBlobLSBLong(image);
419        if (hdr_size != 124)
420                return MagickFalse;
421       
422        /* Fill in DDS info struct */
423        dds_info->flags = ReadBlobLSBLong(image);
424 
425        /* Check required flags */
426        required=(unsigned long) (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT);
427  if ((dds_info->flags & required) != required)
428                return MagickFalse;
429 
430        dds_info->height = ReadBlobLSBLong(image);
431        dds_info->width = ReadBlobLSBLong(image);
432        dds_info->pitchOrLinearSize = ReadBlobLSBLong(image);
433        dds_info->depth = ReadBlobLSBLong(image);
434        dds_info->mipmapcount = ReadBlobLSBLong(image);
435 
436        (void) SeekBlob(image, 44, SEEK_CUR);   /* reserved region of 11 DWORDs */
437 
438  /* Read pixel format structure */
439  hdr_size = ReadBlobLSBLong(image);
440  if (hdr_size != 32)
441    return MagickFalse;
442 
443  dds_info->pixelformat.flags = ReadBlobLSBLong(image);
444  dds_info->pixelformat.fourcc = ReadBlobLSBLong(image);
445  dds_info->pixelformat.rgb_bitcount = ReadBlobLSBLong(image);
446  dds_info->pixelformat.r_bitmask = ReadBlobLSBLong(image);
447  dds_info->pixelformat.g_bitmask = ReadBlobLSBLong(image);
448  dds_info->pixelformat.b_bitmask = ReadBlobLSBLong(image);
449  dds_info->pixelformat.alpha_bitmask = ReadBlobLSBLong(image);
450 
451        dds_info->ddscaps1 = ReadBlobLSBLong(image);
452        dds_info->ddscaps2 = ReadBlobLSBLong(image);
453        (void) SeekBlob(image, 12, SEEK_CUR); /* 3 reserved DWORDs */
454 
455        return MagickTrue;
456}
457
458static void CalculateColors(unsigned short c0, unsigned short c1,
459  DDSColors *c, MagickBooleanType ignoreAlpha)
460{
461  c->a[0] = c->a[1] = c->a[2] = c->a[3] = 0;
462 
463  c->r[0] = (unsigned char) C565_red(c0);
464  c->g[0] = (unsigned char) C565_green(c0);
465  c->b[0] = (unsigned char) C565_blue(c0);
466 
467  c->r[1] = (unsigned char) C565_red(c1);
468  c->g[1] = (unsigned char) C565_green(c1);
469  c->b[1] = (unsigned char) C565_blue(c1);
470 
471  if (ignoreAlpha == MagickTrue || c0 > c1)
472    {
473      c->r[2] = (unsigned char) ((2 * c->r[0] + c->r[1]) / 3);
474      c->g[2] = (unsigned char) ((2 * c->g[0] + c->g[1]) / 3);
475      c->b[2] = (unsigned char) ((2 * c->b[0] + c->b[1]) / 3);
476     
477      c->r[3] = (unsigned char) ((c->r[0] + 2 * c->r[1]) / 3);
478      c->g[3] = (unsigned char) ((c->g[0] + 2 * c->g[1]) / 3);
479      c->b[3] = (unsigned char) ((c->b[0] + 2 * c->b[1]) / 3);
480    }
481  else
482    {
483      c->r[2] = (unsigned char) ((c->r[0] + c->r[1]) / 2);
484      c->g[2] = (unsigned char) ((c->g[0] + c->g[1]) / 2);
485      c->b[2] = (unsigned char) ((c->b[0] + c->b[1]) / 2);
486     
487      c->r[3] = c->g[3] = c->b[3] = 0;
488      c->a[3] = 255;
489    }
490}
491
492static MagickBooleanType ReadDXT1(Image *image, DDSInfo *dds_info)
493{
494  DDSColors
495    colors;
496
497  long
498    j,
499    y;
500       
501  PixelPacket
502    *q;
503 
504  register long
505    i,
506    x;
507 
508  unsigned char
509    code;
510 
511        unsigned short
512    c0,
513    c1;
514       
515  unsigned long
516    bits;
517
518  for (y = 0; y < (long) dds_info->height; y += 4)
519  {
520    for (x = 0; x < (long) dds_info->width; x += 4)
521    {
522      /* Get 4x4 patch of pixels to write on */
523      q = SetImagePixels(image, x, y, Min(4, dds_info->width - x),
524                             Min(4, dds_info->height - y));
525     
526      if (q == (PixelPacket *) NULL)
527        return MagickFalse;
528     
529      /* Read 8 bytes of data from the image */
530      c0 = ReadBlobLSBShort(image);
531      c1 = ReadBlobLSBShort(image);
532      bits = ReadBlobLSBLong(image);
533     
534      CalculateColors(c0, c1, &colors, MagickFalse);
535     
536      /* Write the pixels */
537      for (j = 0; j < 4; j++)
538      {
539        for (i = 0; i < 4; i++)
540        {
541          if ((x + i) < (long) dds_info->width && (y + j) < (long) dds_info->height)
542            {
543              code = (unsigned char) ((bits >> ((j*4+i)*2)) & 0x3);
544              q->red     = ScaleCharToQuantum( colors.r[code] );
545              q->green   = ScaleCharToQuantum( colors.g[code] );
546              q->blue    = ScaleCharToQuantum( colors.b[code] );
547              q->opacity = ScaleCharToQuantum( colors.a[code] );
548              if (colors.a[code] && image->matte == MagickFalse)
549                /* Correct matte */
550                image->matte = MagickTrue;
551              q++;
552            }
553        }
554      }
555     
556      if (SyncImagePixels(image) == MagickFalse)
557        return MagickFalse;
558    }
559  }
560 
561  SkipDXTMipmaps(image, dds_info, 8);
562 
563  return MagickTrue;
564}
565
566static MagickBooleanType ReadDXT3(Image *image, DDSInfo *dds_info)
567{
568  DDSColors
569    colors;
570 
571  long
572    j,
573    y;
574
575  PixelPacket
576    *q;
577 
578  register long
579    i,
580    x;
581 
582  unsigned char
583    alpha;
584 
585  unsigned long
586    a0,
587    a1,
588    bits,
589    code;
590
591  unsigned short
592    c0,
593    c1;
594 
595  for (y = 0; y < (long) dds_info->height; y += 4)
596  {
597    for (x = 0; x < (long) dds_info->width; x += 4)
598    {
599      /* Get 4x4 patch of pixels to write on */
600      q = SetImagePixels(image, x, y, Min(4, dds_info->width - x),
601                         Min(4, dds_info->height - y));
602     
603      if (q == (PixelPacket *) NULL)
604        return MagickFalse;
605     
606      /* Read alpha values (8 bytes) */
607      a0 = ReadBlobLSBLong(image);
608      a1 = ReadBlobLSBLong(image);
609     
610      /* Read 8 bytes of data from the image */
611      c0 = ReadBlobLSBShort(image);
612      c1 = ReadBlobLSBShort(image);
613      bits = ReadBlobLSBLong(image);
614     
615      CalculateColors(c0, c1, &colors, MagickTrue);
616     
617      /* Write the pixels */
618      for (j = 0; j < 4; j++)
619      {
620        for (i = 0; i < 4; i++)
621        {
622          if ((x + i) < (long) dds_info->width && (y + j) < (long) dds_info->height)
623            {
624              code = (bits >> ((4*j+i)*2)) & 0x3;
625              q->red   = ScaleCharToQuantum( colors.r[code] );
626              q->green = ScaleCharToQuantum( colors.g[code] );
627              q->blue  = ScaleCharToQuantum( colors.b[code] );
628             
629              /*
630                Extract alpha value: multiply 0..15 by 17 to get range 0..255
631              */
632              if (j < 2)
633                alpha = 17U * (unsigned char) ((a0 >> (4*(4*j+i))) & 0xf);
634              else
635                alpha = 17U * (unsigned char) ((a1 >> (4*(4*(j-2)+i))) & 0xf);
636             
637              q->opacity = ScaleCharToQuantum( (unsigned char) (255 - alpha) );
638             
639              q++;
640            }
641        }
642      }
643     
644      if (SyncImagePixels(image) == MagickFalse)
645        return MagickFalse;
646    }
647  }
648 
649  SkipDXTMipmaps(image, dds_info, 16);
650 
651  return MagickTrue;
652}
653
654static MagickBooleanType ReadDXT5(Image *image, DDSInfo *dds_info)
655{
656  DDSColors
657    colors;
658 
659  long
660    j,
661    y;
662
663  MagickSizeType
664    alpha_bits;
665 
666  PixelPacket
667    *q;
668 
669  register long
670    i,
671    x;
672
673  unsigned char
674    a0,
675    a1;
676 
677  unsigned long
678    alpha,
679    bits,
680    code,
681    alpha_code;
682
683  unsigned short
684    c0,
685    c1;
686 
687  for (y = 0; y < (long) dds_info->height; y += 4)
688  {
689    for (x = 0; x < (long) dds_info->width; x += 4)
690    {
691      /* Get 4x4 patch of pixels to write on */
692      q = SetImagePixels(image, x, y, Min(4, dds_info->width - x),
693                         Min(4, dds_info->height - y));
694     
695      if (q == (PixelPacket *) NULL)
696        return MagickFalse;
697     
698      /* Read alpha values (8 bytes) */
699      a0 = (unsigned char) ReadBlobByte(image);
700      a1 = (unsigned char) ReadBlobByte(image);
701     
702      alpha_bits = (MagickSizeType)ReadBlobLSBLong(image)
703                 | ((MagickSizeType)ReadBlobLSBShort(image) << 32);
704     
705      /* Read 8 bytes of data from the image */
706      c0 = ReadBlobLSBShort(image);
707      c1 = ReadBlobLSBShort(image);
708      bits = ReadBlobLSBLong(image);
709     
710      CalculateColors(c0, c1, &colors, MagickTrue);
711     
712      /* Write the pixels */
713      for (j = 0; j < 4; j++)
714      {
715        for (i = 0; i < 4; i++)
716        {
717          if ((x + i) < (long) dds_info->width && (y + j) < (long) dds_info->height)
718            {
719              code = (bits >> ((4*j+i)*2)) & 0x3;
720              q->red   = ScaleCharToQuantum( colors.r[code] );
721              q->green = ScaleCharToQuantum( colors.g[code] );
722              q->blue  = ScaleCharToQuantum( colors.b[code] );
723             
724              /* Extract alpha value */
725              alpha_code = (unsigned long) (alpha_bits >> (3*(4*j+i))) & 0x7;
726              if (alpha_code == 0)
727                alpha = a0;
728              else if (alpha_code == 1)
729                alpha = a1;
730              else if (a0 > a1)
731                alpha = ((8-alpha_code) * a0 + (alpha_code-1) * a1) / 7;
732              else if (alpha_code == 6)
733                alpha = alpha_code;
734              else if (alpha_code == 7)
735                alpha = 255;
736              else
737                alpha = (((6-alpha_code) * a0 + (alpha_code-1) * a1) / 5);
738             
739              q->opacity = ScaleCharToQuantum( (unsigned char) (255 - alpha) );
740             
741              q++;
742            }
743        }
744      }
745     
746      if (SyncImagePixels(image) == MagickFalse)
747        return MagickFalse;
748    }
749  }
750 
751  SkipDXTMipmaps(image, dds_info, 16);
752 
753  return MagickTrue;
754}
755
756static MagickBooleanType ReadUncompressedRGB(Image *image, DDSInfo *dds_info)
757{
758  long
759    x, y;
760 
761  PixelPacket
762    *q;
763 
764  for (y = 0; y < (long) dds_info->height; y++)
765  {
766    q = SetImagePixels(image, 0, y, dds_info->width, 1);
767   
768    if (q == (PixelPacket *) NULL)
769      return MagickFalse;
770   
771    for (x = 0; x < (long) dds_info->width; x++)
772    {
773      q->blue  = ScaleCharToQuantum( (unsigned char) ReadBlobByte(image) );
774      q->green = ScaleCharToQuantum( (unsigned char) ReadBlobByte(image) );
775      q->red   = ScaleCharToQuantum( (unsigned char) ReadBlobByte(image) );
776      q++;
777    }
778   
779    if (SyncImagePixels(image) == MagickFalse)
780      return MagickFalse;
781  }
782 
783  SkipRGBMipmaps(image, dds_info, 3);
784 
785  return MagickTrue;
786}
787
788static MagickBooleanType ReadUncompressedRGBA(Image *image, DDSInfo *dds_info)
789{
790  long
791    x, y;
792 
793  PixelPacket
794    *q;
795 
796  for (y = 0; y < (long) dds_info->height; y++)
797  {
798    q = SetImagePixels(image, 0, y, dds_info->width, 1);
799   
800    if (q == (PixelPacket *) NULL)
801      return MagickFalse;
802   
803    for (x = 0; x < (long) dds_info->width; x++)
804    {
805      q->blue    = ScaleCharToQuantum( (unsigned char) ReadBlobByte(image) );
806      q->green   = ScaleCharToQuantum( (unsigned char) ReadBlobByte(image) );
807      q->red     = ScaleCharToQuantum( (unsigned char) ReadBlobByte(image) );
808      q->opacity = ScaleCharToQuantum( (unsigned char) (255 - ReadBlobByte(image)) );
809      q++;
810    }
811   
812    if (SyncImagePixels(image) == MagickFalse)
813      return MagickFalse;
814  }
815 
816  SkipRGBMipmaps(image, dds_info, 4);
817 
818  return MagickTrue;
819}
820
821/*
822  Skip the mipmap images for compressed (DXTn) dds files
823*/
824static void SkipDXTMipmaps(Image *image, DDSInfo *dds_info, int texel_size)
825{
826  register long
827    i;
828
829  MagickOffsetType
830    offset;
831
832  unsigned long
833    h,
834    w;
835 
836  /*
837    Only skip mipmaps for textures and cube maps
838  */
839  if (dds_info->ddscaps1 & DDSCAPS_MIPMAP
840      && (dds_info->ddscaps1 & DDSCAPS_TEXTURE
841          || dds_info->ddscaps2 & DDSCAPS2_CUBEMAP))
842    {
843      w = DIV2(dds_info->width);
844      h = DIV2(dds_info->height);
845     
846      /*
847        Mipmapcount includes the main image, so start from one
848      */
849      for (i = 1; (i < (long) dds_info->mipmapcount) && w && h; i++)
850      {
851        offset = (MagickOffsetType) ((w + 3) / 4) * ((h + 3) / 4) * texel_size;
852        (void) SeekBlob(image, offset, SEEK_CUR);
853       
854        w = DIV2(w);
855        h = DIV2(h);
856      }
857    }
858}
859
860/*
861  Skip the mipmap images for uncompressed (RGB or RGBA) dds files
862*/
863static void SkipRGBMipmaps(Image *image, DDSInfo *dds_info, int pixel_size)
864{
865  MagickOffsetType
866    offset;
867 
868  register long
869    i;
870
871  unsigned long
872    h,
873    w;
874
875  /*
876    Only skip mipmaps for textures and cube maps
877  */
878  if (dds_info->ddscaps1 & DDSCAPS_MIPMAP
879      && (dds_info->ddscaps1 & DDSCAPS_TEXTURE
880          || dds_info->ddscaps2 & DDSCAPS2_CUBEMAP))
881    {
882      w = DIV2(dds_info->width);
883      h = DIV2(dds_info->height);
884     
885      /*
886        Mipmapcount includes the main image, so start from one
887      */
888      for (i=1; (i < (long) dds_info->mipmapcount) && w && h; i++)
889      {
890        offset = (MagickOffsetType) w * h * pixel_size;
891        (void) SeekBlob(image, offset, SEEK_CUR);
892       
893        w = DIV2(w);
894        h = DIV2(h);
895      }
896    }
897}
898
899/*
900%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901%                                                                             %
902%                                                                             %
903%                                                                             %
904%   I s D D S                                                                 %
905%                                                                             %
906%                                                                             %
907%                                                                             %
908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909%
910%  IsDDS() returns MagickTrue if the image format type, identified by the
911%  magick string, is DDS.
912%
913%  The format of the IsDDS method is:
914%
915%      MagickBooleanType IsDDS(const unsigned char *magick,const size_t length)
916%
917%  A description of each parameter follows:
918%
919%    o magick: This string is generally the first few bytes of an image file
920%      or blob.
921%
922%    o length: Specifies the length of the magick string.
923%
924*/
925static MagickBooleanType IsDDS(const unsigned char *magick,const size_t length)
926{
927  if (length < 4)
928    return(MagickFalse);
929  if (LocaleNCompare((char *) magick,"DDS ", 4) == 0)
930    return(MagickTrue);
931  return(MagickFalse);
932}
933
934/*
935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936%                                                                             %
937%                                                                             %
938%                                                                             %
939%   R e g i s t e r D D S I m a g e                                           %
940%                                                                             %
941%                                                                             %
942%                                                                             %
943%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944%
945%  RegisterDDSImage() adds attributes for the DDS image format to
946%  the list of supported formats.  The attributes include the image format
947%  tag, a method to read and/or write the format, whether the format
948%  supports the saving of more than one frame to the same file or blob,
949%  whether the format supports native in-memory I/O, and a brief
950%  description of the format.
951%
952%  The format of the RegisterDDSImage method is:
953%
954%      RegisterDDSImage(void)
955%
956*/
957ModuleExport unsigned long RegisterDDSImage(void)
958{
959  MagickInfo
960    *entry;
961
962  entry = SetMagickInfo("DDS");
963  entry->decoder = (DecodeImageHandler *) ReadDDSImage;
964  entry->magick = (IsImageFormatHandler *) IsDDS;
965  entry->description = ConstantString("Microsoft DirectDraw Surface");
966  entry->module = ConstantString("DDS");
967  (void) RegisterMagickInfo(entry);
968  return(MagickImageCoderSignature);
969}
970
971
972/*
973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974%                                                                             %
975%                                                                             %
976%                                                                             %
977%   U n r e g i s t e r D D S I m a g e                                       %
978%                                                                             %
979%                                                                             %
980%                                                                             %
981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982%
983%  UnregisterDDSImage() removes format registrations made by the
984%  DDS module from the list of supported formats.
985%
986%  The format of the UnregisterDDSImage method is:
987%
988%      UnregisterDDSImage(void)
989%
990*/
991ModuleExport void UnregisterDDSImage(void)
992{
993  (void) UnregisterMagickInfo("DDS");
994}
Note: See TracBrowser for help on using the browser.