Parent Directory
|
Revision Log
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 |