[gimp-dds] / tags / release-2.0.2 / ddsread.c Repository:
ViewVC logotype

View of /tags/release-2.0.2/ddsread.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 95 - (download) (as text) (annotate)
Thu Nov 29 23:58:16 2007 UTC (23 months, 3 weeks ago) by cocidius
File size: 25419 byte(s)
Release 2.0.2 tag
    1 /*
    2    DDS GIMP plugin
    3 
    4    Copyright (C) 2004 Shawn Kirst <skirst@fuse.net>,
    5    with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
    6 
    7    This program is free software; you can redistribute it and/or
    8    modify it under the terms of the GNU General Public
    9    License as published by the Free Software Foundation; either
   10    version 2 of the License, or (at your option) any later version.
   11 
   12    This program is distributed in the hope that it will be useful,
   13    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15    General Public License for more details.
   16 
   17    You should have received a copy of the GNU General Public License
   18    along with this program; see the file COPYING.  If not, write to
   19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   20    Boston, MA 02111-1307, USA.
   21 */
   22 
   23 /*
   24 ** !!! COPYRIGHT NOTICE !!!
   25 **
   26 ** The following is based on code (C) 2003 Arne Reuter <homepage@arnereuter.de>
   27 ** URL: http://www.dr-reuter.de/arne/dds.html
   28 **
   29 */
   30 
   31 #include <stdio.h>
   32 #include <stdlib.h>
   33 #include <string.h>
   34 
   35 #include <gtk/gtk.h>
   36 
   37 #include <libgimp/gimp.h>
   38 #include <libgimp/gimpui.h>
   39 
   40 #include "ddsplugin.h"
   41 #include "dds.h"
   42 #include "dxt.h"
   43 #include "endian.h"
   44 
   45 typedef struct
   46 {
   47    unsigned char rshift, gshift, bshift, ashift;
   48    unsigned char rbits, gbits, bbits, abits;
   49    unsigned int rmask, gmask, bmask, amask;
   50    unsigned int bpp, gimp_bpp;
   51    int tile_height;
   52    unsigned char *palette;
   53 } dds_load_info_t;
   54 
   55 static int read_header(dds_header_t *hdr, FILE *fp);
   56 static int validate_header(dds_header_t *hdr);
   57 static int load_layer(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
   58                       gint32 image, unsigned int level, char *prefix,
   59                       unsigned int *l, guchar *pixels, unsigned char *buf);
   60 static int load_mipmaps(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
   61                         gint32 image, char *prefix, unsigned int *l,
   62                         guchar *pixels, unsigned char *buf);
   63 static int load_face(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
   64                      gint32 image, char *prefix, unsigned int *l,
   65                      guchar *pixels, unsigned char *buf);
   66 static unsigned char color_bits(unsigned int mask);
   67 static unsigned char color_shift(unsigned int mask);
   68 
   69 gint32 read_dds(gchar *filename)
   70 {
   71    gint32 image = 0;
   72    unsigned char *buf;
   73    unsigned int l = 0;
   74    guchar *pixels;
   75    gchar *tmp;
   76    FILE *fp;
   77    dds_header_t hdr;
   78    dds_load_info_t d;
   79    gint *layers, layer_count;
   80    GimpImageBaseType type;
   81    int i, j;
   82 
   83    fp = fopen(filename, "rb");
   84    if(fp == 0)
   85    {
   86       g_message("Error opening file.\n");
   87       return(-1);
   88    }
   89 
   90    if(interactive_dds)
   91    {
   92       if(strrchr(filename, '/'))
   93          tmp = g_strdup_printf("Loading %s:", strrchr(filename, '/') + 1);
   94       else
   95          tmp = g_strdup_printf("Loading %s:", filename);
   96       gimp_progress_init(tmp);
   97       g_free(tmp);
   98    }
   99 
  100    read_header(&hdr, fp);
  101    if(!validate_header(&hdr))
  102    {
  103       fclose(fp);
  104       return(-1);
  105    }
  106 
  107    /* a lot of DDS images out there don't have this for some reason -_- */
  108    if(hdr.pitch_or_linsize == 0)
  109    {
  110       if(hdr.pixelfmt.flags & DDPF_FOURCC) /* assume linear size */
  111       {
  112          hdr.pitch_or_linsize = ((hdr.width + 3) >> 2) * ((hdr.height + 3) >> 2);
  113          if(hdr.pixelfmt.fourcc[3] == '1')
  114             hdr.pitch_or_linsize *= 8;
  115          else
  116             hdr.pitch_or_linsize *= 16;
  117       }
  118       else /* assume pitch */
  119       {
  120          hdr.pitch_or_linsize = hdr.height * hdr.width *
  121             (hdr.pixelfmt.bpp >> 3);
  122       }
  123    }
  124 
  125    if(hdr.pixelfmt.flags & DDPF_FOURCC)
  126    {
  127       if(hdr.pixelfmt.fourcc[0] == 'D')
  128          hdr.pixelfmt.flags |= DDPF_ALPHAPIXELS;
  129    }
  130 
  131    if(hdr.pixelfmt.flags & DDPF_FOURCC)
  132    {
  133       switch(GETL32(hdr.pixelfmt.fourcc))
  134       {
  135          case CHAR32('A', 'T', 'I', '1'):
  136             d.bpp = d.gimp_bpp = 1;
  137             type = GIMP_GRAY;
  138             break;
  139          case CHAR32('A', 'T', 'I', '2'):
  140             d.bpp = d.gimp_bpp = 3;
  141             type = GIMP_RGB;
  142             break;
  143          default:
  144             d.bpp = d.gimp_bpp = 4;
  145             type = GIMP_RGB;
  146             break;
  147       }
  148    }
  149    else
  150    {
  151       d.bpp = hdr.pixelfmt.bpp >> 3;
  152 
  153       if(d.bpp == 2)
  154       {
  155          if(hdr.pixelfmt.amask == 0xf000) // RGBA4
  156          {
  157             d.gimp_bpp = 4;
  158             type = GIMP_RGB;
  159          }
  160          else if(hdr.pixelfmt.amask == 0xff00) //L8A8
  161          {
  162             d.gimp_bpp = 2;
  163             type = GIMP_GRAY;
  164          }
  165          else if(hdr.pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  166          {
  167             if(hdr.pixelfmt.amask == 0x8000) // RGB5A1
  168                d.gimp_bpp = 4;
  169             else
  170                d.gimp_bpp = 3;
  171 
  172             type = GIMP_RGB;
  173          }
  174          else //L16
  175          {
  176             d.gimp_bpp = 1;
  177             type = GIMP_GRAY;
  178          }
  179       }
  180       else
  181       {
  182          if(hdr.pixelfmt.flags & DDPF_PALETTEINDEXED8)
  183          {
  184             type = GIMP_INDEXED;
  185             d.gimp_bpp = 1;
  186          }
  187          else if(hdr.pixelfmt.rmask == 0xe0) // R3G3B2
  188          {
  189             type = GIMP_RGB;
  190             d.gimp_bpp = 3;
  191          }
  192          else
  193          {
  194             /* test alpha only image */
  195             if(d.bpp == 1 && (hdr.pixelfmt.flags & DDPF_ALPHA))
  196             {
  197                d.gimp_bpp = 2;
  198                type = GIMP_GRAY;
  199             }
  200             else
  201             {
  202                d.gimp_bpp = d.bpp;
  203                type = (d.bpp == 1) ? GIMP_GRAY : GIMP_RGB;
  204             }
  205          }
  206       }
  207    }
  208 
  209    image = gimp_image_new(hdr.width, hdr.height, type);
  210 
  211    if(image == -1)
  212    {
  213       g_message("Can't allocate new image.\n");
  214       fclose(fp);
  215       return(-1);
  216    }
  217 
  218    gimp_image_set_filename(image, filename);
  219 
  220    if(hdr.pixelfmt.flags & DDPF_PALETTEINDEXED8)
  221    {
  222       d.palette = g_malloc(256 * 4);
  223       fread(d.palette, 1, 256 * 4, fp);
  224       for(i = j = 0; i < 768; i += 3, j += 4)
  225       {
  226          d.palette[i + 0] = d.palette[j + 0];
  227          d.palette[i + 1] = d.palette[j + 1];
  228          d.palette[i + 2] = d.palette[j + 2];
  229       }
  230       gimp_image_set_colormap(image, d.palette, 256);
  231    }
  232 
  233    d.tile_height = gimp_tile_height();
  234 
  235    pixels = g_new(guchar, d.tile_height * hdr.width * d.gimp_bpp);
  236    buf = g_malloc(hdr.pitch_or_linsize);
  237 
  238    d.rshift = color_shift(hdr.pixelfmt.rmask);
  239    d.gshift = color_shift(hdr.pixelfmt.gmask);
  240    d.bshift = color_shift(hdr.pixelfmt.bmask);
  241    d.ashift = color_shift(hdr.pixelfmt.amask);
  242    d.rbits = color_bits(hdr.pixelfmt.rmask);
  243    d.gbits = color_bits(hdr.pixelfmt.gmask);
  244    d.bbits = color_bits(hdr.pixelfmt.bmask);
  245    d.abits = color_bits(hdr.pixelfmt.amask);
  246    d.rmask = hdr.pixelfmt.rmask >> d.rshift << (8 - d.rbits);
  247    d.gmask = hdr.pixelfmt.gmask >> d.gshift << (8 - d.gbits);
  248    d.bmask = hdr.pixelfmt.bmask >> d.bshift << (8 - d.bbits);
  249    d.amask = hdr.pixelfmt.amask >> d.ashift << (8 - d.abits);
  250 
  251    if(!(hdr.caps.caps2 & DDSCAPS2_CUBEMAP) &&
  252       !(hdr.caps.caps2 & DDSCAPS2_VOLUME))
  253    {
  254       if(!load_layer(fp, &hdr, &d, image, 0, "", &l, pixels, buf))
  255       {
  256          fclose(fp);
  257          gimp_image_delete(image);
  258          return(-1);
  259       }
  260    }
  261 
  262    if(hdr.caps.caps1 & DDSCAPS_COMPLEX)
  263    {
  264       if(hdr.caps.caps2 & DDSCAPS2_CUBEMAP)
  265       {
  266          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) &&
  267             !load_face(fp, &hdr, &d, image, "(positive x)", &l, pixels, buf))
  268          {
  269             fclose(fp);
  270             gimp_image_delete(image);
  271             return(-1);
  272          }
  273          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) &&
  274             !load_face(fp, &hdr, &d, image, "(negative x)", &l, pixels, buf))
  275          {
  276             fclose(fp);
  277             gimp_image_delete(image);
  278             return(-1);
  279          }
  280          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) &&
  281             !load_face(fp, &hdr, &d, image, "(positive y)", &l, pixels, buf))
  282          {
  283             fclose(fp);
  284             gimp_image_delete(image);
  285             return(-1);
  286          }
  287          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) &&
  288             !load_face(fp, &hdr, &d, image, "(negative y)", &l, pixels, buf))
  289          {
  290             fclose(fp);
  291             gimp_image_delete(image);
  292             return(-1);
  293          }
  294          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) &&
  295             !load_face(fp, &hdr, &d, image, "(positive z)", &l, pixels, buf))
  296          {
  297             fclose(fp);
  298             gimp_image_delete(image);
  299             return(-1);
  300          }
  301          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) &&
  302             !load_face(fp, &hdr, &d, image, "(negative z)", &l, pixels, buf))
  303          {
  304             fclose(fp);
  305             gimp_image_delete(image);
  306             return(-1);
  307          }
  308       }
  309       else if((hdr.caps.caps2 & DDSCAPS2_VOLUME) &&
  310               (hdr.flags & DDSD_DEPTH))
  311       {
  312          unsigned int i, level;
  313          char *plane;
  314          for(i = 0; i < hdr.depth; ++i)
  315          {
  316             plane = g_strdup_printf("(z = %d)", i);
  317             if(!load_layer(fp, &hdr, &d, image, 0, plane, &l, pixels, buf))
  318             {
  319                g_free(plane);
  320                fclose(fp);
  321                gimp_image_delete(image);
  322                return(-1);
  323             }
  324             g_free(plane);
  325          }
  326 
  327          if((hdr.flags & DDSD_MIPMAPCOUNT) &&
  328             (hdr.caps.caps1 & DDSCAPS_MIPMAP))
  329          {
  330             for(level = 1; level < hdr.num_mipmaps; ++level)
  331             {
  332                int n = hdr.depth >> level;
  333                if(n < 1) n = 1;
  334                for(i = 0; i < n; ++i)
  335                {
  336                   plane = g_strdup_printf("(z = %d)", i);
  337                   if(!load_layer(fp, &hdr, &d, image, level, plane, &l, pixels, buf))
  338                   {
  339                      g_free(plane);
  340                      fclose(fp);
  341                      gimp_image_delete(image);
  342                      return(-1);
  343                   }
  344                   g_free(plane);
  345                }
  346             }
  347          }
  348       }
  349       else if(!load_mipmaps(fp, &hdr, &d, image, "", &l, pixels, buf))
  350       {
  351          fclose(fp);
  352          gimp_image_delete(image);
  353          return(-1);
  354       }
  355    }
  356 
  357    if(hdr.pixelfmt.flags & DDPF_PALETTEINDEXED8)
  358       g_free(d.palette);
  359 
  360    g_free(buf);
  361    g_free(pixels);
  362    fclose(fp);
  363 
  364    layers = gimp_image_get_layers(image, &layer_count);
  365    gimp_image_set_active_layer(image, layers[0]);
  366 
  367    return(image);
  368 }
  369 
  370 static int read_header(dds_header_t *hdr, FILE *fp)
  371 {
  372    unsigned char buf[DDS_HEADERSIZE];
  373 
  374    memset(hdr, 0, sizeof(dds_header_t));
  375 
  376    if(fread(buf, 1, DDS_HEADERSIZE, fp) != DDS_HEADERSIZE)
  377       return(0);
  378 
  379    hdr->magic[0] = buf[0];
  380    hdr->magic[1] = buf[1];
  381    hdr->magic[2] = buf[2];
  382    hdr->magic[3] = buf[3];
  383 
  384    hdr->size = GETL32(buf + 4);
  385    hdr->flags = GETL32(buf + 8);
  386    hdr->height = GETL32(buf + 12);
  387    hdr->width = GETL32(buf + 16);
  388    hdr->pitch_or_linsize = GETL32(buf + 20);
  389    hdr->depth = GETL32(buf + 24);
  390    hdr->num_mipmaps = GETL32(buf + 28);
  391 
  392    hdr->pixelfmt.size = GETL32(buf + 76);
  393    hdr->pixelfmt.flags = GETL32(buf + 80);
  394    hdr->pixelfmt.fourcc[0] = buf[84];
  395    hdr->pixelfmt.fourcc[1] = buf[85];
  396    hdr->pixelfmt.fourcc[2] = buf[86];
  397    hdr->pixelfmt.fourcc[3] = buf[87];
  398    hdr->pixelfmt.bpp = GETL32(buf + 88);
  399    hdr->pixelfmt.rmask = GETL32(buf + 92);
  400    hdr->pixelfmt.gmask = GETL32(buf + 96);
  401    hdr->pixelfmt.bmask = GETL32(buf + 100);
  402    hdr->pixelfmt.amask = GETL32(buf + 104);
  403 
  404    hdr->caps.caps1 = GETL32(buf + 108);
  405    hdr->caps.caps2 = GETL32(buf + 112);
  406 
  407    return(1);
  408 }
  409 
  410 static int validate_header(dds_header_t *hdr)
  411 {
  412    if(memcmp(hdr->magic, "DDS ", 4))
  413    {
  414       g_message("Invalid DDS file.\n");
  415       return(0);
  416    }
  417 
  418    if((hdr->flags & DDSD_PITCH) == (hdr->flags & DDSD_LINEARSIZE))
  419    {
  420       //g_message("Warning: DDSD_PITCH or DDSD_LINEARSIZE is not set.\n");
  421       if(hdr->pixelfmt.flags & DDPF_FOURCC)
  422          hdr->flags |= DDSD_LINEARSIZE;
  423       else
  424          hdr->flags |= DDSD_PITCH;
  425    }
  426 /*
  427    if((hdr->pixelfmt.flags & DDPF_FOURCC) ==
  428       (hdr->pixelfmt.flags & DDPF_RGB))
  429    {
  430       g_message("Invalid pixel format.\n");
  431       return(0);
  432    }
  433 */
  434    if((hdr->pixelfmt.flags & DDPF_FOURCC) &&
  435       memcmp(hdr->pixelfmt.fourcc, "DXT1", 4) &&
  436       memcmp(hdr->pixelfmt.fourcc, "DXT3", 4) &&
  437       memcmp(hdr->pixelfmt.fourcc, "DXT5", 4) &&
  438       memcmp(hdr->pixelfmt.fourcc, "ATI1", 4) &&
  439       memcmp(hdr->pixelfmt.fourcc, "ATI2", 4))
  440    {
  441       g_message("Invalid compression format.\n"
  442                 "Only DXT1, DXT3, DXT5, ATI1N and ATI2N formats are supported.\n");
  443       return(0);
  444    }
  445 
  446    if(hdr->pixelfmt.flags & DDPF_RGB)
  447    {
  448       if((hdr->pixelfmt.bpp !=  8) &&
  449          (hdr->pixelfmt.bpp != 16) &&
  450          (hdr->pixelfmt.bpp != 24) &&
  451          (hdr->pixelfmt.bpp != 32))
  452       {
  453          g_message("Invalid BPP.\n");
  454          return(0);
  455       }
  456    }
  457    else if(hdr->pixelfmt.flags & DDPF_LUMINANCE)
  458    {
  459       if((hdr->pixelfmt.bpp !=  8) &&
  460          (hdr->pixelfmt.bpp != 16))
  461       {
  462          g_message("Invalid BPP.\n");
  463          return(0);
  464       }
  465 
  466       hdr->pixelfmt.flags |= DDPF_RGB;
  467    }
  468    else if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  469    {
  470       hdr->pixelfmt.flags |= DDPF_RGB;
  471    }
  472 
  473    if(!(hdr->pixelfmt.flags & DDPF_RGB) &&
  474       !(hdr->pixelfmt.flags & DDPF_ALPHA) &&
  475       !(hdr->pixelfmt.flags & DDPF_FOURCC) &&
  476       !(hdr->pixelfmt.flags & DDPF_LUMINANCE))
  477    {
  478       g_message("Unknown pixel format!  Taking a guess, expect trouble!");
  479       switch(GETL32(hdr->pixelfmt.fourcc))
  480       {
  481          case CHAR32('D', 'X', 'T', '1'):
  482          case CHAR32('D', 'X', 'T', '3'):
  483          case CHAR32('D', 'X', 'T', '5'):
  484          case CHAR32('A', 'T', 'I', '1'):
  485          case CHAR32('A', 'T', 'I', '2'):
  486             hdr->pixelfmt.flags |= DDPF_FOURCC;
  487             break;
  488          default:
  489             switch(hdr->pixelfmt.bpp)
  490             {
  491                case 8:
  492                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  493                      hdr->pixelfmt.flags |= DDPF_ALPHA;
  494                   else
  495                      hdr->pixelfmt.flags |= DDPF_LUMINANCE;
  496                   break;
  497                case 16:
  498                case 24:
  499                case 32:
  500                   hdr->pixelfmt.flags |= DDPF_RGB;
  501                   break;
  502                default:
  503                   g_message("Invalid pixel format.");
  504                   return(0);
  505             }
  506             break;
  507       }
  508    }
  509 
  510    return(1);
  511 }
  512 
  513 static int load_layer(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  514                       gint32 image, unsigned int level, char *prefix,
  515                       unsigned int *l, guchar *pixels, unsigned char *buf)
  516 {
  517    GimpDrawable *drawable;
  518    GimpPixelRgn pixel_region;
  519    GimpImageType type = GIMP_RGBA_IMAGE;
  520    gchar *layer_name;
  521    gint x, y, z, n;
  522    gint32 layer;
  523    unsigned int width = hdr->width >> level;
  524    unsigned int height = hdr->height >> level;
  525    unsigned int size = hdr->pitch_or_linsize >> (2 * level);
  526    int format = DDS_COMPRESS_NONE;
  527 
  528    if(width < 1) width = 1;
  529    if(height < 1) height = 1;
  530 
  531    switch(d->bpp)
  532    {
  533       case 1:
  534          if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  535             type = GIMP_INDEXED_IMAGE;
  536          else if(hdr->pixelfmt.rmask == 0xe0)
  537             type = GIMP_RGB_IMAGE;
  538          else if(hdr->pixelfmt.flags & DDPF_ALPHA)
  539             type = GIMP_GRAYA_IMAGE;
  540          else
  541             type = GIMP_GRAY_IMAGE;
  542          break;
  543       case 2:
  544          if(hdr->pixelfmt.amask == 0xf000) //RGBA4
  545             type = GIMP_RGBA_IMAGE;
  546          else if(hdr->pixelfmt.amask == 0xff00) //L8A8
  547             type = GIMP_GRAYA_IMAGE;
  548          else if(hdr->pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  549             type = (hdr->pixelfmt.amask == 0x8000) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
  550          else //L16
  551             type = GIMP_GRAY_IMAGE;
  552          break;
  553       case 3: type = GIMP_RGB_IMAGE;   break;
  554       case 4: type = GIMP_RGBA_IMAGE;  break;
  555    }
  556 
  557    layer_name = (level) ? g_strdup_printf("mipmap %d %s", level, prefix) :
  558                           g_strdup_printf("main surface %s", prefix);
  559 
  560    layer = gimp_layer_new(image, layer_name, width, height, type, 100,
  561                           GIMP_NORMAL_MODE);
  562    g_free(layer_name);
  563 
  564    gimp_image_add_layer(image, layer, *l);
  565    if((*l)++) gimp_drawable_set_visible(layer, FALSE);
  566 
  567    drawable = gimp_drawable_get(layer);
  568 
  569    gimp_pixel_rgn_init(&pixel_region, drawable, 0, 0, drawable->width,
  570                        drawable->height, TRUE, FALSE);
  571 
  572    if(hdr->pixelfmt.flags & DDPF_FOURCC)
  573    {
  574       unsigned int w = (width  + 3) >> 2;
  575       unsigned int h = (height + 3) >> 2;
  576 
  577       switch(GETL32(hdr->pixelfmt.fourcc))
  578       {
  579          case CHAR32('D', 'X', 'T', '1'): format = DDS_COMPRESS_BC1; break;
  580          case CHAR32('D', 'X', 'T', '3'): format = DDS_COMPRESS_BC2; break;
  581          case CHAR32('D', 'X', 'T', '5'): format = DDS_COMPRESS_BC3; break;
  582          case CHAR32('A', 'T', 'I', '1'): format = DDS_COMPRESS_BC4; break;
  583          case CHAR32('A', 'T', 'I', '2'): format = DDS_COMPRESS_BC5; break;
  584       }
  585 
  586       if(w == 0) w = 1;
  587       if(h == 0) h = 1;
  588       size = w * h;
  589       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
  590          size *= 8;
  591       else
  592          size *= 16;
  593    }
  594 
  595    if((hdr->flags & DDSD_LINEARSIZE) &&
  596       !fread(buf, size, 1, fp))
  597    {
  598       g_message("Unexpected EOF.\n");
  599       return(0);
  600    }
  601 
  602    if(hdr->pixelfmt.flags & DDPF_RGB || hdr->pixelfmt.flags & DDPF_ALPHA)
  603    {
  604       z = 0;
  605       for(y = 0, n = 0; y < height; ++y, ++n)
  606       {
  607          if(n >= d->tile_height)
  608          {
  609             gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  610                                     drawable->width, n);
  611             n = 0;
  612             if(interactive_dds)
  613                gimp_progress_update((double)y / (double)hdr->height);
  614          }
  615 
  616          if((hdr->flags & DDSD_PITCH) &&
  617             !fread(buf, width * d->bpp, 1, fp))
  618          {
  619             g_message("Unexpected EOF.\n");
  620             return(0);
  621          }
  622 
  623          if(!(hdr->flags & DDSD_LINEARSIZE)) z = 0;
  624 
  625          for(x = 0; x < drawable->width; ++x)
  626          {
  627             unsigned int pixel = buf[z];
  628             unsigned int pos = (n * drawable->width + x) * d->gimp_bpp;
  629 
  630             if(d->bpp > 1) pixel += ((unsigned int)buf[z + 1] <<  8);
  631             if(d->bpp > 2) pixel += ((unsigned int)buf[z + 2] << 16);
  632             if(d->bpp > 3) pixel += ((unsigned int)buf[z + 3] << 24);
  633 
  634             if(d->bpp >= 3)
  635             {
  636                if(hdr->pixelfmt.amask == 0xc0000000) // handle RGB10A2
  637                {
  638                   pixels[pos + 0] = (pixel >> d->rshift) >> 2;
  639                   pixels[pos + 1] = (pixel >> d->gshift) >> 2;
  640                   pixels[pos + 2] = (pixel >> d->bshift) >> 2;
  641                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  642                      pixels[pos + 3] = (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  643                }
  644                else
  645                {
  646                   pixels[pos] =
  647                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  648                   pixels[pos + 1] =
  649                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  650                   pixels[pos + 2] =
  651                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  652                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  653                   {
  654                      pixels[pos + 3] =
  655                         (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  656                   }
  657                }
  658             }
  659             else if(d->bpp == 2)
  660             {
  661                if(hdr->pixelfmt.amask == 0xf000) //RGBA4
  662                {
  663                   pixels[pos] =
  664                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  665                   pixels[pos + 1] =
  666                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  667                   pixels[pos + 2] =
  668                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  669                   pixels[pos + 3] =
  670                      (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  671                }
  672                else if(hdr->pixelfmt.amask == 0xff00) //L8A8
  673                {
  674                   pixels[pos] =
  675                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  676                   pixels[pos + 1] =
  677                      (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  678                }
  679                else if(hdr->pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  680                {
  681                   pixels[pos] =
  682                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  683                   pixels[pos + 1] =
  684                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  685                   pixels[pos + 2] =
  686                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  687                   if(hdr->pixelfmt.amask == 0x8000)
  688                   {
  689                      pixels[pos + 3] =
  690                          (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  691                   }
  692                }
  693                else //L16
  694                   pixels[pos] = (unsigned char)(255 * ((float)(pixel & 0xffff) / 65535.0f));
  695             }
  696             else
  697             {
  698                if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  699                {
  700                   pixels[pos] = pixel & 0xff;
  701                }
  702                else if(hdr->pixelfmt.rmask == 0xe0) // R3G3B2
  703                {
  704                   pixels[pos] =
  705                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  706                   pixels[pos + 1] =
  707                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  708                   pixels[pos + 2] =
  709                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  710                }
  711                else if(hdr->pixelfmt.flags & DDPF_ALPHA)
  712                {
  713                   pixels[pos + 0] = 255;
  714                   pixels[pos + 1] = pixel & 0xff;
  715                }
  716                else // LUMINANCE
  717                {
  718                   pixels[pos] = pixel & 0xff;
  719                }
  720             }
  721 
  722             z += d->bpp;
  723          }
  724       }
  725 
  726       gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  727                               drawable->width, n);
  728    }
  729    else if(hdr->pixelfmt.flags & DDPF_FOURCC)
  730    {
  731       unsigned char *dst;
  732 
  733       if(!(hdr->flags & DDSD_LINEARSIZE))
  734       {
  735          g_message("Image marked as compressed, but DDSD_LINEARSIZE is not set.\n");
  736          return(0);
  737       }
  738 
  739       dst = g_malloc(width * height * d->gimp_bpp);
  740       memset(dst, 0, width * height * d->gimp_bpp);
  741 
  742       if(d->gimp_bpp == 4)
  743       {
  744         for(y = 0; y < height; ++y)
  745             for(x = 0; x < width; ++x)
  746                dst[y * (width * 4) + x + 3] = 255;
  747       }
  748 
  749       dxt_decompress(dst, buf, format, size, width, height, d->gimp_bpp);
  750 
  751       z = 0;
  752       for(y = 0, n = 0; y < height; ++y, ++n)
  753       {
  754          if(n >= d->tile_height)
  755          {
  756             gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  757                                     drawable->width, n);
  758             n = 0;
  759             if(interactive_dds)
  760                gimp_progress_update((double)y / (double)hdr->height);
  761          }
  762 
  763          memcpy(pixels + n * drawable->width * d->gimp_bpp,
  764                 dst + y * drawable->width * d->gimp_bpp,
  765                 width * d->gimp_bpp);
  766       }
  767 
  768       gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  769                               drawable->width, n);
  770 
  771       g_free(dst);
  772    }
  773 
  774    gimp_drawable_flush(drawable);
  775    gimp_drawable_detach(drawable);
  776 
  777    return(1);
  778 }
  779 
  780 static int load_mipmaps(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  781                         gint32 image, char *prefix, unsigned int *l,
  782                         guchar *pixels, unsigned char *buf)
  783 {
  784    unsigned int level;
  785 
  786    if((hdr->flags & DDSD_MIPMAPCOUNT) &&
  787       (hdr->caps.caps1 & DDSCAPS_MIPMAP))
  788    {
  789       for(level = 1; level < hdr->num_mipmaps; ++level)
  790       {
  791          if(!load_layer(fp, hdr, d, image, level, prefix, l, pixels, buf))
  792             return(0);
  793       }
  794    }
  795    return(1);
  796 }
  797 
  798 static int load_face(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  799                      gint32 image, char *prefix, unsigned int *l,
  800                      guchar *pixels, unsigned char *buf)
  801 {
  802    if(!load_layer(fp, hdr, d, image, 0, prefix, l, pixels, buf))
  803       return(0);
  804    return(load_mipmaps(fp, hdr, d, image, prefix, l, pixels, buf));
  805 }
  806 
  807 static unsigned char color_bits(unsigned int mask)
  808 {
  809    unsigned char i = 0;
  810 
  811    while(mask)
  812    {
  813       if(mask & 1) ++i;
  814       mask >>= 1;
  815    }
  816    return(i);
  817 }
  818 
  819 static unsigned char color_shift(unsigned int mask)
  820 {
  821    unsigned char i = 0;
  822 
  823    if(!mask) return(0);
  824    while(!((mask >> i) & 1)) ++i;
  825    return(i);
  826 }

ViewVC Help
Powered by ViewVC 1.0.4