Re: [Gegl-developer] npy saving operation



Using sprintf like that opens you up to to buffer overflows. Could you
switch that part of the code to use fprintf directly on the file
pointer? It would also simplify the code.

Otherwise, I have nothing against committing this.

On Tue, May 28, 2013 at 5:27 PM, Dov Grobgeld <dov grobgeld gmail com> wrote:
I finished a saver operation for floating point npy images. It may e.g. be
used to debug floating point operations (e.g. gaussian-blur) with numerical
python. The resulting image may be read into numpy as follows:

   import numpy
   img = numpy.load('image.npy')

It may also be viewed in my image viewer giv (though it currently does not
support color npy images).

Is it ok to commit it?

Follows the code.

Regards,
Dov

/* This file is an image processing operation for GEGL
 *
 * GEGL is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * GEGL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright Dov Grobgeld 2013 <dov.grobgeld (a) gmail.com>
 *
 * This operation saves a buffer in the npy file format. It may be
 * read into python as follows:
 *
 *   import numpy
 *   img = numpy.load('image.npy')
 */

#include "config.h"
#include <glib/gi18n-lib.h>


#ifdef GEGL_CHANT_PROPERTIES

gegl_chant_string  (path, _("File"), "",
                    _("Target path and filename, use '-' for stdout."))

#else

#define GEGL_CHANT_TYPE_SINK
#define GEGL_CHANT_C_FILE       "npy-save.c"

#include "gegl-chant.h"
#include <stdio.h>

static int npywrite(FILE *fp, guchar *data, int width, int height, int
num_channels)
{
    char header[100];
    unsigned short header_len;

    // Write header and version number to file
    fwrite("\223NUMPY"
           "\001\000"
           , 1, 8, fp);
    if (num_channels == 3)
      sprintf(header,
              "{'descr': '<f4', 'fortran_order': False, 'shape': (%d, %d,
3), } \n",
              height, width);
    else
      sprintf(header,
              "{'descr': '<f4', 'fortran_order': False, 'shape': (%d, %d), }
\n",
              height, width);

    header_len = strlen(header);
    fwrite(&header_len, 2, 1, fp);
    fwrite(header, header_len, 1, fp);

    fwrite(data, width*height*num_channels, sizeof(float), fp);

    return 0;
}

static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         const GeglRectangle *rect,
         gint                 level)
{
  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);

  FILE     *fp;
  guchar   *data;
  gsize     bpc;
  gsize     numsamples;
  gsize     numchannels;
  gboolean  ret = FALSE;
  const Babl *output_format;
  const Babl *input_format = gegl_buffer_get_format(input);

  // Get the current format and use it to decide whether to save
  // the output in color or gray level formats.
  bpc = sizeof(gfloat);
  if (babl_format_get_n_components(input_format) >= 3)
    {
      numchannels = 3;
      output_format = babl_format("RGB float");
    }
  else
    {
      numchannels = 1;
      output_format = babl_format ("Y float");
    }

  numsamples = rect->width * rect->height * numchannels;

  data = g_malloc (numsamples * bpc);
  gegl_buffer_get (input, rect, 1.0, output_format, data,
                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

  fp = (!strcmp (o->path, "-") ? stdout : fopen(o->path, "wb") );

  npywrite(fp, data, rect->width, rect->height, numchannels);

  g_free (data);

  return ret;
}

static void
gegl_chant_class_init (GeglChantClass *klass)
{
  GeglOperationClass     *operation_class;
  GeglOperationSinkClass *sink_class;

  operation_class = GEGL_OPERATION_CLASS (klass);
  sink_class      = GEGL_OPERATION_SINK_CLASS (klass);

  sink_class->process = process;
  sink_class->needs_full = TRUE;

  gegl_operation_class_set_keys (operation_class,
    "name"        , "gegl:npy-save",
    "categories"  , "output",
    "description" ,
        _("NPY image saver (Numerical python file saver.)"),
        NULL);

  gegl_extension_handler_register_saver (".npy", "gegl:npy-save");
}

#endif


_______________________________________________
gegl-developer-list mailing list
gegl-developer-list gnome org
https://mail.gnome.org/mailman/listinfo/gegl-developer-list



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]