let the save procedure also accept a grayscale layer with alpha channel,
2008-12-26 Sven Neumann <sven@gimp.org> * plug-ins/common/file-gbr.c: let the save procedure also accept a grayscale layer with alpha channel, as we do in the GIH save procedure. * plug-ins/common/file-gih.c: when loading a brush mask pipe, create grayscale layers without an alpha channel. Changed the save procedure to also accept layers without alpha channel. svn path=/trunk/; revision=27831
This commit is contained in:

committed by
Sven Neumann

parent
6f9ccc51f5
commit
d86d085601
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
2008-12-26 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* plug-ins/common/file-gbr.c: let the save procedure accept a
|
||||
grayscale layer with alpha channel, as we do in the GIH save
|
||||
procedure.
|
||||
|
||||
* plug-ins/common/file-gih.c: when loading a brush mask pipe,
|
||||
create grayscale layers without an alpha channel. Changed the save
|
||||
procedure to also accept layers without alpha channel.
|
||||
|
||||
2008-12-25 Martin Nordholts <martinn@svn.gnome.org>
|
||||
|
||||
* app/widgets/gimplayertreeview.[ch]: Make instance members
|
||||
|
@ -173,7 +173,7 @@ query (void)
|
||||
"Tim Newsome, Jens Lautenbacher, Sven Neumann",
|
||||
"1997-2000",
|
||||
N_("GIMP brush"),
|
||||
"RGB, RGBA, GRAY",
|
||||
"RGB*, GRAY*",
|
||||
GIMP_PLUGIN,
|
||||
G_N_ELEMENTS (save_args), 0,
|
||||
save_args, NULL);
|
||||
@ -547,10 +547,12 @@ load_image (const gchar *filename,
|
||||
base_type = GIMP_GRAY;
|
||||
image_type = GIMP_GRAY_IMAGE;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
base_type = GIMP_RGB;
|
||||
image_type = GIMP_RGBA_IMAGE;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_message ("Unsupported brush depth: %d\n"
|
||||
"GIMP Brushes must be GRAY or RGBA\n",
|
||||
@ -614,6 +616,7 @@ save_image (const gchar *filename,
|
||||
break;
|
||||
|
||||
case GIMP_GRAY_IMAGE:
|
||||
case GIMP_GRAYA_IMAGE:
|
||||
bpp = 1;
|
||||
break;
|
||||
|
||||
@ -679,6 +682,12 @@ save_image (const gchar *filename,
|
||||
buffer[x] = 255 - buffer[x];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* invert and drop alpha channel */
|
||||
for (x = 0; x < drawable->width; x++)
|
||||
buffer[x] = 255 - buffer[2 * x];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* add alpha channel */
|
||||
for (x = drawable->width - 1; x >= 0; x--)
|
||||
@ -702,6 +711,9 @@ save_image (const gchar *filename,
|
||||
}
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
gimp_drawable_detach (drawable);
|
||||
|
||||
close (fd);
|
||||
|
||||
return TRUE;
|
||||
|
@ -97,7 +97,7 @@ static struct
|
||||
};
|
||||
|
||||
|
||||
static gint num_useable_layers;
|
||||
static gint num_layers = 0;
|
||||
|
||||
static const gchar *selection_modes[] = { "incremental",
|
||||
"angular",
|
||||
@ -147,7 +147,7 @@ static gboolean gih_load_one_brush (gint fd,
|
||||
static gboolean gih_save_dialog (gint32 image_ID);
|
||||
static gboolean gih_save_one_brush (gint fd,
|
||||
GimpPixelRgn *pixel_rgn,
|
||||
gchar *name);
|
||||
const gchar *name);
|
||||
static gboolean gih_save_image (const gchar *filename,
|
||||
gint32 image_ID,
|
||||
gint32 orig_image_ID,
|
||||
@ -223,12 +223,12 @@ query (void)
|
||||
|
||||
gimp_install_procedure (SAVE_PROC,
|
||||
"saves images in GIMP brush pipe format",
|
||||
"This plug-in saves an image in the GIMP brush pipe format. The image must have an alpha chnannel and can be multi-layered, and additionally the layers can be divided into a rectangular array of brushes.",
|
||||
"This plug-in saves an image in the GIMP brush pipe format. For a colored brush pipe, RGBA layers are used, otherwise the layers should be grayscale masks. The image can be multi-layered, and additionally the layers can be divided into a rectangular array of brushes.",
|
||||
"Tor Lillqvist",
|
||||
"Tor Lillqvist",
|
||||
"1999",
|
||||
N_("GIMP brush (animated)"),
|
||||
"RGBA, GRAYA",
|
||||
"RGB*, GRAY*",
|
||||
GIMP_PLUGIN,
|
||||
G_N_ELEMENTS (gih_save_args), 0,
|
||||
gih_save_args, NULL);
|
||||
@ -255,9 +255,6 @@ run (const gchar *name,
|
||||
gint32 image_ID;
|
||||
gint32 orig_image_ID;
|
||||
gint32 drawable_ID;
|
||||
gint32 *layer_ID;
|
||||
gint nlayers, layer;
|
||||
gchar *layer_name;
|
||||
gint i;
|
||||
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
||||
GError *error = NULL;
|
||||
@ -299,11 +296,10 @@ run (const gchar *name,
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
||||
export = gimp_export_image (&image_ID, &drawable_ID, "GIH",
|
||||
GIMP_EXPORT_CAN_HANDLE_RGB |
|
||||
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
||||
GIMP_EXPORT_CAN_HANDLE_ALPHA |
|
||||
GIMP_EXPORT_CAN_HANDLE_LAYERS |
|
||||
GIMP_EXPORT_NEEDS_ALPHA);
|
||||
GIMP_EXPORT_CAN_HANDLE_RGB |
|
||||
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
||||
GIMP_EXPORT_CAN_HANDLE_ALPHA |
|
||||
GIMP_EXPORT_CAN_HANDLE_LAYERS);
|
||||
if (export == GIMP_EXPORT_CANCEL)
|
||||
{
|
||||
values[0].data.d_status = GIMP_PDB_CANCEL;
|
||||
@ -314,19 +310,7 @@ run (const gchar *name,
|
||||
break;
|
||||
}
|
||||
|
||||
layer_ID = gimp_image_get_layers (image_ID, &nlayers);
|
||||
num_useable_layers = 0;
|
||||
for (layer = 0; layer < nlayers; layer++)
|
||||
{
|
||||
if (!gimp_drawable_has_alpha (layer_ID[layer]))
|
||||
{
|
||||
layer_name = gimp_drawable_get_name (layer_ID[layer]);
|
||||
g_message (_("Layer %s doesn't have an alpha channel, skipped"),
|
||||
layer_name);
|
||||
g_free (layer_name);
|
||||
}
|
||||
num_useable_layers++;
|
||||
}
|
||||
g_free (gimp_image_get_layers (image_ID, &num_layers));
|
||||
|
||||
switch (run_mode)
|
||||
{
|
||||
@ -340,8 +324,7 @@ run (const gchar *name,
|
||||
if (gihparams.rows < 1) gihparams.rows = 1;
|
||||
if (gihparams.cols < 1) gihparams.cols = 1;
|
||||
|
||||
gihparams.ncells = (num_useable_layers *
|
||||
gihparams.rows * gihparams.cols);
|
||||
gihparams.ncells = (num_layers * gihparams.rows * gihparams.cols);
|
||||
|
||||
if (gihparams.cellwidth == 1 && gihparams.cellheight == 1)
|
||||
{
|
||||
@ -448,7 +431,6 @@ static gboolean
|
||||
gih_load_one_brush (gint fd,
|
||||
gint32 image_ID)
|
||||
{
|
||||
static gint num_layers = 0;
|
||||
gchar *name = NULL;
|
||||
BrushHeader bh;
|
||||
guchar *brush_buf = NULL;
|
||||
@ -591,7 +573,8 @@ gih_load_one_brush (gint fd,
|
||||
break;
|
||||
|
||||
default:
|
||||
g_message ("Unsupported brush depth: %d\nGIMP Brushes must be GRAY or RGBA\n",
|
||||
g_message ("Unsupported brush depth: %d\n"
|
||||
"GIMP Brushes must be GRAY or RGBA\n",
|
||||
bh.bytes);
|
||||
return FALSE;
|
||||
}
|
||||
@ -631,7 +614,6 @@ gih_load_one_brush (gint fd,
|
||||
if (image_type == GIMP_GRAY_IMAGE)
|
||||
{
|
||||
gimp_invert (layer_ID);
|
||||
gimp_layer_add_alpha (layer_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1141,9 +1123,8 @@ gih_save_dialog (gint32 image_ID)
|
||||
gihparams.selection[i] = g_strdup (gihparams.selection[i]);
|
||||
|
||||
/* Fix up bogus values */
|
||||
gihparams.ncells =
|
||||
MIN (gihparams.ncells,
|
||||
num_useable_layers * gihparams.rows * gihparams.cols);
|
||||
gihparams.ncells = MIN (gihparams.ncells,
|
||||
num_layers * gihparams.rows * gihparams.cols);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
@ -1159,65 +1140,50 @@ gih_save_dialog (gint32 image_ID)
|
||||
static gboolean
|
||||
gih_save_one_brush (gint fd,
|
||||
GimpPixelRgn *pixel_rgn,
|
||||
gchar *name)
|
||||
const gchar *name)
|
||||
{
|
||||
BrushHeader header;
|
||||
guint x;
|
||||
guint y;
|
||||
guchar *buffer;
|
||||
guint y;
|
||||
|
||||
g_return_val_if_fail (fd != -1, FALSE);
|
||||
g_return_val_if_fail (pixel_rgn != NULL, FALSE);
|
||||
|
||||
if (!name)
|
||||
name = g_strdup (_("Unnamed"));
|
||||
|
||||
if (pixel_rgn->bpp != 2 && pixel_rgn->bpp != 4)
|
||||
{
|
||||
g_free (name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pixel_rgn->w < 1 || pixel_rgn->h < 1)
|
||||
{
|
||||
g_free (name);
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
header.header_size =
|
||||
g_htonl (sizeof (header) + strlen (name) + 1);
|
||||
if (! name)
|
||||
name = _("Unnamed");
|
||||
|
||||
header.header_size = g_htonl (sizeof (header) + strlen (name) + 1);
|
||||
header.version = g_htonl (2);
|
||||
header.width = g_htonl (pixel_rgn->w);
|
||||
header.height = g_htonl (pixel_rgn->h);
|
||||
header.bytes = g_htonl (pixel_rgn->bpp == 2 ? 1 : 4);
|
||||
header.bytes = g_htonl (pixel_rgn->bpp > 2 ? 4 : 1);
|
||||
header.magic_number = g_htonl (GBRUSH_MAGIC);
|
||||
header.spacing = g_htonl (info.spacing);
|
||||
|
||||
if (write (fd, &header, sizeof (header)) != sizeof (header))
|
||||
return FALSE;
|
||||
|
||||
if (write (fd, name, strlen (name) + 1) !=
|
||||
strlen (name) + 1)
|
||||
{
|
||||
g_free (name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
if (write (fd, name, strlen (name) + 1) != strlen (name) + 1)
|
||||
return FALSE;
|
||||
|
||||
buffer = g_malloc (pixel_rgn->w * pixel_rgn->bpp);
|
||||
|
||||
for (y = 0; y < pixel_rgn->h; y++)
|
||||
{
|
||||
gimp_pixel_rgn_get_row (pixel_rgn, buffer,
|
||||
0 + pixel_rgn->x, y + pixel_rgn->y,
|
||||
pixel_rgn->w);
|
||||
guint x;
|
||||
|
||||
if (pixel_rgn->bpp == 2) /* GRAYA */
|
||||
gimp_pixel_rgn_get_row (pixel_rgn, buffer,
|
||||
0 + pixel_rgn->x, y + pixel_rgn->y, pixel_rgn->w);
|
||||
|
||||
switch (pixel_rgn->bpp)
|
||||
{
|
||||
case 1: /* GRAY */
|
||||
for (x = 0; x < pixel_rgn->w; x++)
|
||||
{
|
||||
guchar value = 255 - buffer[2 * x];
|
||||
const guchar value = 255 - buffer[x];
|
||||
|
||||
if (write (fd, &value, 1) != 1)
|
||||
{
|
||||
@ -1225,15 +1191,51 @@ gih_save_one_brush (gint fd,
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pixel_rgn->bpp == 4) /* RGBA */
|
||||
{
|
||||
break;
|
||||
|
||||
case 2: /* GRAYA, alpha channel is ignored */
|
||||
for (x = 0; x < pixel_rgn->w; x++)
|
||||
{
|
||||
const guchar value = 255 - buffer[2 * x];
|
||||
|
||||
if (write (fd, &value, 1) != 1)
|
||||
{
|
||||
g_free (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* RGB, alpha channel is added */
|
||||
for (x = 0; x < pixel_rgn->w; x++)
|
||||
{
|
||||
guchar value[4];
|
||||
|
||||
value[0] = buffer[3 * x + 0];
|
||||
value[1] = buffer[3 * x + 1];
|
||||
value[2] = buffer[3 * x + 2];
|
||||
value[3] = 255;
|
||||
|
||||
if (write (fd, value, 4) != 4)
|
||||
{
|
||||
g_free (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* RGBA */
|
||||
if (write (fd, buffer, pixel_rgn->w * pixel_rgn->bpp) !=
|
||||
pixel_rgn->w * pixel_rgn->bpp)
|
||||
{
|
||||
g_free (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1249,16 +1251,16 @@ gih_save_image (const gchar *filename,
|
||||
gint32 drawable_ID,
|
||||
GError **error)
|
||||
{
|
||||
GimpDrawable *drawable;
|
||||
GimpPixelRgn pixel_rgn;
|
||||
GimpParasite *pipe_parasite;
|
||||
gchar *header;
|
||||
gchar *parstring;
|
||||
gint32 *layer_ID;
|
||||
gint fd;
|
||||
gint nlayers, layer, row, col;
|
||||
gint imagew, imageh, offsetx, offsety;
|
||||
gint k, x, y, thisx, thisy, xnext, ynext, thisw, thish;
|
||||
gchar *header;
|
||||
gchar *parstring;
|
||||
gint32 *layer_ID;
|
||||
gint fd;
|
||||
gint nlayers, layer;
|
||||
gint row, col;
|
||||
gint imagew, imageh;
|
||||
gint offsetx, offsety;
|
||||
gint k;
|
||||
|
||||
if (gihparams.ncells < 1)
|
||||
return FALSE;
|
||||
@ -1287,8 +1289,8 @@ gih_save_image (const gchar *filename,
|
||||
|
||||
if (write (fd, header, strlen (header)) != strlen (header))
|
||||
{
|
||||
g_free (header);
|
||||
g_free (parstring);
|
||||
g_free (header);
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
@ -1305,19 +1307,21 @@ gih_save_image (const gchar *filename,
|
||||
|
||||
layer_ID = gimp_image_get_layers (image_ID, &nlayers);
|
||||
|
||||
k = 0;
|
||||
for (layer = 0; layer < nlayers; layer++)
|
||||
for (layer = 0, k = 0; layer < nlayers; layer++)
|
||||
{
|
||||
if (!gimp_drawable_has_alpha (layer_ID[layer]))
|
||||
continue;
|
||||
GimpDrawable *drawable = gimp_drawable_get (layer_ID[layer]);
|
||||
gchar *name = gimp_drawable_get_name (drawable->drawable_id);
|
||||
|
||||
drawable = gimp_drawable_get (layer_ID[layer]);
|
||||
gimp_drawable_offsets (layer_ID[layer], &offsetx, &offsety);
|
||||
gimp_drawable_offsets (drawable->drawable_id, &offsetx, &offsety);
|
||||
|
||||
for (row = 0; row < gihparams.rows; row++)
|
||||
{
|
||||
y = (row * imageh) / gihparams.rows ;
|
||||
gint y, ynext;
|
||||
gint thisy, thish;
|
||||
|
||||
y = (row * imageh) / gihparams.rows;
|
||||
ynext = ((row + 1) * imageh / gihparams.rows);
|
||||
|
||||
/* Assume layer is offset to positive direction in x and y.
|
||||
* That's reasonable, as otherwise all of the layer
|
||||
* won't be visible.
|
||||
@ -1329,16 +1333,20 @@ gih_save_image (const gchar *filename,
|
||||
|
||||
for (col = 0; col < gihparams.cols; col++)
|
||||
{
|
||||
GimpPixelRgn pixel_rgn;
|
||||
gint x, xnext;
|
||||
gint thisx, thisw;
|
||||
|
||||
x = (col * imagew / gihparams.cols);
|
||||
xnext = ((col + 1) * imagew / gihparams.cols);
|
||||
thisx = MAX (0, x - offsetx);
|
||||
thisw = (xnext - offsetx) - thisx;
|
||||
thisw = MIN (thisw, drawable->width - thisx);
|
||||
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable, thisx, thisy,
|
||||
thisw, thish, FALSE, FALSE);
|
||||
|
||||
if (! gih_save_one_brush (fd, &pixel_rgn,
|
||||
gimp_drawable_get_name (layer_ID[layer])))
|
||||
if (! gih_save_one_brush (fd, &pixel_rgn, name))
|
||||
{
|
||||
close (fd);
|
||||
return FALSE;
|
||||
@ -1349,10 +1357,14 @@ gih_save_image (const gchar *filename,
|
||||
}
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
gimp_drawable_detach (drawable);
|
||||
}
|
||||
|
||||
gimp_progress_update (1.0);
|
||||
|
||||
g_free (layer_ID);
|
||||
|
||||
close (fd);
|
||||
|
||||
return TRUE;
|
||||
|
Reference in New Issue
Block a user