[gimp] file-pnm: Add support for saving PFM (portable floatmap) files in color and gray
- From: Mukund Sivaraman <muks src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] file-pnm: Add support for saving PFM (portable floatmap) files in color and gray
- Date: Tue, 20 Jan 2015 16:14:49 +0000 (UTC)
commit 51e4491fbf5291d0539b37c8e4f6c3c5c16071b8
Author: Mukund Sivaraman <muks banu com>
Date: Tue Jan 20 20:14:07 2015 +0530
file-pnm: Add support for saving PFM (portable floatmap) files in color and gray
plug-ins/common/file-pnm.c | 325 ++++++++++++++++++++++++++++++--------------
1 files changed, 223 insertions(+), 102 deletions(-)
---
diff --git a/plug-ins/common/file-pnm.c b/plug-ins/common/file-pnm.c
index 4be4737..f895a1e 100644
--- a/plug-ins/common/file-pnm.c
+++ b/plug-ins/common/file-pnm.c
@@ -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);
+ switch (run_mode)
+ {
+ 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;
+ /* 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;
+ 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);
- }
- break;
-
- case GIMP_RUN_WITH_LAST_VALS:
- /* Possibly retrieve data */
- gimp_get_data (name, &psvals);
- break;
+ case GIMP_RUN_NONINTERACTIVE:
+ /* Make sure all the arguments are there! */
+ if (nparams != 5)
+ {
+ status = GIMP_PDB_CALLING_ERROR;
+ }
+ break;
- default:
- 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,18 +1305,35 @@ save_image (GFile *file,
default:
g_warning ("PNM: Unknown drawable_type\n");
- return FALSE;
+ goto out;
}
}
}
-
- if (! output_write (output, header_string, strlen (header_string), error))
+ else
{
- g_object_unref (output);
- g_object_unref (buffer);
- return FALSE;
+ 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))
+ goto out;
+
rowinfo.zero_is_black = FALSE;
if (drawable_type == GIMP_INDEXED_IMAGE)
@@ -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 (! saverow (&rowinfo, d, error))
- {
- g_free (rowbuf);
- g_free (data);
- g_object_unref (output);
- g_object_unref (buffer);
- return FALSE;
+ if (ypos % 32 == 0)
+ gimp_progress_update ((double) (yres - ypos) / (double) yres);
}
- 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;
+
+ out:
+ if (comment)
+ g_free (comment);
+ if (buffer)
+ g_object_unref (buffer);
+ if (output)
+ g_object_unref (output);
- return TRUE;
+ return status;
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]