Below is a patch to add support for saving TGA files upside down. Although it sounds strange to do, it is a supported feature of the file format and OpenGL expects its textures to be upside down. Support already exists for reading such files but it was impossible to save them. Brandon Index: tga.c =================================================================== RCS file: /cvs/gnome/gimp/plug-ins/common/tga.c,v retrieving revision 1.20 diff -c -r1.20 tga.c *** tga.c 2000/08/28 00:42:20 1.20 --- tga.c 2000/09/09 23:16:49 *************** *** 95,105 **** --- 95,107 ---- typedef struct _TgaSaveVals { gint rle; + gint vertrev; } TgaSaveVals; static TgaSaveVals tsvals = { 1, /* rle */ + 0, /* Bottom to Top ordering */ }; typedef struct _TgaSaveInterface *************** *** 1186,1192 **** struct tga_header hdr; int (*myfwrite)(guchar *, int, int, FILE *); ! guchar *data; drawable = gimp_drawable_get(drawable_ID); dtype = gimp_drawable_type(drawable_ID); --- 1188,1194 ---- struct tga_header hdr; int (*myfwrite)(guchar *, int, int, FILE *); ! guchar *data, *tmpbuf; drawable = gimp_drawable_get(drawable_ID); dtype = gimp_drawable_type(drawable_ID); *************** *** 1199,1205 **** memset (&hdr, 0, sizeof (hdr)); /* We like our images top-to-bottom, thank you! */ ! hdr.descriptor |= TGA_DESC_VERTICAL; /* Choose the imageType based on our drawable and compression option. */ switch (dtype) --- 1201,1210 ---- memset (&hdr, 0, sizeof (hdr)); /* We like our images top-to-bottom, thank you! */ ! /* Not all of us :-P */ ! if (!tsvals.vertrev) { ! hdr.descriptor |= TGA_DESC_VERTICAL; ! } /* Choose the imageType based on our drawable and compression option. */ switch (dtype) *************** *** 1363,1369 **** { /* Get a horizontal slice of the image. */ tileheight = MIN(tileheight, height - i); ! gimp_pixel_rgn_get_rect(&pixel_rgn, data, 0, i, width, tileheight); #ifdef VERBOSE if (verbose > 1) --- 1368,1388 ---- { /* Get a horizontal slice of the image. */ tileheight = MIN(tileheight, height - i); ! if (!tsvals.vertrev) { ! gimp_pixel_rgn_get_rect(&pixel_rgn, data, 0, i, width, tileheight); ! } else { ! gimp_pixel_rgn_get_rect(&pixel_rgn, data, 0, MAX(height - i - tileheight, 0), width, tileheight); ! bsize = width * pelbytes; /* the width of a row */ ! tmpbuf = (guchar *) g_malloc(bsize); ! for (j = 0; j < tileheight/2; j++) ! { ! memcpy(tmpbuf, data + (j * bsize), bsize); /* Move top row to the tmpbuf */ ! memcpy(data + (j * bsize), data + ((tileheight - j - 1) * bsize), ! bsize); /* Move bottom row to the top */ ! memcpy(data + ((tileheight - j - 1) * bsize), tmpbuf, bsize); ! } ! g_free(tmpbuf); ! } #ifdef VERBOSE if (verbose > 1) *************** *** 1473,1478 **** --- 1492,1506 ---- GTK_SIGNAL_FUNC (gimp_toggle_button_update), &tsvals.rle); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), tsvals.rle); + gtk_widget_show (toggle); + + /* Bottom to Top Ordering */ + toggle = gtk_check_button_new_with_label (_("Upside Down Image")); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT (toggle), "toggled", + GTK_SIGNAL_FUNC (gimp_toggle_button_update), + &tsvals.vertrev); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), tsvals.vertrev); gtk_widget_show (toggle); gtk_widget_show (vbox);