mirror of https://github.com/GNOME/gimp.git
file-pnm: Add support for saving PFM (portable floatmap) files in color and gray
This commit is contained in:
parent
b6095b6fa5
commit
51e4491fbf
|
@ -44,6 +44,7 @@
|
|||
#define PBM_SAVE_PROC "file-pbm-save"
|
||||
#define PGM_SAVE_PROC "file-pgm-save"
|
||||
#define PPM_SAVE_PROC "file-ppm-save"
|
||||
#define PFM_SAVE_PROC "file-pfm-save"
|
||||
#define PLUG_IN_BINARY "file-pnm"
|
||||
#define PLUG_IN_ROLE "gimp-file-pnm"
|
||||
|
||||
|
@ -112,9 +113,6 @@ typedef struct
|
|||
* by the spec anyways so this shouldn't
|
||||
* be an issue. */
|
||||
|
||||
#define SAVE_COMMENT_STRING "# CREATOR: GIMP PNM Filter Version 1.1\n"
|
||||
|
||||
|
||||
/* Declare some local functions.
|
||||
*/
|
||||
static void query (void);
|
||||
|
@ -129,6 +127,7 @@ static gint save_image (GFile *file,
|
|||
gint32 image_ID,
|
||||
gint32 drawable_ID,
|
||||
gboolean pbm,
|
||||
gboolean float_format,
|
||||
GError **error);
|
||||
|
||||
static gboolean save_dialog (void);
|
||||
|
@ -247,6 +246,15 @@ query (void)
|
|||
{ GIMP_PDB_INT32, "raw", "TRUE for raw output, FALSE for ascii output" }
|
||||
};
|
||||
|
||||
static const GimpParamDef pfm_save_args[] =
|
||||
{
|
||||
{ GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
|
||||
{ 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" }
|
||||
};
|
||||
|
||||
gimp_install_procedure (LOAD_PROC,
|
||||
"Loads files in the PNM file format",
|
||||
"This plug-in loads files in the various Netpbm portable file formats.",
|
||||
|
@ -317,20 +325,35 @@ query (void)
|
|||
G_N_ELEMENTS (save_args), 0,
|
||||
save_args, NULL);
|
||||
|
||||
gimp_install_procedure (PFM_SAVE_PROC,
|
||||
"Saves files in the PFM file format",
|
||||
"PFM saving handles all images without transparency.",
|
||||
"Mukund Sivaraman",
|
||||
"Mukund Sivaraman",
|
||||
"2015",
|
||||
N_("PFM image"),
|
||||
"RGB, GRAY, INDEXED",
|
||||
GIMP_PLUGIN,
|
||||
G_N_ELEMENTS (pfm_save_args), 0,
|
||||
pfm_save_args, NULL);
|
||||
|
||||
gimp_register_file_handler_mime (PNM_SAVE_PROC, "image/x-portable-anymap");
|
||||
gimp_register_file_handler_mime (PBM_SAVE_PROC, "image/x-portable-bitmap");
|
||||
gimp_register_file_handler_mime (PGM_SAVE_PROC, "image/x-portable-graymap");
|
||||
gimp_register_file_handler_mime (PPM_SAVE_PROC, "image/x-portable-pixmap");
|
||||
gimp_register_file_handler_mime (PPM_SAVE_PROC, "image/x-portable-floatmap");
|
||||
|
||||
gimp_register_file_handler_uri (PNM_SAVE_PROC);
|
||||
gimp_register_file_handler_uri (PBM_SAVE_PROC);
|
||||
gimp_register_file_handler_uri (PGM_SAVE_PROC);
|
||||
gimp_register_file_handler_uri (PPM_SAVE_PROC);
|
||||
gimp_register_file_handler_uri (PFM_SAVE_PROC);
|
||||
|
||||
gimp_register_save_handler (PNM_SAVE_PROC, "pnm", "");
|
||||
gimp_register_save_handler (PBM_SAVE_PROC, "pbm", "");
|
||||
gimp_register_save_handler (PGM_SAVE_PROC, "pgm", "");
|
||||
gimp_register_save_handler (PPM_SAVE_PROC, "ppm", "");
|
||||
gimp_register_save_handler (PFM_SAVE_PROC, "pfm", "");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -342,12 +365,13 @@ run (const gchar *name,
|
|||
{
|
||||
static GimpParam values[2];
|
||||
GimpRunMode run_mode;
|
||||
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
||||
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
||||
gint32 image_ID;
|
||||
gint32 drawable_ID;
|
||||
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
||||
GError *error = NULL;
|
||||
gboolean pbm = FALSE; /* flag for PBM output */
|
||||
GimpExportReturn export = GIMP_EXPORT_CANCEL;
|
||||
GError *error = NULL;
|
||||
gboolean pbm = FALSE; /* flag for PBM output */
|
||||
gboolean float_format = FALSE; /* flag for PFM output */
|
||||
|
||||
INIT_I18N ();
|
||||
gegl_init (NULL, NULL);
|
||||
|
@ -378,7 +402,8 @@ run (const gchar *name,
|
|||
else if (strcmp (name, PNM_SAVE_PROC) == 0 ||
|
||||
strcmp (name, PBM_SAVE_PROC) == 0 ||
|
||||
strcmp (name, PGM_SAVE_PROC) == 0 ||
|
||||
strcmp (name, PPM_SAVE_PROC) == 0)
|
||||
strcmp (name, PPM_SAVE_PROC) == 0 ||
|
||||
strcmp (name, PFM_SAVE_PROC) == 0)
|
||||
{
|
||||
image_ID = param[1].data.d_int32;
|
||||
drawable_ID = param[2].data.d_int32;
|
||||
|
@ -408,12 +433,19 @@ run (const gchar *name,
|
|||
export = gimp_export_image (&image_ID, &drawable_ID, "PGM",
|
||||
GIMP_EXPORT_CAN_HANDLE_GRAY);
|
||||
}
|
||||
else
|
||||
else if (strcmp (name, PPM_SAVE_PROC) == 0)
|
||||
{
|
||||
export = gimp_export_image (&image_ID, &drawable_ID, "PPM",
|
||||
GIMP_EXPORT_CAN_HANDLE_RGB |
|
||||
GIMP_EXPORT_CAN_HANDLE_INDEXED);
|
||||
}
|
||||
else
|
||||
{
|
||||
export = gimp_export_image (&image_ID, &drawable_ID, "PFM",
|
||||
GIMP_EXPORT_CAN_HANDLE_RGB |
|
||||
GIMP_EXPORT_CAN_HANDLE_GRAY);
|
||||
float_format = TRUE;
|
||||
}
|
||||
|
||||
if (export == GIMP_EXPORT_CANCEL)
|
||||
{
|
||||
|
@ -426,47 +458,69 @@ run (const gchar *name,
|
|||
break;
|
||||
}
|
||||
|
||||
switch (run_mode)
|
||||
if (strcmp (name, PFM_SAVE_PROC) != 0)
|
||||
{
|
||||
case GIMP_RUN_INTERACTIVE:
|
||||
/* Possibly retrieve data */
|
||||
gimp_get_data (name, &psvals);
|
||||
|
||||
/* First acquire information with a dialog */
|
||||
if (! save_dialog ())
|
||||
status = GIMP_PDB_CANCEL;
|
||||
break;
|
||||
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
/* Make sure all the arguments are there! */
|
||||
if (nparams != 6)
|
||||
switch (run_mode)
|
||||
{
|
||||
status = GIMP_PDB_CALLING_ERROR;
|
||||
case GIMP_RUN_INTERACTIVE:
|
||||
/* Possibly retrieve data */
|
||||
gimp_get_data (name, &psvals);
|
||||
|
||||
/* First acquire information with a dialog */
|
||||
if (! save_dialog ())
|
||||
status = GIMP_PDB_CANCEL;
|
||||
break;
|
||||
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
/* Make sure all the arguments are there! */
|
||||
if (nparams != 6)
|
||||
{
|
||||
status = GIMP_PDB_CALLING_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
psvals.raw = (param[5].data.d_int32) ? TRUE : FALSE;
|
||||
pbm = (strcmp (name, PBM_SAVE_PROC) == 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
/* Possibly retrieve data */
|
||||
gimp_get_data (name, &psvals);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (run_mode)
|
||||
{
|
||||
psvals.raw = (param[5].data.d_int32) ? TRUE : FALSE;
|
||||
pbm = (strcmp (name, PBM_SAVE_PROC) == 0);
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
/* Make sure all the arguments are there! */
|
||||
if (nparams != 5)
|
||||
{
|
||||
status = GIMP_PDB_CALLING_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
/* Possibly retrieve data */
|
||||
gimp_get_data (name, &psvals);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == GIMP_PDB_SUCCESS)
|
||||
{
|
||||
if (save_image (g_file_new_for_uri (param[3].data.d_string),
|
||||
image_ID, drawable_ID, pbm,
|
||||
image_ID, drawable_ID, pbm, float_format,
|
||||
&error))
|
||||
{
|
||||
/* Store psvals data */
|
||||
gimp_set_data (name, &psvals, sizeof (PNMSaveVals));
|
||||
if (strcmp (name, PFM_SAVE_PROC) != 0)
|
||||
{
|
||||
/* Store psvals data */
|
||||
gimp_set_data (name, &psvals, sizeof (PNMSaveVals));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1044,6 +1098,17 @@ pnmsaverow_raw (PNMRowInfo *ri,
|
|||
return output_write (ri->output, data, ri->xres * ri->np, error);
|
||||
}
|
||||
|
||||
/* Writes out RGB and grayscale float rows */
|
||||
static gboolean
|
||||
pnmsaverow_float (PNMRowInfo *ri,
|
||||
const float *data,
|
||||
GError **error)
|
||||
{
|
||||
return output_write (ri->output, data,
|
||||
ri->xres * ri->np * sizeof (float),
|
||||
error);
|
||||
}
|
||||
|
||||
/* Writes out indexed raw rows */
|
||||
static gboolean
|
||||
pnmsaverow_raw_indexed (PNMRowInfo *ri,
|
||||
|
@ -1110,10 +1175,12 @@ save_image (GFile *file,
|
|||
gint32 image_ID,
|
||||
gint32 drawable_ID,
|
||||
gboolean pbm,
|
||||
gboolean float_format,
|
||||
GError **error)
|
||||
{
|
||||
GOutputStream *output;
|
||||
GeglBuffer *buffer;
|
||||
gboolean status = FALSE;
|
||||
GOutputStream *output = NULL;
|
||||
GeglBuffer *buffer = NULL;
|
||||
const Babl *format;
|
||||
const gchar *header_string = NULL;
|
||||
GimpImageType drawable_type;
|
||||
|
@ -1122,20 +1189,18 @@ save_image (GFile *file,
|
|||
guchar red[256];
|
||||
guchar grn[256];
|
||||
guchar blu[256];
|
||||
guchar *data;
|
||||
guchar *d;
|
||||
gchar *rowbuf;
|
||||
gchar buf[BUFLEN];
|
||||
gint np = 0;
|
||||
gint xres, yres;
|
||||
gint ypos, yend;
|
||||
gint rowbufsize = 0;
|
||||
gchar *comment = NULL;
|
||||
|
||||
/* Make sure we're not saving an image with an alpha channel */
|
||||
if (gimp_drawable_has_alpha (drawable_ID))
|
||||
{
|
||||
g_message (_("Cannot save images with alpha channel."));
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gimp_progress_init_printf (_("Saving '%s'"),
|
||||
|
@ -1146,7 +1211,7 @@ save_image (GFile *file,
|
|||
NULL, FALSE, G_FILE_CREATE_NONE,
|
||||
NULL, error));
|
||||
if (! output)
|
||||
return FALSE;
|
||||
goto out;
|
||||
|
||||
buffer = gimp_drawable_get_buffer (drawable_ID);
|
||||
|
||||
|
@ -1156,7 +1221,7 @@ save_image (GFile *file,
|
|||
drawable_type = gimp_drawable_type (drawable_ID);
|
||||
|
||||
/* write out magic number */
|
||||
if (!psvals.raw)
|
||||
if (!float_format && !psvals.raw)
|
||||
{
|
||||
if (pbm)
|
||||
{
|
||||
|
@ -1196,11 +1261,11 @@ save_image (GFile *file,
|
|||
|
||||
default:
|
||||
g_warning ("PNM: Unknown drawable_type\n");
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!float_format)
|
||||
{
|
||||
if (pbm)
|
||||
{
|
||||
|
@ -1240,17 +1305,34 @@ save_image (GFile *file,
|
|||
|
||||
default:
|
||||
g_warning ("PNM: Unknown drawable_type\n");
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (drawable_type)
|
||||
{
|
||||
case GIMP_GRAY_IMAGE:
|
||||
header_string = "Pf\n";
|
||||
format = babl_format ("Y float");
|
||||
np = 1;
|
||||
break;
|
||||
|
||||
case GIMP_RGB_IMAGE:
|
||||
header_string = "PF\n";
|
||||
format = babl_format ("RGB float");
|
||||
np = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("PFM: Unknown drawable_type\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (! output_write (output, header_string, strlen (header_string), error))
|
||||
{
|
||||
g_object_unref (output);
|
||||
g_object_unref (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
goto out;
|
||||
|
||||
rowinfo.zero_is_black = FALSE;
|
||||
|
||||
|
@ -1307,81 +1389,120 @@ save_image (GFile *file,
|
|||
}
|
||||
|
||||
/* write out comment string */
|
||||
if (! output_write (output, SAVE_COMMENT_STRING, strlen (SAVE_COMMENT_STRING),
|
||||
error))
|
||||
{
|
||||
g_object_unref (output);
|
||||
g_object_unref (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
comment = g_strdup_printf("# Created by GIMP version %s PNM plug-in\n",
|
||||
GIMP_VERSION);
|
||||
|
||||
if (! output_write (output, comment, strlen (comment), error))
|
||||
goto out;
|
||||
|
||||
/* write out resolution and maxval */
|
||||
if (pbm)
|
||||
g_snprintf (buf, sizeof (buf), "%d %d\n", xres, yres);
|
||||
else
|
||||
else if (!float_format)
|
||||
g_snprintf (buf, sizeof (buf), "%d %d\n255\n", xres, yres);
|
||||
else
|
||||
g_snprintf (buf, sizeof (buf), "%d %d\n%f\n", xres, yres,
|
||||
G_BYTE_ORDER == G_BIG_ENDIAN ? 1.0f : -1.0f);
|
||||
|
||||
if (! output_write (output, buf, strlen (buf), error))
|
||||
goto out;
|
||||
|
||||
if (!float_format)
|
||||
{
|
||||
g_object_unref (output);
|
||||
g_object_unref (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
guchar *data;
|
||||
guchar *d;
|
||||
gchar *rowbuf = NULL;
|
||||
|
||||
/* allocate a buffer for retrieving information from the pixel region */
|
||||
data = g_new (guchar,
|
||||
gimp_tile_height () * xres *
|
||||
babl_format_get_bytes_per_pixel (format));
|
||||
/* allocate a buffer for retrieving information from the pixel region */
|
||||
data = g_new (guchar,
|
||||
gimp_tile_height () * xres *
|
||||
babl_format_get_bytes_per_pixel (format));
|
||||
|
||||
rowbuf = g_new (gchar, rowbufsize + 1);
|
||||
rowbuf = g_new (gchar, rowbufsize + 1);
|
||||
|
||||
rowinfo.output = output;
|
||||
rowinfo.rowbuf = rowbuf;
|
||||
rowinfo.xres = xres;
|
||||
rowinfo.np = np;
|
||||
rowinfo.output = output;
|
||||
rowinfo.rowbuf = rowbuf;
|
||||
rowinfo.xres = xres;
|
||||
rowinfo.np = np;
|
||||
|
||||
d = NULL; /* only to please the compiler */
|
||||
d = NULL; /* only to please the compiler */
|
||||
|
||||
/* Write the body out */
|
||||
for (ypos = 0; ypos < yres; ypos++)
|
||||
{
|
||||
if ((ypos % gimp_tile_height ()) == 0)
|
||||
/* Write the body out */
|
||||
for (ypos = 0; ypos < yres; ypos++)
|
||||
{
|
||||
yend = ypos + gimp_tile_height ();
|
||||
yend = MIN (yend, yres);
|
||||
if ((ypos % gimp_tile_height ()) == 0)
|
||||
{
|
||||
yend = ypos + gimp_tile_height ();
|
||||
yend = MIN (yend, yres);
|
||||
|
||||
gegl_buffer_get (buffer,
|
||||
GEGL_RECTANGLE (0, ypos, xres, yend - ypos), 1.0,
|
||||
format, data,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
|
||||
d = data;
|
||||
}
|
||||
|
||||
if (! saverow (&rowinfo, d, error))
|
||||
{
|
||||
g_free (rowbuf);
|
||||
g_free (data);
|
||||
goto out;
|
||||
}
|
||||
|
||||
d += xres * (np ? np : 1);
|
||||
|
||||
if (ypos % 32 == 0)
|
||||
gimp_progress_update ((double) ypos / (double) yres);
|
||||
}
|
||||
|
||||
g_free (rowbuf);
|
||||
g_free (data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* allocate a buffer for retrieving information from the pixel
|
||||
region */
|
||||
gfloat *data = g_new (gfloat, xres * np);
|
||||
|
||||
rowinfo.output = output;
|
||||
rowinfo.rowbuf = NULL;
|
||||
rowinfo.xres = xres;
|
||||
rowinfo.np = np;
|
||||
|
||||
/* Write the body out in reverse row order */
|
||||
for (ypos = yres - 1; ypos >= 0; ypos--)
|
||||
{
|
||||
gegl_buffer_get (buffer,
|
||||
GEGL_RECTANGLE (0, ypos, xres, yend - ypos), 1.0,
|
||||
GEGL_RECTANGLE (0, ypos, xres, 1), 1.0,
|
||||
format, data,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
|
||||
d = data;
|
||||
if (! pnmsaverow_float (&rowinfo, data, error))
|
||||
{
|
||||
g_free (data);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ypos % 32 == 0)
|
||||
gimp_progress_update ((double) (yres - ypos) / (double) yres);
|
||||
}
|
||||
|
||||
if (! saverow (&rowinfo, d, error))
|
||||
{
|
||||
g_free (rowbuf);
|
||||
g_free (data);
|
||||
g_object_unref (output);
|
||||
g_object_unref (buffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
d += xres * (np ? np : 1);
|
||||
|
||||
if (ypos % 32 == 0)
|
||||
gimp_progress_update ((double) ypos / (double) yres);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
g_free (rowbuf);
|
||||
g_free (data);
|
||||
|
||||
g_object_unref (buffer);
|
||||
g_object_unref (output);
|
||||
|
||||
gimp_progress_update (1.0);
|
||||
status = TRUE;
|
||||
|
||||
return TRUE;
|
||||
out:
|
||||
if (comment)
|
||||
g_free (comment);
|
||||
if (buffer)
|
||||
g_object_unref (buffer);
|
||||
if (output)
|
||||
g_object_unref (output);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
Loading…
Reference in New Issue