[gimp] plug-ins: add PFM reading support to file-pnm
- From: Tobias Ellinghaus <et src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: add PFM reading support to file-pnm
- Date: Fri, 16 Jan 2015 14:38:45 +0000 (UTC)
commit 1c283737e55021b3a10a9662b62f2ea25ae6ce0f
Author: Tobias Ellinghaus <me houz org>
Date: Fri Jan 16 15:37:24 2015 +0100
plug-ins: add PFM reading support to file-pnm
Thanks muks for cleaning this up
plug-ins/common/file-pnm.c | 125 ++++++++++++++++++++++++++++++++++++++------
1 files changed, 109 insertions(+), 16 deletions(-)
---
diff --git a/plug-ins/common/file-pnm.c b/plug-ins/common/file-pnm.c
index c625ab3..a3fcbe1 100644
--- a/plug-ins/common/file-pnm.c
+++ b/plug-ins/common/file-pnm.c
@@ -23,12 +23,15 @@
* does not contain any code from the netpbm or pbmplus distributions.
*
* 2006: pbm saving written by Martin K Collins (martin mkcollins org)
+ * 2015: pfm reading written by Tobias Ellinghaus (me houz org)
*/
#include "config.h"
#include <setjmp.h>
#include <stdlib.h>
+#include <math.h>
+#include <errno.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
@@ -73,8 +76,10 @@ struct _PNMScanner
struct _PNMInfo
{
gint xres, yres; /* The size of the image */
+ gboolean float_format; /* Whether it is a floating point format */
gint maxval; /* For ascii image files, the max value
* which we need to normalize to */
+ gfloat scale_factor; /* PFM files have a scale factor */
gint np; /* Number of image planes (0 for pbm) */
gboolean asciibody; /* 1 if ascii body, 0 if raw body */
jmp_buf jmpbuf; /* Where to jump to on an error loading */
@@ -137,6 +142,9 @@ static void pnm_load_raw (PNMScanner *scan,
static void pnm_load_rawpbm (PNMScanner *scan,
PNMInfo *info,
GeglBuffer *buffer);
+static void pnm_load_rawpfm (PNMScanner *scan,
+ PNMInfo *info,
+ GeglBuffer *buffer);
static gboolean pnmsaverow_ascii (PNMRowInfo *ri,
const guchar *data,
@@ -188,12 +196,14 @@ static const struct
PNMLoaderFunc loader;
} pnm_types[] =
{
- { '1', 0, 1, 1, pnm_load_ascii }, /* ASCII PBM */
- { '2', 1, 1, 255, pnm_load_ascii }, /* ASCII PGM */
- { '3', 3, 1, 255, pnm_load_ascii }, /* ASCII PPM */
- { '4', 0, 0, 1, pnm_load_rawpbm }, /* RAW PBM */
- { '5', 1, 0, 255, pnm_load_raw }, /* RAW PGM */
- { '6', 3, 0, 255, pnm_load_raw }, /* RAW PPM */
+ { '1', 0, 1, 1, pnm_load_ascii }, /* ASCII PBM */
+ { '2', 1, 1, 255, pnm_load_ascii }, /* ASCII PGM */
+ { '3', 3, 1, 255, pnm_load_ascii }, /* ASCII PPM */
+ { '4', 0, 0, 1, pnm_load_rawpbm }, /* RAW PBM */
+ { '5', 1, 0, 255, pnm_load_raw }, /* RAW PGM */
+ { '6', 3, 0, 255, pnm_load_raw }, /* RAW PPM */
+ { 'F', 3, 0, 0, pnm_load_rawpfm }, /* RAW PFM (color) */
+ { 'f', 1, 0, 0, pnm_load_rawpfm }, /* RAW PFM (grayscale) */
{ 0 , 0, 0, 0, NULL}
};
@@ -253,10 +263,11 @@ query (void)
gimp_register_file_handler_mime (LOAD_PROC, "image/x-portable-anymap");
gimp_register_file_handler_uri (LOAD_PROC);
gimp_register_magic_load_handler (LOAD_PROC,
- "pnm,ppm,pgm,pbm",
+ "pnm,ppm,pgm,pbm,pfm",
"",
- "0,string,P1,0,string,P2,0,string,P3,0,"
- "string,P4,0,string,P5,0,string,P6");
+ "0,string,P1,0,string,P2,0,string,P3,"
+ "0,string,P4,0,string,P5,0,string,P6,"
+ "0,string,PF,0,string,Pf");
gimp_install_procedure (PNM_SAVE_PROC,
"Saves files in the PNM file format",
@@ -535,10 +546,11 @@ load_image (GFile *file,
for (ctr = 0; pnm_types[ctr].name; ctr++)
if (buf[1] == pnm_types[ctr].name)
{
- pnminfo->np = pnm_types[ctr].np;
- pnminfo->asciibody = pnm_types[ctr].asciibody;
- pnminfo->maxval = pnm_types[ctr].maxval;
- pnminfo->loader = pnm_types[ctr].loader;
+ pnminfo->np = pnm_types[ctr].np;
+ pnminfo->asciibody = pnm_types[ctr].asciibody;
+ pnminfo->float_format = g_ascii_tolower (pnm_types[ctr].name) == 'f';
+ pnminfo->maxval = pnm_types[ctr].maxval;
+ pnminfo->loader = pnm_types[ctr].loader;
}
if (!pnminfo->loader)
@@ -565,7 +577,21 @@ load_image (GFile *file,
CHECK_FOR_ERROR (pnminfo->yres > GIMP_MAX_IMAGE_SIZE, pnminfo->jmpbuf,
_("Image height is larger than GIMP can handle."));
- if (pnminfo->np != 0) /* pbm's don't have a maxval field */
+ if (pnminfo->float_format)
+ {
+ gchar *endptr = NULL;
+
+ pnmscanner_gettoken (scan, buf, BUFLEN);
+ CHECK_FOR_ERROR (pnmscanner_eof (scan), pnminfo->jmpbuf,
+ _("Premature end of file."));
+
+ pnminfo->scale_factor = g_ascii_strtod (buf, &endptr);
+ CHECK_FOR_ERROR (endptr == NULL || *endptr != 0 || errno == ERANGE,
+ pnminfo->jmpbuf, _("Bogus scale factor."));
+ CHECK_FOR_ERROR (!isnormal (pnminfo->scale_factor),
+ pnminfo->jmpbuf, _("Unsupported scale factor."));
+ }
+ else if (pnminfo->np != 0) /* pbm's don't have a maxval field */
{
pnmscanner_gettoken (scan, buf, BUFLEN);
CHECK_FOR_ERROR (pnmscanner_eof (scan), pnminfo->jmpbuf,
@@ -578,8 +604,10 @@ load_image (GFile *file,
/* Create a new image of the proper size and associate the filename with it.
*/
- image_ID = gimp_image_new (pnminfo->xres, pnminfo->yres,
- (pnminfo->np >= 3) ? GIMP_RGB : GIMP_GRAY);
+ image_ID = gimp_image_new_with_precision (pnminfo->xres, pnminfo->yres,
+ (pnminfo->np >= 3) ? GIMP_RGB : GIMP_GRAY,
+ pnminfo->float_format ? GIMP_PRECISION_FLOAT_LINEAR
+ : GIMP_PRECISION_U8_GAMMA);
gimp_image_set_filename (image_ID, g_file_get_uri (file));
layer_ID = gimp_layer_new (image_ID, _("Background"),
@@ -864,6 +892,71 @@ pnm_load_rawpbm (PNMScanner *scan,
gimp_progress_update (1.0);
}
+static void
+pnm_load_rawpfm (PNMScanner *scan,
+ PNMInfo *info,
+ GeglBuffer *buffer)
+{
+ GInputStream *input;
+ gfloat *data;
+ gint x, y;
+ gboolean swap_byte_order;
+
+ swap_byte_order =
+ (info->scale_factor >= 0.0) ^ (G_BYTE_ORDER == G_BIG_ENDIAN);
+
+ data = g_new (gfloat, info->xres * info->np);
+
+ input = pnmscanner_input (scan);
+
+ for (y = info->yres - 1; y >= 0; y--)
+ {
+ gsize bytes_read;
+ GError *error = NULL;
+
+ if (g_input_stream_read_all (input, data,
+ info->xres * info->np * sizeof (float),
+ &bytes_read, NULL, &error))
+ {
+ CHECK_FOR_ERROR
+ (info->xres * info->np * sizeof (float) != bytes_read,
+ info->jmpbuf, _("Premature end of file."));
+ }
+ else
+ {
+ CHECK_FOR_ERROR (FALSE, info->jmpbuf, "%s", error->message);
+ }
+
+ for (x = 0; x < info->xres * info->np; x++)
+ {
+ if (swap_byte_order)
+ {
+ union { gfloat f; guint32 i; } v;
+
+ v.f = data[x];
+ v.i = GUINT32_SWAP_LE_BE (v.i);
+ data[x] = v.f;
+ }
+
+ /* let's see if this is what people want, the PFM specs are a little vague
+ * about what the scale factor should be used for */
+ data[x] *= fabsf (info->scale_factor);
+ data[x] = fmaxf(0.0f, fminf(FLT_MAX, data[x]));
+ }
+
+ gegl_buffer_set (buffer,
+ GEGL_RECTANGLE (0, y, info->xres, 1), 0,
+ NULL, data, GEGL_AUTO_ROWSTRIDE);
+
+ if (y % 32 == 0)
+ gimp_progress_update ((double) y / (double) info->yres);
+ }
+
+ g_free (data);
+
+ gimp_progress_update (1.0);
+}
+
static gboolean
output_write (GOutputStream *output,
gconstpointer buffer,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]