static void gimp_tile_put (GimpTile *tile) { extern GIOChannel *_writechannel; GPTileReq tile_req; GPTileData tile_data; GPTileData *tile_info; GimpWireMessage msg; tile_req.drawable_ID = -1; tile_req.tile_num = 0; tile_req.shadow = 0; gp_lock (); if (! gp_tile_req_write (_writechannel, &tile_req, NULL)) gimp_quit (); gimp_read_expect_msg (&msg, GP_TILE_DATA); tile_info = msg.data; tile_data.drawable_ID = tile->drawable->drawable_id; tile_data.tile_num = tile->tile_num; tile_data.shadow = tile->shadow; tile_data.bpp = tile->bpp; tile_data.width = tile->ewidth; tile_data.height = tile->eheight; tile_data.use_shm = tile_info->use_shm; tile_data.data = NULL; if (tile_info->use_shm) memcpy (gimp_shm_addr (), tile->data, tile->ewidth * tile->eheight * tile->bpp); else tile_data.data = tile->data; if (! gp_tile_data_write (_writechannel, &tile_data, NULL)) gimp_quit (); if (! tile_info->use_shm) tile_data.data = NULL; gimp_wire_destroy (&msg); gimp_read_expect_msg (&msg, GP_TILE_ACK); gp_unlock (); gimp_wire_destroy (&msg); }
static void gimp_tile_get (GimpTile *tile) { extern GIOChannel *_writechannel; GPTileReq tile_req; GPTileData *tile_data; GimpWireMessage msg; tile_req.drawable_ID = tile->drawable->drawable_id; tile_req.tile_num = tile->tile_num; tile_req.shadow = tile->shadow; gp_lock (); if (! gp_tile_req_write (_writechannel, &tile_req, NULL)) gimp_quit (); gimp_read_expect_msg (&msg, GP_TILE_DATA); tile_data = msg.data; if (tile_data->drawable_ID != tile->drawable->drawable_id || tile_data->tile_num != tile->tile_num || tile_data->shadow != tile->shadow || tile_data->width != tile->ewidth || tile_data->height != tile->eheight || tile_data->bpp != tile->bpp) { g_message ("received tile info did not match computed tile info"); gimp_quit (); } if (tile_data->use_shm) { tile->data = g_memdup (gimp_shm_addr (), tile->ewidth * tile->eheight * tile->bpp); } else { tile->data = tile_data->data; tile_data->data = NULL; } if (! gp_tile_ack_write (_writechannel, NULL)) gimp_quit (); gp_unlock (); gimp_wire_destroy (&msg); }
static void indexed_autostretch_hsv (gint32 image_ID) { guchar *cmap; AutostretchData data = {0.0, 1.0, 0.0, 1.0}; gint ncols, i; cmap = gimp_image_get_colormap (image_ID, &ncols); if (!cmap) { g_message (_("autostretch_hsv: cmap was NULL! Quitting...\n")); gimp_quit (); } for (i = 0; i < ncols; i++) { find_max (&cmap[i * 3], 3, &data); } for (i = 0; i < ncols; i++) { autostretch_hsv_func (&cmap[i * 3], &cmap[i * 3], 3, &data); } gimp_image_set_colormap (image_ID, cmap, ncols); }
static void query (void) { char *date=NULL; static GimpParamDef load_args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_STRING, "filename", "The name of the file to load" }, { GIMP_PDB_STRING, "raw_filename", "The name of the file to load." }, }; static GimpParamDef load_return_vals[] = { { GIMP_PDB_IMAGE, "image", "Output image" }, }; static int nload_args = (int)sizeof (load_args) / (int)sizeof (load_args[0]); static int nload_return_vals = (int)sizeof (load_return_vals) / (int)sizeof (load_return_vals[0]); static GimpParamDef save_args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_IMAGE, "image", "Input image" }, { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" }, { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" }, { GIMP_PDB_STRING, "raw_filename", "The name of the file to save the image in" }, }; static int nsave_args = (int)sizeof (save_args) / (int)sizeof (save_args[0]); m_new (date, char,(200 + strlen(version())), gimp_quit()) sprintf (date,"%s\n2005-2007", version()); gimp_install_procedure ("file_pnm_load", "loads files of the pnm file format", "This plug-in loades PNM files. " "The RAW_WIDTH, RAW_HEIGHT, RAW_TYPE and RAW_MAXVAL " "variables can be used to load raw data ending with " "\".raw\" .", "Kai-Uwe Behrmann", "2005-2007 Kai-Uwe Behrmann", date, "<Load>/PNM", NULL, GIMP_PLUGIN, nload_args, nload_return_vals, load_args, load_return_vals); gimp_register_load_handler ("file_pnm_load", "pgm,pnm,ppm,pfm,raw", ""); gimp_install_procedure ("file_pnm_save", "saves files in the pnm file format", "This plug-in saves PNM files.", "Kai-Uwe Behrmann", "2005-2007 Kai-Uwe Behrmann", date, "<Save>/PNM", "RGB*, GRAY*, U16_RGB*, U16_GRAY*", GIMP_PLUGIN, nsave_args, 0, save_args, NULL); gimp_register_save_handler ("file_pnm_save", "pgm,pnm,ppm", ""); gimp_install_procedure ("file_pfm_save", "saves files in the pfm file format", "This plug-in saves PFM files.", "Kai-Uwe Behrmann", "2005-2007 Kai-Uwe Behrmann", date, "<Save>/PFM", "FLOAT_RGB*, FLOAT_GRAY*", GIMP_PLUGIN, nsave_args, 0, save_args, NULL); gimp_register_save_handler ("file_pfm_save", "pfm", ""); m_free (date) }
static gint32 ReadImage (FILE *fd, const gchar *filename, gint len, gint height, CMap cmap, gint ncols, gint format, gint interlace, gint number, guint leftpos, guint toppos, guint screenwidth, guint screenheight) { static gint32 image_ID = -1; static gint frame_number = 1; gint32 layer_ID; GimpPixelRgn pixel_rgn; GimpDrawable *drawable; guchar *dest, *temp; guchar c; gint xpos = 0, ypos = 0, pass = 0; gint cur_progress, max_progress; gint v; gint i, j; gchar *framename; gchar *framename_ptr; gboolean alpha_frame = FALSE; static gint previous_disposal; /* Guard against bogus frame size */ if (len < 1 || height < 1) { g_message ("Bogus frame dimensions"); return -1; } /* ** Initialize the Compression routines */ if (! ReadOK (fd, &c, 1)) { g_message ("EOF / read error on image data"); return -1; } if (LZWReadByte (fd, TRUE, c) < 0) { g_message ("Error while reading"); return -1; } if (frame_number == 1) { /* Guard against bogus logical screen size values */ if (screenwidth == 0) screenwidth = len; if (screenheight == 0) screenheight = height; image_ID = gimp_image_new (screenwidth, screenheight, GIMP_INDEXED); gimp_image_set_filename (image_ID, filename); for (i = 0, j = 0; i < ncols; i++) { used_cmap[0][i] = gimp_cmap[j++] = cmap[0][i]; used_cmap[1][i] = gimp_cmap[j++] = cmap[1][i]; used_cmap[2][i] = gimp_cmap[j++] = cmap[2][i]; } gimp_image_set_colormap (image_ID, gimp_cmap, ncols); if (Gif89.delayTime < 0) framename = g_strdup (_("Background")); else framename = g_strdup_printf (_("Background (%d%s)"), 10 * Gif89.delayTime, "ms"); previous_disposal = Gif89.disposal; if (Gif89.transparent == -1) { layer_ID = gimp_layer_new (image_ID, framename, len, height, GIMP_INDEXED_IMAGE, 100, GIMP_NORMAL_MODE); } else { layer_ID = gimp_layer_new (image_ID, framename, len, height, GIMP_INDEXEDA_IMAGE, 100, GIMP_NORMAL_MODE); alpha_frame=TRUE; } g_free (framename); } else /* NOT FIRST FRAME */ { gimp_progress_set_text_printf (_("Opening '%s' (frame %d)"), gimp_filename_to_utf8 (filename), frame_number); gimp_progress_pulse (); /* If the colourmap is now different, we have to promote to RGB! */ if (! promote_to_rgb) { for (i = 0; i < ncols; i++) { if ((used_cmap[0][i] != cmap[0][i]) || (used_cmap[1][i] != cmap[1][i]) || (used_cmap[2][i] != cmap[2][i])) { /* Everything is RGB(A) from now on... sigh. */ promote_to_rgb = TRUE; /* Promote everything we have so far into RGB(A) */ #ifdef GIFDEBUG g_print ("GIF: Promoting image to RGB...\n"); #endif gimp_image_convert_rgb (image_ID); break; } } } if (Gif89.delayTime < 0) framename = g_strdup_printf (_("Frame %d"), frame_number); else framename = g_strdup_printf (_("Frame %d (%d%s)"), frame_number, 10 * Gif89.delayTime, "ms"); switch (previous_disposal) { case 0x00: break; /* 'don't care' */ case 0x01: framename_ptr = framename; framename = g_strconcat (framename, " (combine)", NULL); g_free (framename_ptr); break; case 0x02: framename_ptr = framename; framename = g_strconcat (framename, " (replace)", NULL); g_free (framename_ptr); break; case 0x03: /* Rarely-used, and unhandled by many loaders/players (including GIMP: we treat as 'combine' mode). */ framename_ptr = framename; framename = g_strconcat (framename, " (combine) (!)", NULL); g_free (framename_ptr); break; case 0x04: /* I've seen a composite of this type. stvo_online_banner2.gif */ case 0x05: case 0x06: /* I've seen a composite of this type. bn31.Gif */ case 0x07: framename_ptr = framename; framename = g_strconcat (framename, " (unknown disposal)", NULL); g_free (framename_ptr); g_message (_("GIF: Undocumented GIF composite type %d is " "not handled. Animation might not play or " "re-save perfectly."), previous_disposal); break; default: g_message ("Disposal word got corrupted. Bug."); break; } previous_disposal = Gif89.disposal; layer_ID = gimp_layer_new (image_ID, framename, len, height, promote_to_rgb ? GIMP_RGBA_IMAGE : GIMP_INDEXEDA_IMAGE, 100, GIMP_NORMAL_MODE); alpha_frame = TRUE; g_free (framename); } frame_number++; gimp_image_insert_layer (image_ID, layer_ID, -1, 0); gimp_layer_translate (layer_ID, (gint) leftpos, (gint) toppos); drawable = gimp_drawable_get (layer_ID); cur_progress = 0; max_progress = height; if (alpha_frame) dest = (guchar *) g_malloc (len * height * (promote_to_rgb ? 4 : 2)); else dest = (guchar *) g_malloc (len * height); #ifdef GIFDEBUG g_print ("GIF: reading %d by %d%s GIF image, ncols=%d\n", len, height, interlace ? " interlaced" : "", ncols); #endif if (! alpha_frame && promote_to_rgb) { /* I don't see how one would easily construct a GIF in which this could happen, but it's a mad mad world. */ g_message ("Ouch! Can't handle non-alpha RGB frames.\n" "Please file a bug report in GIMP's bugzilla."); gimp_quit (); } while ((v = LZWReadByte (fd, FALSE, c)) >= 0) { if (alpha_frame) { if (((guchar) v > highest_used_index) && !(v == Gif89.transparent)) highest_used_index = (guchar) v; if (promote_to_rgb) { temp = dest + ( (ypos * len) + xpos ) * 4; *(temp ) = (guchar) cmap[0][v]; *(temp+1) = (guchar) cmap[1][v]; *(temp+2) = (guchar) cmap[2][v]; *(temp+3) = (guchar) ((v == Gif89.transparent) ? 0 : 255); } else { temp = dest + ( (ypos * len) + xpos ) * 2; *temp = (guchar) v; *(temp+1) = (guchar) ((v == Gif89.transparent) ? 0 : 255); } } else { if ((guchar) v > highest_used_index) highest_used_index = (guchar) v; temp = dest + (ypos * len) + xpos; *temp = (guchar) v; } xpos++; if (xpos == len) { xpos = 0; if (interlace) { switch (pass) { case 0: case 1: ypos += 8; break; case 2: ypos += 4; break; case 3: ypos += 2; break; } if (ypos >= height) { pass++; switch (pass) { case 1: ypos = 4; break; case 2: ypos = 2; break; case 3: ypos = 1; break; default: goto fini; } } } else { ypos++; } if (frame_number == 1) { cur_progress++; if ((cur_progress % 16) == 0) gimp_progress_update ((gdouble) cur_progress / (gdouble) max_progress); } } if (ypos >= height) break; } fini: if (LZWReadByte (fd, FALSE, c) >= 0) g_print ("GIF: too much input data, ignoring extra...\n"); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); gimp_pixel_rgn_set_rect (&pixel_rgn, dest, 0, 0, drawable->width, drawable->height); g_free (dest); gimp_drawable_flush (drawable); gimp_drawable_detach (drawable); return image_ID; }
static gint LZWReadByte (FILE *fd, gint just_reset_LZW, gint input_code_size) { static gint fresh = FALSE; gint code, incode; static gint code_size, set_code_size; static gint max_code, max_code_size; static gint firstcode, oldcode; static gint clear_code, end_code; static gint table[2][(1 << MAX_LZW_BITS)]; static gint stack[(1 << (MAX_LZW_BITS)) * 2], *sp; gint i; if (just_reset_LZW) { if (input_code_size > MAX_LZW_BITS) { g_message ("Value out of range for code size (corrupted file?)"); return -1; } set_code_size = input_code_size; code_size = set_code_size + 1; clear_code = 1 << set_code_size; end_code = clear_code + 1; max_code_size = 2 * clear_code; max_code = clear_code + 2; GetCode (fd, 0, TRUE); fresh = TRUE; sp = stack; for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1 << MAX_LZW_BITS); ++i) { table[0][i] = 0; table[1][i] = 0; } return 0; } else if (fresh) { fresh = FALSE; do { firstcode = oldcode = GetCode (fd, code_size, FALSE); } while (firstcode == clear_code); return firstcode; } if (sp > stack) return *--sp; while ((code = GetCode (fd, code_size, FALSE)) >= 0) { if (code == clear_code) { for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1 << MAX_LZW_BITS); ++i) { table[0][i] = 0; table[1][i] = 0; } code_size = set_code_size + 1; max_code_size = 2 * clear_code; max_code = clear_code + 2; sp = stack; firstcode = oldcode = GetCode (fd, code_size, FALSE); return firstcode; } else if (code == end_code) { gint count; guchar buf[260]; if (ZeroDataBlock) return -2; while ((count = GetDataBlock (fd, buf)) > 0) ; if (count != 0) g_print ("GIF: missing EOD in data stream (common occurence)"); return -2; } incode = code; if (code >= max_code) { *sp++ = firstcode; code = oldcode; } while (code >= clear_code) { *sp++ = table[1][code]; if (code == table[0][code]) { g_message ("Circular table entry. Corrupt file."); gimp_quit (); } code = table[0][code]; } *sp++ = firstcode = table[1][code]; if ((code = max_code) < (1 << MAX_LZW_BITS)) { table[0][code] = oldcode; table[1][code] = firstcode; ++max_code; if ((max_code >= max_code_size) && (max_code_size < (1 << MAX_LZW_BITS))) { max_code_size *= 2; ++code_size; } } oldcode = incode; if (sp > stack) return *--sp; } return code; }
static gint32 load_image (char *filename) { GPixelRgn pixel_rgn; TileDrawable *drawable; gint32 image_ID; gint32 layer_ID; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; FILE *infile; guchar *buf; guchar **rowbuf; char *name; int image_type; int layer_type; int tile_height; int scanlines; int i, start, end; int m; int depth = 8; /* We set up the normal JPEG error routines. */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_error_exit; if ((infile = fopen (filename, "rb")) == NULL) { g_warning ("can't open \"%s\"\n", filename); gimp_quit (); } if( strrchr(filename,'.') && strcmp( strrchr(filename, '.'), ".jp4") == 0 ) depth = 16; name = malloc (strlen (filename) + 12); sprintf (name, "%s %s:", _("Loading"), filename); gimp_progress_init (name); free (name); image_ID = -1; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp (jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress (&cinfo); if (infile) fclose (infile); if (image_ID != -1) gimp_image_delete (image_ID); gimp_quit (); } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress (&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src (&cinfo, infile); setup_read_icc_profile(&cinfo); for (m = 0; m < 16; m++) jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header (&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ prepareColour( &cinfo ); /* Step 5: Start decompressor */ jpeg_start_decompress (&cinfo); /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* temporary buffer */ tile_height = gimp_tile_height (); buf = g_new (guchar, tile_height * cinfo.output_width * cinfo.output_components); rowbuf = g_new (guchar*, tile_height); for (i = 0; i < tile_height; i++) rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i; /* Create a new image of the proper size and associate the filename with it. */ if(depth == 8) { switch (cinfo.output_components) { case 1: image_type = GRAY; layer_type = GRAY_IMAGE; break; case 3: image_type = RGB; layer_type = RGB_IMAGE; break; case 4: image_type = RGB; layer_type = RGBA_IMAGE; break; default: gimp_quit (); } } else { switch (cinfo.output_components) { case 1: image_type = U16_GRAY; layer_type = U16_GRAY_IMAGE; break; case 3: image_type = U16_RGB; layer_type = U16_RGB_IMAGE; break; case 4: image_type = U16_RGB; layer_type = U16_RGBA_IMAGE; break; default: gimp_quit (); } } image_ID = gimp_image_new (cinfo.output_width / (depth/8), cinfo.output_height, image_type); gimp_image_set_filename (image_ID, filename); layer_ID = gimp_layer_new (image_ID, _("Background"), cinfo.output_width / (depth/8), cinfo.output_height, layer_type, 100, NORMAL_MODE); gimp_image_add_layer (image_ID, layer_ID, 0); drawable = gimp_drawable_get (layer_ID); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { start = cinfo.output_scanline; end = cinfo.output_scanline + tile_height; end = MIN (end,CAST(int) cinfo.output_height); scanlines = end - start; for (i = 0; i < scanlines; i++) jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1); /* for (i = start; i < end; i++) gimp_pixel_rgn_set_row (&pixel_rgn, tilerow[i - start], 0, i, drawable->width); */ if(cinfo.out_color_space == JCS_CMYK) for(i = 0; i < scanlines*drawable->width*cinfo.output_components; ++i) buf[i] = 255 - buf[i]; if(depth == 16 && 0) for(i = 0; i < scanlines*drawable->width*cinfo.output_components; ++i) { unsigned char c = buf[2*i]; buf[2*i] = buf[2*i+1]; buf[2*i+1] = c; } gimp_pixel_rgn_set_rect (&pixel_rgn, buf, 0, start, drawable->width, scanlines); gimp_progress_update ((double) cinfo.output_scanline / (double) cinfo.output_height); } // Step 6a: read icc profile { LPBYTE Buffer = NULL; size_t Len = 0; cmsHPROFILE hProfile=NULL; if (read_icc_profile(&cinfo, &Buffer, &Len)) { printf ("%s:%d %s() embedded profile found\n",__FILE__,__LINE__,__func__); } else if (read_icc_profile2(&cinfo, &Buffer, &Len)) { printf ("%s:%d %s() default profile selected\n",__FILE__,__LINE__,__func__); } if(Buffer && Len) { hProfile = cmsOpenProfileFromMem(Buffer, Len); if (hProfile) { gimp_image_set_icc_profile_by_mem (image_ID, Len, Buffer, ICC_IMAGE_PROFILE); cmsCloseProfile (hProfile); free(Buffer); printf ("%s:%d %s() set profile\n",__FILE__,__LINE__,__func__); } } } /* Step 7: Finish decompression */ jpeg_finish_decompress (&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress (&cinfo); /* free up the temporary buffers */ g_free (rowbuf); g_free (buf); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose (infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.num_warnings is nonzero). */ /* Tell the GIMP to display the image. */ gimp_drawable_flush (drawable); return image_ID; }