diff --git a/ChangeLog b/ChangeLog index 228113c34b..6a3b6aec65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue May 5 11:40:28 PDT 1998 Manish Singh + + * plug-ins/psd/psd.c: updates from Adam + + * plug-ins/script-fu/scripts/text-circle.scm: new version + Mon May 4 21:24:03 PDT 1998 Manish Singh * Made 0.99.29 release diff --git a/plug-ins/common/psd.c b/plug-ins/common/psd.c index 1c2bed5422..366b85d43f 100644 --- a/plug-ins/common/psd.c +++ b/plug-ins/common/psd.c @@ -1,5 +1,5 @@ /* - * PSD Plugin version 1.9.9.9 (BETA) + * PSD Plugin version 1.9.9.9b (BETA) * This GIMP plug-in is designed to load Adobe Photoshop(tm) files (.PSD) * * Adam D. Moss @@ -36,6 +36,12 @@ /* * Revision history: * + * 98.05.04 / v1.9.9.9b / Adam D. Moss + * Changed the Pascal-style string-reading stuff. That fixed + * some file-padding problems. Made all debugging output + * compile-time optional (please leave it enabled for now). + * Reduced memory requirements; still much room for improvement. + * * 98.04.28 / v1.9.9.9 / Adam D. Moss * Fixed the correct channel interlacing of 'raw' flat images. * Thanks to Christian Kirsch and Jay Cox for spotting this. @@ -75,7 +81,7 @@ * CMYK -> RGB * Load BITMAP mode * - * File saving. (I am not going to be able to do this for + * File saving. (I am unlikely to be able to do this for * practical reasons. Suggest someone works on it as a * separate plugin - please let me know.) * @@ -91,17 +97,26 @@ /* *** DEFINES *** */ + +/* set to TRUE if you want debugging, FALSE otherwise */ +#define PSD_DEBUG TRUE + /* the max number of layers that this plugin should try to load */ #define MAX_LAYERS 100 + /* the max number of channels that this plugin should let a layer have */ #define MAX_CHANNELS 30 + /* *** END OF DEFINES *** */ + +#define IFDBG if (PSD_DEBUG) + #include #include -#include #include +#include #include #include "libgimp/gimp.h" @@ -178,7 +193,7 @@ typedef struct PsdLayer gboolean protecttrans; gboolean visible; - guchar* name; + gchar* name; gint32 lm_x; gint32 lm_y; @@ -217,7 +232,7 @@ static PSDimage psd_image; static struct { - guchar signature[4]; + gchar signature[4]; gushort version; guchar reserved[6]; gushort channels; @@ -270,9 +285,9 @@ static void xfread_interlaced(FILE *fd, guchar *buf, long len, gchar *why, static void *xmalloc(size_t n); static void read_whole_file(FILE *fd); static void reshuffle_cmap(guchar *map256); -static guchar *getpascalstring(FILE *fd, guchar *why); -void throwchunk(size_t n, FILE * fd, guchar *why); -void dumpchunk(size_t n, FILE * fd, guchar *why); +static guchar *getpascalstring(FILE *fd, gchar *why); +void throwchunk(size_t n, FILE * fd, gchar *why); +void dumpchunk(size_t n, FILE * fd, gchar *why); MAIN() @@ -487,7 +502,7 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) { if ( (ID < 0x0bb6) && (ID >0x07d0) ) { - printf ("\t\tPath data is irrelevant to GIMP at this time.\n"); + IFDBG printf ("\t\tPath data is irrelevant to GIMP at this time.\n"); throwchunk(Size, fd, "dispatch_res path throw"); (*offset) += Size; } @@ -498,22 +513,30 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) { gint32 remaining = Size; - printf ("\t\tALPHA CHANNEL NAMES:\n"); + IFDBG printf ("\t\tALPHA CHANNEL NAMES:\n"); if (Size > 0) { do { - guint32 alpha_name_len; - psd_image.aux_channel[psd_image.num_aux_channels].name = getpascalstring(fd, "alpha channel name"); + (*offset)++; + remaining--; + + if (psd_image.aux_channel[psd_image.num_aux_channels].name) + { + guint32 alpha_name_len; - alpha_name_len = - strlen(psd_image.aux_channel[psd_image.num_aux_channels].name); - - printf("\t\t\tname: \"%s\"\n", - psd_image.aux_channel[psd_image.num_aux_channels].name); + alpha_name_len = + strlen(psd_image.aux_channel[psd_image.num_aux_channels].name); + + IFDBG printf("\t\t\tname: \"%s\"\n", + psd_image.aux_channel[psd_image.num_aux_channels].name); + (*offset) += alpha_name_len; + remaining -= alpha_name_len; + } + psd_image.num_aux_channels++; if (psd_image.num_aux_channels > MAX_CHANNELS) @@ -521,9 +544,6 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) printf("\nPSD: Sorry - this image has too many aux channels. Tell Adam!\n"); gimp_quit(); } - - (*offset) += alpha_name_len+1; - remaining -= alpha_name_len+1; } while (remaining > 0); } @@ -533,88 +553,89 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) } break; case 0x03ef: - printf("\t\tDISPLAYINFO STRUCTURE: unhandled\n"); - throwchunk(Size, fd, "dispatch_res"); - (*offset) += Size; + IFDBG printf("\t\tDISPLAYINFO STRUCTURE: unhandled\n"); + throwchunk(Size, fd, "dispatch_res"); + (*offset) += Size; break; case 0x03f0: /* FIXME: untested */ { - guint32 caption_len; - psd_image.caption = getpascalstring(fd, "caption string"); - caption_len = strlen(psd_image.caption); - - printf("\t\t\tcontent: \"%s\"\n",psd_image.caption); - (*offset) += caption_len+1; + (*offset)++; + + if (psd_image.caption) + { + IFDBG printf("\t\t\tcontent: \"%s\"\n",psd_image.caption); + (*offset) += strlen(psd_image.caption); + } } break; case 0x03f2: - printf("\t\tBACKGROUND COLOR: unhandled\n"); + IFDBG printf("\t\tBACKGROUND COLOR: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f4: - printf("\t\tGREY/MULTICHANNEL HALFTONING INFO: unhandled\n"); + IFDBG printf("\t\tGREY/MULTICHANNEL HALFTONING INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f5: - printf("\t\tCOLOUR HALFTONING INFO: unhandled\n"); + IFDBG printf("\t\tCOLOUR HALFTONING INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f6: - printf("\t\tDUOTONE HALFTONING INFO: unhandled\n"); + IFDBG printf("\t\tDUOTONE HALFTONING INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f7: - printf("\t\tGREYSCALE/MULTICHANNEL TRANSFER FUNCTION: unhandled\n"); + IFDBG printf("\t\tGREYSCALE/MULTICHANNEL TRANSFER FUNCTION: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f8: - printf("\t\tCOLOUR TRANSFER FUNCTION: unhandled\n"); + IFDBG printf("\t\tCOLOUR TRANSFER FUNCTION: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f9: - printf("\t\tDUOTONE TRANSFER FUNCTION: unhandled\n"); + IFDBG printf("\t\tDUOTONE TRANSFER FUNCTION: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03fa: - printf("\t\tDUOTONE IMAGE INFO: unhandled\n"); + IFDBG printf("\t\tDUOTONE IMAGE INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03fb: - printf("\t\tEFFECTIVE BLACK/WHITE VALUES: unhandled\n"); + IFDBG printf("\t\tEFFECTIVE BLACK/WHITE VALUES: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03fe: - printf("\t\tQUICK MASK INFO: unhandled\n"); + IFDBG printf("\t\tQUICK MASK INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x0400: { - printf("\t\tLAYER STATE INFO:\n"); + IFDBG printf("\t\tLAYER STATE INFO:\n"); psd_image.active_layer_num = getgshort(fd, "ID target_layer_num"); - printf("\t\t\ttarget: %d\n",(gint)psd_image.active_layer_num); + IFDBG printf("\t\t\ttarget: %d\n",(gint)psd_image.active_layer_num); (*offset) += 2; } break; case 0x0402: - printf("\t\tLAYER GROUP INFO: unhandled\n"); - printf("\t\t\t(Inferred number of layers: %d)\n",(gint)(Size/2)); + IFDBG printf("\t\tLAYER GROUP INFO: unhandled\n"); + IFDBG printf("\t\t\t(Inferred number of layers: %d)\n",(gint)(Size/2)); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x0405: - printf ("\t\tIMAGE MODE FOR RAW FORMAT: unhandled\n"); + IFDBG printf ("\t\tIMAGE MODE FOR RAW FORMAT: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; @@ -629,14 +650,14 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) case 0x0406: case 0x0bb7: case 0x2710: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03e8: case 0x03eb: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; @@ -644,13 +665,13 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) case 0x03fc: case 0x03ff: case 0x0403: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; default: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; @@ -668,7 +689,7 @@ do_layer_record(FILE *fd, guint32 *offset, gint layernum) guchar flags; gint i; - printf("\t\t\tLAYER RECORD (layer %d)\n", (int)layernum); + IFDBG printf("\t\t\tLAYER RECORD (layer %d)\n", (int)layernum); /* table 11-12 */ @@ -686,7 +707,7 @@ do_layer_record(FILE *fd, guint32 *offset, gint layernum) psd_image.layer[layernum].width = right-left; psd_image.layer[layernum].height = bottom-top; - printf("\t\t\t\tLayer extents: (%d,%d) -> (%d,%d)\n",left,top,right,bottom); + IFDBG printf("\t\t\t\tLayer extents: (%d,%d) -> (%d,%d)\n",left,top,right,bottom); psd_image.layer[layernum].num_channels = getgshort (fd, "layer num_channels"); @@ -698,23 +719,23 @@ do_layer_record(FILE *fd, guint32 *offset, gint layernum) gimp_quit(); } - printf("\t\t\t\tNumber of channels: %d\n", + IFDBG printf("\t\t\t\tNumber of channels: %d\n", (int)psd_image.layer[layernum].num_channels); for (i=0;i 0) { - printf("Warning: layer record dross: "); - dumpchunk(totaloff-(*offset), fd, "layer record dross throw"); + IFDBG + { + printf("Warning: layer record dross: "); + dumpchunk(totaloff-(*offset), fd, "layer record dross throw"); + } + else + { + throwchunk(totaloff-(*offset), fd, "layer record dross throw"); + } (*offset) = totaloff; } } @@ -831,12 +862,12 @@ do_layer_struct(FILE *fd, guint32 *offset) { gint i; - printf("\t\tLAYER STRUCTURE SECTION\n"); + IFDBG printf("\t\tLAYER STRUCTURE SECTION\n"); psd_image.num_layers = getgshort(fd, "layer struct numlayers"); (*offset)+=2; - printf("\t\t\tCanonical number of layers: %d%s\n", + IFDBG printf("\t\t\tCanonical number of layers: %d%s\n", psd_image.num_layers>0? (int)psd_image.num_layers:abs(psd_image.num_layers), psd_image.num_layers>0?"":" (absolute/alpha)"); @@ -895,14 +926,15 @@ do_layer_pixeldata(FILE *fd, guint32 *offset) compression = getgshort(fd, "layer channel compression type"); (*offset)+=2; - printf("\t\t\tLayer (%d) Channel (%d:%d) Compression: %d (%s)\n", - layeri, - channeli, - psd_image.layer[layeri].channel[channeli].type, - compression, - compression==0?"raw":(compression==1?"RLE":"UNKNOWN!")); - - printf("\t\t\t\tLoading channel data (%d bytes)...\n", + IFDBG + printf("\t\t\tLayer (%d) Channel (%d:%d) Compression: %d (%s)\n", + layeri, + channeli, + psd_image.layer[layeri].channel[channeli].type, + compression, + compression==0?"raw":(compression==1?"RLE":"UNKNOWN!")); + + IFDBG printf("\t\t\t\tLoading channel data (%d bytes)...\n", width*height); psd_image.layer[layeri].channel[channeli].data = @@ -966,7 +998,7 @@ do_layer_pixeldata(FILE *fd, guint32 *offset) width); } - printf("\t\t\t\t\tActual compressed size was %d bytes\n", + IFDBG printf("\t\t\t\t\tActual compressed size was %d bytes\n", (*offset)-blockread); } break; @@ -993,8 +1025,8 @@ do_layers(FILE *fd, guint32 *offset) section_length = getglong(fd, "layerinfo sectionlength"); (*offset)+=4; - printf("\tLAYER INFO SECTION\n"); - printf("\t\tSECTION LENGTH: %u\n",section_length); + IFDBG printf("\tLAYER INFO SECTION\n"); + IFDBG printf("\t\tSECTION LENGTH: %u\n",section_length); do_layer_struct(fd, offset); @@ -1013,8 +1045,8 @@ do_layer_and_mask(FILE *fd) guint32 offset_now = ftell(fd); - printf("LAYER AND MASK INFO\n"); - printf("\tSECTION LENGTH: %u\n",Size); + IFDBG printf("LAYER AND MASK INFO\n"); + IFDBG printf("\tSECTION LENGTH: %u\n",Size); if (Size == 0) return; @@ -1023,12 +1055,15 @@ do_layer_and_mask(FILE *fd) if (offset < Size) { - printf("PSD: Supposedly there are %d bytes of mask info left.\n", - Size-offset); - if ((Size-offset == 4) || (Size-offset == 24)) - printf(" That sounds good to me.\n"); - else - printf(" That sounds strange to me.\n"); + IFDBG + { + printf("PSD: Supposedly there are %d bytes of mask info left.\n", + Size-offset); + if ((Size-offset == 4) || (Size-offset == 24)) + printf(" That sounds good to me.\n"); + else + printf(" That sounds strange to me.\n"); + } /* if ((getguchar(fd, "mask info throw")!=0) || @@ -1058,7 +1093,7 @@ do_image_resources(FILE *fd) guint32 offset = 0; - printf("IMAGE RESOURCE BLOCK:\n"); + IFDBG printf("IMAGE RESOURCE BLOCK:\n"); /* FIXME: too trusting that the file isn't corrupt */ while (offset < PSDheader.imgreslen-1) @@ -1078,28 +1113,40 @@ do_image_resources(FILE *fd) ID = getgshort(fd, "ID num"); - offset+=2; - printf("\tID: 0x%04x / ",ID); + offset += 2; + IFDBG printf("\tID: 0x%04x / ",ID); Name = getpascalstring(fd, "ID name"); - offset += strlen(Name)+1; + offset++; - if (!strlen(Name)&1) + if (Name) { - throwchunk(1, fd, "ID name throw"); - offset ++; + IFDBG printf("\"%s\" ", Name); + offset += strlen(Name); + + if (!(strlen(Name)&1)) + { + throwchunk(1, fd, "ID name throw"); + offset ++; + } + g_free(Name); + } + else + { + throwchunk(1, fd, "ID name throw2"); + offset++; } - g_free(Name); Size = getglong(fd, "ID Size"); - offset+=4; - printf("Size: %d\n", Size); + offset += 4; + IFDBG printf("Size: %d\n", Size); dispatch_resID(ID, fd, &offset, Size); if (Size&1) { + IFDBG printf("+1"); throwchunk(1, fd, "ID content throw"); offset ++; } @@ -1233,7 +1280,7 @@ void extract_data_and_channels(guchar* src, gint gimpstep, gint psstep, guchar* aux_data; GPixelRgn pixel_rgn; - printf("Extracting primary channel data (%d channels)\n" + IFDBG printf("Extracting primary channel data (%d channels)\n" "\tand %d auxiliary channels.\n", gimpstep, psstep-gimpstep); primary_data = xmalloc(width * height * gimpstep); @@ -1298,7 +1345,7 @@ void extract_data_and_channels(guchar* src, gint gimpstep, gint psstep, } g_free(aux_data); - printf("Done with that.\n\n"); + IFDBG printf("Done with that.\n\n"); } @@ -1310,7 +1357,7 @@ void extract_channels(guchar* src, gint num_wanted, gint psstep, guchar* aux_data; GPixelRgn pixel_rgn; - printf("Extracting %d/%d auxiliary channels.\n", num_wanted, psstep); + IFDBG printf("Extracting %d/%d auxiliary channels.\n", num_wanted, psstep); aux_data = xmalloc(width * height); { @@ -1348,7 +1395,7 @@ void extract_channels(guchar* src, gint num_wanted, gint psstep, } g_free(aux_data); - printf("Done with that.\n\n"); + IFDBG printf("Done with that.\n\n"); } @@ -1360,7 +1407,7 @@ resize_mask(guchar* src, guchar* dest, { int x,y; - printf("--> %p %p : %d %d . %d %d . %d %d\n", + IFDBG printf("--> %p %p : %d %d . %d %d . %d %d\n", src, dest, src_x, src_y, src_w, src_h, @@ -1390,9 +1437,10 @@ load_image(char *name) { FILE *fd; gboolean want_aux; - char *name_buf, *cmykbuf; + char *name_buf; + guchar *cmykbuf; static int number = 1; - unsigned char *dest, *temp; + guchar *dest, *temp; long channels, nguchars; psd_imagetype imagetype; int cmyk = 0, step = 1; @@ -1403,7 +1451,7 @@ load_image(char *name) gint32 iter; - printf("------- %s ---------------------------------\n",name); + IFDBG printf("------- %s ---------------------------------\n",name); name_buf = xmalloc(strlen(name) + 11); @@ -1449,13 +1497,13 @@ load_image(char *name) numc = psd_image.layer[lnum].num_channels; - printf("Hey, it's a LAYER with %d channels!\n", numc); + IFDBG printf("Hey, it's a LAYER with %d channels!\n", numc); switch (gimagetype) { case GRAY: { - printf("It's GRAY.\n"); + IFDBG printf("It's GRAY.\n"); if (!psd_layer_has_alpha(&psd_image.layer[lnum])) { merged_data = xmalloc(psd_image.layer[lnum].width * @@ -1463,6 +1511,9 @@ load_image(char *name) memcpy(merged_data, psd_image.layer[lnum].channel[0].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); } else { @@ -1471,6 +1522,11 @@ load_image(char *name) psd_image.layer[lnum].channel[0].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); + if (psd_image.layer[lnum].channel[1].data) + g_free(psd_image.layer[lnum].channel[1].data); } layer_ID = gimp_layer_new (image_ID, @@ -1484,7 +1540,7 @@ load_image(char *name) }; break; /* case GRAY */ case RGB: { - printf("It's RGB.\n"); + IFDBG printf("It's RGB.\n"); if (!psd_layer_has_alpha(&psd_image.layer[lnum])) { merged_data = @@ -1493,6 +1549,13 @@ load_image(char *name) psd_image.layer[lnum].channel[2].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); + if (psd_image.layer[lnum].channel[1].data) + g_free(psd_image.layer[lnum].channel[1].data); + if (psd_image.layer[lnum].channel[2].data) + g_free(psd_image.layer[lnum].channel[2].data); } else { @@ -1503,6 +1566,15 @@ load_image(char *name) psd_image.layer[lnum].channel[0].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); + if (psd_image.layer[lnum].channel[1].data) + g_free(psd_image.layer[lnum].channel[1].data); + if (psd_image.layer[lnum].channel[2].data) + g_free(psd_image.layer[lnum].channel[2].data); + if (psd_image.layer[lnum].channel[3].data) + g_free(psd_image.layer[lnum].channel[3].data); } layer_ID = gimp_layer_new (image_ID, @@ -1548,7 +1620,12 @@ load_image(char *name) psd_image.layer[lnum].lm_height, psd_image.layer[lnum].width, psd_image.layer[lnum].height); - + + /* won't be needing the original data any more */ + if (psd_image.layer[lnum].channel[iter].data) + g_free(psd_image.layer[lnum].channel[iter].data); + + /* give it to GIMP */ mask_id = gimp_layer_create_mask(layer_ID, 0); gimp_image_add_layer_mask(image_ID, layer_ID, mask_id); @@ -1610,7 +1687,7 @@ load_image(char *name) (psd_image.num_layers > 0)) { want_aux = TRUE; - printf("::::::::::: WANT AUX :::::::::::::::::::::::::::::::::::::::\n"); + IFDBG printf("::::::::::: WANT AUX :::::::::::::::::::::::::::::::::::::::\n"); } else { @@ -1622,7 +1699,7 @@ load_image(char *name) if (want_aux || (psd_image.num_layers==0)) /* PS2-style - NO LAYERS. */ { - printf("Image data %ld chars\n", PSDheader.imgdatalen); + IFDBG printf("Image data %ld chars\n", PSDheader.imgdatalen); step = PSDheader.channels; @@ -1682,7 +1759,7 @@ load_image(char *name) return(-1); } - printf( + IFDBG printf( "psd:%d gimp:%d gimpbase:%d\n", imagetype, psd_type_to_gimp_type(imagetype), @@ -1845,7 +1922,7 @@ load_image(char *name) } else { - printf("Uhhh... uhm... extra channels... heavy...\n"); + IFDBG printf("Uhhh... uhm... extra channels... heavy...\n"); extract_data_and_channels(dest, channels, step, image_ID, drawable, @@ -1866,7 +1943,7 @@ load_image(char *name) gimp_displays_flush(); - printf("--- %d layers : pos %ld : a-alph %d ---\n", + IFDBG printf("--- %d layers : pos %ld : a-alph %d ---\n", psd_image.num_layers, (long int)ftell(fd), psd_image.absolute_alpha); @@ -1896,7 +1973,7 @@ decode(long clen, long uclen, char * src, char * dst, int step) src += *w++; packbitsdecode(&clen, uclen, src, dst++, step); } - printf("clen %ld\n", clen); + IFDBG printf("clen %ld\n", clen); } @@ -2093,7 +2170,7 @@ cmyk_to_rgb(gint *c, gint *m, gint *y, gint *k) void -dumpchunk(size_t n, FILE * fd, guchar *why) +dumpchunk(size_t n, FILE * fd, gchar *why) { guint32 i; @@ -2109,7 +2186,7 @@ dumpchunk(size_t n, FILE * fd, guchar *why) void -throwchunk(size_t n, FILE * fd, guchar *why) +throwchunk(size_t n, FILE * fd, gchar *why) { guchar *tmpchunk; @@ -2126,7 +2203,7 @@ throwchunk(size_t n, FILE * fd, guchar *why) #if 0 static guchar * -getchunk(size_t n, FILE * fd, char *why) +getchunk(size_t n, FILE * fd, gchar *why) { guchar *tmpchunk; @@ -2138,21 +2215,23 @@ getchunk(size_t n, FILE * fd, char *why) static guchar * -getpascalstring(FILE *fd, guchar *why) +getpascalstring(FILE *fd, gchar *why) { guchar *tmpchunk; guchar len; xfread(fd, &len, 1, why); - tmpchunk = xmalloc(len+1); - if (len==0) { - tmpchunk[0]=0; - return(tmpchunk); + return (NULL); + + /* tmpchunk[0]=0; + return (tmpchunk);*/ } + tmpchunk = xmalloc(len+1); + xfread(fd, tmpchunk, len, why); tmpchunk[len]=0; @@ -2161,7 +2240,7 @@ getpascalstring(FILE *fd, guchar *why) static guchar -getguchar(FILE *fd, char *why) +getguchar(FILE *fd, gchar *why) { gint tmp; @@ -2179,7 +2258,7 @@ getguchar(FILE *fd, char *why) static gshort -getgshort(FILE *fd, char *why) +getgshort(FILE *fd, gchar *why) { gushort w; guchar b1, b2; @@ -2194,7 +2273,7 @@ getgshort(FILE *fd, char *why) static glong -getglong(FILE *fd, char * why) +getglong(FILE *fd, gchar *why) { unsigned char s1, s2, s3, s4; gulong w; @@ -2211,7 +2290,7 @@ getglong(FILE *fd, char * why) static void -xfread(FILE * fd, void * buf, long len, char* why) +xfread(FILE * fd, void * buf, long len, gchar *why) { if (fread(buf, len, 1, fd) == 0) { @@ -2223,7 +2302,7 @@ xfread(FILE * fd, void * buf, long len, char* why) static void -xfread_interlaced(FILE* fd, guchar* buf, long len, gchar* why, gint step) +xfread_interlaced(FILE* fd, guchar* buf, long len, gchar *why, gint step) { guchar* dest; gint pix, pos, bpplane; @@ -2232,7 +2311,7 @@ xfread_interlaced(FILE* fd, guchar* buf, long len, gchar* why, gint step) if (len%step != 0) { - printf("PSD: Stern warning: data size is not a factor of step size.\n"); + printf("PSD: Stern warning: data size is not a factor of step size!\n"); } for (pix=0; pix>", (int)PSDheader.compression); + IFDBG printf("<>", (int)PSDheader.compression); if (PSDheader.compression == 1) /* RLE */ { PSDheader.rowlength = xmalloc(PSDheader.rows * @@ -2343,7 +2422,7 @@ read_whole_file(FILE * fd) gimp_quit(); } w = PSDheader.mode; - printf("HEAD:\n" + IFDBG printf("HEAD:\n" "\tChannels %d\n\tRows %ld\n\tColumns %ld\n\tDepth %d\n\tMode %d (%s)\n" "\tColour data %ld guchars\n", PSDheader.channels, PSDheader.rows, @@ -2351,7 +2430,7 @@ read_whole_file(FILE * fd) w, modename[w < 10 ? w : 10], psd_image.colmaplen); /* printf("\tImage resource length: %lu\n", PSDheader.imgreslen);*/ - printf("\tLayer/Mask Data length: %lu\n", PSDheader.miscsizelen); + IFDBG printf("\tLayer/Mask Data length: %lu\n", PSDheader.miscsizelen); w = PSDheader.compression; - printf("\tCompression %d (%s)\n", w, w ? "RLE" : "raw"); + IFDBG printf("\tCompression %d (%s)\n", w, w ? "RLE" : "raw"); } diff --git a/plug-ins/psd/psd.c b/plug-ins/psd/psd.c index 1c2bed5422..366b85d43f 100644 --- a/plug-ins/psd/psd.c +++ b/plug-ins/psd/psd.c @@ -1,5 +1,5 @@ /* - * PSD Plugin version 1.9.9.9 (BETA) + * PSD Plugin version 1.9.9.9b (BETA) * This GIMP plug-in is designed to load Adobe Photoshop(tm) files (.PSD) * * Adam D. Moss @@ -36,6 +36,12 @@ /* * Revision history: * + * 98.05.04 / v1.9.9.9b / Adam D. Moss + * Changed the Pascal-style string-reading stuff. That fixed + * some file-padding problems. Made all debugging output + * compile-time optional (please leave it enabled for now). + * Reduced memory requirements; still much room for improvement. + * * 98.04.28 / v1.9.9.9 / Adam D. Moss * Fixed the correct channel interlacing of 'raw' flat images. * Thanks to Christian Kirsch and Jay Cox for spotting this. @@ -75,7 +81,7 @@ * CMYK -> RGB * Load BITMAP mode * - * File saving. (I am not going to be able to do this for + * File saving. (I am unlikely to be able to do this for * practical reasons. Suggest someone works on it as a * separate plugin - please let me know.) * @@ -91,17 +97,26 @@ /* *** DEFINES *** */ + +/* set to TRUE if you want debugging, FALSE otherwise */ +#define PSD_DEBUG TRUE + /* the max number of layers that this plugin should try to load */ #define MAX_LAYERS 100 + /* the max number of channels that this plugin should let a layer have */ #define MAX_CHANNELS 30 + /* *** END OF DEFINES *** */ + +#define IFDBG if (PSD_DEBUG) + #include #include -#include #include +#include #include #include "libgimp/gimp.h" @@ -178,7 +193,7 @@ typedef struct PsdLayer gboolean protecttrans; gboolean visible; - guchar* name; + gchar* name; gint32 lm_x; gint32 lm_y; @@ -217,7 +232,7 @@ static PSDimage psd_image; static struct { - guchar signature[4]; + gchar signature[4]; gushort version; guchar reserved[6]; gushort channels; @@ -270,9 +285,9 @@ static void xfread_interlaced(FILE *fd, guchar *buf, long len, gchar *why, static void *xmalloc(size_t n); static void read_whole_file(FILE *fd); static void reshuffle_cmap(guchar *map256); -static guchar *getpascalstring(FILE *fd, guchar *why); -void throwchunk(size_t n, FILE * fd, guchar *why); -void dumpchunk(size_t n, FILE * fd, guchar *why); +static guchar *getpascalstring(FILE *fd, gchar *why); +void throwchunk(size_t n, FILE * fd, gchar *why); +void dumpchunk(size_t n, FILE * fd, gchar *why); MAIN() @@ -487,7 +502,7 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) { if ( (ID < 0x0bb6) && (ID >0x07d0) ) { - printf ("\t\tPath data is irrelevant to GIMP at this time.\n"); + IFDBG printf ("\t\tPath data is irrelevant to GIMP at this time.\n"); throwchunk(Size, fd, "dispatch_res path throw"); (*offset) += Size; } @@ -498,22 +513,30 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) { gint32 remaining = Size; - printf ("\t\tALPHA CHANNEL NAMES:\n"); + IFDBG printf ("\t\tALPHA CHANNEL NAMES:\n"); if (Size > 0) { do { - guint32 alpha_name_len; - psd_image.aux_channel[psd_image.num_aux_channels].name = getpascalstring(fd, "alpha channel name"); + (*offset)++; + remaining--; + + if (psd_image.aux_channel[psd_image.num_aux_channels].name) + { + guint32 alpha_name_len; - alpha_name_len = - strlen(psd_image.aux_channel[psd_image.num_aux_channels].name); - - printf("\t\t\tname: \"%s\"\n", - psd_image.aux_channel[psd_image.num_aux_channels].name); + alpha_name_len = + strlen(psd_image.aux_channel[psd_image.num_aux_channels].name); + + IFDBG printf("\t\t\tname: \"%s\"\n", + psd_image.aux_channel[psd_image.num_aux_channels].name); + (*offset) += alpha_name_len; + remaining -= alpha_name_len; + } + psd_image.num_aux_channels++; if (psd_image.num_aux_channels > MAX_CHANNELS) @@ -521,9 +544,6 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) printf("\nPSD: Sorry - this image has too many aux channels. Tell Adam!\n"); gimp_quit(); } - - (*offset) += alpha_name_len+1; - remaining -= alpha_name_len+1; } while (remaining > 0); } @@ -533,88 +553,89 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) } break; case 0x03ef: - printf("\t\tDISPLAYINFO STRUCTURE: unhandled\n"); - throwchunk(Size, fd, "dispatch_res"); - (*offset) += Size; + IFDBG printf("\t\tDISPLAYINFO STRUCTURE: unhandled\n"); + throwchunk(Size, fd, "dispatch_res"); + (*offset) += Size; break; case 0x03f0: /* FIXME: untested */ { - guint32 caption_len; - psd_image.caption = getpascalstring(fd, "caption string"); - caption_len = strlen(psd_image.caption); - - printf("\t\t\tcontent: \"%s\"\n",psd_image.caption); - (*offset) += caption_len+1; + (*offset)++; + + if (psd_image.caption) + { + IFDBG printf("\t\t\tcontent: \"%s\"\n",psd_image.caption); + (*offset) += strlen(psd_image.caption); + } } break; case 0x03f2: - printf("\t\tBACKGROUND COLOR: unhandled\n"); + IFDBG printf("\t\tBACKGROUND COLOR: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f4: - printf("\t\tGREY/MULTICHANNEL HALFTONING INFO: unhandled\n"); + IFDBG printf("\t\tGREY/MULTICHANNEL HALFTONING INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f5: - printf("\t\tCOLOUR HALFTONING INFO: unhandled\n"); + IFDBG printf("\t\tCOLOUR HALFTONING INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f6: - printf("\t\tDUOTONE HALFTONING INFO: unhandled\n"); + IFDBG printf("\t\tDUOTONE HALFTONING INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f7: - printf("\t\tGREYSCALE/MULTICHANNEL TRANSFER FUNCTION: unhandled\n"); + IFDBG printf("\t\tGREYSCALE/MULTICHANNEL TRANSFER FUNCTION: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f8: - printf("\t\tCOLOUR TRANSFER FUNCTION: unhandled\n"); + IFDBG printf("\t\tCOLOUR TRANSFER FUNCTION: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03f9: - printf("\t\tDUOTONE TRANSFER FUNCTION: unhandled\n"); + IFDBG printf("\t\tDUOTONE TRANSFER FUNCTION: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03fa: - printf("\t\tDUOTONE IMAGE INFO: unhandled\n"); + IFDBG printf("\t\tDUOTONE IMAGE INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03fb: - printf("\t\tEFFECTIVE BLACK/WHITE VALUES: unhandled\n"); + IFDBG printf("\t\tEFFECTIVE BLACK/WHITE VALUES: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03fe: - printf("\t\tQUICK MASK INFO: unhandled\n"); + IFDBG printf("\t\tQUICK MASK INFO: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x0400: { - printf("\t\tLAYER STATE INFO:\n"); + IFDBG printf("\t\tLAYER STATE INFO:\n"); psd_image.active_layer_num = getgshort(fd, "ID target_layer_num"); - printf("\t\t\ttarget: %d\n",(gint)psd_image.active_layer_num); + IFDBG printf("\t\t\ttarget: %d\n",(gint)psd_image.active_layer_num); (*offset) += 2; } break; case 0x0402: - printf("\t\tLAYER GROUP INFO: unhandled\n"); - printf("\t\t\t(Inferred number of layers: %d)\n",(gint)(Size/2)); + IFDBG printf("\t\tLAYER GROUP INFO: unhandled\n"); + IFDBG printf("\t\t\t(Inferred number of layers: %d)\n",(gint)(Size/2)); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x0405: - printf ("\t\tIMAGE MODE FOR RAW FORMAT: unhandled\n"); + IFDBG printf ("\t\tIMAGE MODE FOR RAW FORMAT: unhandled\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; @@ -629,14 +650,14 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) case 0x0406: case 0x0bb7: case 0x2710: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; case 0x03e8: case 0x03eb: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; @@ -644,13 +665,13 @@ dispatch_resID(guint ID, FILE *fd, guint32 *offset, guint32 Size) case 0x03fc: case 0x03ff: case 0x0403: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; default: - printf ("\t\t\n"); + IFDBG printf ("\t\t\n"); throwchunk(Size, fd, "dispatch_res"); (*offset) += Size; break; @@ -668,7 +689,7 @@ do_layer_record(FILE *fd, guint32 *offset, gint layernum) guchar flags; gint i; - printf("\t\t\tLAYER RECORD (layer %d)\n", (int)layernum); + IFDBG printf("\t\t\tLAYER RECORD (layer %d)\n", (int)layernum); /* table 11-12 */ @@ -686,7 +707,7 @@ do_layer_record(FILE *fd, guint32 *offset, gint layernum) psd_image.layer[layernum].width = right-left; psd_image.layer[layernum].height = bottom-top; - printf("\t\t\t\tLayer extents: (%d,%d) -> (%d,%d)\n",left,top,right,bottom); + IFDBG printf("\t\t\t\tLayer extents: (%d,%d) -> (%d,%d)\n",left,top,right,bottom); psd_image.layer[layernum].num_channels = getgshort (fd, "layer num_channels"); @@ -698,23 +719,23 @@ do_layer_record(FILE *fd, guint32 *offset, gint layernum) gimp_quit(); } - printf("\t\t\t\tNumber of channels: %d\n", + IFDBG printf("\t\t\t\tNumber of channels: %d\n", (int)psd_image.layer[layernum].num_channels); for (i=0;i 0) { - printf("Warning: layer record dross: "); - dumpchunk(totaloff-(*offset), fd, "layer record dross throw"); + IFDBG + { + printf("Warning: layer record dross: "); + dumpchunk(totaloff-(*offset), fd, "layer record dross throw"); + } + else + { + throwchunk(totaloff-(*offset), fd, "layer record dross throw"); + } (*offset) = totaloff; } } @@ -831,12 +862,12 @@ do_layer_struct(FILE *fd, guint32 *offset) { gint i; - printf("\t\tLAYER STRUCTURE SECTION\n"); + IFDBG printf("\t\tLAYER STRUCTURE SECTION\n"); psd_image.num_layers = getgshort(fd, "layer struct numlayers"); (*offset)+=2; - printf("\t\t\tCanonical number of layers: %d%s\n", + IFDBG printf("\t\t\tCanonical number of layers: %d%s\n", psd_image.num_layers>0? (int)psd_image.num_layers:abs(psd_image.num_layers), psd_image.num_layers>0?"":" (absolute/alpha)"); @@ -895,14 +926,15 @@ do_layer_pixeldata(FILE *fd, guint32 *offset) compression = getgshort(fd, "layer channel compression type"); (*offset)+=2; - printf("\t\t\tLayer (%d) Channel (%d:%d) Compression: %d (%s)\n", - layeri, - channeli, - psd_image.layer[layeri].channel[channeli].type, - compression, - compression==0?"raw":(compression==1?"RLE":"UNKNOWN!")); - - printf("\t\t\t\tLoading channel data (%d bytes)...\n", + IFDBG + printf("\t\t\tLayer (%d) Channel (%d:%d) Compression: %d (%s)\n", + layeri, + channeli, + psd_image.layer[layeri].channel[channeli].type, + compression, + compression==0?"raw":(compression==1?"RLE":"UNKNOWN!")); + + IFDBG printf("\t\t\t\tLoading channel data (%d bytes)...\n", width*height); psd_image.layer[layeri].channel[channeli].data = @@ -966,7 +998,7 @@ do_layer_pixeldata(FILE *fd, guint32 *offset) width); } - printf("\t\t\t\t\tActual compressed size was %d bytes\n", + IFDBG printf("\t\t\t\t\tActual compressed size was %d bytes\n", (*offset)-blockread); } break; @@ -993,8 +1025,8 @@ do_layers(FILE *fd, guint32 *offset) section_length = getglong(fd, "layerinfo sectionlength"); (*offset)+=4; - printf("\tLAYER INFO SECTION\n"); - printf("\t\tSECTION LENGTH: %u\n",section_length); + IFDBG printf("\tLAYER INFO SECTION\n"); + IFDBG printf("\t\tSECTION LENGTH: %u\n",section_length); do_layer_struct(fd, offset); @@ -1013,8 +1045,8 @@ do_layer_and_mask(FILE *fd) guint32 offset_now = ftell(fd); - printf("LAYER AND MASK INFO\n"); - printf("\tSECTION LENGTH: %u\n",Size); + IFDBG printf("LAYER AND MASK INFO\n"); + IFDBG printf("\tSECTION LENGTH: %u\n",Size); if (Size == 0) return; @@ -1023,12 +1055,15 @@ do_layer_and_mask(FILE *fd) if (offset < Size) { - printf("PSD: Supposedly there are %d bytes of mask info left.\n", - Size-offset); - if ((Size-offset == 4) || (Size-offset == 24)) - printf(" That sounds good to me.\n"); - else - printf(" That sounds strange to me.\n"); + IFDBG + { + printf("PSD: Supposedly there are %d bytes of mask info left.\n", + Size-offset); + if ((Size-offset == 4) || (Size-offset == 24)) + printf(" That sounds good to me.\n"); + else + printf(" That sounds strange to me.\n"); + } /* if ((getguchar(fd, "mask info throw")!=0) || @@ -1058,7 +1093,7 @@ do_image_resources(FILE *fd) guint32 offset = 0; - printf("IMAGE RESOURCE BLOCK:\n"); + IFDBG printf("IMAGE RESOURCE BLOCK:\n"); /* FIXME: too trusting that the file isn't corrupt */ while (offset < PSDheader.imgreslen-1) @@ -1078,28 +1113,40 @@ do_image_resources(FILE *fd) ID = getgshort(fd, "ID num"); - offset+=2; - printf("\tID: 0x%04x / ",ID); + offset += 2; + IFDBG printf("\tID: 0x%04x / ",ID); Name = getpascalstring(fd, "ID name"); - offset += strlen(Name)+1; + offset++; - if (!strlen(Name)&1) + if (Name) { - throwchunk(1, fd, "ID name throw"); - offset ++; + IFDBG printf("\"%s\" ", Name); + offset += strlen(Name); + + if (!(strlen(Name)&1)) + { + throwchunk(1, fd, "ID name throw"); + offset ++; + } + g_free(Name); + } + else + { + throwchunk(1, fd, "ID name throw2"); + offset++; } - g_free(Name); Size = getglong(fd, "ID Size"); - offset+=4; - printf("Size: %d\n", Size); + offset += 4; + IFDBG printf("Size: %d\n", Size); dispatch_resID(ID, fd, &offset, Size); if (Size&1) { + IFDBG printf("+1"); throwchunk(1, fd, "ID content throw"); offset ++; } @@ -1233,7 +1280,7 @@ void extract_data_and_channels(guchar* src, gint gimpstep, gint psstep, guchar* aux_data; GPixelRgn pixel_rgn; - printf("Extracting primary channel data (%d channels)\n" + IFDBG printf("Extracting primary channel data (%d channels)\n" "\tand %d auxiliary channels.\n", gimpstep, psstep-gimpstep); primary_data = xmalloc(width * height * gimpstep); @@ -1298,7 +1345,7 @@ void extract_data_and_channels(guchar* src, gint gimpstep, gint psstep, } g_free(aux_data); - printf("Done with that.\n\n"); + IFDBG printf("Done with that.\n\n"); } @@ -1310,7 +1357,7 @@ void extract_channels(guchar* src, gint num_wanted, gint psstep, guchar* aux_data; GPixelRgn pixel_rgn; - printf("Extracting %d/%d auxiliary channels.\n", num_wanted, psstep); + IFDBG printf("Extracting %d/%d auxiliary channels.\n", num_wanted, psstep); aux_data = xmalloc(width * height); { @@ -1348,7 +1395,7 @@ void extract_channels(guchar* src, gint num_wanted, gint psstep, } g_free(aux_data); - printf("Done with that.\n\n"); + IFDBG printf("Done with that.\n\n"); } @@ -1360,7 +1407,7 @@ resize_mask(guchar* src, guchar* dest, { int x,y; - printf("--> %p %p : %d %d . %d %d . %d %d\n", + IFDBG printf("--> %p %p : %d %d . %d %d . %d %d\n", src, dest, src_x, src_y, src_w, src_h, @@ -1390,9 +1437,10 @@ load_image(char *name) { FILE *fd; gboolean want_aux; - char *name_buf, *cmykbuf; + char *name_buf; + guchar *cmykbuf; static int number = 1; - unsigned char *dest, *temp; + guchar *dest, *temp; long channels, nguchars; psd_imagetype imagetype; int cmyk = 0, step = 1; @@ -1403,7 +1451,7 @@ load_image(char *name) gint32 iter; - printf("------- %s ---------------------------------\n",name); + IFDBG printf("------- %s ---------------------------------\n",name); name_buf = xmalloc(strlen(name) + 11); @@ -1449,13 +1497,13 @@ load_image(char *name) numc = psd_image.layer[lnum].num_channels; - printf("Hey, it's a LAYER with %d channels!\n", numc); + IFDBG printf("Hey, it's a LAYER with %d channels!\n", numc); switch (gimagetype) { case GRAY: { - printf("It's GRAY.\n"); + IFDBG printf("It's GRAY.\n"); if (!psd_layer_has_alpha(&psd_image.layer[lnum])) { merged_data = xmalloc(psd_image.layer[lnum].width * @@ -1463,6 +1511,9 @@ load_image(char *name) memcpy(merged_data, psd_image.layer[lnum].channel[0].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); } else { @@ -1471,6 +1522,11 @@ load_image(char *name) psd_image.layer[lnum].channel[0].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); + if (psd_image.layer[lnum].channel[1].data) + g_free(psd_image.layer[lnum].channel[1].data); } layer_ID = gimp_layer_new (image_ID, @@ -1484,7 +1540,7 @@ load_image(char *name) }; break; /* case GRAY */ case RGB: { - printf("It's RGB.\n"); + IFDBG printf("It's RGB.\n"); if (!psd_layer_has_alpha(&psd_image.layer[lnum])) { merged_data = @@ -1493,6 +1549,13 @@ load_image(char *name) psd_image.layer[lnum].channel[2].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); + if (psd_image.layer[lnum].channel[1].data) + g_free(psd_image.layer[lnum].channel[1].data); + if (psd_image.layer[lnum].channel[2].data) + g_free(psd_image.layer[lnum].channel[2].data); } else { @@ -1503,6 +1566,15 @@ load_image(char *name) psd_image.layer[lnum].channel[0].data, psd_image.layer[lnum].width * psd_image.layer[lnum].height); + + if (psd_image.layer[lnum].channel[0].data) + g_free(psd_image.layer[lnum].channel[0].data); + if (psd_image.layer[lnum].channel[1].data) + g_free(psd_image.layer[lnum].channel[1].data); + if (psd_image.layer[lnum].channel[2].data) + g_free(psd_image.layer[lnum].channel[2].data); + if (psd_image.layer[lnum].channel[3].data) + g_free(psd_image.layer[lnum].channel[3].data); } layer_ID = gimp_layer_new (image_ID, @@ -1548,7 +1620,12 @@ load_image(char *name) psd_image.layer[lnum].lm_height, psd_image.layer[lnum].width, psd_image.layer[lnum].height); - + + /* won't be needing the original data any more */ + if (psd_image.layer[lnum].channel[iter].data) + g_free(psd_image.layer[lnum].channel[iter].data); + + /* give it to GIMP */ mask_id = gimp_layer_create_mask(layer_ID, 0); gimp_image_add_layer_mask(image_ID, layer_ID, mask_id); @@ -1610,7 +1687,7 @@ load_image(char *name) (psd_image.num_layers > 0)) { want_aux = TRUE; - printf("::::::::::: WANT AUX :::::::::::::::::::::::::::::::::::::::\n"); + IFDBG printf("::::::::::: WANT AUX :::::::::::::::::::::::::::::::::::::::\n"); } else { @@ -1622,7 +1699,7 @@ load_image(char *name) if (want_aux || (psd_image.num_layers==0)) /* PS2-style - NO LAYERS. */ { - printf("Image data %ld chars\n", PSDheader.imgdatalen); + IFDBG printf("Image data %ld chars\n", PSDheader.imgdatalen); step = PSDheader.channels; @@ -1682,7 +1759,7 @@ load_image(char *name) return(-1); } - printf( + IFDBG printf( "psd:%d gimp:%d gimpbase:%d\n", imagetype, psd_type_to_gimp_type(imagetype), @@ -1845,7 +1922,7 @@ load_image(char *name) } else { - printf("Uhhh... uhm... extra channels... heavy...\n"); + IFDBG printf("Uhhh... uhm... extra channels... heavy...\n"); extract_data_and_channels(dest, channels, step, image_ID, drawable, @@ -1866,7 +1943,7 @@ load_image(char *name) gimp_displays_flush(); - printf("--- %d layers : pos %ld : a-alph %d ---\n", + IFDBG printf("--- %d layers : pos %ld : a-alph %d ---\n", psd_image.num_layers, (long int)ftell(fd), psd_image.absolute_alpha); @@ -1896,7 +1973,7 @@ decode(long clen, long uclen, char * src, char * dst, int step) src += *w++; packbitsdecode(&clen, uclen, src, dst++, step); } - printf("clen %ld\n", clen); + IFDBG printf("clen %ld\n", clen); } @@ -2093,7 +2170,7 @@ cmyk_to_rgb(gint *c, gint *m, gint *y, gint *k) void -dumpchunk(size_t n, FILE * fd, guchar *why) +dumpchunk(size_t n, FILE * fd, gchar *why) { guint32 i; @@ -2109,7 +2186,7 @@ dumpchunk(size_t n, FILE * fd, guchar *why) void -throwchunk(size_t n, FILE * fd, guchar *why) +throwchunk(size_t n, FILE * fd, gchar *why) { guchar *tmpchunk; @@ -2126,7 +2203,7 @@ throwchunk(size_t n, FILE * fd, guchar *why) #if 0 static guchar * -getchunk(size_t n, FILE * fd, char *why) +getchunk(size_t n, FILE * fd, gchar *why) { guchar *tmpchunk; @@ -2138,21 +2215,23 @@ getchunk(size_t n, FILE * fd, char *why) static guchar * -getpascalstring(FILE *fd, guchar *why) +getpascalstring(FILE *fd, gchar *why) { guchar *tmpchunk; guchar len; xfread(fd, &len, 1, why); - tmpchunk = xmalloc(len+1); - if (len==0) { - tmpchunk[0]=0; - return(tmpchunk); + return (NULL); + + /* tmpchunk[0]=0; + return (tmpchunk);*/ } + tmpchunk = xmalloc(len+1); + xfread(fd, tmpchunk, len, why); tmpchunk[len]=0; @@ -2161,7 +2240,7 @@ getpascalstring(FILE *fd, guchar *why) static guchar -getguchar(FILE *fd, char *why) +getguchar(FILE *fd, gchar *why) { gint tmp; @@ -2179,7 +2258,7 @@ getguchar(FILE *fd, char *why) static gshort -getgshort(FILE *fd, char *why) +getgshort(FILE *fd, gchar *why) { gushort w; guchar b1, b2; @@ -2194,7 +2273,7 @@ getgshort(FILE *fd, char *why) static glong -getglong(FILE *fd, char * why) +getglong(FILE *fd, gchar *why) { unsigned char s1, s2, s3, s4; gulong w; @@ -2211,7 +2290,7 @@ getglong(FILE *fd, char * why) static void -xfread(FILE * fd, void * buf, long len, char* why) +xfread(FILE * fd, void * buf, long len, gchar *why) { if (fread(buf, len, 1, fd) == 0) { @@ -2223,7 +2302,7 @@ xfread(FILE * fd, void * buf, long len, char* why) static void -xfread_interlaced(FILE* fd, guchar* buf, long len, gchar* why, gint step) +xfread_interlaced(FILE* fd, guchar* buf, long len, gchar *why, gint step) { guchar* dest; gint pix, pos, bpplane; @@ -2232,7 +2311,7 @@ xfread_interlaced(FILE* fd, guchar* buf, long len, gchar* why, gint step) if (len%step != 0) { - printf("PSD: Stern warning: data size is not a factor of step size.\n"); + printf("PSD: Stern warning: data size is not a factor of step size!\n"); } for (pix=0; pix>", (int)PSDheader.compression); + IFDBG printf("<>", (int)PSDheader.compression); if (PSDheader.compression == 1) /* RLE */ { PSDheader.rowlength = xmalloc(PSDheader.rows * @@ -2343,7 +2422,7 @@ read_whole_file(FILE * fd) gimp_quit(); } w = PSDheader.mode; - printf("HEAD:\n" + IFDBG printf("HEAD:\n" "\tChannels %d\n\tRows %ld\n\tColumns %ld\n\tDepth %d\n\tMode %d (%s)\n" "\tColour data %ld guchars\n", PSDheader.channels, PSDheader.rows, @@ -2351,7 +2430,7 @@ read_whole_file(FILE * fd) w, modename[w < 10 ? w : 10], psd_image.colmaplen); /* printf("\tImage resource length: %lu\n", PSDheader.imgreslen);*/ - printf("\tLayer/Mask Data length: %lu\n", PSDheader.miscsizelen); + IFDBG printf("\tLayer/Mask Data length: %lu\n", PSDheader.miscsizelen); w = PSDheader.compression; - printf("\tCompression %d (%s)\n", w, w ? "RLE" : "raw"); + IFDBG printf("\tCompression %d (%s)\n", w, w ? "RLE" : "raw"); } diff --git a/plug-ins/script-fu/scripts/text-circle.scm b/plug-ins/script-fu/scripts/text-circle.scm index 745cab8f06..635be82b00 100644 --- a/plug-ins/script-fu/scripts/text-circle.scm +++ b/plug-ins/script-fu/scripts/text-circle.scm @@ -1,9 +1,26 @@ ;; text-circle.scm -- a script for The GIMP 1.0 ;; Author: Shuji Narazaki -;; Time-stamp: <1998/01/28 22:09:41 narazaki@InetQ.or.jp> -;; Version 2.3 +;; Time-stamp: <1998/04/30 22:00:40 narazaki@InetQ.or.jp> +;; Version 2.4 ;; Thanks: ;; jseymour@jimsun.LinxNet.com (Jim Seymour) +;; Sven Neumann + +;; Note: +;; Please remove /usr/local/share/gimp/scripts/circle-logo.scm, which is +;; obsolete version of this script. + +;; Implementation memo: +;; This script uses "extra-pole". +;; Namely, when rendering a letter, gimp-text is invoked with the letter +;; followed by " lAgy", then strips it by gimp-layer-resize. I call this " lAgy" +;; extra-pole. Why is it needed? +;; Since a text is located by its left-upper corner's position, THERE IS NO WAY +;; TO PLACE LETTERS ON A BASE LINE! +;; (FURTHERMORE, GIMP-TEXT EATS WHITESPACES AT THE BEGINNING/END OF LINE.) +;; Thus, as a dirty trick, by adding tall letters: "lA", and "gy" which have +;; large descent value to each letter temporally, most letters in most fonts +;; are aligned correctly. But don't expect completeness :-< (if (not (symbol-bound? 'script-fu-text-circle-text (the-environment))) (define script-fu-text-circle-text @@ -18,6 +35,8 @@ (define script-fu-text-circle-font-size 18)) (if (not (symbol-bound? 'script-fu-text-circle-antialias (the-environment))) (define script-fu-text-circle-antialias TRUE)) +(if (not (symbol-bound? 'script-fu-text-circle-extra-pole (the-environment))) + (define script-fu-text-circle-extra-pole TRUE)) (if (not (symbol-bound? 'script-fu-text-circle-font-foundry (the-environment))) (define script-fu-text-circle-font-foundry "\"*\"")) (if (not (symbol-bound? 'script-fu-text-circle-font-family (the-environment))) @@ -30,10 +49,14 @@ (define script-fu-text-circle-font-width "\"*\"")) (if (not (symbol-bound? 'script-fu-text-circle-font-spacing (the-environment))) (define script-fu-text-circle-font-spacing "\"*\"")) +(if (not (symbol-bound? 'script-fu-text-circle-debug? (the-environment))) + (define script-fu-text-circle-debug? #f)) (define (script-fu-text-circle text radius start-angle fill-angle font-size antialias foundry family weight slant width spacing) + ;;(set! script-fu-text-circle-debug? #t) + (define extra-pole TRUE) ; for debugging purpose (define modulo fmod) ; in R4RS way (define (wrap-string str) (string-append "\"" str "\"")) (define (white-space-string? str) @@ -48,7 +71,11 @@ (rad-90 (/ *pi* 2)) (center-x (/ drawable-size 2)) (center-y center-x) - (fixed-pole " ]Ag") ; some fonts have no "]" "g" has desc. + ;; widths of " lAgy" and of "l Agy" will be different, because gimp-text + ;; strips spaces at the beginning of a string![Mon Apr 27 15:10:39 1998] + (fixed-pole0 "l Agy") + ;; the following used as real pad. + (fixed-pole " lAgy") (font-infos (gimp-text-get-extents fixed-pole font-size PIXELS "*" family "*" slant "*" "*")) (desc (nth 3 font-infos)) @@ -65,13 +92,15 @@ (set! fill-angle-rad (* (/ fill-angle 360) 2 *pi*)) (set! radian-step (/ fill-angle-rad char-num)) ;; set extra - (let ((temp-pole-layer (car (gimp-text img -1 0 0 - fixed-pole - 1 antialias - font-size PIXELS - "*" family "*" slant "*" "*")))) - (set! extra (car (gimp-drawable-width temp-pole-layer))) - (gimp-image-remove-layer img temp-pole-layer)) + (if (eq? extra-pole TRUE) + (let ((temp-pole-layer (car (gimp-text img -1 0 0 + fixed-pole0 + 1 antialias + font-size PIXELS + "*" family "*" slant "*" "*")))) + (set! extra (car (gimp-drawable-width temp-pole-layer))) + (gimp-image-remove-layer img temp-pole-layer)) + (set! extra 0)) ;; make width-list ;; In a situation, ;; (car (gimp-drawable-width (car (gimp-text ...))) @@ -86,7 +115,7 @@ (while (< index char-num) (set! temp-str (substring text index (+ index 1))) (if (white-space-string? temp-str) - (set! temp-str "]")) + (set! temp-str "x")) (set! temp-layer (car (gimp-text img -1 0 0 temp-str 1 antialias @@ -111,43 +140,49 @@ (if (not (white-space-string? letter)) ;; Running gimp-text with " " causes an error! (let* ((new-layer (car (gimp-text img -1 0 0 - (string-append letter fixed-pole) + (if (eq? extra-pole TRUE) + (string-append letter fixed-pole) + letter) 1 antialias font-size PIXELS "*" family "*" slant "*" "*"))) (width (car (gimp-drawable-width new-layer))) (height (car (gimp-drawable-height new-layer))) (rotate-radius (- (/ height 2) desc)) - (new-width (- width extra 1)) + (new-width (- width extra)) (angle (+ start-angle-rad (- (nth index angle-list) rad-90)))) ;; delete fixed-pole (gimp-layer-resize new-layer new-width height 0 0) (set! width (car (gimp-drawable-width new-layer))) - (gimp-layer-translate new-layer - (+ center-x - (* radius (cos angle)) - (* rotate-radius - (cos (if (< 0 fill-angle-rad) - angle - (+ angle *pi*)))) - (- (/ width 2))) - (+ center-y - (* radius (sin angle)) - (* rotate-radius - (sin (if (< 0 fill-angle-rad) - angle - (+ angle *pi*)))) - (- (/ height 2)))) - (gimp-rotate img new-layer 1 - ((if (< 0 fill-angle-rad) + -) angle rad-90)))) + (if (not script-fu-text-circle-debug?) + (begin + (gimp-layer-translate new-layer + (+ center-x + (* radius (cos angle)) + (* rotate-radius + (cos (if (< 0 fill-angle-rad) + angle + (+ angle *pi*)))) + (- (/ width 2))) + (+ center-y + (* radius (sin angle)) + (* rotate-radius + (sin (if (< 0 fill-angle-rad) + angle + (+ angle *pi*)))) + (- (/ height 2)))) + (gimp-rotate img new-layer 1 + ((if (< 0 fill-angle-rad) + -) angle rad-90)))))) (set! index (+ index 1))) (gimp-layer-set-visible BG-layer 0) - (set! merged-layer - (car (gimp-image-merge-visible-layers img CLIP-TO-IMAGE))) - (gimp-layer-set-name merged-layer - (if (< (length text) 16) - (wrap-string text) - "Circle Logo")) + (if (not script-fu-text-circle-debug?) + (begin + (set! merged-layer + (car (gimp-image-merge-visible-layers img CLIP-TO-IMAGE))) + (gimp-layer-set-name merged-layer + (if (< (length text) 16) + (wrap-string text) + "Text Circle")))) (gimp-layer-set-visible BG-layer 1) (gimp-image-enable-undo img) (gimp-image-clean-all img) @@ -158,6 +193,7 @@ (set! script-fu-text-circle-fill-angle fill-angle) (set! script-fu-text-circle-font-size font-size) (set! script-fu-text-circle-antialias antialias) + (set! script-fu-text-circle-extra-pole extra-pole) (set! script-fu-text-circle-font-foundry (wrap-string foundry)) (set! script-fu-text-circle-font-family (wrap-string family)) (set! script-fu-text-circle-font-weight (wrap-string weight))