# HG changeset patch # User address@hidden # 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. + address@hidden(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 +## +## 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 +## . + +## -*- texinfo -*- +## @deftypefn {Function File} address@hidden =} imfinfo (@var{filename}) +## @deftypefnx{Function File} address@hidden =} 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 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\ address@hidden {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\ address@hidden, imread}\n\ address@hidden 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++ ***