static void do_zcrop (gint32 drawable_id, gint32 image_id) { GeglBuffer *drawable_buffer; GeglBuffer *shadow_buffer; gfloat *linear_buf; const Babl *format; gint x, y, width, height; gint components; gint8 *killrows; gint8 *killcols; gint32 livingrows, livingcols, destrow, destcol; gint32 selection_copy_id; gboolean has_alpha; drawable_buffer = gimp_drawable_get_buffer (drawable_id); shadow_buffer = gimp_drawable_get_shadow_buffer (drawable_id); width = gegl_buffer_get_width (drawable_buffer); height = gegl_buffer_get_height (drawable_buffer); has_alpha = gimp_drawable_has_alpha (drawable_id); if (has_alpha) format = babl_format ("R'G'B'A float"); else format = babl_format ("R'G'B' float"); components = babl_format_get_n_components (format); killrows = g_new (gint8, height); killcols = g_new (gint8, width); linear_buf = g_new (gfloat, (width > height ? width : height) * components); /* search which rows to remove */ livingrows = 0; for (y = 0; y < height; y++) { gegl_buffer_get (drawable_buffer, GEGL_RECTANGLE (0, y, width, 1), 1.0, format, linear_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); killrows[y] = TRUE; for (x = components; x < width * components; x += components) { if (! colors_equal (linear_buf, &linear_buf[x], components, has_alpha)) { livingrows++; killrows[y] = FALSE; break; } } } gimp_progress_update (0.25); /* search which columns to remove */ livingcols = 0; for (x = 0; x < width; x++) { gegl_buffer_get (drawable_buffer, GEGL_RECTANGLE (x, 0, 1, height), 1.0, format, linear_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); killcols[x] = TRUE; for (y = components; y < height * components; y += components) { if (! colors_equal (linear_buf, &linear_buf[y], components, has_alpha)) { livingcols++; killcols[x] = FALSE; break; } } } gimp_progress_update (0.5); if ((livingcols == 0 || livingrows == 0) || (livingcols == width && livingrows == height)) { g_message (_("Nothing to crop.")); g_free (linear_buf); g_free (killrows); g_free (killcols); return; } /* restitute living rows */ destrow = 0; for (y = 0; y < height; y++) { if (!killrows[y]) { gegl_buffer_copy (drawable_buffer, GEGL_RECTANGLE (0, y, width, 1), GEGL_ABYSS_NONE, shadow_buffer, GEGL_RECTANGLE (0, destrow, width, 1)); destrow++; } } gimp_progress_update (0.75); /* restitute living columns */ destcol = 0; for (x = 0; x < width; x++) { if (!killcols[x]) { gegl_buffer_copy (shadow_buffer, GEGL_RECTANGLE (x, 0, 1, height), GEGL_ABYSS_NONE, shadow_buffer, GEGL_RECTANGLE (destcol, 0, 1, height)); destcol++; } } gimp_progress_update (1.00); gimp_image_undo_group_start (image_id); selection_copy_id = gimp_selection_save (image_id); gimp_selection_none (image_id); gegl_buffer_flush (shadow_buffer); gimp_drawable_merge_shadow (drawable_id, TRUE); gegl_buffer_flush (drawable_buffer); gimp_image_select_item (image_id, GIMP_CHANNEL_OP_REPLACE, selection_copy_id); gimp_image_remove_channel (image_id, selection_copy_id); gimp_image_crop (image_id, livingcols, livingrows, 0, 0); gimp_image_undo_group_end (image_id); g_object_unref (shadow_buffer); g_object_unref (drawable_buffer); g_free (linear_buf); g_free (killrows); g_free (killcols); }
static void do_zcrop (GimpDrawable *drawable, gint32 image_id) { GimpPixelRgn srcPR, destPR; gint width, height, x, y; gint bytes; guchar *buffer; gint8 *killrows; gint8 *killcols; gint32 livingrows, livingcols, destrow, destcol; gint total_area, area; gboolean has_alpha; width = drawable->width; height = drawable->height; bytes = drawable->bpp; total_area = width * height * 4; area = 0; killrows = g_new (gint8, height); killcols = g_new (gint8, width); buffer = g_malloc ((width > height ? width : height) * bytes); /* initialize the pixel regions */ gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE); has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); livingrows = 0; for (y = 0; y < height; y++) { gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width); killrows[y] = TRUE; for (x = 0; x < width * bytes; x += bytes) { if (! colors_equal (buffer, &buffer[x], bytes, has_alpha)) { livingrows++; killrows[y] = FALSE; break; } } area += width; if (y % 20 == 0) gimp_progress_update ((double) area / (double) total_area); } livingcols = 0; for (x = 0; x < width; x++) { gimp_pixel_rgn_get_col (&srcPR, buffer, x, 0, height); killcols[x] = TRUE; for (y = 0; y < height * bytes; y += bytes) { if (! colors_equal (buffer, &buffer[y], bytes, has_alpha)) { livingcols++; killcols[x] = FALSE; break; } } area += height; if (x % 20 == 0) gimp_progress_update ((double) area / (double) total_area); } if ((livingcols == 0 || livingrows==0) || (livingcols == width && livingrows == height)) { g_message (_("Nothing to crop.")); g_free (killrows); g_free (killcols); return; } destrow = 0; for (y = 0; y < height; y++) { if (!killrows[y]) { gimp_pixel_rgn_get_row (&srcPR, buffer, 0, y, width); gimp_pixel_rgn_set_row (&destPR, buffer, 0, destrow, width); destrow++; } area += width; if (y % 20 == 0) gimp_progress_update ((double) area / (double) total_area); } destcol = 0; gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, TRUE); for (x = 0; x < width; x++) { if (!killcols[x]) { gimp_pixel_rgn_get_col (&srcPR, buffer, x, 0, height); gimp_pixel_rgn_set_col (&destPR, buffer, destcol, 0, height); destcol++; } area += height; if (x % 20 == 0) gimp_progress_update ((double) area / (double) total_area); } g_free (buffer); g_free (killrows); g_free (killcols); gimp_progress_update (1.00); gimp_image_undo_group_start (image_id); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_image_crop (image_id, livingcols, livingrows, 0, 0); gimp_image_undo_group_end (image_id); }
void cmd_color(const char* cmd, size_t cmdlen, char* args, size_t argslen) { const char* usage = "Usage: /color R G B (R G B must be between 0 and 255)"; Color color = Color(0,0,0); bool valid = true; // split lines up int i = 0; int n = 1; const char delim = ' '; char c = '\0'; while ((c = args[i++]) != '\0') { if (!isdigit(c) && c != delim) break; if (c == delim) { args[i-1] = '\0'; n++; } } i = 0; if (c != '\0') valid = false; // encountered invalid char if (n != 3) valid = false; // invalid arg count if (!valid) { chat_client->send_system_message(usage); return; } char buf[3+1] = {'\0'}; int j = 0; // copy red while ((c = args[i++]) != '\0' && j < 3) buf[j++] = c; buf[j] = '\0'; if (args[i-1] != '\0') valid = false; else { int r = atoi(buf); if (r > 0xFF) valid = false; else color.r = r; } printf("r: %s\n", buf); j = 0; // copy green while ((c = args[i++]) != '\0' && j < 3) buf[j++] = c; buf[j] = '\0'; if (args[i-1] != '\0') valid = false; else { int g = atoi(buf); if (g > 0xFF) valid = false; else color.g = g; } printf("g: %s\n", buf); j = 0; // copy blue while ((c = args[i++]) != '\0' && j < 3) buf[j++] = c; buf[j] = '\0'; if (args[i-1] != '\0') valid = false; else { int b = atoi(buf); if (b > 0xFF) valid = false; else color.b = b; } printf("b: %s\n", buf); if (!valid) { chat_client->send_system_message(usage); return; } class Agents::Agent* you = ClientState::player_agent.you(); if (you != NULL && colors_equal(you->status.color, color)) { static const char msgfmt[] = "Your color is already %d %d %d"; static const size_t msg_len = sizeof(msgfmt) + 3*3 - 3*2; static char msg[msg_len+1] = {'\0'}; snprintf(msg, msg_len+1, msgfmt, color.r, color.g, color.b); chat_client->send_system_message(msg); } colorme_CtoS msg; msg.color = color; msg.send(); }