[gimp-dds] / tags / release-1.2.1 / ddswrite.c Repository:
ViewVC logotype

View of /tags/release-1.2.1/ddswrite.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 56 - (download) (as text) (annotate)
Wed Jan 31 18:56:21 2007 UTC (2 years, 9 months ago) by cocidius
File size: 41708 byte(s)
1.2.1 release
    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 #include <stdio.h>
   24 #include <stdlib.h>
   25 #include <string.h>
   26 
   27 #include <gtk/gtk.h>
   28 
   29 #include <libgimp/gimp.h>
   30 #include <libgimp/gimpui.h>
   31 
   32 #include "ddsplugin.h"
   33 #include "dds.h"
   34 #include "dxt.h"
   35 #include "endian.h"
   36 
   37 #define IS_POT(x)  (!((x) & ((x) - 1)))
   38 
   39 static gint save_dialog(gint32 image_id, gint32 drawable);
   40 static void save_dialog_response(GtkWidget *widget, gint response_id, gpointer data);
   41 static void compression_selected(GtkWidget *widget, gpointer data);
   42 static void toggle_clicked(GtkWidget *widget, gpointer data);
   43 static int write_image(FILE *fp, gint32 image_id, gint32 drawable_id);
   44 
   45 static int runme = 0;
   46 
   47 const char *cubemap_face_names[4][6] =
   48 {
   49    {
   50       "positive x", "negative x",
   51       "positive y", "negative y",
   52       "positive z", "negative z"
   53    },
   54    {
   55       "pos x", "neg x",
   56       "pos y", "neg y",
   57       "pos z", "neg z",
   58    },
   59    {
   60       "+x", "-x",
   61       "+y", "-y",
   62       "+z", "-z"
   63    },
   64    {
   65       "right", "left",
   66       "top", "bottom",
   67       "back", "front"
   68    }
   69 };
   70 
   71 static gint cubemap_faces[6];
   72 static gint is_cubemap = 0;
   73 static gint is_volume = 0;
   74 
   75 GtkWidget *mipmap_check;
   76 GtkWidget *compress_opt;
   77 GtkWidget *compress_menu;
   78 GtkWidget *format_opt;
   79 
   80 static struct
   81 {
   82    int compression;
   83    char *string;
   84 } compression_strings[] =
   85 {
   86    {DDS_COMPRESS_NONE, "None"},
   87    {DDS_COMPRESS_DXT1, "DXT1"},
   88    {DDS_COMPRESS_DXT3, "DXT3"},
   89    {DDS_COMPRESS_DXT5, "DXT5"},
   90    {DDS_COMPRESS_ATI1, "ATI1"},
   91    {DDS_COMPRESS_ATI2, "ATI2"},
   92    {-1, 0}
   93 };
   94 
   95 static struct
   96 {
   97    int format;
   98    char *string;
   99 } format_strings[] =
  100 {
  101    {DDS_FORMAT_DEFAULT, "Default"},
  102    {DDS_FORMAT_RGB8, "RGB8"},
  103    {DDS_FORMAT_RGBA8, "RGBA8"},
  104    {DDS_FORMAT_BGR8, "BGR8"},
  105    {DDS_FORMAT_ABGR8, "ABGR8"},
  106    {DDS_FORMAT_R5G6B5, "R5G6B5"},
  107    {DDS_FORMAT_RGBA4, "RGBA4"},
  108    {DDS_FORMAT_RGB5A1, "RGB5A1"},
  109    {DDS_FORMAT_RGB10A2, "RGB10A2"},
  110    {DDS_FORMAT_R3G3B2, "R3G3B2"},
  111    {DDS_FORMAT_L8, "L8"},
  112    {DDS_FORMAT_L8A8, "L8A8"},
  113    {-1, 0}
  114 };
  115 
  116 static int check_cubemap(gint32 image_id)
  117 {
  118    gint *layers, num_layers;
  119    int cubemap = 0, i, j, k, w, h;
  120    char *layer_name;
  121    GimpDrawable *drawable;
  122    GimpImageType type;
  123 
  124    layers = gimp_image_get_layers(image_id, &num_layers);
  125 
  126    if(num_layers == 6)
  127    {
  128       for(i = 0; i < 6; ++i)
  129          cubemap_faces[i] = -1;
  130 
  131       for(i = 0; i < 6; ++i)
  132       {
  133          layer_name = (char*)gimp_drawable_get_name(layers[i]);
  134          for(j = 0; j < 6; ++j)
  135          {
  136             for(k = 0; k < 4; ++k)
  137             {
  138                if(strstr(layer_name, cubemap_face_names[k][j]))
  139                {
  140                   if(cubemap_faces[j] == -1)
  141                   {
  142                      cubemap_faces[j] = layers[i];
  143                      break;
  144                   }
  145                }
  146             }
  147          }
  148       }
  149 
  150       cubemap = 1;
  151 
  152       /* check for 6 valid faces */
  153       for(i = 0; i < 6; ++i)
  154       {
  155          if(cubemap_faces[i] == -1)
  156          {
  157             cubemap = 0;
  158             break;
  159          }
  160       }
  161 
  162       /* make sure they are all the same size */
  163       if(cubemap)
  164       {
  165          drawable = gimp_drawable_get(cubemap_faces[0]);
  166          w = drawable->width;
  167          h = drawable->height;
  168          gimp_drawable_detach(drawable);
  169          for(i = 1; i < 6 && cubemap; ++i)
  170          {
  171             drawable = gimp_drawable_get(cubemap_faces[i]);
  172             if(drawable->width  != w ||
  173                drawable->height != h)
  174             {
  175                cubemap = 0;
  176             }
  177             gimp_drawable_detach(drawable);
  178          }
  179 
  180          if(cubemap == 0)
  181          {
  182             g_message("DDS: It appears that your image is a cube map,\n"
  183                       "but not all layers are the same size, thus a cube\n"
  184                       "map cannot be written.");
  185          }
  186       }
  187 
  188       /* make sure they are all the same type */
  189       if(cubemap)
  190       {
  191          type = gimp_drawable_type(cubemap_faces[0]);
  192          for(i = 1; i < 6; ++i)
  193          {
  194             if(gimp_drawable_type(cubemap_faces[i]) != type)
  195             {
  196                cubemap = 0;
  197                break;
  198             }
  199          }
  200 
  201          if(cubemap == 0)
  202          {
  203             g_message("DDS: It appears that your image is a cube map,\n"
  204                       "but not all layers are the same type, thus a cube\n"
  205                       "map cannot be written (Perhaps some layers have\n"
  206                       "transparency and others do not?).");
  207          }
  208       }
  209    }
  210 
  211    return(cubemap);
  212 }
  213 
  214 static int check_volume(gint32 image_id)
  215 {
  216    gint *layers, num_layers;
  217    int volume = 0, i, w, h;
  218    GimpDrawable *drawable;
  219    GimpImageType type;
  220 
  221    layers = gimp_image_get_layers(image_id, &num_layers);
  222 
  223    if(num_layers > 1)
  224    {
  225       volume = 1;
  226 
  227       drawable = gimp_drawable_get(layers[0]);
  228       w = drawable->width;
  229       h = drawable->height;
  230       gimp_drawable_detach(drawable);
  231       for(i = 1; i < num_layers && volume; ++i)
  232       {
  233          drawable = gimp_drawable_get(layers[i]);
  234          if(drawable->width  != w ||
  235             drawable->height != h)
  236          {
  237             volume = 0;
  238          }
  239          gimp_drawable_detach(drawable);
  240       }
  241 
  242       if(!volume)
  243       {
  244          g_message("DDS: It appears your image may be a volume map,\n"
  245                    "but not all layers are the same size, thus a volume\n"
  246                    "map cannot be written.");
  247       }
  248 
  249       if(volume)
  250       {
  251          type = gimp_drawable_type(layers[0]);
  252          for(i = 1; i < num_layers; ++i)
  253          {
  254             if(gimp_drawable_type(layers[i]) != type)
  255             {
  256                volume = 0;
  257                break;
  258             }
  259          }
  260 
  261          if(!volume)
  262          {
  263             g_message("DDS: It appears your image may be a volume map,\n"
  264                       "but not all layers are the same type, thus a volume\n"
  265                       "map cannot be written (Perhaps some layers have\n"
  266                       "transparency and others do not?).");
  267          }
  268       }
  269    }
  270 
  271    return(volume);
  272 }
  273 
  274 GimpPDBStatusType write_dds(gchar *filename, gint32 image_id, gint32 drawable_id)
  275 {
  276    FILE *fp;
  277    gchar *tmp;
  278    int rc = 0;
  279 
  280    is_cubemap = check_cubemap(image_id);
  281    is_volume = check_volume(image_id);
  282 
  283    if(interactive_dds)
  284    {
  285       if(!save_dialog(image_id, drawable_id))
  286          return(GIMP_PDB_CANCEL);
  287    }
  288    else
  289    {
  290       if(ddsvals.savetype == DDS_SAVE_CUBEMAP && !is_cubemap)
  291       {
  292          g_message("DDS: Cannot save image as cube map");
  293          return(GIMP_PDB_EXECUTION_ERROR);
  294       }
  295 
  296       if(ddsvals.savetype == DDS_SAVE_VOLUMEMAP && !is_volume)
  297       {
  298          g_message("DDS: Cannot save image as volume map");
  299          return(GIMP_PDB_EXECUTION_ERROR);
  300       }
  301 
  302       if(ddsvals.savetype == DDS_SAVE_VOLUMEMAP &&
  303          ddsvals.compression != DDS_COMPRESS_NONE)
  304       {
  305          g_message("DDS: Cannot save volume map with compression");
  306          return(GIMP_PDB_EXECUTION_ERROR);
  307       }
  308    }
  309 
  310    fp = fopen(filename, "wb");
  311    if(fp == 0)
  312    {
  313       g_message("Error opening %s", filename);
  314       return(GIMP_PDB_EXECUTION_ERROR);
  315    }
  316 
  317    if(interactive_dds)
  318    {
  319       if(strrchr(filename, '/'))
  320          tmp = g_strdup_printf("Saving %s:", strrchr(filename, '/') + 1);
  321       else
  322          tmp = g_strdup_printf("Saving %s:", filename);
  323       gimp_progress_init(tmp);
  324       g_free(tmp);
  325    }
  326 
  327    rc = write_image(fp, image_id, drawable_id);
  328 
  329    fclose(fp);
  330 
  331    return(rc ? GIMP_PDB_SUCCESS : GIMP_PDB_EXECUTION_ERROR);
  332 }
  333 
  334 #define TO_R5G6B5(r, g, b) \
  335    (unsigned short)((unsigned short)((((r) >> 3) & 0x1f) << 11) |\
  336                     (unsigned short)((((g) >> 2) & 0x3f) <<  5) |\
  337                     (unsigned short)((((b) >> 3) & 0x1f)      ))
  338 #define TO_RGBA4(r, g, b, a) \
  339    (unsigned short)((unsigned short)((((a) >> 4) & 0x0f) << 12) |\
  340                     (unsigned short)((((r) >> 4) & 0x0f) <<  8) |\
  341                     (unsigned short)((((g) >> 4) & 0x0f) <<  4) |\
  342                     (unsigned short)((((b) >> 4) & 0x0f)      ))
  343 #define TO_RGB5A1(r, g, b, a) \
  344    (unsigned short)((unsigned short)((((a) >> 7) & 0x01) << 15) |\
  345                     (unsigned short)((((r) >> 3) & 0x1f) << 10) |\
  346                     (unsigned short)((((g) >> 3) & 0x1f) <<  5) |\
  347                     (unsigned short)((((b) >> 3) & 0x1f)      ))
  348 #define TO_RGB10A2(r, g, b, a) \
  349    (unsigned int)((unsigned int)((((a) >> 6) & 0x003) << 30) | \
  350                   (unsigned int)((((r) << 2) & 0x3ff) << 20) | \
  351                   (unsigned int)((((g) << 2) & 0x3ff) << 10) | \
  352                   (unsigned int)((((b) << 2) & 0x3ff)      ))
  353 #define TO_R3G3B2(r, g, b) \
  354    (unsigned char)(((((r) >> 5) & 0x07) << 5) |\
  355                    ((((g) >> 5) & 0x07) << 2) |\
  356                    ((((b) >> 6) & 0x03)     ))
  357 
  358 static void swap_rb(unsigned char *pixels, unsigned int n, int bpp)
  359 {
  360    unsigned int i;
  361    unsigned char t;
  362 
  363    for(i = 0; i < n; ++i)
  364    {
  365       t = pixels[bpp * i + 0];
  366       pixels[bpp * i + 0] = pixels[bpp * i + 2];
  367       pixels[bpp * i + 2] = t;
  368    }
  369 }
  370 
  371 static void convert_pixels(unsigned char *dst, unsigned char *src,
  372                            int format, int w, int h, int bpp,
  373                            unsigned char *palette, int mipmaps)
  374 {
  375    unsigned int i, num_pixels;
  376    unsigned char r, g, b, a;
  377 
  378    num_pixels = get_mipmapped_size(w, h, 1, 0, mipmaps, DDS_COMPRESS_NONE);
  379 
  380    for(i = 0; i < num_pixels; ++i)
  381    {
  382       if(bpp == 1)
  383       {
  384          if(palette)
  385          {
  386             r = palette[3 * src[i] + 0];
  387             g = palette[3 * src[i] + 1];
  388             b = palette[3 * src[i] + 2];
  389          }
  390          else
  391             r = g = b = src[i];
  392 
  393          a = 255;
  394       }
  395       else if(bpp == 2)
  396       {
  397          r = g = b = src[2 * i];
  398          a = src[2 * i + 1];
  399       }
  400       else if(bpp == 3)
  401       {
  402          b = src[3 * i + 0];
  403          g = src[3 * i + 1];
  404          r = src[3 * i + 2];
  405          a = 255;
  406       }
  407       else
  408       {
  409          b = src[4 * i + 0];
  410          g = src[4 * i + 1];
  411          r = src[4 * i + 2];
  412          a = src[4 * i + 3];
  413       }
  414 
  415       switch(format)
  416       {
  417          case DDS_FORMAT_RGB8:
  418             dst[3 * i + 0] = b;
  419             dst[3 * i + 1] = g;
  420             dst[3 * i + 2] = r;
  421             break;
  422          case DDS_FORMAT_RGBA8:
  423             dst[4 * i + 0] = b;
  424             dst[4 * i + 1] = g;
  425             dst[4 * i + 2] = r;
  426             dst[4 * i + 3] = a;
  427             break;
  428          case DDS_FORMAT_BGR8:
  429             dst[4 * i + 0] = r;
  430             dst[4 * i + 1] = g;
  431             dst[4 * i + 2] = b;
  432             dst[4 * i + 3] = 255;
  433             break;
  434          case DDS_FORMAT_ABGR8:
  435             dst[4 * i + 0] = r;
  436             dst[4 * i + 1] = g;
  437             dst[4 * i + 2] = b;
  438             dst[4 * i + 3] = a;
  439             break;
  440          case DDS_FORMAT_R5G6B5:
  441             *((unsigned short*)(&dst[2 * i])) = TO_R5G6B5(r, g, b);
  442             break;
  443          case DDS_FORMAT_RGBA4:
  444             *((unsigned short*)(&dst[2 * i])) = TO_RGBA4(r, g, b, a);
  445             break;
  446          case DDS_FORMAT_RGB5A1:
  447             *((unsigned short*)(&dst[2 * i])) = TO_RGB5A1(r, g, b, a);
  448             break;
  449          case DDS_FORMAT_RGB10A2:
  450             *((unsigned int*)(&dst[4 * i])) = TO_RGB10A2(r, g, b, a);
  451             break;
  452          case DDS_FORMAT_R3G3B2:
  453             dst[i] = TO_R3G3B2(r, g, b);
  454             break;
  455          case DDS_FORMAT_L8:
  456             dst[i] = (unsigned char)((float)r * 0.3f + (float)g * 0.59f + (float)b * 0.11f);
  457             break;
  458          case DDS_FORMAT_L8A8:
  459             dst[2 * i + 0] = (unsigned char)((float)r * 0.3f + (float)g * 0.59f + (float)b * 0.11f);
  460             dst[2 * i + 1] = a;
  461             break;
  462          default:
  463             break;
  464       }
  465    }
  466 }
  467 
  468 static void convert_volume_pixels(unsigned char *dst, unsigned char *src,
  469                                   int format, int w, int h, int d, int bpp,
  470                                   unsigned char *palette, int mipmaps)
  471 {
  472    unsigned int i, num_pixels;
  473    unsigned char r, g, b, a;
  474 
  475    num_pixels = get_volume_mipmapped_size(w, h, d, 1, 0, mipmaps,
  476                                           DDS_COMPRESS_NONE);
  477 
  478    for(i = 0; i < num_pixels; ++i)
  479    {
  480       if(bpp == 1)
  481       {
  482          if(palette)
  483          {
  484             r = palette[3 * src[i] + 0];
  485             g = palette[3 * src[i] + 1];
  486             b = palette[3 * src[i] + 2];
  487          }
  488          else
  489             r = g = b = src[i];
  490 
  491          a = 255;
  492       }
  493       else if(bpp == 2)
  494       {
  495          r = g = b = src[2 * i];
  496          a = src[2 * i + 1];
  497       }
  498       else if(bpp == 3)
  499       {
  500          b = src[3 * i + 0];
  501          g = src[3 * i + 1];
  502          r = src[3 * i + 2];
  503          a = 255;
  504       }
  505       else
  506       {
  507          b = src[4 * i + 0];
  508          g = src[4 * i + 1];
  509          r = src[4 * i + 2];
  510          a = src[4 * i + 3];
  511       }
  512 
  513       switch(format)
  514       {
  515          case DDS_FORMAT_RGB8:
  516             dst[3 * i + 0] = b;
  517             dst[3 * i + 1] = g;
  518             dst[3 * i + 2] = r;
  519             break;
  520          case DDS_FORMAT_RGBA8:
  521             dst[4 * i + 0] = b;
  522             dst[4 * i + 1] = g;
  523             dst[4 * i + 2] = r;
  524             dst[4 * i + 3] = a;
  525             break;
  526          case DDS_FORMAT_BGR8:
  527             dst[4 * i + 0] = r;
  528             dst[4 * i + 1] = g;
  529             dst[4 * i + 2] = b;
  530             dst[4 * i + 3] = 255;
  531             break;
  532          case DDS_FORMAT_ABGR8:
  533             dst[4 * i + 0] = r;
  534             dst[4 * i + 1] = g;
  535             dst[4 * i + 2] = b;
  536             dst[4 * i + 3] = a;
  537             break;
  538          case DDS_FORMAT_R5G6B5:
  539             *((unsigned short*)(&dst[2 * i])) = TO_R5G6B5(r, g, b);
  540             break;
  541          case DDS_FORMAT_RGBA4:
  542             *((unsigned short*)(&dst[2 * i])) = TO_RGBA4(r, g, b, a);
  543             break;
  544          case DDS_FORMAT_RGB5A1:
  545             *((unsigned short*)(&dst[2 * i])) = TO_RGB5A1(r, g, b, a);
  546             break;
  547          case DDS_FORMAT_RGB10A2:
  548             *((unsigned int*)(&dst[4 * i])) = TO_RGB10A2(r, g, b, a);
  549             break;
  550          case DDS_FORMAT_R3G3B2:
  551             dst[i] = TO_R3G3B2(r, g, b);
  552             break;
  553          case DDS_FORMAT_L8:
  554             dst[i] = (unsigned char)((float)r * 0.3f + (float)g * 0.59f + (float)b * 0.11f);
  555             break;
  556          case DDS_FORMAT_L8A8:
  557             dst[2 * i + 0] = (unsigned char)((float)r * 0.3f + (float)g * 0.59f + (float)b * 0.11f);
  558             dst[2 * i + 1] = a;
  559             break;
  560          default:
  561             break;
  562       }
  563    }
  564 }
  565 
  566 static void write_layer(FILE *fp, gint32 image_id, gint32 drawable_id,
  567                         int w, int h, int bpp, int fmtbpp, int mipmaps)
  568 {
  569    GimpDrawable *drawable;
  570    GimpPixelRgn rgn;
  571    GimpImageType basetype, type;
  572    unsigned char *src, *dst, *fmtdst, *tmp, c;
  573    unsigned char *palette = NULL;
  574    int i, x, y, size, fmtsize, offset, colors;
  575 
  576    basetype = gimp_image_base_type(image_id);
  577    type = gimp_drawable_type(drawable_id);
  578 
  579    drawable = gimp_drawable_get(drawable_id);
  580    src = g_malloc(w * h * bpp);
  581    gimp_pixel_rgn_init(&rgn, drawable, 0, 0, w, h, 0, 0);
  582    gimp_pixel_rgn_get_rect(&rgn, src, 0, 0, w, h);
  583 
  584    if(basetype == GIMP_INDEXED)
  585    {
  586       palette = gimp_image_get_colormap(image_id, &colors);
  587 
  588       if(type == GIMP_INDEXEDA_IMAGE)
  589       {
  590          tmp = g_malloc(w * h);
  591          for(i = 0; i < w * h; ++i)
  592             tmp[i] = src[2 * i];
  593          g_free(src);
  594          src = tmp;
  595          bpp = 1;
  596       }
  597    }
  598 
  599    if(bpp >= 3)
  600       swap_rb(src, w * h, bpp);
  601 
  602    if(ddsvals.swapRA && bpp == 4)
  603    {
  604       for(y = 0; y < drawable->height; ++y)
  605       {
  606          for(x = 0; x < drawable->width; ++x)
  607          {
  608             c = src[y * (drawable->width * 4) + (x * 4) + 2];
  609             src[y * (drawable->width * 4) + (x * 4) + 2] =
  610                src[y * (drawable->width * 4) + (x * 4) + 3];
  611             src[y * (drawable->width * 4) + (x * 4) + 3] = c;
  612          }
  613       }
  614    }
  615 
  616    if(ddsvals.compression == DDS_COMPRESS_NONE)
  617    {
  618       if(mipmaps > 1)
  619       {
  620          /* pre-convert indexed images to RGB for better quality mipmaps
  621             if a pixel format conversion is requested */
  622          if(ddsvals.format > DDS_FORMAT_DEFAULT && basetype == GIMP_INDEXED)
  623          {
  624             fmtsize = get_mipmapped_size(w, h, 3, 0, mipmaps, DDS_COMPRESS_NONE);
  625             fmtdst = g_malloc(fmtsize);
  626             convert_pixels(fmtdst, src, DDS_FORMAT_RGB8, w, h, bpp,
  627                            palette, 1);
  628             g_free(src);
  629             src = fmtdst;
  630             bpp = 3;
  631             palette = NULL;
  632          }
  633 
  634          size = get_mipmapped_size(w, h, bpp, 0, mipmaps, DDS_COMPRESS_NONE);
  635          dst = g_malloc(size);
  636          generate_mipmaps(dst, src, w, h, bpp, palette != NULL, mipmaps);
  637 
  638          offset = 0;
  639 
  640          if(ddsvals.format > DDS_FORMAT_DEFAULT)
  641          {
  642             fmtsize = get_mipmapped_size(w, h, fmtbpp, 0, mipmaps,
  643                                          DDS_COMPRESS_NONE);
  644             fmtdst = g_malloc(fmtsize);
  645 
  646             convert_pixels(fmtdst, dst, ddsvals.format, w, h, bpp,
  647                            palette, mipmaps);
  648 
  649             g_free(dst);
  650             dst = fmtdst;
  651             bpp = fmtbpp;
  652          }
  653 
  654          for(i = 0; i < mipmaps; ++i)
  655          {
  656             size = get_mipmapped_size(w, h, bpp, i, 1, DDS_COMPRESS_NONE);
  657             fwrite(dst + offset, 1, size, fp);
  658             offset += size;
  659          }
  660 
  661          g_free(dst);
  662       }
  663       else
  664       {
  665          if(ddsvals.format > DDS_FORMAT_DEFAULT)
  666          {
  667             fmtdst = g_malloc(h * w * fmtbpp);
  668             convert_pixels(fmtdst, src, ddsvals.format, w, h, bpp,
  669                            palette, 1);
  670             g_free(src);
  671             src = fmtdst;
  672             bpp = fmtbpp;
  673          }
  674 
  675          fwrite(src, 1, h * w * bpp, fp);
  676       }
  677    }
  678    else
  679    {
  680       size = get_mipmapped_size(w, h, bpp, 0, mipmaps, ddsvals.compression);
  681 
  682       dst = g_malloc(size);
  683 
  684       if(basetype == GIMP_INDEXED)
  685       {
  686          fmtsize = get_mipmapped_size(w, h, 3, 0, mipmaps,
  687                                       DDS_COMPRESS_NONE);
  688          fmtdst = g_malloc(fmtsize);
  689          convert_pixels(fmtdst, src, DDS_FORMAT_RGB8, w, h, bpp,
  690                         palette, mipmaps);
  691          g_free(src);
  692          src = fmtdst;
  693          bpp = 3;
  694       }
  695 
  696       dxt_compress(dst, src, ddsvals.compression, w, h, bpp, mipmaps);
  697 
  698       offset = 0;
  699 
  700       for(i = 0; i < mipmaps; ++i)
  701       {
  702          size = get_mipmapped_size(w, h, bpp, i, 1, ddsvals.compression);
  703          fwrite(dst + offset, 1, size, fp);
  704          offset += size;
  705       }
  706 
  707       g_free(dst);
  708    }
  709 
  710    g_free(src);
  711 
  712    gimp_drawable_detach(drawable);
  713 }
  714 
  715 static void write_volume_mipmaps(FILE *fp, gint32 image_id, gint32 *layers,
  716                                  int w, int h, int d, int bpp, int fmtbpp,
  717                                  int mipmaps)
  718 {
  719    int i, size, offset, colors;
  720    unsigned char *src, *dst, *tmp, *fmtdst;
  721    unsigned char *palette = 0;
  722    GimpDrawable *drawable;
  723    GimpPixelRgn rgn;
  724    GimpImageType type;
  725 
  726    type = gimp_image_base_type(image_id);
  727 
  728    if(ddsvals.compression != DDS_COMPRESS_NONE) return;
  729 
  730    src = g_malloc(w * h * bpp * d);
  731 
  732    if(gimp_image_base_type(image_id) == GIMP_INDEXED)
  733       palette = gimp_image_get_colormap(image_id, &colors);
  734 
  735    offset = 0;
  736    for(i = 0; i < d; ++i)
  737    {
  738       drawable = gimp_drawable_get(layers[i]);
  739       gimp_pixel_rgn_init(&rgn, drawable, 0, 0, w, h, 0, 0);
  740       gimp_pixel_rgn_get_rect(&rgn, src + offset, 0, 0, w, h);
  741       offset += (w * h * bpp);
  742       gimp_drawable_detach(drawable);
  743    }
  744 
  745    if(gimp_drawable_type(layers[0]) == GIMP_INDEXEDA_IMAGE)
  746    {
  747       tmp = g_malloc(w * h * d);
  748       for(i = 0; i < w * h * d; ++i)
  749          tmp[i] = src[2 * i];
  750       g_free(src);
  751       src = tmp;
  752       bpp = 1;
  753    }
  754 
  755    if(bpp >= 3)
  756       swap_rb(src, w * h * d, bpp);
  757 
  758    /* pre-convert indexed images to RGB for better mipmaps if a
  759       pixel format conversion is requested */
  760    if(ddsvals.format > DDS_FORMAT_DEFAULT && type == GIMP_INDEXED)
  761    {
  762       size = get_volume_mipmapped_size(w, h, d, 3, 0, mipmaps,
  763                                        DDS_COMPRESS_NONE);
  764       dst = g_malloc(size);
  765       convert_volume_pixels(dst, src, DDS_FORMAT_RGB8, w, h, d, bpp,
  766                             palette, 1);
  767       g_free(src);
  768       src = dst;
  769       bpp = 3;
  770       palette = NULL;
  771    }
  772 
  773    size = get_volume_mipmapped_size(w, h, d, bpp, 0, mipmaps,
  774                                     ddsvals.compression);
  775 
  776    dst = g_malloc(size);
  777 
  778    offset = get_volume_mipmapped_size(w, h, d, bpp, 0, 1,
  779                                       ddsvals.compression);
  780 
  781    generate_volume_mipmaps(dst, src, w, h, d, bpp,
  782                            palette != NULL, mipmaps);
  783 
  784    if(ddsvals.format > DDS_FORMAT_DEFAULT)
  785    {
  786       size = get_volume_mipmapped_size(w, h, d, fmtbpp, 0, mipmaps,
  787                                        ddsvals.compression);
  788       offset = get_volume_mipmapped_size(w, h, d, fmtbpp, 0, 1,
  789                                          ddsvals.compression);
  790       fmtdst = g_malloc(size);
  791 
  792       convert_volume_pixels(fmtdst, dst, ddsvals.format, w, h, d, bpp,
  793                             palette, mipmaps);
  794       g_free(dst);
  795       dst = fmtdst;
  796    }
  797 
  798    fwrite(dst + offset, 1, size, fp);
  799 
  800    g_free(src);
  801    g_free(dst);
  802 }
  803 
  804 static int write_image(FILE *fp, gint32 image_id, gint32 drawable_id)
  805 {
  806    GimpDrawable *drawable;
  807    GimpImageType drawable_type, basetype;
  808    GimpPixelRgn rgn;
  809    int i, w, h, bpp = 0, fmtbpp = 0, has_alpha = 0;
  810    int num_mipmaps;
  811    unsigned char hdr[DDS_HEADERSIZE];
  812    unsigned int flags = 0, pflags = 0, caps = 0, caps2 = 0, size = 0;
  813    unsigned int rmask = 0, gmask = 0, bmask = 0, amask = 0;
  814    char *format = "XXXX";
  815    gint32 num_layers, *layers;
  816    guchar *cmap;
  817    gint colors;
  818    unsigned char zero[4] = {0, 0, 0, 0};
  819 
  820    layers = gimp_image_get_layers(image_id, &num_layers);
  821 
  822    drawable = gimp_drawable_get(drawable_id);
  823 
  824    w = drawable->width;
  825    h = drawable->height;
  826 
  827    basetype = gimp_image_base_type(image_id);
  828    drawable_type = gimp_drawable_type(drawable_id);
  829    gimp_pixel_rgn_init(&rgn, drawable, 0, 0, w, h, 0, 0);
  830 
  831    if((ddsvals.compression != DDS_COMPRESS_NONE) &&
  832       !(IS_POT(w) && IS_POT(h)))
  833    {
  834       ddsvals.compression = DDS_COMPRESS_NONE;
  835       g_message("DDS: Cannot compress non power-of-2 sized images.\n"
  836                 "Saved image will not be compressed.");
  837    }
  838 
  839    switch(drawable_type)
  840    {
  841       case GIMP_RGB_IMAGE:      bpp = 3; break;
  842       case GIMP_RGBA_IMAGE:     bpp = 4; break;
  843       case GIMP_GRAY_IMAGE:     bpp = 1; break;
  844       case GIMP_GRAYA_IMAGE:    bpp = 2; break;
  845       case GIMP_INDEXED_IMAGE:  bpp = 1; break;
  846       case GIMP_INDEXEDA_IMAGE: bpp = 2; break;
  847       default:
  848          break;
  849    }
  850 
  851    if(ddsvals.format > DDS_FORMAT_DEFAULT)
  852    {
  853       switch(ddsvals.format)
  854       {
  855          case DDS_FORMAT_RGB8:
  856             fmtbpp = 3;
  857             rmask = 0x00ff0000;
  858             gmask = 0x0000ff00;
  859             bmask = 0x000000ff;
  860             amask = 0xff000000;
  861             break;
  862          case DDS_FORMAT_RGBA8:
  863             fmtbpp = 4;
  864             has_alpha = 1;
  865             rmask = 0x00ff0000;
  866             gmask = 0x0000ff00;
  867             bmask = 0x000000ff;
  868             amask = 0xff000000;
  869             break;
  870          case DDS_FORMAT_BGR8:
  871             fmtbpp = 4;
  872             rmask = 0x000000ff;
  873             gmask = 0x0000ff00;
  874             bmask = 0x00ff0000;
  875             amask = 0x00000000;
  876             break;
  877          case DDS_FORMAT_ABGR8:
  878             fmtbpp = 4;
  879             has_alpha = 1;
  880             rmask = 0x000000ff;
  881             gmask = 0x0000ff00;
  882             bmask = 0x00ff0000;
  883             amask = 0xff000000;
  884             break;
  885          case DDS_FORMAT_R5G6B5:
  886             fmtbpp = 2;
  887             rmask = 0x0000f800;
  888             gmask = 0x000007e0;
  889             bmask = 0x0000001f;
  890             amask = 0x00000000;
  891             break;
  892          case DDS_FORMAT_RGBA4:
  893             fmtbpp = 2;
  894             has_alpha = 1;
  895             rmask = 0x00000f00;
  896             gmask = 0x000000f0;
  897             bmask = 0x0000000f;
  898             amask = 0x0000f000;
  899             break;
  900          case DDS_FORMAT_RGB5A1:
  901             fmtbpp = 2;
  902             has_alpha = 1;
  903             rmask = 0x00007c00;
  904             gmask = 0x000003e0;
  905             bmask = 0x0000001f;
  906             amask = 0x00008000;
  907             break;
  908          case DDS_FORMAT_RGB10A2:
  909             fmtbpp = 4;
  910             has_alpha = 1;
  911             rmask = 0x3ff00000;
  912             gmask = 0x000ffc00;
  913             bmask = 0x000003ff;
  914             amask = 0xc0000000;
  915             break;
  916          case DDS_FORMAT_R3G3B2:
  917             fmtbpp = 1;
  918             has_alpha = 0;
  919             rmask = 0x000000e0;
  920             gmask = 0x0000001c;
  921             bmask = 0x00000003;
  922             amask = 0x00000000;
  923             break;
  924          case DDS_FORMAT_L8:
  925             fmtbpp = 1;
  926             has_alpha = 0;
  927             rmask = 0x000000ff;
  928             gmask = 0x000000ff;
  929             bmask = 0x000000ff;
  930             amask = 0x00000000;
  931             break;
  932          case DDS_FORMAT_L8A8:
  933             fmtbpp = 2;
  934             has_alpha = 1;
  935             rmask = 0x000000ff;
  936             gmask = 0x000000ff;
  937             bmask = 0x000000ff;
  938             amask = 0x0000ff00;
  939             break;
  940          default:
  941             break;
  942       }
  943    }
  944    else if(bpp == 1)
  945    {
  946       if(basetype == GIMP_INDEXED)
  947       {
  948          fmtbpp = 1;
  949          has_alpha = 0;
  950          rmask = bmask = gmask = amask = 0;
  951       }
  952       else
  953       {
  954          fmtbpp = 1;
  955          has_alpha = 0;
  956          rmask = 0x000000ff;
  957          gmask = bmask = amask = 0;
  958       }
  959    }
  960    else if(bpp == 2)
  961    {
  962       if(basetype == GIMP_INDEXED)
  963       {
  964          fmtbpp = 1;
  965          has_alpha = 0;
  966          rmask = gmask = bmask = amask = 0;
  967       }
  968       else
  969       {
  970          fmtbpp = 2;
  971          has_alpha = 1;
  972          rmask = 0x000000ff;
  973          gmask = 0x000000ff;
  974          bmask = 0x000000ff;
  975          amask = 0x0000ff00;
  976       }
  977    }
  978    else if(bpp == 3)
  979    {
  980       fmtbpp = 3;
  981       rmask = 0x00ff0000;
  982       gmask = 0x0000ff00;
  983       bmask = 0x000000ff;
  984       amask = 0x00000000;
  985    }
  986    else
  987    {
  988       fmtbpp = 4;
  989       has_alpha = 1;
  990       rmask = 0x00ff0000;
  991       gmask = 0x0000ff00;
  992       bmask = 0x000000ff;
  993       amask = 0xff000000;
  994    }
  995 
  996    memset(hdr, 0, DDS_HEADERSIZE);
  997 
  998    memcpy(hdr, "DDS ", 4);
  999    PUTL32(hdr + 4, 124);
 1000    PUTL32(hdr + 12, h);
 1001    PUTL32(hdr + 16, w);
 1002    PUTL32(hdr + 76, 32);
 1003    PUTL32(hdr + 88, fmtbpp << 3);
 1004    PUTL32(hdr + 92,  rmask);
 1005    PUTL32(hdr + 96,  gmask);
 1006    PUTL32(hdr + 100, bmask);
 1007    PUTL32(hdr + 104, amask);
 1008 
 1009    flags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
 1010 
 1011    caps = DDSCAPS_TEXTURE;
 1012    if(ddsvals.mipmaps)
 1013    {
 1014       flags |= DDSD_MIPMAPCOUNT;
 1015       caps |= (DDSCAPS_COMPLEX | DDSCAPS_MIPMAP);
 1016       num_mipmaps = get_num_mipmaps(w, h);
 1017    }
 1018    else
 1019       num_mipmaps = 1;
 1020 
 1021    if(ddsvals.savetype == DDS_SAVE_CUBEMAP && is_cubemap)
 1022    {
 1023       caps |= DDSCAPS_COMPLEX;
 1024       caps2 |= (DDSCAPS2_CUBEMAP |
 1025                 DDSCAPS2_CUBEMAP_POSITIVEX |
 1026                 DDSCAPS2_CUBEMAP_NEGATIVEX |
 1027                 DDSCAPS2_CUBEMAP_POSITIVEY |
 1028                 DDSCAPS2_CUBEMAP_NEGATIVEY |
 1029                 DDSCAPS2_CUBEMAP_POSITIVEZ |
 1030                 DDSCAPS2_CUBEMAP_NEGATIVEZ);
 1031    }
 1032    else if(ddsvals.savetype == DDS_SAVE_VOLUMEMAP && is_volume)
 1033    {
 1034       PUTL32(hdr + 24, num_layers);
 1035       flags |= DDSD_DEPTH;
 1036       caps |= DDSCAPS_COMPLEX;
 1037       caps2 |= DDSCAPS2_VOLUME;
 1038    }
 1039 
 1040    PUTL32(hdr + 28, num_mipmaps);
 1041    PUTL32(hdr + 108, caps);
 1042    PUTL32(hdr + 112, caps2);
 1043 
 1044    if(ddsvals.compression == DDS_COMPRESS_NONE)
 1045    {
 1046       flags |= DDSD_PITCH;
 1047 
 1048       if(ddsvals.format > DDS_FORMAT_DEFAULT)
 1049       {
 1050          if((fmtbpp == 1 || ddsvals.format == DDS_FORMAT_L8A8) &&
 1051             (ddsvals.format != DDS_FORMAT_R3G3B2))
 1052             pflags |= DDPF_LUMINANCE;
 1053          else
 1054             pflags |= DDPF_RGB;
 1055       }
 1056       else
 1057       {
 1058          if(bpp == 1)
 1059          {
 1060             if(basetype == GIMP_INDEXED)
 1061                pflags |= DDPF_PALETTEINDEXED8;
 1062             else
 1063                pflags |= DDPF_LUMINANCE;
 1064          }
 1065          else if(bpp == 2 && basetype == GIMP_INDEXED)
 1066             pflags |= DDPF_PALETTEINDEXED8;
 1067          else
 1068             pflags |= DDPF_RGB;
 1069       }
 1070 
 1071       if(has_alpha) pflags |= DDPF_ALPHAPIXELS;
 1072 
 1073       PUTL32(hdr + 8, flags);
 1074       PUTL32(hdr + 20, w * fmtbpp);
 1075       PUTL32(hdr + 80, pflags);
 1076    }
 1077    else
 1078    {
 1079       flags |= DDSD_LINEARSIZE;
 1080       PUTL32(hdr + 8, flags);
 1081       PUTL32(hdr + 80, DDPF_FOURCC);
 1082       switch(ddsvals.compression)
 1083       {
 1084          case DDS_COMPRESS_DXT1: format = "DXT1"; break;
 1085          case DDS_COMPRESS_DXT3: format = "DXT3"; break;
 1086          case DDS_COMPRESS_DXT5: format = "DXT5"; break;
 1087          case DDS_COMPRESS_ATI1: format = "ATI1"; break;
 1088          case DDS_COMPRESS_ATI2: format = "ATI2"; break;
 1089       }
 1090       memcpy(hdr + 84, format, 4);
 1091 
 1092       size = ((w + 3) >> 2) * ((h + 3) >> 2);
 1093       if(ddsvals.compression == DDS_COMPRESS_DXT1 ||
 1094          ddsvals.compression == DDS_COMPRESS_ATI1)
 1095          size *= 8;
 1096       else
 1097          size *= 16;
 1098 
 1099       PUTL32(hdr + 20, size);
 1100    }
 1101 
 1102    fwrite(hdr, DDS_HEADERSIZE, 1, fp);
 1103 
 1104    if(basetype == GIMP_INDEXED && ddsvals.format == DDS_FORMAT_DEFAULT &&
 1105       ddsvals.compression == DDS_COMPRESS_NONE)
 1106    {
 1107       cmap = gimp_image_get_colormap(image_id, &colors);
 1108       for(i = 0; i < colors; ++i)
 1109       {
 1110          fwrite(&cmap[3 * i], 1, 3, fp);
 1111          if(i == ddsvals.transindex)
 1112             fputc(0, fp);
 1113          else
 1114             fputc(255, fp);
 1115       }
 1116       for(; i < 256; ++i)
 1117          fwrite(zero, 1, 4, fp);
 1118    }
 1119 
 1120    if(ddsvals.savetype == DDS_SAVE_CUBEMAP)
 1121    {
 1122       for(i = 0; i < 6; ++i)
 1123       {
 1124          write_layer(fp, image_id, cubemap_faces[i], w, h, bpp, fmtbpp,
 1125                      num_mipmaps);
 1126          if(interactive_dds)
 1127             gimp_progress_update((float)(i + 1) / 6.0);
 1128       }
 1129    }
 1130    else if(ddsvals.savetype == DDS_SAVE_VOLUMEMAP)
 1131    {
 1132       for(i = 0; i < num_layers; ++i)
 1133       {
 1134          write_layer(fp, image_id, layers[i], w, h, bpp, fmtbpp, 1);
 1135          if(interactive_dds)
 1136             gimp_progress_update((float)i / (float)num_layers);
 1137       }
 1138 
 1139       if(num_mipmaps > 1)
 1140          write_volume_mipmaps(fp, image_id, layers, w, h, num_layers,
 1141                               bpp, fmtbpp, num_mipmaps);
 1142    }
 1143    else
 1144    {
 1145       write_layer(fp, image_id, drawable_id, w, h, bpp, fmtbpp,
 1146                   num_mipmaps);
 1147    }
 1148 
 1149    if(interactive_dds)
 1150       gimp_progress_update(1.0);
 1151 
 1152    gimp_drawable_detach(drawable);
 1153 
 1154    return(1);
 1155 }
 1156 
 1157 static void save_dialog_response(GtkWidget *widget, gint response_id,
 1158                                  gpointer data)
 1159 {
 1160    switch(response_id)
 1161    {
 1162       case GTK_RESPONSE_OK:
 1163          runme = 1;
 1164       default:
 1165          gtk_widget_destroy(widget);
 1166          break;
 1167    }
 1168 }
 1169 
 1170 static void compression_selected(GtkWidget *widget, gpointer data)
 1171 {
 1172    ddsvals.compression = (gint)(long)data;
 1173    gtk_widget_set_sensitive(format_opt, ddsvals.compression == DDS_COMPRESS_NONE);
 1174 }
 1175 
 1176 static void savetype_selected(GtkWidget *widget, gpointer data)
 1177 {
 1178    int n = (int)(long)data;
 1179 
 1180    ddsvals.savetype = n;
 1181 
 1182    switch(n)
 1183    {
 1184       case 0:
 1185       case 1:
 1186          gtk_widget_set_sensitive(compress_opt, 1);
 1187          break;
 1188       case 2:
 1189          ddsvals.compression = DDS_COMPRESS_NONE;
 1190          gtk_menu_set_active(GTK_MENU(compress_menu), DDS_COMPRESS_NONE);
 1191          gtk_widget_set_sensitive(compress_opt, 0);
 1192          break;
 1193    }
 1194 }
 1195 
 1196 static void format_selected(GtkWidget *widget, gpointer data)
 1197 {
 1198    ddsvals.format = (gint)(long)data;
 1199 }
 1200 
 1201 static void toggle_clicked(GtkWidget *widget, gpointer data)
 1202 {
 1203    int *flag = (int*)data;
 1204    (*flag) = !(*flag);
 1205 }
 1206 
 1207 static void transindex_clicked(GtkWidget *widget, gpointer data)
 1208 {
 1209    GtkWidget *spin = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "spin"));
 1210 
 1211    if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
 1212    {
 1213       ddsvals.transindex = 0;
 1214       gtk_widget_set_sensitive(spin, 1);
 1215       gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), 0);
 1216    }
 1217    else
 1218    {
 1219       gtk_widget_set_sensitive(spin, 0);
 1220       ddsvals.transindex = -1;
 1221    }
 1222 }
 1223 
 1224 static void transindex_changed(GtkWidget *widget, gpointer data)
 1225 {
 1226    ddsvals.transindex = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
 1227 }
 1228 
 1229 static gint save_dialog(gint32 image_id, gint32 drawable_id)
 1230 {
 1231    GtkWidget *dlg;
 1232    GtkWidget *vbox, *hbox;
 1233    GtkWidget *table;
 1234    GtkWidget *label;
 1235    GtkWidget *opt;
 1236    GtkWidget *menu;
 1237    GtkWidget *menuitem;
 1238    GtkWidget *check;
 1239    GtkWidget *spin;
 1240    GimpImageType type, basetype;
 1241    int i, w, h;
 1242 
 1243    if(is_cubemap)
 1244       ddsvals.savetype = DDS_SAVE_CUBEMAP;
 1245    else if(is_volume)
 1246       ddsvals.savetype = DDS_SAVE_VOLUMEMAP;
 1247    else
 1248       ddsvals.savetype = DDS_SAVE_SELECTED_LAYER;
 1249 
 1250    basetype = gimp_image_base_type(image_id);
 1251    type = gimp_drawable_type(drawable_id);
 1252 
 1253    w = gimp_image_width(image_id);
 1254    h = gimp_image_height(image_id);
 1255 
 1256    dlg = gimp_dialog_new("Save as DDS", "dds", NULL, GTK_WIN_POS_MOUSE,
 1257                          gimp_standard_help_func, SAVE_PROC,
 1258                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 1259                          GTK_STOCK_OK, GTK_RESPONSE_OK,
 1260                          NULL);
 1261 
 1262    gtk_signal_connect(GTK_OBJECT(dlg), "response",
 1263                       GTK_SIGNAL_FUNC(save_dialog_response),
 1264                       0);
 1265    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
 1266                       GTK_SIGNAL_FUNC(gtk_main_quit),
 1267                       0);
 1268 
 1269    vbox = gtk_vbox_new(0, 8);
 1270    gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
 1271    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), vbox, 1, 1, 0);
 1272    gtk_widget_show(vbox);
 1273 
 1274    table = gtk_table_new(3, 2, 0);
 1275    gtk_widget_show(table);
 1276    gtk_box_pack_start(GTK_BOX(vbox), table, 1, 1, 0);
 1277    gtk_table_set_row_spacings(GTK_TABLE(table), 8);
 1278    gtk_table_set_col_spacings(GTK_TABLE(table), 8);
 1279 
 1280    label = gtk_label_new("Compression:");
 1281    gtk_widget_show(label);
 1282    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
 1283                     (GtkAttachOptions)(GTK_FILL),
 1284                     (GtkAttachOptions)(0), 0, 0);
 1285    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1286 
 1287    opt = gtk_option_menu_new();
 1288    gtk_widget_show(opt);
 1289    gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 0, 1,
 1290                     (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
 1291                     (GtkAttachOptions)(GTK_EXPAND), 0, 0);
 1292 
 1293    menu = gtk_menu_new();
 1294 
 1295    for(i = 0; compression_strings[i].string; ++i)
 1296    {
 1297       menuitem = gtk_menu_item_new_with_label(compression_strings[i].string);
 1298       gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
 1299                          GTK_SIGNAL_FUNC(compression_selected),
 1300                          (gpointer)(long)compression_strings[i].compression);
 1301       gtk_widget_show(menuitem);
 1302       gtk_menu_append(GTK_MENU(menu), menuitem);
 1303    }
 1304 
 1305    gtk_menu_set_active(GTK_MENU(menu), ddsvals.compression);
 1306 
 1307    gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
 1308 
 1309    compress_opt = opt;
 1310    compress_menu = menu;
 1311 
 1312    label = gtk_label_new("Format:");
 1313    gtk_widget_show(label);
 1314    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
 1315                     (GtkAttachOptions)(GTK_FILL),
 1316                     (GtkAttachOptions)(0), 0, 0);
 1317    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1318 
 1319    opt = gtk_option_menu_new();
 1320    gtk_widget_show(opt);
 1321    gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 1, 2,
 1322                     (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
 1323                     (GtkAttachOptions)(GTK_EXPAND), 0, 0);
 1324 
 1325    menu = gtk_menu_new();
 1326 
 1327    for(i = 0; format_strings[i].string; ++i)
 1328    {
 1329       menuitem = gtk_menu_item_new_with_label(format_strings[i].string);
 1330       gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
 1331                          GTK_SIGNAL_FUNC(format_selected),
 1332                          (gpointer)(long)format_strings[i].format);
 1333       gtk_widget_show(menuitem);
 1334       gtk_menu_append(GTK_MENU(menu), menuitem);
 1335    }
 1336 
 1337    gtk_menu_set_active(GTK_MENU(menu), ddsvals.format);
 1338 
 1339    gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
 1340 
 1341    gtk_widget_set_sensitive(opt, ddsvals.compression == DDS_COMPRESS_NONE);
 1342 
 1343    format_opt = opt;
 1344 
 1345    label = gtk_label_new("Save:");
 1346    gtk_widget_show(label);
 1347    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
 1348                     (GtkAttachOptions)(GTK_FILL),
 1349                     (GtkAttachOptions)(0), 0, 0);
 1350    gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 1351 
 1352    opt = gtk_option_menu_new();
 1353    gtk_widget_show(opt);
 1354    gtk_table_attach(GTK_TABLE(table), opt, 1, 2, 2, 3,
 1355                     (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
 1356                     (GtkAttachOptions)(GTK_EXPAND), 0, 0);
 1357 
 1358    menu = gtk_menu_new();
 1359 
 1360    menuitem = gtk_menu_item_new_with_label("Selected layer");
 1361    gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
 1362                       GTK_SIGNAL_FUNC(savetype_selected),
 1363                       (gpointer)DDS_SAVE_SELECTED_LAYER);
 1364    gtk_widget_show(menuitem);
 1365    gtk_menu_append(GTK_MENU(menu), menuitem);
 1366    menuitem = gtk_menu_item_new_with_label("As cube map");
 1367    gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
 1368                       GTK_SIGNAL_FUNC(savetype_selected),
 1369                       (gpointer)DDS_SAVE_CUBEMAP);
 1370    gtk_widget_show(menuitem);
 1371    gtk_menu_append(GTK_MENU(menu), menuitem);
 1372    gtk_widget_set_sensitive(menuitem, is_cubemap);
 1373    menuitem = gtk_menu_item_new_with_label("As volume map");
 1374    gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
 1375                       GTK_SIGNAL_FUNC(savetype_selected),
 1376                       (gpointer)DDS_SAVE_VOLUMEMAP);
 1377    gtk_widget_show(menuitem);
 1378    gtk_menu_append(GTK_MENU(menu), menuitem);
 1379    gtk_widget_set_sensitive(menuitem, is_volume);
 1380 
 1381    gtk_menu_set_active(GTK_MENU(menu), ddsvals.savetype);
 1382 
 1383    gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu);
 1384 
 1385    gtk_widget_set_sensitive(opt, is_cubemap || is_volume);
 1386 
 1387    check = gtk_check_button_new_with_label("Generate mipmaps");
 1388    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), ddsvals.mipmaps);
 1389    gtk_box_pack_start(GTK_BOX(vbox), check, 0, 0, 0);
 1390    gtk_signal_connect(GTK_OBJECT(check), "clicked",
 1391                       GTK_SIGNAL_FUNC(toggle_clicked), &ddsvals.mipmaps);
 1392    gtk_widget_show(check);
 1393    mipmap_check = check;
 1394 
 1395    check = gtk_check_button_new_with_label("Swap red and alpha");
 1396    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), ddsvals.swapRA);
 1397    gtk_box_pack_start(GTK_BOX(vbox), check, 0, 0, 0);
 1398    gtk_signal_connect(GTK_OBJECT(check), "clicked",
 1399                       GTK_SIGNAL_FUNC(toggle_clicked), &ddsvals.swapRA);
 1400    gtk_widget_show(check);
 1401    gtk_widget_set_sensitive(check, type == GIMP_RGBA_IMAGE);
 1402 
 1403    if(is_volume && ddsvals.savetype == DDS_SAVE_VOLUMEMAP)
 1404    {
 1405       ddsvals.compression = DDS_COMPRESS_NONE;
 1406       gtk_menu_set_active(GTK_MENU(compress_menu), DDS_COMPRESS_NONE);
 1407       gtk_widget_set_sensitive(compress_opt, 0);
 1408    }
 1409 
 1410    hbox = gtk_hbox_new(0, 8);
 1411    gtk_box_pack_start(GTK_BOX(vbox), hbox, 1, 1, 0);
 1412    gtk_widget_show(hbox);
 1413 
 1414    check = gtk_check_button_new_with_label("Transparent index:");
 1415    gtk_box_pack_start(GTK_BOX(hbox), check, 0, 0, 0);
 1416    gtk_signal_connect(GTK_OBJECT(check), "clicked",
 1417                       GTK_SIGNAL_FUNC(transindex_clicked), 0);
 1418    gtk_widget_show(check);
 1419 
 1420    spin = gtk_spin_button_new(GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 255, 1, 1, 0)), 1, 0);
 1421    gtk_box_pack_start(GTK_BOX(hbox), spin, 1, 1, 0);
 1422    gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin),
 1423                                      GTK_UPDATE_IF_VALID);
 1424    gtk_signal_connect(GTK_OBJECT(spin), "value_changed",
 1425                       GTK_SIGNAL_FUNC(transindex_changed), 0);
 1426    gtk_widget_show(spin);
 1427 
 1428    g_object_set_data(G_OBJECT(check), "spin", spin);
 1429 
 1430    if(basetype != GIMP_INDEXED)
 1431    {
 1432       gtk_widget_set_sensitive(check, 0);
 1433       gtk_widget_set_sensitive(spin, 0);
 1434    }
 1435    else if(ddsvals.transindex < 0)
 1436    {
 1437       gtk_widget_set_sensitive(spin, 0);
 1438    }
 1439    else if(ddsvals.transindex >= 0)
 1440    {
 1441       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), 1);
 1442       gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), ddsvals.transindex);
 1443    }
 1444 
 1445    gtk_widget_show(dlg);
 1446 
 1447    runme = 0;
 1448 
 1449    gtk_main();
 1450 
 1451    return(runme);
 1452 }

ViewVC Help
Powered by ViewVC 1.0.4