00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifdef HAVE_CONFIG_H
00012 #include "config.h"
00013 #endif
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <ctype.h>
00019
00020 #include <gtk/gtk.h>
00021
00022 #include <libgimp/gimp.h>
00023 #include <libgimp/gimpui.h>
00024
00025 #ifdef HAVE_GIMP_1_2
00026 #define GIMP20_CONST
00027 #else
00028 #define GIMP20_CONST const
00029 #endif
00030
00031
00032
00033
00034 static void query (void);
00035 static void run (GIMP20_CONST gchar *name,
00036 gint nparams,
00037 GIMP20_CONST GimpParam *param,
00038 gint *nreturn_vals,
00039 GimpParam **return_vals);
00040 static void load_palette(gchar *filename);
00041 static void choose_palette (void);
00042 static gint32 load_image (gchar *filename);
00043 static gint32 save_image (gchar *filename,
00044 gint32 image_ID,
00045 gint32 drawable_ID,
00046 gint32 orig_image_ID);
00047 #ifdef HAVE_GIMP_1_2
00048 static GimpRunModeType run_mode;
00049 #else
00050 static GimpRunMode run_mode;
00051 #endif
00052
00053 static guchar gimp_cmap[768] = {
00054 0x00, 0x00, 0x00, 0xF8, 0xF0, 0xCC, 0xF4, 0xE4, 0xA4, 0xF0, 0xDC, 0x78,
00055 0xEC, 0xD0, 0x50, 0xEC, 0xC8, 0x28, 0xD8, 0xAC, 0x20, 0xC4, 0x94, 0x18,
00056 0xB0, 0x80, 0x10, 0x9C, 0x68, 0x0C, 0x88, 0x54, 0x08, 0x74, 0x44, 0x04,
00057 0x60, 0x30, 0x00, 0x4C, 0x24, 0x00, 0x38, 0x14, 0x00, 0xF8, 0xFC, 0xFC,
00058 0xFC, 0xD8, 0xD8, 0xFC, 0xB8, 0xB8, 0xFC, 0x98, 0x9C, 0xFC, 0x78, 0x80,
00059 0xFC, 0x58, 0x64, 0xFC, 0x38, 0x4C, 0xFC, 0x1C, 0x34, 0xDC, 0x14, 0x28,
00060 0xC0, 0x0C, 0x1C, 0xA4, 0x08, 0x14, 0x88, 0x04, 0x0C, 0x6C, 0x00, 0x04,
00061 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x18, 0x00, 0x00, 0xFC, 0xEC, 0xD8,
00062 0xFC, 0xDC, 0xB8, 0xFC, 0xCC, 0x98, 0xFC, 0xBC, 0x7C, 0xFC, 0xAC, 0x5C,
00063 0xFC, 0x9C, 0x3C, 0xFC, 0x8C, 0x1C, 0xFC, 0x7C, 0x00, 0xE0, 0x6C, 0x00,
00064 0xC0, 0x60, 0x00, 0xA4, 0x50, 0x00, 0x88, 0x44, 0x00, 0x6C, 0x34, 0x00,
00065 0x50, 0x24, 0x00, 0x34, 0x18, 0x00, 0x18, 0x08, 0x00, 0xFC, 0xFC, 0xD8,
00066 0xF4, 0xF4, 0x9C, 0xEC, 0xEC, 0x60, 0xE4, 0xE4, 0x2C, 0xDC, 0xDC, 0x00,
00067 0xC0, 0xC0, 0x00, 0xA4, 0xA4, 0x00, 0x88, 0x88, 0x00, 0x6C, 0x6C, 0x00,
00068 0x50, 0x50, 0x00, 0x34, 0x34, 0x00, 0x18, 0x18, 0x00, 0xD8, 0xFC, 0xD8,
00069 0xB0, 0xFC, 0xAC, 0x8C, 0xFC, 0x80, 0x6C, 0xFC, 0x54, 0x50, 0xFC, 0x28,
00070 0x38, 0xFC, 0x00, 0x28, 0xDC, 0x00, 0x1C, 0xC0, 0x00, 0x14, 0xA4, 0x00,
00071 0x0C, 0x88, 0x00, 0x04, 0x6C, 0x00, 0x00, 0x50, 0x00, 0x00, 0x34, 0x00,
00072 0x00, 0x18, 0x00, 0xD4, 0xD8, 0xFC, 0xB8, 0xB8, 0xFC, 0x98, 0x98, 0xFC,
00073 0x7C, 0x7C, 0xFC, 0x5C, 0x5C, 0xFC, 0x3C, 0x3C, 0xFC, 0x00, 0x00, 0xFC,
00074 0x00, 0x00, 0xE0, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x88,
00075 0x00, 0x00, 0x6C, 0x00, 0x00, 0x50, 0x00, 0x00, 0x34, 0x00, 0x00, 0x18,
00076 0xE8, 0xC8, 0xE8, 0xD4, 0x98, 0xD4, 0xC4, 0x6C, 0xC4, 0xB0, 0x48, 0xB0,
00077 0xA0, 0x28, 0xA0, 0x8C, 0x10, 0x8C, 0x7C, 0x00, 0x7C, 0x6C, 0x00, 0x6C,
00078 0x60, 0x00, 0x60, 0x50, 0x00, 0x50, 0x44, 0x00, 0x44, 0x34, 0x00, 0x34,
00079 0x24, 0x00, 0x24, 0x18, 0x00, 0x18, 0xF4, 0xE8, 0xE4, 0xEC, 0xDC, 0xD4,
00080 0xE4, 0xCC, 0xC0, 0xE0, 0xC0, 0xB0, 0xD8, 0xB0, 0xA0, 0xD0, 0xA4, 0x90,
00081 0xC8, 0x98, 0x80, 0xC4, 0x8C, 0x74, 0xAC, 0x7C, 0x64, 0x98, 0x6C, 0x58,
00082 0x80, 0x5C, 0x4C, 0x6C, 0x4C, 0x3C, 0x54, 0x3C, 0x30, 0x3C, 0x2C, 0x24,
00083 0x28, 0x1C, 0x14, 0x10, 0x0C, 0x08, 0xEC, 0xEC, 0xEC, 0xDC, 0xDC, 0xDC,
00084 0xCC, 0xCC, 0xCC, 0xBC, 0xBC, 0xBC, 0xAC, 0xAC, 0xAC, 0x9C, 0x9C, 0x9C,
00085 0x8C, 0x8C, 0x8C, 0x7C, 0x7C, 0x7C, 0x6C, 0x6C, 0x6C, 0x60, 0x60, 0x60,
00086 0x50, 0x50, 0x50, 0x44, 0x44, 0x44, 0x34, 0x34, 0x34, 0x24, 0x24, 0x24,
00087 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0xE8, 0xE0, 0xD4, 0xD8, 0xC8, 0xB0,
00088 0xC8, 0xB0, 0x90, 0xB8, 0x98, 0x70, 0xA8, 0x84, 0x58, 0x98, 0x70, 0x40,
00089 0x88, 0x5C, 0x2C, 0x7C, 0x4C, 0x18, 0x6C, 0x3C, 0x0C, 0x5C, 0x34, 0x0C,
00090 0x4C, 0x2C, 0x0C, 0x3C, 0x24, 0x0C, 0x2C, 0x1C, 0x08, 0x20, 0x14, 0x08,
00091 0xEC, 0xE8, 0xE4, 0xDC, 0xD4, 0xD0, 0xCC, 0xC4, 0xBC, 0xBC, 0xB0, 0xAC,
00092 0xAC, 0xA0, 0x98, 0x9C, 0x90, 0x88, 0x8C, 0x80, 0x78, 0x7C, 0x70, 0x68,
00093 0x6C, 0x60, 0x5C, 0x60, 0x54, 0x50, 0x50, 0x48, 0x44, 0x44, 0x3C, 0x38,
00094 0x34, 0x30, 0x2C, 0x24, 0x20, 0x20, 0x18, 0x14, 0x14, 0xE0, 0xE8, 0xD4,
00095 0xC8, 0xD4, 0xB4, 0xB4, 0xC0, 0x98, 0x9C, 0xAC, 0x7C, 0x88, 0x98, 0x60,
00096 0x70, 0x84, 0x4C, 0x5C, 0x70, 0x38, 0x4C, 0x5C, 0x28, 0x40, 0x50, 0x20,
00097 0x38, 0x44, 0x1C, 0x30, 0x3C, 0x18, 0x28, 0x30, 0x14, 0x20, 0x24, 0x10,
00098 0x18, 0x1C, 0x08, 0x0C, 0x10, 0x04, 0xEC, 0xD8, 0xCC, 0xDC, 0xB8, 0xA0,
00099 0xCC, 0x98, 0x7C, 0xBC, 0x80, 0x5C, 0xAC, 0x64, 0x3C, 0x9C, 0x50, 0x24,
00100 0x8C, 0x3C, 0x0C, 0x7C, 0x2C, 0x00, 0x6C, 0x24, 0x00, 0x60, 0x20, 0x00,
00101 0x50, 0x1C, 0x00, 0x44, 0x14, 0x00, 0x34, 0x10, 0x00, 0x24, 0x0C, 0x00,
00102 0xF0, 0xF0, 0xFC, 0xE4, 0xE4, 0xFC, 0xD8, 0xD8, 0xFC, 0xCC, 0xCC, 0xFC,
00103 0xC0, 0xC0, 0xFC, 0xB4, 0xB4, 0xFC, 0xA8, 0xA8, 0xFC, 0x9C, 0x9C, 0xFC,
00104 0x84, 0xD0, 0x00, 0x84, 0xB0, 0x00, 0x7C, 0x94, 0x00, 0x68, 0x78, 0x00,
00105 0x50, 0x58, 0x00, 0x3C, 0x40, 0x00, 0x2C, 0x24, 0x00, 0x1C, 0x08, 0x00,
00106 0x20, 0x00, 0x00, 0xEC, 0xD8, 0xC4, 0xDC, 0xC0, 0xB4, 0xCC, 0xB4, 0xA0,
00107 0xBC, 0x9C, 0x94, 0xAC, 0x90, 0x80, 0x9C, 0x84, 0x74, 0x8C, 0x74, 0x64,
00108 0x7C, 0x64, 0x58, 0x6C, 0x54, 0x4C, 0x60, 0x48, 0x44, 0x50, 0x40, 0x38,
00109 0x44, 0x34, 0x2C, 0x34, 0x2C, 0x24, 0x24, 0x18, 0x18, 0x18, 0x10, 0x10,
00110 0xFC, 0xF8, 0xFC, 0xAC, 0xD4, 0xF0, 0x70, 0xAC, 0xE4, 0x34, 0x8C, 0xD8,
00111 0x00, 0x6C, 0xD0, 0x30, 0x8C, 0xD8, 0x6C, 0xB0, 0xE4, 0xB0, 0xD4, 0xF0,
00112 0xFC, 0xFC, 0xF8, 0xFC, 0xEC, 0x40, 0xFC, 0xC0, 0x28, 0xFC, 0x8C, 0x10,
00113 0xFC, 0x50, 0x00, 0xC8, 0x38, 0x00, 0x98, 0x28, 0x00, 0x68, 0x18, 0x00,
00114 0x7C, 0xDC, 0x7C, 0x44, 0xB4, 0x44, 0x18, 0x90, 0x18, 0x00, 0x6C, 0x00,
00115 0xF8, 0xB8, 0xFC, 0xFC, 0x64, 0xEC, 0xFC, 0x00, 0xB4, 0xCC, 0x00, 0x70,
00116 0xFC, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x00,
00117 0xFC, 0xFC, 0xFC, 0x61, 0x61, 0x61, 0xC0, 0xC0, 0xC0, 0xFC, 0x00, 0xF1 };
00118
00119 GimpPlugInInfo PLUG_IN_INFO =
00120 {
00121 NULL,
00122 NULL,
00123 query,
00124 run,
00125 };
00126
00127 struct u7frame {
00128 gint16 leftX;
00129 gint16 leftY;
00130 gint16 rightX;
00131 gint16 rightY;
00132 gint16 width;
00133 gint16 height;
00134 gint32 datalen;
00135 guchar *pixels;
00136 };
00137
00138 struct u7shape {
00139 int num_frames;
00140 struct u7frame *frames;
00141 };
00142
00143
00144 MAIN ()
00145
00146 static void
00147 query (void)
00148 {
00149 static GimpParamDef load_args[] = {
00150 { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
00151 { GIMP_PDB_STRING, "filename", "The name of the file to load" },
00152 { GIMP_PDB_STRING, "raw_filename", "The name entered" }
00153 };
00154 static GimpParamDef load_return_vals[] = {
00155 { GIMP_PDB_IMAGE, "image", "Output image" }
00156 };
00157 static gint nload_args = sizeof (load_args) / sizeof (load_args[0]);
00158 static gint nload_return_vals = (sizeof (load_return_vals) /
00159 sizeof (load_return_vals[0]));
00160
00161 static GimpParamDef save_args[] = {
00162 { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
00163 { GIMP_PDB_IMAGE, "image", "Image to save" },
00164 { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
00165 { GIMP_PDB_STRING, "filename", "The name of the file to save" },
00166 { GIMP_PDB_STRING, "raw_filename", "The name entered" }
00167 };
00168 static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
00169
00170 gimp_install_procedure ("file_shp_load",
00171 "loads files in Ultima 7 SHP format",
00172 "FIXME: write help for shp_load",
00173 "Tristan Tarrant",
00174 "Tristan Tarrant",
00175 "2000",
00176 "<Load>/SHP",
00177 NULL,
00178 GIMP_PLUGIN,
00179 nload_args, nload_return_vals,
00180 load_args, load_return_vals);
00181
00182 gimp_register_magic_load_handler ("file_shp_load",
00183 "shp",
00184 "",
00185 "");
00186
00187 gimp_install_procedure ("file_shp_save",
00188 "Save files in Ultima 7 SHP format",
00189 "FIXME: write help for shp_save",
00190 "Tristan Tarrant",
00191 "Tristan Tarrant",
00192 "2000",
00193 "<Save>/SHP",
00194 "INDEXEDA",
00195 GIMP_PLUGIN,
00196 nsave_args, 0,
00197 save_args, NULL);
00198
00199 gimp_register_save_handler ("file_shp_save",
00200 "shp",
00201 "");
00202 }
00203
00204 static void
00205 run (GIMP20_CONST gchar *name,
00206 gint nparams,
00207 GIMP20_CONST GimpParam *param,
00208 gint *nreturn_vals,
00209 GimpParam **return_vals)
00210 {
00211 static GimpParam values[2];
00212 GimpPDBStatusType status = GIMP_PDB_SUCCESS;
00213 gint32 image_ID;
00214 gint32 drawable_ID;
00215 gint32 orig_image_ID;
00216
00217 run_mode = param[0].data.d_int32;
00218
00219 *nreturn_vals = 1;
00220 *return_vals = values;
00221 values[0].type = GIMP_PDB_STATUS;
00222 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
00223
00224 if (strcmp (name, "file_shp_load") == 0) {
00225 gimp_ui_init ("u7shp", FALSE);
00226 choose_palette();
00227 image_ID = load_image (param[1].data.d_string);
00228
00229 if (image_ID != -1) {
00230 *nreturn_vals = 2;
00231 values[1].type = GIMP_PDB_IMAGE;
00232 values[1].data.d_image = image_ID;
00233 } else {
00234 status = GIMP_PDB_EXECUTION_ERROR;
00235 }
00236 } else if (strcmp (name, "file_shp_save") == 0) {
00237 image_ID = orig_image_ID = param[1].data.d_int32;
00238 drawable_ID = param[2].data.d_int32;
00239 save_image (param[3].data.d_string,
00240 image_ID,
00241 drawable_ID,
00242 orig_image_ID);
00243 } else{
00244 status = GIMP_PDB_CALLING_ERROR;
00245 }
00246 values[0].data.d_status = status;
00247 }
00248
00249 unsigned int read1(FILE *f)
00250 {
00251 unsigned char b0;
00252 b0 = fgetc(f);
00253 return b0;
00254 }
00255
00256 unsigned int read2(FILE *f)
00257 {
00258 unsigned char b0, b1;
00259 b0 = fgetc(f);
00260 b1 = fgetc(f);
00261 return (b0 + (b1<<8));
00262 }
00263
00264
00265 signed int read2signed(FILE *f)
00266 {
00267 unsigned char b0, b1;
00268 signed int i0;
00269 b0 = fgetc(f);
00270 b1 = fgetc(f);
00271 i0 = b0 + (b1<<8);
00272 if (i0 >= 32768) { i0 = i0 - 65536; }
00273 return (i0);
00274 }
00275
00276 unsigned int read4(FILE *f)
00277 {
00278 unsigned char b0, b1, b2, b3;
00279 b0 = fgetc(f);
00280 b1 = fgetc(f);
00281 b2 = fgetc(f);
00282 b3 = fgetc(f);
00283 return (b0 + (b1<<8) + (b2<<16) + (b3<<24));
00284 }
00285
00286 void write1(FILE *f, unsigned char b)
00287 {
00288 fputc(b, f);
00289 }
00290
00291 void write2(FILE *f, unsigned int b)
00292 {
00293 fputc(b & 0xFF, f);
00294 fputc((b >> 8) & 0xFF, f);
00295 }
00296
00297 void write4(FILE *f, unsigned int b)
00298 {
00299 fputc(b & 0xFF, f);
00300 fputc((b >> 8) & 0xFF, f);
00301 fputc((b >> 16) & 0xFF, f);
00302 fputc((b >> 24) & 0xFF, f);
00303 }
00304
00305 unsigned char *out1(unsigned char *p, unsigned char b)
00306 {
00307 *p++ = b;
00308 return p;
00309 }
00310
00311 unsigned char *out2(unsigned char *p, unsigned int b)
00312 {
00313 *p++ = b & 0xFF;
00314 *p++ = (b >> 8) & 0xFF;
00315 return p;
00316 }
00317
00318 unsigned char *out4(unsigned char *p, unsigned int b)
00319 {
00320 *p++ = b & 0xFF;
00321 *p++ = (b >> 8) & 0xFF;
00322 *p++ = (b >> 16) & 0xFF;
00323 *p++ = (b >> 24) & 0xFF;
00324 return p;
00325 }
00326
00327 static void load_palette (gchar *filename)
00328 {
00329 FILE *fp;
00330 long len;
00331 int i;
00332
00333 fp = fopen (filename, "rb");
00334 if (!fp) {
00335 return;
00336 }
00337 fseek(fp, 0, SEEK_END);
00338 len = ftell(fp);
00339 fseek(fp, 0, SEEK_SET);
00340 if(len==768) {
00341 for(i=0;i<256;i++) {
00342 gimp_cmap[i*3]=read1(fp) << 2;
00343 gimp_cmap[i*3+1]=read1(fp) << 2;
00344 gimp_cmap[i*3+2]=read1(fp) << 2;
00345 }
00346 } else if(len==1536) {
00347 for(i=0;i<256;i++) {
00348 gimp_cmap[i*3]=read1(fp) << 2;
00349 read1(fp);
00350 gimp_cmap[i*3+1]=read1(fp) << 2;
00351 read1(fp);
00352 gimp_cmap[i*3+2]=read1(fp) << 2;
00353 read1(fp);
00354 }
00355 }
00356 fclose(fp);
00357 }
00358
00359 static void file_sel_delete( GtkWidget *widget, GtkWidget **file_sel )
00360 {
00361 gtk_widget_destroy( *file_sel );
00362 *file_sel = NULL;
00363 }
00364
00365 static void file_selected( GtkWidget *widget, gboolean *selected )
00366 {
00367 *selected = TRUE;
00368 }
00369
00370 gchar* file_select( gchar *title )
00371 {
00372 GtkWidget *file_sel;
00373 gchar *filename;
00374 gboolean selected = FALSE;
00375
00376 file_sel = gtk_file_selection_new( title );
00377 gtk_window_set_modal( GTK_WINDOW( file_sel ), TRUE );
00378
00379 gtk_signal_connect( GTK_OBJECT( file_sel ), "destroy",
00380 GTK_SIGNAL_FUNC( file_sel_delete ), &file_sel );
00381
00382 gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION( file_sel )->cancel_button ), "clicked", GTK_SIGNAL_FUNC( file_sel_delete ), &file_sel );
00383
00384 gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION( file_sel )->ok_button ), "clicked", GTK_SIGNAL_FUNC( file_selected ), &selected );
00385
00386 gtk_widget_show( file_sel );
00387
00388 while( ( ! selected ) && ( file_sel ) )
00389 gtk_main_iteration();
00390
00391
00392 if( ! selected )
00393 return NULL;
00394
00395
00396 filename = g_strdup( gtk_file_selection_get_filename( GTK_FILE_SELECTION( file_sel ) ) );
00397 gtk_widget_destroy( file_sel );
00398 return filename;
00399 }
00400
00401
00402
00403 static void choose_palette()
00404 {
00405 load_palette(file_select("Choose palette"));
00406 }
00407
00408
00409 static gint32 load_image (gchar *filename)
00410 {
00411 FILE *fp;
00412 gint32 file_size;
00413 gint32 shape_size;
00414 gint32 hdr_size;
00415 guchar *pixptr, *eod;
00416 gint32 frame_offset;
00417 gint16 slice;
00418 gint32 image_ID = -1;
00419 gint32 layer_ID = -1;
00420 gint16 slice_type;
00421 gint16 slice_length;
00422 gint16 block_type;
00423 gint16 block_length;
00424
00425
00426 gint16 max_leftX = -1, max_rightX = -1;
00427 gint16 max_leftY = -1, max_rightY = -1;
00428 signed int offsetX;
00429 signed int offsetY;
00430 gchar *framename;
00431 guchar block;
00432 guchar pix;
00433 GimpDrawable *drawable;
00434 GimpPixelRgn pixel_rgn;
00435 GimpImageType image_type;
00436 int i;
00437 int j;
00438
00439
00440 signed int temp_int;
00441
00442 struct u7shape shape;
00443 struct u7frame *frame;
00444
00445 fp = fopen (filename, "rb");
00446 if (!fp) {
00447 g_message ("SHP: can't open \"%s\"\n", filename);
00448 return -1;
00449 }
00450 fseek(fp, 0, SEEK_END);
00451 file_size = ftell(fp);
00452 fseek(fp, 0, SEEK_SET);
00453
00454 shape_size = read4(fp);
00455
00456 if(file_size!=shape_size) {
00457 image_type = GIMP_INDEXED_IMAGE;
00458 shape.num_frames = file_size/64;
00459 fseek(fp, 0, SEEK_SET);
00460 #ifdef DEBUG
00461 printf("num_frames = %d\n", shape.num_frames);
00462 #endif
00463 shape.frames = g_new(struct u7frame, shape.num_frames);
00464 max_leftX = 0; max_leftY = 0; max_rightX = 7; max_rightY = 7;
00465
00466
00467 for(i=0; i<shape.num_frames; i++) {
00468 frame = &shape.frames[i];
00469 frame->width = 8;
00470 frame->height = 8;
00471 frame->leftX = 0;
00472 frame->leftY = 0;
00473 frame->pixels = (char *)g_malloc(64);
00474 fread(frame->pixels, 1, 64, fp);
00475 }
00476 } else {
00477 image_type = GIMP_INDEXEDA_IMAGE;
00478 hdr_size = read4(fp);
00479 shape.num_frames = (hdr_size-4)/4;
00480
00481
00482 #ifdef DEBUG
00483 printf("num_frames = %d\n", shape.num_frames);
00484 #endif
00485 shape.frames = g_new(struct u7frame, shape.num_frames);
00486
00487 for(i=0; i<shape.num_frames; i++) {
00488 frame = &shape.frames[i];
00489
00490 fseek(fp, (i+1)*4, SEEK_SET);
00491 frame_offset = read4(fp);
00492 fseek(fp, frame_offset, SEEK_SET);
00493 frame->rightX = read2(fp);
00494 frame->leftX = read2(fp);
00495 frame->leftY = read2(fp);
00496 frame->rightY = read2(fp);
00497
00498 if (frame->leftX > max_leftX)
00499 max_leftX = frame->leftX;
00500 if (frame->rightX > max_rightX)
00501 max_rightX = frame->rightX;
00502 if (frame->leftY > max_leftY)
00503 max_leftY = frame->leftY;
00504 if (frame->rightY > max_rightY)
00505 max_rightY = frame->rightY;
00506
00507 frame->width = frame->leftX+frame->rightX+1;
00508
00509
00510 frame->height = frame->leftY+frame->rightY+1;
00511
00512
00513 pixptr = frame->pixels = g_new0(char, frame->width*frame->height*2);
00514 eod = frame->pixels+frame->width*frame->height*2;
00515 while((slice=read2(fp))!=0) {
00516 slice_type = slice & 0x1;
00517 slice_length = slice >> 1;
00518
00519
00520 offsetX = read2signed(fp);
00521 offsetY = read2signed(fp);
00522
00523 temp_int = (frame->leftY + offsetY)*frame->width*2 +
00524 (frame->leftX + offsetX)*2;
00525
00526 pixptr = frame->pixels;
00527 pixptr = pixptr + temp_int;
00528
00529
00530
00531
00532
00533 if(pixptr<frame->pixels)
00534 pixptr = frame->pixels;
00535 if(slice_type) {
00536 while(slice_length>0) {
00537 block = read1(fp);
00538 block_type = block & 0x1;
00539 block_length = block >> 1;
00540 if(block_type) {
00541 pix = read1(fp);
00542 for(j=0;j<block_length;j++) {
00543 *pixptr++ = pix;
00544 *pixptr++ = 255;
00545 }
00546 } else {
00547 for(j=0;j<block_length;j++) {
00548 pix = read1(fp);
00549 *pixptr++ = pix;
00550 *pixptr++ = 255;
00551 }
00552 }
00553 slice_length -= block_length;
00554 }
00555 } else {
00556
00557 for(j=0;j<slice_length;j++) {
00558 pix = read1(fp);
00559 *pixptr++ = pix;
00560 *pixptr++ = 255;
00561 }
00562 }
00563 }
00564 }
00565 }
00566 image_ID = gimp_image_new (max_leftX+max_rightX+1,
00567 max_leftY+max_rightY+1, GIMP_INDEXED);
00568 gimp_image_set_filename (image_ID, filename);
00569 gimp_image_set_cmap (image_ID, gimp_cmap, 256);
00570 for(i=0; i<shape.num_frames; i++) {
00571 framename = g_strdup_printf ("Frame %d", i);
00572 frame = &shape.frames[i];
00573 layer_ID = gimp_layer_new (image_ID, framename,
00574 frame->width, frame->height,
00575 image_type, 100, GIMP_NORMAL_MODE);
00576 g_free (framename);
00577 gimp_image_add_layer (image_ID, layer_ID, 0);
00578 gimp_layer_translate (layer_ID, (gint)(max_leftX-frame->leftX),
00579 (gint)(max_leftY-frame->leftY));
00580
00581 drawable = gimp_drawable_get (layer_ID);
00582
00583 gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE);
00584 gimp_pixel_rgn_set_rect (&pixel_rgn, frame->pixels, 0, 0, drawable->width, drawable->height);
00585
00586 gimp_drawable_flush (drawable);
00587 gimp_drawable_detach (drawable);
00588 }
00589
00590 fclose(fp);
00591
00592 for(i=0; i<shape.num_frames; i++) {
00593 g_free(shape.frames[i].pixels);
00594 }
00595
00596 g_free(shape.frames);
00597
00598 gimp_image_add_hguide(image_ID, max_leftY);
00599 #ifdef DEBUG
00600 printf("Added hguide=%d\n", max_leftY);
00601 #endif
00602 gimp_image_add_vguide(image_ID, max_leftX);
00603 #ifdef DEBUG
00604 printf("Added vguide=%d\n", max_leftX);
00605 #endif
00606
00607 return image_ID;
00608 }
00609
00610 static int find_runs(short *runs, unsigned char *pixptr, int x, int w)
00611 {
00612 int runcnt = 0;
00613 while (x < w && pixptr[1] != 0) {
00614 int run = 0;
00615 while (x < w - 1 && pixptr[0] == pixptr[2] && pixptr[3]!=0) {
00616 #ifdef DEBUG
00617 if(pixptr[3]==0)
00618 printf("Warning: found pixel pair, but second is transparent\n");
00619 #endif
00620 x++;
00621 pixptr+=2;
00622 run++;
00623 }
00624 if (run) {
00625 run = ((run + 1)<<1)|1;
00626 x++;
00627 pixptr+=2;
00628 } else {
00629 do {
00630 x++;
00631 pixptr+=2;
00632 run += 2;
00633 } while (x < w && pixptr[1] != 0 &&
00634 (x == w - 1 || pixptr[0] != pixptr[2]));
00635 }
00636
00637 runs[runcnt++] = run;
00638 }
00639 runs[runcnt] = 0;
00640 return x;
00641 }
00642
00643 static int skip_transparent(unsigned char **pixptr, int x, int w)
00644 {
00645 unsigned char *pixel = *pixptr;
00646 while (x < w && pixel[1] == 0) {
00647 x++;
00648 pixel+=2;
00649 }
00650 *pixptr = pixel;
00651 return x;
00652 }
00653
00654 static gint32 save_image (gchar *filename,
00655 gint32 image_ID,
00656 gint32 drawable_ID,
00657 gint32 orig_image_ID)
00658 {
00659 FILE *fp;
00660 gint32 shape_size;
00661 gint32 hdr_size;
00662 gint32 max_width;
00663 gint32 max_height;
00664 gint offsetX;
00665 gint offsetY;
00666 gchar *name_buf;
00667 GimpDrawable *drawable;
00668 GimpPixelRgn pixel_rgn;
00669 guchar *pixptr;
00670 guchar *pix;
00671 guchar *out;
00672 guchar *outptr;
00673 int i;
00674 int j;
00675 int k;
00676 int newx;
00677 int x;
00678 int y;
00679 int hotx;
00680 int hoty;
00681 gint32 guide_ID;
00682 gint32 *layers;
00683 int nlayers;
00684 int pos;
00685
00686 struct u7shape shape;
00687 struct u7frame *frame;
00688
00689 if (run_mode != GIMP_RUN_NONINTERACTIVE) {
00690 name_buf = g_strdup_printf ("Saving %s:", filename);
00691 gimp_progress_init (name_buf);
00692 g_free (name_buf);
00693 }
00694
00695
00696 guide_ID = gimp_image_find_next_guide(image_ID, 0);
00697 hotx = -1;
00698 hoty = -1;
00699 while(guide_ID>0) {
00700 int orientation;
00701 #ifdef DEBUG
00702 printf("Found guide %d:", guide_ID);
00703 #endif
00704 orientation = gimp_image_get_guide_orientation(image_ID, guide_ID);
00705 switch(orientation) {
00706 #ifdef HAVE_GIMP_1_2
00707 case GIMP_HORIZONTAL:
00708 #else
00709 case GIMP_ORIENTATION_HORIZONTAL:
00710 #endif
00711 if(hoty<0) {
00712 hoty = gimp_image_get_guide_position(image_ID, guide_ID);
00713 #ifdef DEBUG
00714 printf(", horizontal=%d\n", hoty);
00715 #endif
00716 }
00717 break;
00718 #ifdef HAVE_GIMP_1_2
00719 case GIMP_VERTICAL:
00720 #else
00721 case GIMP_ORIENTATION_VERTICAL:
00722 #endif
00723 if(hotx<0) {
00724 hotx = gimp_image_get_guide_position(image_ID, guide_ID);
00725 #ifdef DEBUG
00726 printf(", vertical=%d\n", hotx);
00727 #endif
00728 }
00729 break;
00730 default:
00731 break;
00732 }
00733 guide_ID = gimp_image_find_next_guide(image_ID, guide_ID);
00734 }
00735
00736
00737 layers = gimp_image_get_layers (image_ID, &nlayers);
00738
00739 if (nlayers > 0 && !gimp_drawable_is_indexed(layers[0])) {
00740 g_message ("SHP: You can only save indexed images!");
00741 return -1;
00742 }
00743
00744 max_width = gimp_image_width (image_ID);
00745 max_height = gimp_image_height (image_ID);
00746
00747 shape.num_frames = nlayers;
00748 hdr_size = (nlayers+1)*4;
00749 shape.frames = (struct u7frame *)malloc(sizeof(struct u7frame)*shape.num_frames);
00750
00751 for (k=0;k<nlayers;k++) {
00752 frame = &shape.frames[k];
00753 drawable = gimp_drawable_get (layers[k]);
00754 gimp_drawable_offsets (layers[k], &offsetX, &offsetY);
00755 frame->width = drawable->width;
00756 frame->height = drawable->height;
00757 frame->leftX = hotx - offsetX;
00758 frame->leftY = hoty - offsetY;
00759 frame->rightX = frame->width-frame->leftX-1;
00760 frame->rightY = frame->height-frame->leftY-1;
00761 pix = (gchar *)malloc(frame->width*frame->height*2);
00762 pixptr = pix;
00763 out = (gchar *)malloc(frame->width*frame->height*8);
00764 outptr = out;
00765 gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
00766 drawable->width, drawable->height, FALSE, FALSE);
00767 gimp_pixel_rgn_get_rect (&pixel_rgn, pixptr, 0, 0,
00768 drawable->width, drawable->height);
00769
00770 newx = 0;
00771 for (y = 0; y < frame->height; y++) {
00772 for (x = 0; (x = skip_transparent(&pixptr, x, frame->width)) < frame->width; x = newx) {
00773 short runs[100];
00774 newx = find_runs(runs, pixptr, x, frame->width);
00775 if (!runs[1] && !(runs[0]&1)) {
00776 int len = runs[0] >> 1;
00777 outptr = out2(outptr, runs[0]);
00778 outptr = out2(outptr, x - frame->leftX);
00779 outptr = out2(outptr, y - frame->leftY);
00780 for(i=0; i<len; i++) {
00781 *outptr++ = *pixptr;
00782 pixptr +=2;
00783 }
00784 } else {
00785 outptr = out2(outptr, ((newx - x)<<1)|1);
00786 outptr = out2(outptr, x - frame->leftX);
00787 outptr = out2(outptr, y - frame->leftY);
00788 for (i = 0; runs[i]; i++) {
00789 int len = runs[i]>>1;
00790 if (runs[i]&1) {
00791 while (len) {
00792 int c = len > 127 ? 127 : len;
00793 *outptr++ = (c<<1)|1;
00794 *outptr++ = *pixptr;
00795 pixptr += (c*2);
00796 len -= c;
00797 }
00798 } else while (len > 0) {
00799 int c;
00800 c = len > 127 ? 127 : len;
00801 *outptr++ = c<<1;
00802 for(j=0; j<c; j++) {
00803 *outptr++ = *pixptr;
00804 pixptr +=2;
00805 }
00806 len -= c;
00807 }
00808 }
00809 }
00810 }
00811 }
00812 outptr = out2(outptr, 0);
00813 frame->datalen = outptr - out;
00814 frame->pixels = (gchar *) malloc(frame->datalen);
00815 memcpy(frame->pixels, out, frame->datalen);
00816 free(out);
00817 free(pix);
00818 gimp_drawable_detach(drawable);
00819 }
00820
00821 fp = fopen (filename, "wb");
00822 if (!fp) {
00823 g_message ("SHP: can't create \"%s\"\n", filename);
00824 return -1;
00825 }
00826
00827 shape_size = 0;
00828 write4(fp, shape_size);
00829 for(i=0; i<shape.num_frames; i++)
00830 write4(fp, 0);
00831 for(i=0; i<shape.num_frames; i++) {
00832 frame = &shape.frames[shape.num_frames-i-1];
00833 pos = ftell(fp);
00834 fseek(fp, (i+1)*4, SEEK_SET);
00835 write4(fp, pos);
00836 fseek(fp, pos, SEEK_SET);
00837 write2(fp, frame->rightX);
00838 write2(fp, frame->leftX);
00839 write2(fp, frame->leftY);
00840 write2(fp, frame->rightY);
00841 fwrite(frame->pixels, 1, frame->datalen, fp);
00842 }
00843
00844 pos = ftell(fp);
00845 fseek(fp, 0, SEEK_SET);
00846 write4(fp, pos);
00847
00848 fclose(fp);
00849
00850 for(i=0; i<shape.num_frames; i++) {
00851 free(shape.frames[i].pixels);
00852 }
00853 free(shape.frames);
00854
00855 return 0;
00856 }