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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 126 - (download) (as text) (annotate)
Fri Dec 12 19:25:26 2008 UTC (11 months, 1 week ago) by cocidius
File size: 28239 byte(s)
Release 2.0.7 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 FOURCC('A', 'T', 'I', '1'):
  146             d.bpp = d.gimp_bpp = 1;
  147             type = GIMP_GRAY;
  148             break;
  149          case FOURCC('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 FOURCC('D', 'X', 'T', '1'):
  498          case FOURCC('D', 'X', 'T', '3'):
  499          case FOURCC('D', 'X', 'T', '5'):
  500          case FOURCC('A', 'T', 'I', '1'):
  501          case FOURCC('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(hdr->pixelfmt.flags & DDPF_FOURCC)
  545    {
  546       width  = MAX(width,  4);
  547       height = MAX(height, 4);
  548    }
  549    else
  550    {
  551       if(width < 1) width = 1;
  552       if(height < 1) height = 1;
  553    }
  554 
  555    switch(d->bpp)
  556    {
  557       case 1:
  558          if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  559             type = GIMP_INDEXED_IMAGE;
  560          else if(hdr->pixelfmt.rmask == 0xe0)
  561             type = GIMP_RGB_IMAGE;
  562          else if(hdr->pixelfmt.flags & DDPF_ALPHA)
  563             type = GIMP_GRAYA_IMAGE;
  564          else
  565             type = GIMP_GRAY_IMAGE;
  566          break;
  567       case 2:
  568          if(hdr->pixelfmt.amask == 0xf000) //RGBA4
  569             type = GIMP_RGBA_IMAGE;
  570          else if(hdr->pixelfmt.amask == 0xff00) //L8A8
  571             type = GIMP_GRAYA_IMAGE;
  572          else if(hdr->pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  573             type = (hdr->pixelfmt.amask == 0x8000) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
  574          else //L16
  575             type = GIMP_GRAY_IMAGE;
  576          break;
  577       case 3: type = GIMP_RGB_IMAGE;   break;
  578       case 4: type = GIMP_RGBA_IMAGE;  break;
  579    }
  580 
  581    layer_name = (level) ? g_strdup_printf("mipmap %d %s", level, prefix) :
  582                           g_strdup_printf("main surface %s", prefix);
  583 
  584    layer = gimp_layer_new(image, layer_name, width, height, type, 100,
  585                           GIMP_NORMAL_MODE);
  586    g_free(layer_name);
  587 
  588    gimp_image_add_layer(image, layer, *l);
  589    if((*l)++) gimp_drawable_set_visible(layer, FALSE);
  590 
  591    drawable = gimp_drawable_get(layer);
  592 
  593    gimp_pixel_rgn_init(&pixel_region, drawable, 0, 0, drawable->width,
  594                        drawable->height, TRUE, FALSE);
  595 
  596    if(hdr->pixelfmt.flags & DDPF_FOURCC)
  597    {
  598       unsigned int w = (width  + 3) >> 2;
  599       unsigned int h = (height + 3) >> 2;
  600 
  601       switch(GETL32(hdr->pixelfmt.fourcc))
  602       {
  603          case FOURCC('D', 'X', 'T', '1'): format = DDS_COMPRESS_BC1; break;
  604          case FOURCC('D', 'X', 'T', '3'): format = DDS_COMPRESS_BC2; break;
  605          case FOURCC('D', 'X', 'T', '5'): format = DDS_COMPRESS_BC3; break;
  606          case FOURCC('A', 'T', 'I', '1'): format = DDS_COMPRESS_BC4; break;
  607          case FOURCC('A', 'T', 'I', '2'): format = DDS_COMPRESS_BC5; break;
  608       }
  609 
  610       size = w * h;
  611       if(format == DDS_COMPRESS_BC1 || format == DDS_COMPRESS_BC4)
  612          size *= 8;
  613       else
  614          size *= 16;
  615    }
  616 
  617    if((hdr->flags & DDSD_LINEARSIZE) &&
  618       !fread(buf, size, 1, fp))
  619    {
  620       g_message("Unexpected EOF.\n");
  621       return(0);
  622    }
  623 
  624    if(hdr->pixelfmt.flags & DDPF_RGB || hdr->pixelfmt.flags & DDPF_ALPHA)
  625    {
  626       z = 0;
  627       for(y = 0, n = 0; y < height; ++y, ++n)
  628       {
  629          if(n >= d->tile_height)
  630          {
  631             gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  632                                     drawable->width, n);
  633             n = 0;
  634             if(interactive_dds)
  635                gimp_progress_update((double)y / (double)hdr->height);
  636          }
  637 
  638          if((hdr->flags & DDSD_PITCH) &&
  639             !fread(buf, width * d->bpp, 1, fp))
  640          {
  641             g_message("Unexpected EOF.\n");
  642             return(0);
  643          }
  644 
  645          if(!(hdr->flags & DDSD_LINEARSIZE)) z = 0;
  646 
  647          for(x = 0; x < drawable->width; ++x)
  648          {
  649             unsigned int pixel = buf[z];
  650             unsigned int pos = (n * drawable->width + x) * d->gimp_bpp;
  651 
  652             if(d->bpp > 1) pixel += ((unsigned int)buf[z + 1] <<  8);
  653             if(d->bpp > 2) pixel += ((unsigned int)buf[z + 2] << 16);
  654             if(d->bpp > 3) pixel += ((unsigned int)buf[z + 3] << 24);
  655 
  656             if(d->bpp >= 3)
  657             {
  658                if(hdr->pixelfmt.amask == 0xc0000000) // handle RGB10A2
  659                {
  660                   pixels[pos + 0] = (pixel >> d->rshift) >> 2;
  661                   pixels[pos + 1] = (pixel >> d->gshift) >> 2;
  662                   pixels[pos + 2] = (pixel >> d->bshift) >> 2;
  663                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  664                      pixels[pos + 3] = (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  665                }
  666                else
  667                {
  668                   pixels[pos] =
  669                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  670                   pixels[pos + 1] =
  671                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  672                   pixels[pos + 2] =
  673                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  674                   if(hdr->pixelfmt.flags & DDPF_ALPHAPIXELS)
  675                   {
  676                      pixels[pos + 3] =
  677                         (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  678                   }
  679                }
  680             }
  681             else if(d->bpp == 2)
  682             {
  683                if(hdr->pixelfmt.amask == 0xf000) //RGBA4
  684                {
  685                   pixels[pos] =
  686                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  687                   pixels[pos + 1] =
  688                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  689                   pixels[pos + 2] =
  690                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  691                   pixels[pos + 3] =
  692                      (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  693                }
  694                else if(hdr->pixelfmt.amask == 0xff00) //L8A8
  695                {
  696                   pixels[pos] =
  697                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  698                   pixels[pos + 1] =
  699                      (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  700                }
  701                else if(hdr->pixelfmt.bmask == 0x1f) //R5G6B5 or RGB5A1
  702                {
  703                   pixels[pos] =
  704                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  705                   pixels[pos + 1] =
  706                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  707                   pixels[pos + 2] =
  708                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  709                   if(hdr->pixelfmt.amask == 0x8000)
  710                   {
  711                      pixels[pos + 3] =
  712                          (pixel >> d->ashift << (8 - d->abits) & d->amask) * 255 / d->amask;
  713                   }
  714                }
  715                else //L16
  716                   pixels[pos] = (unsigned char)(255 * ((float)(pixel & 0xffff) / 65535.0f));
  717             }
  718             else
  719             {
  720                if(hdr->pixelfmt.flags & DDPF_PALETTEINDEXED8)
  721                {
  722                   pixels[pos] = pixel & 0xff;
  723                }
  724                else if(hdr->pixelfmt.rmask == 0xe0) // R3G3B2
  725                {
  726                   pixels[pos] =
  727                      (pixel >> d->rshift << (8 - d->rbits) & d->rmask) * 255 / d->rmask;
  728                   pixels[pos + 1] =
  729                      (pixel >> d->gshift << (8 - d->gbits) & d->gmask) * 255 / d->gmask;
  730                   pixels[pos + 2] =
  731                      (pixel >> d->bshift << (8 - d->bbits) & d->bmask) * 255 / d->bmask;
  732                }
  733                else if(hdr->pixelfmt.flags & DDPF_ALPHA)
  734                {
  735                   pixels[pos + 0] = 255;
  736                   pixels[pos + 1] = pixel & 0xff;
  737                }
  738                else // LUMINANCE
  739                {
  740                   pixels[pos] = pixel & 0xff;
  741                }
  742             }
  743 
  744             z += d->bpp;
  745          }
  746       }
  747 
  748       gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  749                               drawable->width, n);
  750    }
  751    else if(hdr->pixelfmt.flags & DDPF_FOURCC)
  752    {
  753       unsigned char *dst;
  754 
  755       if(!(hdr->flags & DDSD_LINEARSIZE))
  756       {
  757          g_message("Image marked as compressed, but DDSD_LINEARSIZE is not set.\n");
  758          return(0);
  759       }
  760 
  761       dst = g_malloc(width * height * d->gimp_bpp);
  762       memset(dst, 0, width * height * d->gimp_bpp);
  763 
  764       if(d->gimp_bpp == 4)
  765       {
  766         for(y = 0; y < height; ++y)
  767             for(x = 0; x < width; ++x)
  768                dst[y * (width * 4) + x + 3] = 255;
  769       }
  770 
  771       dxt_decompress(dst, buf, format, size, width, height, d->gimp_bpp);
  772 
  773       z = 0;
  774       for(y = 0, n = 0; y < height; ++y, ++n)
  775       {
  776          if(n >= d->tile_height)
  777          {
  778             gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  779                                     drawable->width, n);
  780             n = 0;
  781             if(interactive_dds)
  782                gimp_progress_update((double)y / (double)hdr->height);
  783          }
  784 
  785          memcpy(pixels + n * drawable->width * d->gimp_bpp,
  786                 dst + y * drawable->width * d->gimp_bpp,
  787                 width * d->gimp_bpp);
  788       }
  789 
  790       gimp_pixel_rgn_set_rect(&pixel_region, pixels, 0, y - n,
  791                               drawable->width, n);
  792 
  793       g_free(dst);
  794    }
  795 
  796    gimp_drawable_flush(drawable);
  797    gimp_drawable_detach(drawable);
  798 
  799    return(1);
  800 }
  801 
  802 static int load_mipmaps(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  803                         gint32 image, char *prefix, unsigned int *l,
  804                         guchar *pixels, unsigned char *buf)
  805 {
  806    unsigned int level;
  807 
  808    if((hdr->flags & DDSD_MIPMAPCOUNT) &&
  809       (hdr->caps.caps1 & DDSCAPS_MIPMAP))
  810    {
  811       for(level = 1; level < hdr->num_mipmaps; ++level)
  812       {
  813          if(!load_layer(fp, hdr, d, image, level, prefix, l, pixels, buf))
  814             return(0);
  815       }
  816    }
  817    return(1);
  818 }
  819 
  820 static int load_face(FILE *fp, dds_header_t *hdr, dds_load_info_t *d,
  821                      gint32 image, char *prefix, unsigned int *l,
  822                      guchar *pixels, unsigned char *buf)
  823 {
  824    if(!load_layer(fp, hdr, d, image, 0, prefix, l, pixels, buf))
  825       return(0);
  826    return(load_mipmaps(fp, hdr, d, image, prefix, l, pixels, buf));
  827 }
  828 
  829 static unsigned char color_bits(unsigned int mask)
  830 {
  831    unsigned char i = 0;
  832 
  833    while(mask)
  834    {
  835       if(mask & 1) ++i;
  836       mask >>= 1;
  837    }
  838    return(i);
  839 }
  840 
  841 static unsigned char color_shift(unsigned int mask)
  842 {
  843    unsigned char i = 0;
  844 
  845    if(!mask) return(0);
  846    while(!((mask >> i) & 1)) ++i;
  847    return(i);
  848 }
  849 
  850 static void load_dialog_response(GtkWidget *widget, gint response_id,
  851                                  gpointer data)
  852 {
  853    switch(response_id)
  854    {
  855       case GTK_RESPONSE_OK:
  856          runme = 1;
  857       default:
  858          gtk_widget_destroy(widget);
  859          break;
  860    }
  861 }
  862 
  863 static void toggle_clicked(GtkWidget *widget, gpointer data)
  864 {
  865    int *flag = (int*)data;
  866    (*flag) = !(*flag);
  867 }
  868 
  869 static int load_dialog(void)
  870 {
  871    GtkWidget *dlg;
  872    GtkWidget *vbox;
  873    GtkWidget *check;
  874 
  875    dlg = gimp_dialog_new("Load DDS", "dds", NULL, GTK_WIN_POS_MOUSE,
  876                          gimp_standard_help_func, LOAD_PROC,
  877                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  878                          GTK_STOCK_OK, GTK_RESPONSE_OK,
  879                          NULL);
  880 
  881    gtk_signal_connect(GTK_OBJECT(dlg), "response",
  882                       GTK_SIGNAL_FUNC(load_dialog_response),
  883                       0);
  884    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
  885                       GTK_SIGNAL_FUNC(gtk_main_quit),
  886                       0);
  887 
  888    vbox = gtk_vbox_new(0, 8);
  889    gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
  890    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), vbox, 1, 1, 0);
  891    gtk_widget_show(vbox);
  892 
  893    check = gtk_check_button_new_with_label("Load mipmaps");
  894    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), dds_read_vals.mipmaps);
  895    gtk_signal_connect(GTK_OBJECT(check), "clicked",
  896                       GTK_SIGNAL_FUNC(toggle_clicked), &dds_read_vals.mipmaps);
  897    gtk_box_pack_start(GTK_BOX(vbox), check, 1, 1, 0);
  898    gtk_widget_show(check);
  899 
  900    check = gtk_check_button_new_with_label("Show this dialog");
  901    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), dds_read_vals.show_dialog);
  902    gtk_signal_connect(GTK_OBJECT(check), "clicked",
  903                       GTK_SIGNAL_FUNC(toggle_clicked), &dds_read_vals.show_dialog);
  904    gtk_box_pack_start(GTK_BOX(vbox), check, 1, 1, 0);
  905    gtk_widget_show(check);
  906 
  907    gtk_widget_show(dlg);
  908 
  909    runme = 0;
  910 
  911    gtk_main();
  912 
  913    return(runme);
  914 }

ViewVC Help
Powered by ViewVC 1.0.4