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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 106 - (download) (as text) (annotate)
Thu May 8 01:29:25 2008 UTC (18 months, 2 weeks ago) by cocidius
File size: 28150 byte(s)
Release 2.0.4 tag
    1 /*
    2    DDS GIMP plugin
    3 
    4    Copyright (C) 2004-2008 Shawn Kirst <skirst@insightbb.com>,
    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 static int load_dialog(void);
   69 
   70 static int runme = 0;
   71 
   72 GimpPDBStatusType read_dds(gchar *filename, gint32 *imageID)
   73 {
   74    gint32 image = 0;
   75    unsigned char *buf;
   76    unsigned int l = 0;
   77    guchar *pixels;
   78    gchar *tmp;
   79    FILE *fp;
   80    dds_header_t hdr;
   81    dds_load_info_t d;
   82    gint *layers, layer_count;
   83    GimpImageBaseType type;
   84    int i, j;
   85 
   86    if(interactive_dds && dds_read_vals.show_dialog)
   87    {
   88       if(!load_dialog())
   89          return(GIMP_PDB_CANCEL);
   90    }
   91 
   92    fp = fopen(filename, "rb");
   93    if(fp == 0)
   94    {
   95       g_message("Error opening file.\n");
   96       return(GIMP_PDB_EXECUTION_ERROR);
   97    }
   98 
   99    if(interactive_dds)
  100    {
  101       if(strrchr(filename, '/'))
  102          tmp = g_strdup_printf("Loading %s:", strrchr(filename, '/') + 1);
  103       else
  104          tmp = g_strdup_printf("Loading %s:", filename);
  105       gimp_progress_init(tmp);
  106       g_free(tmp);
  107    }
  108 
  109    read_header(&hdr, fp);
  110    if(!validate_header(&hdr))
  111    {
  112       fclose(fp);
  113       g_message("Invalid DDS header!\n");
  114       return(GIMP_PDB_EXECUTION_ERROR);
  115    }
  116 
  117    /* a lot of DDS images out there don't have this for some reason -_- */
  118    if(hdr.pitch_or_linsize == 0)
  119    {
  120       if(hdr.pixelfmt.flags & DDPF_FOURCC) /* assume linear size */
  121       {
  122          hdr.pitch_or_linsize = ((hdr.width + 3) >> 2) * ((hdr.height + 3) >> 2);
  123          if(hdr.pixelfmt.fourcc[3] == '1')
  124             hdr.pitch_or_linsize *= 8;
  125          else
  126             hdr.pitch_or_linsize *= 16;
  127       }
  128       else /* assume pitch */
  129       {
  130          hdr.pitch_or_linsize = hdr.height * hdr.width *
  131             (hdr.pixelfmt.bpp >> 3);
  132       }
  133    }
  134 
  135    if(hdr.pixelfmt.flags & DDPF_FOURCC)
  136    {
  137       if(hdr.pixelfmt.fourcc[0] == 'D')
  138          hdr.pixelfmt.flags |= DDPF_ALPHAPIXELS;
  139    }
  140 
  141    if(hdr.pixelfmt.flags & DDPF_FOURCC)
  142    {
  143       switch(GETL32(hdr.pixelfmt.fourcc))
  144       {
  145          case CHAR32('A', 'T', 'I', '1'):
  146             d.bpp = d.gimp_bpp = 1;
  147             type = GIMP_GRAY;
  148             break;
  149          case CHAR32('A', 'T', 'I', '2'):
  150             d.bpp = d.gimp_bpp = 3;
  151             type = GIMP_RGB;
  152             break;
  153          default:
  154             d.bpp = d.gimp_bpp = 4;
  155             type = GIMP_RGB;
  156             break;
  157       }
  158    }
  159    else
  160    {
  161       d.bpp = hdr.pixelfmt.bpp >> 3;
  162 
  163       if(d.bpp == 2)
  164       {
  165          if(hdr.pixelfmt.amask == 0xf000) // RGBA4
  166          {
  167             d.gimp_bpp = 4;
  168             type = GIMP_RGB;
  169          }
  170          else if(hdr.pixelfmt.amask == 0xff00) //L8A8
  171          {
  172             d.gimp_bpp = 2;
  173             type = GIMP_GRAY;
  174          }
  175          else if(hdr.pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  176          {
  177             if(hdr.pixelfmt.amask == 0x8000) // RGB5A1
  178                d.gimp_bpp = 4;
  179             else
  180                d.gimp_bpp = 3;
  181 
  182             type = GIMP_RGB;
  183          }
  184          else //L16
  185          {
  186             d.gimp_bpp = 1;
  187             type = GIMP_GRAY;
  188          }
  189       }
  190       else
  191       {
  192          if(hdr.pixelfmt.flags & DDPF_PALETTEINDEXED8)
  193          {
  194             type = GIMP_INDEXED;
  195             d.gimp_bpp = 1;
  196          }
  197          else if(hdr.pixelfmt.rmask == 0xe0) // R3G3B2
  198          {
  199             type = GIMP_RGB;
  200             d.gimp_bpp = 3;
  201          }
  202          else
  203          {
  204             /* test alpha only image */
  205             if(d.bpp == 1 && (hdr.pixelfmt.flags & DDPF_ALPHA))
  206             {
  207                d.gimp_bpp = 2;
  208                type = GIMP_GRAY;
  209             }
  210             else
  211             {
  212                d.gimp_bpp = d.bpp;
  213                type = (d.bpp == 1) ? GIMP_GRAY : GIMP_RGB;
  214             }
  215          }
  216       }
  217    }
  218 
  219    image = gimp_image_new(hdr.width, hdr.height, type);
  220 
  221    if(image == -1)
  222    {
  223       g_message("Can't allocate new image.\n");
  224       fclose(fp);
  225       return(GIMP_PDB_EXECUTION_ERROR);
  226    }
  227 
  228    gimp_image_set_filename(image, filename);
  229 
  230    if(hdr.pixelfmt.flags & DDPF_PALETTEINDEXED8)
  231    {
  232       d.palette = g_malloc(256 * 4);
  233       fread(d.palette, 1, 256 * 4, fp);
  234       for(i = j = 0; i < 768; i += 3, j += 4)
  235       {
  236          d.palette[i + 0] = d.palette[j + 0];
  237          d.palette[i + 1] = d.palette[j + 1];
  238          d.palette[i + 2] = d.palette[j + 2];
  239       }
  240       gimp_image_set_colormap(image, d.palette, 256);
  241    }
  242 
  243    d.tile_height = gimp_tile_height();
  244 
  245    pixels = g_new(guchar, d.tile_height * hdr.width * d.gimp_bpp);
  246    buf = g_malloc(hdr.pitch_or_linsize);
  247 
  248    d.rshift = color_shift(hdr.pixelfmt.rmask);
  249    d.gshift = color_shift(hdr.pixelfmt.gmask);
  250    d.bshift = color_shift(hdr.pixelfmt.bmask);
  251    d.ashift = color_shift(hdr.pixelfmt.amask);
  252    d.rbits = color_bits(hdr.pixelfmt.rmask);
  253    d.gbits = color_bits(hdr.pixelfmt.gmask);
  254    d.bbits = color_bits(hdr.pixelfmt.bmask);
  255    d.abits = color_bits(hdr.pixelfmt.amask);
  256    d.rmask = hdr.pixelfmt.rmask >> d.rshift << (8 - d.rbits);
  257    d.gmask = hdr.pixelfmt.gmask >> d.gshift << (8 - d.gbits);
  258    d.bmask = hdr.pixelfmt.bmask >> d.bshift << (8 - d.bbits);
  259    d.amask = hdr.pixelfmt.amask >> d.ashift << (8 - d.abits);
  260 
  261    if(!(hdr.caps.caps2 & DDSCAPS2_CUBEMAP) &&
  262       !(hdr.caps.caps2 & DDSCAPS2_VOLUME))
  263    {
  264       if(!load_layer(fp, &hdr, &d, image, 0, "", &l, pixels, buf))
  265       {
  266          fclose(fp);
  267          gimp_image_delete(image);
  268          return(GIMP_PDB_EXECUTION_ERROR);
  269       }
  270    }
  271 
  272    if(hdr.caps.caps1 & DDSCAPS_COMPLEX)
  273    {
  274       if(hdr.caps.caps2 & DDSCAPS2_CUBEMAP)
  275       {
  276          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) &&
  277             !load_face(fp, &hdr, &d, image, "(positive x)", &l, pixels, buf))
  278          {
  279             fclose(fp);
  280             gimp_image_delete(image);
  281             return(GIMP_PDB_EXECUTION_ERROR);
  282          }
  283          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) &&
  284             !load_face(fp, &hdr, &d, image, "(negative x)", &l, pixels, buf))
  285          {
  286             fclose(fp);
  287             gimp_image_delete(image);
  288             return(GIMP_PDB_EXECUTION_ERROR);
  289          }
  290          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) &&
  291             !load_face(fp, &hdr, &d, image, "(positive y)", &l, pixels, buf))
  292          {
  293             fclose(fp);
  294             gimp_image_delete(image);
  295             return(GIMP_PDB_EXECUTION_ERROR);
  296          }
  297          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) &&
  298             !load_face(fp, &hdr, &d, image, "(negative y)", &l, pixels, buf))
  299          {
  300             fclose(fp);
  301             gimp_image_delete(image);
  302             return(GIMP_PDB_EXECUTION_ERROR);
  303          }
  304          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) &&
  305             !load_face(fp, &hdr, &d, image, "(positive z)", &l, pixels, buf))
  306          {
  307             fclose(fp);
  308             gimp_image_delete(image);
  309             return(GIMP_PDB_EXECUTION_ERROR);
  310          }
  311          if((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) &&
  312             !load_face(fp, &hdr, &d, image, "(negative z)", &l, pixels, buf))
  313          {
  314             fclose(fp);
  315             gimp_image_delete(image);
  316             return(GIMP_PDB_EXECUTION_ERROR);
  317          }
  318       }
  319       else if((hdr.caps.caps2 & DDSCAPS2_VOLUME) &&
  320               (hdr.flags & DDSD_DEPTH))
  321       {
  322          unsigned int i, level;
  323          char *plane;
  324          for(i = 0; i < hdr.depth; ++i)
  325          {
  326             plane = g_strdup_printf("(z = %d)", i);
  327             if(!load_layer(fp, &hdr, &d, image, 0, plane, &l, pixels, buf))
  328             {
  329                g_free(plane);
  330                fclose(fp);
  331                gimp_image_delete(image);
  332                return(GIMP_PDB_EXECUTION_ERROR);
  333             }
  334             g_free(plane);
  335          }
  336 
  337          if((hdr.flags & DDSD_MIPMAPCOUNT) &&
  338             (hdr.caps.caps1 & DDSCAPS_MIPMAP) &&
  339             (dds_read_vals.mipmaps != 0))
  340          {
  341             for(level = 1; level < hdr.num_mipmaps; ++level)
  342             {
  343                int n = hdr.depth >> level;
  344                if(n < 1) n = 1;
  345                for(i = 0; i < n; ++i)
  346                {
  347                   plane = g_strdup_printf("(z = %d)", i);
  348                   if(!load_layer(fp, &hdr, &d, image, level, plane, &l, pixels, buf))
  349                   {
  350                      g_free(plane);
  351                      fclose(fp);
  352                      gimp_image_delete(image);
  353                      return(GIMP_PDB_EXECUTION_ERROR);
  354                   }
  355                   g_free(plane);
  356                }
  357             }
  358          }
  359       }
  360       else if(dds_read_vals.mipmaps)
  361       {
  362          if(!load_mipmaps(fp, &hdr, &d, image, "", &l, pixels, buf))
  363          {
  364             fclose(fp);
  365             gimp_image_delete(image);
  366             return(GIMP_PDB_EXECUTION_ERROR);
  367          }
  368       }
  369    }
  370 
  371    if(hdr.pixelfmt.flags & DDPF_PALETTEINDEXED8)
  372       g_free(d.palette);
  373 
  374    g_free(buf);
  375    g_free(pixels);
  376    fclose(fp);
  377 
  378    layers = gimp_image_get_layers(image, &layer_count);
  379    gimp_image_set_active_layer(image, layers[0]);
  380 
  381    *imageID = image;
  382 
  383    return(GIMP_PDB_SUCCESS);
  384 }
  385 
  386 static int read_header(dds_header_t *hdr, FILE *fp)
  387 {
  388    unsigned char buf[DDS_HEADERSIZE];
  389 
  390    memset(hdr, 0, sizeof(dds_header_t));
  391 
  392    if(fread(buf, 1, DDS_HEADERSIZE, fp) != DDS_HEADERSIZE)
  393       return(0);
  394 
  395    hdr->magic[0] = buf[0];
  396    hdr->magic[1] = buf[1];
  397    hdr->magic[2] = buf[2];
  398    hdr->magic[3] = buf[3];
  399 
  400    hdr->size = GETL32(buf + 4);
  401    hdr->flags = GETL32(buf + 8);
  402    hdr->height = GETL32(buf + 12);
  403    hdr->width = GETL32(buf + 16);
  404    hdr->pitch_or_linsize = GETL32(buf + 20);
  405    hdr->depth = GETL32(buf + 24);
  406    hdr->num_mipmaps = GETL32(buf + 28);
  407 
  408    hdr->pixelfmt.size = GETL32(buf + 76);
  409    hdr->pixelfmt.flags = GETL32(buf + 80);
  410    hdr->pixelfmt.fourcc[0] = buf[84];
  411    hdr->pixelfmt.fourcc[1] = buf[85];
  412    hdr->pixelfmt.fourcc[2] = buf[86];
  413    hdr->pixelfmt.fourcc[3] = buf[87];
  414    hdr->pixelfmt.bpp = GETL32(buf + 88);
  415    hdr->pixelfmt.rmask = GETL32(buf + 92);
  416    hdr->pixelfmt.gmask = GETL32(buf + 96);
  417    hdr->pixelfmt.bmask = GETL32(buf + 100);
  418    hdr->pixelfmt.amask = GETL32(buf + 104);
  419 
  420    hdr->caps.caps1 = GETL32(buf + 108);
  421    hdr->caps.caps2 = GETL32(buf + 112);
  422 
  423    return(1);
  424 }
  425 
  426 static int validate_header(dds_header_t *hdr)
  427 {
  428    if(memcmp(hdr->magic, "DDS ", 4))
  429    {
  430       g_message("Invalid DDS file.\n");
  431       return(0);
  432    }
  433 
  434    if((hdr->flags & DDSD_PITCH) == (hdr->flags & DDSD_LINEARSIZE))
  435    {
  436       //g_message("Warning: DDSD_PITCH or DDSD_LINEARSIZE is not set.\n");
  437       if(hdr->pixelfmt.flags & DDPF_FOURCC)
  438          hdr->flags |= DDSD_LINEARSIZE;
  439       else
  440          hdr->flags |= DDSD_PITCH;
  441    }
  442 /*
  443    if((hdr->pixelfmt.flags & DDPF_FOURCC) ==
  444       (hdr->pixelfmt.flags & DDPF_RGB))
  445    {
  446       g_message("Invalid pixel format.\n");
  447       return(0);
  448    }
  449 */
  450    if((hdr->pixelfmt.flags & DDPF_FOURCC) &&
  451       memcmp(hdr->pixelfmt.fourcc, "DXT1", 4) &&
  452       memcmp(hdr->pixelfmt.fourcc, "DXT3", 4) &&
  453       memcmp(hdr->pixelfmt.fourcc, "DXT5", 4) &&
  454       memcmp(hdr->pixelfmt.fourcc, "ATI1", 4) &&
  455       memcmp(hdr->pixelfmt.fourcc, "ATI2", 4))
  456    {
  457       g_message("Invalid compression format.\n"
  458                 "Only DXT1, DXT3, DXT5, ATI1N and ATI2N formats are supported.\n");
  459       return(0);
  460    }
  461 
  462    if(hdr->pixelfmt.flags & DDPF_RGB)
  463    {
  464       if((hdr->pixelfmt.bpp !=  8) &&
  465          (hdr->pixelfmt.bpp != 16) &&
  466          (hdr->pixelfmt.bpp != 24) &&
  467          (hdr->pixelfmt.bpp != 32))
  468       {
  469          g_message("Invalid BPP.\n");
  470          return(0);
  471       }
  472    }
  473    else if(hdr->pixelfmt.flags & DDPF_LUMINANCE)
  474    {
  475       if((hdr->pixelfmt.bpp !=  8) &&
  476          (hdr->pixelfmt.bpp != 16))
  477       {
  478          g_message("Invalid BPP.\n");
  479          return(0);
  480       }
  481 
  482       hdr->pixelfmt.flags |= DDPF_RGB;
  483    }
  484    else if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  485    {
  486       hdr->pixelfmt.flags |= DDPF_RGB;
  487    }
  488 
  489    if(!(hdr->pixelfmt.flags & DDPF_RGB) &&
  490       !(hdr->pixelfmt.flags & DDPF_ALPHA) &&
  491       !(hdr->pixelfmt.flags & DDPF_FOURCC) &&
  492       !(hdr->pixelfmt.flags & DDPF_LUMINANCE))
  493    {
  494       g_message("Unknown pixel format!  Taking a guess, expect trouble!");
  495       switch(GETL32(hdr->pixelfmt.fourcc))
  496       {
  497          case CHAR32('D', 'X', 'T', '1'):
  498          case CHAR32('D', 'X', 'T', '3'):
  499          case CHAR32('D', 'X', 'T', '5'):
  500          case CHAR32('A', 'T', 'I', '1'):
  501          case CHAR32('A', 'T', 'I', '2'):
  502             hdr->pixelfmt.flags |= DDPF_FOURCC;
  503             break;
  504          default:
  505             switch(hdr->pixelfmt.bpp)
  506             {
  507                case 8:
  508                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  509                      hdr->pixelfmt.flags |= DDPF_ALPHA;
  510                   else
  511                      hdr->pixelfmt.flags |= DDPF_LUMINANCE;
  512                   break;
  513                case 16:
  514                case 24:
  515                case 32:
  516                   hdr->pixelfmt.flags |= DDPF_RGB;
  517                   break;
  518                default:
  519                   g_message("Invalid pixel format.");
  520                   return(0);
  521             }
  522             break;
  523       }
  524    }
  525 
  526    return(1);
  527 }
  528 
  529 static int load_layer(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  530                       gint32 image, unsigned int level, char *prefix,
  531                       unsigned int *l, guchar *pixels, unsigned char *buf)
  532 {
  533    GimpDrawable *drawable;
  534    GimpPixelRgn pixel_region;
  535    GimpImageType type = GIMP_RGBA_IMAGE;
  536    gchar *layer_name;
  537    gint x, y, z, n;
  538    gint32 layer;
  539    unsigned int width = hdr->width >> level;
  540    unsigned int height = hdr->height >> level;
  541    unsigned int size = hdr->pitch_or_linsize >> (2 * level);
  542    int format = DDS_COMPRESS_NONE;
  543 
  544    if(width < 1) width = 1;
  545    if(height < 1) height = 1;
  546 
  547    switch(d->bpp)
  548    {
  549       case 1:
  550          if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  551             type = GIMP_INDEXED_IMAGE;
  552          else if(hdr->pixelfmt.rmask == 0xe0)
  553             type = GIMP_RGB_IMAGE;
  554          else if(hdr->pixelfmt.flags & DDPF_ALPHA)
  555             type = GIMP_GRAYA_IMAGE;
  556          else
  557             type = GIMP_GRAY_IMAGE;
  558          break;
  559       case 2:
  560          if(hdr->pixelfmt.amask == 0xf000) //RGBA4
  561             type = GIMP_RGBA_IMAGE;
  562          else if(hdr->pixelfmt.amask == 0xff00) //L8A8
  563             type = GIMP_GRAYA_IMAGE;
  564          else if(hdr->pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  565             type = (hdr->pixelfmt.amask == 0x8000) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
  566          else //L16
  567             type = GIMP_GRAY_IMAGE;
  568          break;
  569       case 3: type = GIMP_RGB_IMAGE;   break;
  570       case 4: type = GIMP_RGBA_IMAGE;  break;
  571    }
  572 
  573    layer_name = (level) ? g_strdup_printf("mipmap %d %s", level, prefix) :
  574                           g_strdup_printf("main surface %s", prefix);
  575 
  576    layer = gimp_layer_new(image, layer_name, width, height, type, 100,
  577                           GIMP_NORMAL_MODE);
  578    g_free(layer_name);
  579 
  580    gimp_image_add_layer(image, layer, *l);
  581    if((*l)++) gimp_drawable_set_visible(layer, FALSE);
  582 
  583    drawable = gimp_drawable_get(layer);
  584 
  585    gimp_pixel_rgn_init(&pixel_region, drawable, 0, 0, drawable->width,
  586                        drawable->height, TRUE, FALSE);
  587 
  588    if(hdr->pixelfmt.flags & DDPF_FOURCC)
  589    {
  590       unsigned int w = (width  + 3) >> 2;
  591       unsigned int h = (height + 3) >> 2;
  592 
  593       switch(GETL32(hdr->pixelfmt.fourcc))
  594       {
  595          case CHAR32('D', 'X', 'T', '1'): format = DDS_COMPRESS_BC1; break;
  596          case CHAR32('D', 'X', 'T', '3'): format = DDS_COMPRESS_BC2; break;
  597          case CHAR32('D', 'X', 'T', '5'): format = DDS_COMPRESS_BC3; break;
  598          case CHAR32('A', 'T', 'I', '1'): format = DDS_COMPRESS_BC4; break;
  599          case CHAR32('A', 'T', 'I', '2'): format = DDS_COMPRESS_BC5; break;
  600       }
  601 
  602       if(w == 0) w = 1;
  603       if(h == 0) h = 1;
  604       size = w * h;
  605       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
  606          size *= 8;
  607       else
  608          size *= 16;
  609    }
  610 
  611    if((hdr->flags & DDSD_LINEARSIZE) &&
  612       !fread(buf, size, 1, fp))
  613    {
  614       g_message("Unexpected EOF.\n");
  615       return(0);
  616    }
  617 
  618    if(hdr->pixelfmt.flags & DDPF_RGB || hdr->pixelfmt.flags & DDPF_ALPHA)
  619    {
  620       z = 0;
  621       for(y = 0, n = 0; y < height; ++y, ++n)
  622       {
  623          if(n >= d->tile_height)
  624          {
  625             gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  626                                     drawable->width, n);
  627             n = 0;
  628             if(interactive_dds)
  629                gimp_progress_update((double)y / (double)hdr->height);
  630          }
  631 
  632          if((hdr->flags & DDSD_PITCH) &&
  633             !fread(buf, width * d->bpp, 1, fp))
  634          {
  635             g_message("Unexpected EOF.\n");
  636             return(0);
  637          }
  638 
  639          if(!(hdr->flags & DDSD_LINEARSIZE)) z = 0;
  640 
  641          for(x = 0; x < drawable->width; ++x)
  642          {
  643             unsigned int pixel = buf[z];
  644             unsigned int pos = (n * drawable->width + x) * d->gimp_bpp;
  645 
  646             if(d->bpp > 1) pixel += ((unsigned int)buf[z + 1] <<  8);
  647             if(d->bpp > 2) pixel += ((unsigned int)buf[z + 2] << 16);
  648             if(d->bpp > 3) pixel += ((unsigned int)buf[z + 3] << 24);
  649 
  650             if(d->bpp >= 3)
  651             {
  652                if(hdr->pixelfmt.amask == 0xc0000000) // handle RGB10A2
  653                {
  654                   pixels[pos + 0] = (pixel >> d->rshift) >> 2;
  655                   pixels[pos + 1] = (pixel >> d->gshift) >> 2;
  656                   pixels[pos + 2] = (pixel >> d->bshift) >> 2;
  657                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  658                      pixels[pos + 3] = (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  659                }
  660                else
  661                {
  662                   pixels[pos] =
  663                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  664                   pixels[pos + 1] =
  665                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  666                   pixels[pos + 2] =
  667                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  668                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  669                   {
  670                      pixels[pos + 3] =
  671                         (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  672                   }
  673                }
  674             }
  675             else if(d->bpp == 2)
  676             {
  677                if(hdr->pixelfmt.amask == 0xf000) //RGBA4
  678                {
  679                   pixels[pos] =
  680                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  681                   pixels[pos + 1] =
  682                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  683                   pixels[pos + 2] =
  684                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  685                   pixels[pos + 3] =
  686                      (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  687                }
  688                else if(hdr->pixelfmt.amask == 0xff00) //L8A8
  689                {
  690                   pixels[pos] =
  691                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  692                   pixels[pos + 1] =
  693                      (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  694                }
  695                else if(hdr->pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  696                {
  697                   pixels[pos] =
  698                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  699                   pixels[pos + 1] =
  700                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  701                   pixels[pos + 2] =
  702                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  703                   if(hdr->pixelfmt.amask == 0x8000)
  704                   {
  705                      pixels[pos + 3] =
  706                          (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  707                   }
  708                }
  709                else //L16
  710                   pixels[pos] = (unsigned char)(255 * ((float)(pixel & 0xffff) / 65535.0f));
  711             }
  712             else
  713             {
  714                if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  715                {
  716                   pixels[pos] = pixel & 0xff;
  717                }
  718                else if(hdr->pixelfmt.rmask == 0xe0) // R3G3B2
  719                {
  720                   pixels[pos] =
  721                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  722                   pixels[pos + 1] =
  723                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  724                   pixels[pos + 2] =
  725                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  726                }
  727                else if(hdr->pixelfmt.flags & DDPF_ALPHA)
  728                {
  729                   pixels[pos + 0] = 255;
  730                   pixels[pos + 1] = pixel & 0xff;
  731                }
  732                else // LUMINANCE
  733                {
  734                   pixels[pos] = pixel & 0xff;
  735                }
  736             }
  737 
  738             z += d->bpp;
  739          }
  740       }
  741 
  742       gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  743                               drawable->width, n);
  744    }
  745    else if(hdr->pixelfmt.flags & DDPF_FOURCC)
  746    {
  747       unsigned char *dst;
  748 
  749       if(!(hdr->flags & DDSD_LINEARSIZE))
  750       {
  751          g_message("Image marked as compressed, but DDSD_LINEARSIZE is not set.\n");
  752          return(0);
  753       }
  754 
  755       dst = g_malloc(width * height * d->gimp_bpp);
  756       memset(dst, 0, width * height * d->gimp_bpp);
  757 
  758       if(d->gimp_bpp == 4)
  759       {
  760         for(y = 0; y < height; ++y)
  761             for(x = 0; x < width; ++x)
  762                dst[y * (width * 4) + x + 3] = 255;
  763       }
  764 
  765       dxt_decompress(dst, buf, format, size, width, height, d->gimp_bpp);
  766 
  767       z = 0;
  768       for(y = 0, n = 0; y < height; ++y, ++n)
  769       {
  770          if(n >= d->tile_height)
  771          {
  772             gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  773                                     drawable->width, n);
  774             n = 0;
  775             if(interactive_dds)
  776                gimp_progress_update((double)y / (double)hdr->height);
  777          }
  778 
  779          memcpy(pixels + n * drawable->width * d->gimp_bpp,
  780                 dst + y * drawable->width * d->gimp_bpp,
  781                 width * d->gimp_bpp);
  782       }
  783 
  784       gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  785                               drawable->width, n);
  786 
  787       g_free(dst);
  788    }
  789 
  790    gimp_drawable_flush(drawable);
  791    gimp_drawable_detach(drawable);
  792 
  793    return(1);
  794 }
  795 
  796 static int load_mipmaps(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  797                         gint32 image, char *prefix, unsigned int *l,
  798                         guchar *pixels, unsigned char *buf)
  799 {
  800    unsigned int level;
  801 
  802    if((hdr->flags & DDSD_MIPMAPCOUNT) &&
  803       (hdr->caps.caps1 & DDSCAPS_MIPMAP))
  804    {
  805       for(level = 1; level < hdr->num_mipmaps; ++level)
  806       {
  807          if(!load_layer(fp, hdr, d, image, level, prefix, l, pixels, buf))
  808             return(0);
  809       }
  810    }
  811    return(1);
  812 }
  813 
  814 static int load_face(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  815                      gint32 image, char *prefix, unsigned int *l,
  816                      guchar *pixels, unsigned char *buf)
  817 {
  818    if(!load_layer(fp, hdr, d, image, 0, prefix, l, pixels, buf))
  819       return(0);
  820    return(load_mipmaps(fp, hdr, d, image, prefix, l, pixels, buf));
  821 }
  822 
  823 static unsigned char color_bits(unsigned int mask)
  824 {
  825    unsigned char i = 0;
  826 
  827    while(mask)
  828    {
  829       if(mask & 1) ++i;
  830       mask >>= 1;
  831    }
  832    return(i);
  833 }
  834 
  835 static unsigned char color_shift(unsigned int mask)
  836 {
  837    unsigned char i = 0;
  838 
  839    if(!mask) return(0);
  840    while(!((mask >> i) & 1)) ++i;
  841    return(i);
  842 }
  843 
  844 static void load_dialog_response(GtkWidget *widget, gint response_id,
  845                                  gpointer data)
  846 {
  847    switch(response_id)
  848    {
  849       case GTK_RESPONSE_OK:
  850          runme = 1;
  851       default:
  852          gtk_widget_destroy(widget);
  853          break;
  854    }
  855 }
  856 
  857 static void toggle_clicked(GtkWidget *widget, gpointer data)
  858 {
  859    int *flag = (int*)data;
  860    (*flag) = !(*flag);
  861 }
  862 
  863 static int load_dialog(void)
  864 {
  865    GtkWidget *dlg;
  866    GtkWidget *vbox;
  867    GtkWidget *check;
  868 
  869    dlg = gimp_dialog_new("Load DDS", "dds", NULL, GTK_WIN_POS_MOUSE,
  870                          gimp_standard_help_func, LOAD_PROC,
  871                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  872                          GTK_STOCK_OK, GTK_RESPONSE_OK,
  873                          NULL);
  874 
  875    gtk_signal_connect(GTK_OBJECT(dlg), "response",
  876                       GTK_SIGNAL_FUNC(load_dialog_response),
  877                       0);
  878    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
  879                       GTK_SIGNAL_FUNC(gtk_main_quit),
  880                       0);
  881 
  882    vbox = gtk_vbox_new(0, 8);
  883    gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
  884    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), vbox, 1, 1, 0);
  885    gtk_widget_show(vbox);
  886 
  887    check = gtk_check_button_new_with_label("Load mipmaps");
  888    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), dds_read_vals.mipmaps);
  889    gtk_signal_connect(GTK_OBJECT(check), "clicked",
  890                       GTK_SIGNAL_FUNC(toggle_clicked), &dds_read_vals.mipmaps);
  891    gtk_box_pack_start(GTK_BOX(vbox), check, 1, 1, 0);
  892    gtk_widget_show(check);
  893 
  894    check = gtk_check_button_new_with_label("Show this dialog");
  895    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), dds_read_vals.show_dialog);
  896    gtk_signal_connect(GTK_OBJECT(check), "clicked",
  897                       GTK_SIGNAL_FUNC(toggle_clicked), &dds_read_vals.show_dialog);
  898    gtk_box_pack_start(GTK_BOX(vbox), check, 1, 1, 0);
  899    gtk_widget_show(check);
  900 
  901    gtk_widget_show(dlg);
  902 
  903    runme = 0;
  904 
  905    gtk_main();
  906 
  907    return(runme);
  908 }

ViewVC Help
Powered by ViewVC 1.0.4