[Changeset] imfinfo

Søren Hauberg soren at hauberg.org
Wed Sep 24 13:51:43 CDT 2008


Hi,
  The attached changeset implement the 'imfinfo' function for reading
header information from image files. I'm not sure if this function is
part of core Matlab or the Image Processing Toolbox. But it was fairly
easy to add to core Octave, so that's what I'm proposing.

Søren
-------------- next part --------------
# HG changeset patch
# User sh at sh-laptop
# Date 1222281944 -7200
# Node ID 5c269b623ff8a4e39dca7f004cddd283b94c5629
# Parent  31d7885d98690ca9823082227870063bfb43514c
Add the 'imfinfo' function for reading image file information.

diff --git a/doc/interpreter/image.txi b/doc/interpreter/image.txi
--- a/doc/interpreter/image.txi
+++ b/doc/interpreter/image.txi
@@ -63,6 +63,13 @@
 @DOCSTRING(saveimage)
 
 @DOCSTRING(IMAGE_PATH)
+
+It is possible to get information about an image file on disk, without actually
+reading in into Octave. This is done using the @code{imfinfo} function which
+provides read access to many of the parameters stored in the header of the image
+file.
+
+ at DOCSTRING(imfinfo)
 
 @node Displaying Images
 @section Displaying Images
diff --git a/scripts/image/Makefile.in b/scripts/image/Makefile.in
--- a/scripts/image/Makefile.in
+++ b/scripts/image/Makefile.in
@@ -35,9 +35,10 @@
 
 SOURCES = __img__.m __img_via_file__.m autumn.m bone.m brighten.m colormap.m \
   contrast.m cool.m copper.m flag.m gmap40.m gray.m gray2ind.m hot.m hsv.m \
-  hsv2rgb.m image.m image_viewer.m imagesc.m imread.m imshow.m imwrite.m \
-  ind2gray.m ind2rgb.m jet.m ntsc2rgb.m ocean.m pink.m prism.m rainbow.m \
-  rgb2hsv.m rgb2ind.m rgb2ntsc.m saveimage.m spring.m summer.m white.m winter.m
+  hsv2rgb.m image.m image_viewer.m imagesc.m imfinfo.m imread.m imshow.m \
+  imwrite.m ind2gray.m ind2rgb.m jet.m ntsc2rgb.m ocean.m pink.m prism.m \
+  rainbow.m rgb2hsv.m rgb2ind.m rgb2ntsc.m saveimage.m spring.m summer.m \
+  white.m winter.m
 
 IMAGES = default.img
 
diff --git a/scripts/image/imfinfo.m b/scripts/image/imfinfo.m
new file mode 100644
--- /dev/null
+++ b/scripts/image/imfinfo.m
@@ -0,0 +1,127 @@
+## Copyright (C) 2008 Soren Hauberg <hauberg at gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave 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
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{info} =} imfinfo (@var{filename})
+## @deftypefnx{Function File} {@var{info} =} imfinfo (@var{url})
+## Read image information from a file.
+##
+## @code{imfinfo} returns a structure containing information about the image
+## stored in the file @var{filename}. The output structure contains the following
+## fields.
+##
+## @table @samp
+## @item Filename
+## The full name of the image file.
+## @item FileSize
+## Number of bytes of the image on disk
+## @item FileModDate
+## Date of last modification to the file.
+## @item Height
+## Image height in pixels.
+## @item Width
+## Image Width in pixels.
+## @item BitDepth
+## Number of bits per channel per pixel.
+## @item Format
+## Image format (e.g. @code{"jpeg"}).
+## @item LongFormat
+## Long form image format description.
+## @item XResolution
+## X resolution of the image.
+## @item YResolution
+## Y resolution of the image.
+## @item TotalColors
+## Number of unique colors in the image.
+## @item TileName
+## Tile name.
+## @item AnimationDelay
+## Time in 1/100ths of a second (0 to 65535) which must expire before displaying
+## the next image in an animated sequence.
+## @item AnimationIterations
+## Number of iterations to loop an animation (e.g. Netscape loop extension) for.
+## @item ByteOrder
+## Endian option for formats that support it. Is either @code{"little-endian"},
+## @code{"big-endian"}, or @code{"undefined"}.
+## @item Gamma
+## Gamma level of the image. The same color image displayed on two different
+## workstations  may  look  different due to differences in the display monitor.
+## @item Matte
+## @code{true} if the image has transparency.
+## @item ModulusDepth
+## Image modulus depth (minimum number of bits required to support red/green/blue
+## components without loss of accuracy).
+## @item Quality
+## JPEG/MIFF/PNG compression level.
+## @item QuantizeColors
+## Preferred number of colors in the image.
+## @item ResolutionUnits
+## Units of image resolution. Is either @code{"pixels per inch"},
+## @code{"pixels per centimeter"}, or @code{"undefined"}.
+## @item ColorType
+## Image type. Is either @code{"grayscale"}, @code{"indexed"}, @code{"truecolor"},
+## or @code{"undefined"}.
+## @item View
+## FlashPix viewing parameters.
+## @end table
+##
+## @seealso{imread, imwrite}
+## @end deftypefn
+
+function info = imfinfo (filename)
+
+  if (nargin < 1)
+    print_usage ();
+  endif
+
+  if (!ischar (filename))
+    error ("imfinfo: filename must be a string")
+  endif
+
+  filename = tilde_expand (filename);
+
+  fn = file_in_path (IMAGE_PATH, filename);
+  if (isempty (fn))
+    ## Couldn't find file. See if it's an URL.
+    [contents, isurl] = urlread (filename);
+    if (isurl)
+      ## The file contents has been downloaded. Now we write it to a temproray file.
+      ## XXX: Isn't there an easier way of doing this?
+      ## XXX: Does this approach have endian-issues?
+      [fid, tmpname, msg] = mkstemp ("octave_imfinfo_XXXXXX", true);
+      if (fid < 0)
+        error ("imfinfo: couldn't create temporary file for storing %s", filename);
+      endif
+      fwrite (fid, contents);
+      fclose (fid);
+      fn = tmpname;
+    else
+      error ("imfinfo: cannot find %s", filename);
+    endif
+  endif
+
+  [statinfo, err, msg] = stat (fn);
+  if (err != 0)
+    error ("imfinfo: error reading '%s': %s", fn, msg);
+  endif
+
+  FileModDate = datestr (statinfo.mtime); # XXX: is this the right way to get the date?
+  
+  info = __magick_finfo__ (filename);
+  info.FileModDate = FileModDate;
+endfunction
diff --git a/src/DLD-FUNCTIONS/__magick_read__.cc b/src/DLD-FUNCTIONS/__magick_read__.cc
--- a/src/DLD-FUNCTIONS/__magick_read__.cc
+++ b/src/DLD-FUNCTIONS/__magick_read__.cc
@@ -799,6 +799,147 @@
 return retval;
 }
 
+template<class T> inline
+octave_value magick_to_octave_value (const T magick)
+{
+  return octave_value (magick);
+}
+
+inline
+octave_value magick_to_octave_value (const Magick::EndianType magick)
+{
+  switch (magick)
+    {
+      case Magick::LSBEndian:
+        return octave_value ("little-endian");
+      case Magick::MSBEndian:
+        return octave_value ("big-endian");
+      default:
+        return octave_value ("undefined");
+    }
+}
+
+inline
+octave_value magick_to_octave_value (const Magick::ResolutionType magick)
+{
+  switch (magick)
+    {
+      case Magick::PixelsPerInchResolution:
+        return octave_value ("pixels per inch");
+      case Magick::PixelsPerCentimeterResolution:
+        return octave_value ("pixels per centimeter");
+      default:
+        return octave_value ("undefined");
+    }
+}
+
+inline
+octave_value magick_to_octave_value (const Magick::ImageType magick)
+{
+  switch (magick)
+    {
+      case Magick::BilevelType:
+      case Magick::GrayscaleType:
+      case Magick::GrayscaleMatteType:
+        return octave_value ("grayscale");
+      case Magick::PaletteType:
+      case Magick::PaletteMatteType:
+        return octave_value ("indexed");
+      case Magick::TrueColorType:
+      case Magick::TrueColorMatteType:
+      case Magick::ColorSeparationType:
+        return octave_value ("truecolor");
+      default:
+        return octave_value ("undefined");
+    }
+}
+
+DEFUN_DLD (__magick_finfo__, args, ,
+  "-*- texinfo -*-\n\
+ at deftypefn {Loadable File} {} __magick_finfo__(@var{fname})\n\
+Reads image information with GraphicsMagick++. In general you should not be using\n\
+this function. Instead you should use @code{imfinfo}.\n\
+ at seealso{imfinfo, imread}\n\
+ at end deftypefn")
+{
+  octave_value_list output;
+
+#ifdef HAVE_MAGICK
+
+  if (args.length () < 1 || ! args (0).is_string ())
+    {
+      print_usage ();
+      return output;
+    }
+  const std::string filename = args (0).string_value ();
+
+  try
+    {
+      // Read the file
+      Magick::Image im;
+      im.read (filename);
+      
+      // Read properties
+      Octave_map st;
+      st.assign ("Filename", filename);
+      
+      // We put this in a try-block because GraphicsMagick will throw exceptions
+      // if a parameter isn't present in the current image.
+      #define GET_PARAM(NAME, OUTNAME) \
+          try {\
+            st.assign (OUTNAME, magick_to_octave_value (im.NAME ()));\
+          } catch (Magick::Warning& w) {}
+
+        // Annoying CamelCase naming is for Matlab compatibility
+        GET_PARAM (fileSize, "FileSize")
+        GET_PARAM (rows, "Height")
+        GET_PARAM (columns, "Width")
+        GET_PARAM (depth, "BitDepth")
+        GET_PARAM (magick, "Format")
+        GET_PARAM (format, "LongFormat")
+        GET_PARAM (xResolution, "XResolution")
+        GET_PARAM (yResolution, "YResolution")
+        GET_PARAM (totalColors, "TotalColors")
+        GET_PARAM (tileName, "TileName")
+        GET_PARAM (animationDelay, "AnimationDelay")
+        GET_PARAM (animationIterations, "AnimationIterations")
+        GET_PARAM (endian, "ByteOrder")
+        GET_PARAM (gamma, "Gamma")
+        GET_PARAM (matte, "Matte")
+        GET_PARAM (modulusDepth, "ModulusDepth")
+        GET_PARAM (quality, "Quality")
+        GET_PARAM (quantizeColors, "QuantizeColors")
+        GET_PARAM (resolutionUnits, "ResolutionUnits")
+        GET_PARAM (type, "ColorType")
+        GET_PARAM (view, "View")
+        
+      #undef GET_PARAM
+      
+      output (0) = st;
+    }
+  catch (Magick::Warning& w)
+    {
+      warning ("Magick++ warning: %s", w.what ());
+    }
+  catch (Magick::ErrorCoder& e)
+    {
+      warning ("Magick++ coder error: %s", e.what ());
+    }
+  catch (Magick::Exception& e)
+    {
+      error ("Magick++ exception: %s", e.what ());
+      return output;
+    }
+
+#else
+
+  error ("imfinfo: not available in this version of Octave");
+
+#endif
+
+  return output;
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***


More information about the Octave-maintainers mailing list