Mercurial > hg > octave-nkf
view src/DLD-FUNCTIONS/__magick_read__.cc @ 13294:7dce7e110511
make concatenation of class objects work
* data.h: New file.
* src/Makefile.am (octinclude_HEADERS): Add it to the list.
* data.cc (attempt_type_conversion): New static function.
(do_class_concat): New function.
(do_cat): Use it if any elements of the list are objects.
Check whether any elements of the list are objects or cells.
Check whether all elements of the list are complex.
Check whether the first element of the list is a struct.
Maybe convert elements of the list to cells.
New tests for horzcat and vertcat.
* data.h (do_class_concat): Provide decl.
* ov-class.h (octave_class::octave_class): Allow optional parent
list.
* ov.h, ov.h (octave_value::octave_value (const Octave_map&,
const std::string&)): Likewise.
* pt-mat.cc (do_class_concat): New static function.
(tree_matrix::rvalue1): Use it to concatenate objects.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 07 Oct 2011 22:16:07 -0400 |
parents | 50db905c3cf1 |
children | 72c96de7a403 |
line wrap: on
line source
/* Copyright (C) 2002-2011 Andy Adler Copyright (C) 2008 Thomas L. Scofield Copyright (C) 2010 David Grundberg 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/>. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <cmath> #include "file-stat.h" #include "oct-env.h" #include "oct-time.h" #include "defun-dld.h" #include "error.h" #include "ov-struct.h" #ifdef HAVE_MAGICK #include <Magick++.h> #include <clocale> octave_value_list read_indexed_images (std::vector<Magick::Image>& imvec, const Array<int>& frameidx, bool wantalpha) { octave_value_list output; int rows = imvec[0].baseRows (); int columns = imvec[0].baseColumns (); int nframes = frameidx.length (); dim_vector idim = dim_vector (); idim.resize (4); idim(0) = rows; idim(1) = columns; idim(2) = 1; idim(3) = nframes; Array<int> idx (dim_vector (4, 1)); Magick::ImageType type = imvec[0].type (); unsigned int mapsize = imvec[0].colorMapSize (); unsigned int i = mapsize; unsigned int depth = 0; while (i >>= 1) depth++; i = 0; depth--; while (depth >>= 1) i++; depth = 1 << i; switch (depth) { case 1: case 2: case 4: case 8: { uint8NDArray im = uint8NDArray (idim); idx(2) = 0; for (int frame = 0; frame < nframes; frame++) { imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows); const Magick::IndexPacket *pix = imvec[frameidx(frame)].getConstIndexes (); i = 0; idx(3) = frame; for (int y = 0; y < rows; y++) { idx(0) = y; for (int x = 0; x < columns; x++) { idx(1) = x; im(idx) = static_cast<octave_uint8> (pix[i++]); } } } output(0) = octave_value (im); } break; case 16: { uint16NDArray im = uint16NDArray (idim); idx(2) = 0; for (int frame = 0; frame < nframes; frame++) { imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows); const Magick::IndexPacket *pix = imvec[frameidx(frame)].getConstIndexes (); i = 0; idx(3) = frame; for (int y = 0; y < rows; y++) { idx(0) = y; for (int x = 0; x < columns; x++) { idx(1) = x; im(idx) = static_cast<octave_uint16> (pix[i++]); } } } output(0) = octave_value (im); } break; default: error ("__magic_read__: index depths greater than 16-bit are not supported"); return octave_value_list (); } Matrix map = Matrix (mapsize, 3); Matrix alpha; switch (type) { case Magick::PaletteMatteType: #if 0 warning ("palettematte"); Matrix map (mapsize, 3); Matrix alpha (mapsize, 1); for (i = 0; i < mapsize; i++) { warning ("%d", i); Magick::ColorRGB c = imvec[0].colorMap (i); map(i,0) = c.red (); map(i,1) = c.green (); map(i,2) = c.blue (); alpha(i,1) = c.alpha (); } break; #endif case Magick::PaletteType: alpha = Matrix (0, 0); for (i = 0; i < mapsize; i++) { Magick::ColorRGB c = imvec[0].colorMap (i); map(i,0) = c.red (); map(i,1) = c.green (); map(i,2) = c.blue (); } break; default: error ("__magick_read__: unsupported indexed image type"); return octave_value_list (); } if (wantalpha) output(2) = alpha; output(1) = map; return output; } template <class T> octave_value_list read_images (const std::vector<Magick::Image>& imvec, const Array<int>& frameidx, unsigned int depth) { typedef typename T::element_type P; octave_value_list retval (3, Matrix ()); T im; int rows = imvec[0].baseRows (); int columns = imvec[0].baseColumns (); int nframes = frameidx.length (); dim_vector idim = dim_vector (); idim.resize (4); idim(0) = rows; idim(1) = columns; idim(2) = 1; idim(3) = nframes; Magick::ImageType type = imvec[0].type (); const int divisor = (((1 << QuantumDepth) - 1) / ((1 << depth) - 1)); switch (type) { case Magick::BilevelType: case Magick::GrayscaleType: { im = T (idim); P *vec = im.fortran_vec (); for (int frame = 0; frame < nframes; frame++) { const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows); P *rbuf = vec; for (int y = 0; y < rows; y++) { for (int x = 0; x < columns; x++) { *rbuf = pix->red / divisor; pix++; rbuf += rows; } rbuf -= rows * columns - 1; } // Next frame. vec += rows * columns * idim(2); } } break; case Magick::GrayscaleMatteType: { idim(2) = 2; im = T (idim); P *vec = im.fortran_vec (); for (int frame = 0; frame < nframes; frame++) { const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows); P *rbuf = vec; P *obuf = vec + rows * columns; for (int y = 0; y < rows; y++) { for (int x = 0; x < columns; x++) { *rbuf = pix->red / divisor; *obuf = pix->opacity / divisor; pix++; rbuf += rows; obuf += rows; } rbuf -= rows * columns - 1; obuf -= rows * columns - 1; } // Next frame. vec += rows * columns * idim(2); } } break; case Magick::PaletteType: case Magick::TrueColorType: { idim(2) = 3; im = T (idim); P *vec = im.fortran_vec (); for (int frame = 0; frame < nframes; frame++) { const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows); P *rbuf = vec; P *gbuf = vec + rows * columns; P *bbuf = vec + rows * columns * 2; for (int y = 0; y < rows; y++) { for (int x = 0; x < columns; x++) { *rbuf = pix->red / divisor; *gbuf = pix->green / divisor; *bbuf = pix->blue / divisor; pix++; rbuf += rows; gbuf += rows; bbuf += rows; } rbuf -= rows * columns - 1; gbuf -= rows * columns - 1; bbuf -= rows * columns - 1; } // Next frame. vec += rows * columns * idim(2); } } break; case Magick::PaletteMatteType: case Magick::TrueColorMatteType: case Magick::ColorSeparationType: { idim(2) = 4; im = T (idim); P *vec = im.fortran_vec (); for (int frame = 0; frame < nframes; frame++) { const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows); P *rbuf = vec; P *gbuf = vec + rows * columns; P *bbuf = vec + rows * columns * 2; P *obuf = vec + rows * columns * 3; for (int y = 0; y < rows; y++) { for (int x = 0; x < columns; x++) { *rbuf = pix->red / divisor; *gbuf = pix->green / divisor; *bbuf = pix->blue / divisor; *obuf = pix->opacity / divisor; pix++; rbuf += rows; gbuf += rows; bbuf += rows; obuf += rows; } rbuf -= rows * columns - 1; gbuf -= rows * columns - 1; bbuf -= rows * columns - 1; obuf -= rows * columns - 1; } // Next frame. vec += rows * columns * idim(2); } } break; default: error ("__magick_read__: undefined ImageMagick image type"); return retval; } retval(0) = im; return retval; } #endif static void maybe_initialize_magick (void) { #ifdef HAVE_MAGICK static bool initialized = false; if (! initialized) { // Save the locale as GraphicsMagick might change this (depending on version) const char *static_locale = setlocale (LC_ALL, NULL); const std::string locale (static_locale); std::string program_name = octave_env::get_program_invocation_name (); Magick::InitializeMagick (program_name.c_str ()); // Restore locale from before GraphicsMagick initialisation setlocale (LC_ALL, locale.c_str ()); if (QuantumDepth < 32) warning ("your version of %s limits images to %d bits per pixel", MagickPackageName, QuantumDepth); initialized = true; } #endif } DEFUN_DLD (__magick_read__, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Function File} {@var{m} =} __magick_read__(@var{fname}, @var{index})\n\ @deftypefnx {Function File} {[@var{m}, @var{colormap}] =} __magick_read__(@var{fname}, @var{index})\n\ @deftypefnx {Function File} {[@var{m}, @var{colormap}, @var{alpha}] =} __magick_read__(@var{fname}, @var{index})\n\ Read images with ImageMagick++. In general you should not be using this\n\ function. Instead use @code{imread}.\n\ @seealso{imread}\n\ @end deftypefn") { octave_value_list output; #ifdef HAVE_MAGICK maybe_initialize_magick (); if (args.length () > 3 || args.length () < 1 || ! args(0).is_string () || nargout > 3) { print_usage (); return output; } Array<int> frameidx; bool all_frames = false; if (args.length () == 2 && args(1).is_real_type ()) frameidx = args(1).int_vector_value(); else if (args.length () == 3 && args(1).is_string () && args(1).string_value() == "frames") { if (args(2).is_string () && args(2).string_value() == "all") all_frames = true; else if (args(2).is_real_type ()) frameidx = args(2).int_vector_value(); } else { frameidx = Array<int> (dim_vector (1, 1)); frameidx(0) = 1; } std::vector<Magick::Image> imvec; try { // Read a file into vector of image objects Magick::readImages (&imvec, args(0).string_value ()); } 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; } int nframes = imvec.size (); if (all_frames) { frameidx = Array<int> (dim_vector (1, nframes)); for (int i = 0; i < frameidx.length (); i++) frameidx(i) = i; } else { for (int i = 0; i < frameidx.length (); i++) { frameidx(i) = frameidx(i) - 1; if (frameidx(i) >= nframes || frameidx(i) < 0) { error ("__magick_read__: invalid INDEX vector"); return output; } } } Magick::ClassType klass = imvec[0].classType (); if (klass == Magick::PseudoClass && nargout > 1) output = read_indexed_images (imvec, frameidx, (nargout == 3)); else { unsigned int depth = imvec[0].modulusDepth (); if (depth > 1) { --depth; int i = 1; while (depth >>= 1) i++; depth = 1 << i; } switch (depth) { case 1: output = read_images<boolNDArray> (imvec, frameidx, depth); break; case 2: case 4: case 8: output = read_images<uint8NDArray> (imvec, frameidx, depth) ; break; case 16: output = read_images<uint16NDArray> (imvec, frameidx, depth); break; case 32: case 64: default: error ("__magick_read__: image depths greater than 16-bit are not supported"); } } #else error ("imread: image reading capabilities were disabled when Octave was compiled"); #endif return output; } /* ## No test needed for internal helper function. %!assert (1) */ #ifdef HAVE_MAGICK static void jpg_settings (std::vector<Magick::Image>& imvec, const Octave_map& options, bool) { bool something_set = false; // Quality setting octave_value result; Octave_map::const_iterator p; bool found_it = false; for (p = options.begin (); p != options.end (); p++) { if (options.key (p) == "Quality") { found_it = true; result = options.contents (p).elem (0); break; } } if (found_it && (! result.is_empty ())) { something_set = true; if (result.is_real_type ()) { int qlev = result.int_value (); if (qlev < 0 || qlev > 100) warning ("warning: Quality setting invalid--use default of 75"); else { for (size_t fnum = 0; fnum < imvec.size (); fnum++) imvec[fnum].quality (static_cast<unsigned int>(qlev)); } } else warning ("warning: Quality setting invalid--use default of 75"); } // Other settings go here if (! something_set) warning ("__magick_write__ warning: all write parameters ignored"); } static void encode_bool_image (std::vector<Magick::Image>& imvec, const octave_value& img) { unsigned int nframes = 1; boolNDArray m = img.bool_array_value (); dim_vector dsizes = m.dims (); if (dsizes.length () == 4) nframes = dsizes(3); Array<octave_idx_type> idx (dim_vector (dsizes.length (), 1)); octave_idx_type rows = m.rows (); octave_idx_type columns = m.columns (); for (unsigned int ii = 0; ii < nframes; ii++) { Magick::Image im(Magick::Geometry (columns, rows), "black"); im.classType (Magick::DirectClass); im.depth (1); for (int y = 0; y < columns; y++) { idx(1) = y; for (int x = 0; x < rows; x++) { if (nframes > 1) { idx(2) = 0; idx(3) = ii; } idx(0) = x; if (m(idx)) im.pixelColor (y, x, "white"); } } im.quantizeColorSpace (Magick::GRAYColorspace); im.quantizeColors (2); im.quantize (); imvec.push_back (im); } } template <class T> static void encode_uint_image (std::vector<Magick::Image>& imvec, const octave_value& img, bool has_map) { unsigned int bitdepth = 0; T m; if (img.is_uint8_type ()) { bitdepth = 8; m = img.uint8_array_value (); } else if (img.is_uint16_type ()) { bitdepth = 16; m = img.uint16_array_value (); } else error ("__magick_write__: invalid image class"); dim_vector dsizes = m.dims (); unsigned int nframes = 1; if (dsizes.length () == 4) nframes = dsizes(3); bool is_color = ((dsizes.length () > 2) && (dsizes(2) > 2)); bool has_alpha = (dsizes.length () > 2 && (dsizes(2) == 2 || dsizes(2) == 4)); Array<octave_idx_type> idx (dim_vector (dsizes.length (), 1)); octave_idx_type rows = m.rows (); octave_idx_type columns = m.columns (); unsigned int div_factor = (1 << bitdepth) - 1; for (unsigned int ii = 0; ii < nframes; ii++) { Magick::Image im (Magick::Geometry (columns, rows), "black"); im.depth (bitdepth); if (has_map) im.classType (Magick::PseudoClass); else im.classType (Magick::DirectClass); if (is_color) { if (has_alpha) im.type (Magick::TrueColorMatteType); else im.type (Magick::TrueColorType); Magick::ColorRGB c; for (int y = 0; y < columns; y++) { idx(1) = y; for (int x = 0; x < rows; x++) { idx(0) = x; if (nframes > 1) idx(3) = ii; idx(2) = 0; c.red (static_cast<double>(m(idx)) / div_factor); idx(2) = 1; c.green (static_cast<double>(m(idx)) / div_factor); idx(2) = 2; c.blue (static_cast<double>(m(idx)) / div_factor); if (has_alpha) { idx(2) = 3; c.alpha (static_cast<double>(m(idx)) / div_factor); } im.pixelColor (y, x, c); } } } else { if (has_alpha) im.type (Magick::GrayscaleMatteType); else im.type (Magick::GrayscaleType); Magick::ColorGray c; for (int y = 0; y < columns; y++) { idx(1) = y; for (int x=0; x < rows; x++) { idx(0) = x; if (nframes > 1) { idx(2) = 0; idx(3) = ii; } if (has_alpha) { idx(2) = 1; c.alpha (static_cast<double>(m(idx)) / div_factor); idx(2) = 0; } c.shade (static_cast<double>(m(idx)) / div_factor); im.pixelColor (y, x, c); } } im.quantizeColorSpace (Magick::GRAYColorspace); im.quantizeColors (1 << bitdepth); im.quantize (); } imvec.push_back (im); } } static void encode_map (std::vector<Magick::Image>& imvec, const NDArray& cmap) { unsigned int mapsize = cmap.dim1 (); for (size_t fnum = 0; fnum < imvec.size (); fnum++) { imvec[fnum].colorMapSize (mapsize); imvec[fnum].type (Magick::PaletteType); } for (unsigned int ii = 0; ii < mapsize; ii++) { Magick::ColorRGB c (cmap(ii,0), cmap(ii,1), cmap(ii,2)); // FIXME -- is this case needed? if (cmap.dim2 () == 4) c.alpha (cmap(ii,3)); try { for_each (imvec.begin (), imvec.end (), Magick::colorMapImage (ii, c)); } 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 ()); } } } static void write_image (const std::string& filename, const std::string& fmt, const octave_value& img, const octave_value& map = octave_value (), const octave_value& params = octave_value ()) { std::vector<Magick::Image> imvec; bool has_map = map.is_defined (); if (has_map) { error ("__magick_write__: direct saving of indexed images not currently supported; use ind2rgb and save converted image"); return; } if (img.is_bool_type ()) encode_bool_image (imvec, img); else if (img.is_uint8_type ()) encode_uint_image<uint8NDArray> (imvec, img, has_map); else if (img.is_uint16_type ()) encode_uint_image<uint16NDArray> (imvec, img, has_map); else error ("__magick_write__: image type not supported"); if (! error_state && has_map) { NDArray cmap = map.array_value (); if (! error_state) encode_map (imvec, cmap); } if (! error_state && params.is_defined ()) { Octave_map options = params.map_value (); // Insert calls here to handle parameters for various image formats if (fmt == "jpg" || fmt == "jpeg") jpg_settings (imvec, options, has_map); else warning ("warning: your parameter(s) currently not supported"); } try { Magick::writeImages (imvec.begin (), imvec.end (), fmt + ":" + filename); } 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 ()); } } #endif DEFUN_DLD (__magick_write__, args, , "-*- texinfo -*-\n\ @deftypefn {Function File} {} __magick_write__(@var{fname}, @var{fmt}, @var{img})\n\ @deftypefnx {Function File} {} __magick_write__(@var{fname}, @var{fmt}, @var{img}, @var{map})\n\ Write images with ImageMagick++. In general you should not be using this\n\ function. Instead use @code{imwrite}.\n\ @seealso{imread}\n\ @end deftypefn") { octave_value_list retval; #ifdef HAVE_MAGICK maybe_initialize_magick (); int nargin = args.length (); if (nargin > 2) { std::string filename = args(0).string_value (); if (! error_state) { std::string fmt = args(1).string_value (); if (! error_state) { if (nargin > 4) write_image (filename, fmt, args(2), args(3), args(4)); else if (nargin > 3) if (args(3).is_real_type ()) write_image (filename, fmt, args(2), args(3)); else write_image (filename, fmt, args(2), octave_value(), args(3)); else write_image (filename, fmt, args(2)); } else error ("__magick_write__: FMT must be string"); } else error ("__magick_write__: FNAME must be a string"); } else print_usage (); #else error ("__magick_write__: not available in this version of Octave"); #endif return retval; } /* ## No test needed for internal helper function. %!assert (1) */ #ifdef HAVE_MAGICK template<class T> static octave_value magick_to_octave_value (const T magick) { return octave_value (magick); } static 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"); } } static 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"); } } static 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"); } } // 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 \ { \ info.contents (OUTNAME)(frame,0) = magick_to_octave_value (im.NAME ()); \ } \ catch (Magick::Warning& w) \ { \ } #endif DEFUN_DLD (__magick_finfo__, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} __magick_finfo__(@var{fname})\n\ Read image information with GraphicsMagick++. In general you should\n\ not be using this function. Instead use @code{imfinfo}.\n\ @seealso{imfinfo, imread}\n\ @end deftypefn") { octave_value retval; #ifdef HAVE_MAGICK maybe_initialize_magick (); if (args.length () < 1 || ! args (0).is_string ()) { print_usage (); return retval; } const std::string filename = args (0).string_value (); try { // Read the file. std::vector<Magick::Image> imvec; Magick::readImages (&imvec, args(0).string_value ()); int nframes = imvec.size (); // Create the right size for the output. static const char *fields[] = { "Filename", "FileModDate", "FileSize", "Height", "Width", "BitDepth", "Format", "LongFormat", "XResolution", "YResolution", "TotalColors", "TileName", "AnimationDelay", "AnimationIterations", "ByteOrder", "Gamma", "Matte", "ModulusDepth", "Quality", "QuantizeColors", "ResolutionUnits", "ColorType", "View", 0 }; Octave_map info (string_vector (fields), dim_vector (nframes, 1)); file_stat fs (filename); std::string filetime; if (fs) { octave_localtime mtime = fs.mtime (); filetime = mtime.strftime ("%e-%b-%Y %H:%M:%S"); } else { std::string msg = fs.error (); error ("imfinfo: error reading `%s': %s", filename.c_str (), msg.c_str ()); return retval; } // For each frame in the image (some images contain multiple // layers, each to be treated like a separate image). for (int frame = 0; frame < nframes; frame++) { Magick::Image im = imvec[frame]; // Add file name and timestamp. info.contents ("Filename")(frame,0) = filename; info.contents ("FileModDate")(frame,0) = filetime; // 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") } retval = octave_value (info); } 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 retval; } #else error ("imfinfo: not available in this version of Octave"); #endif return retval; } /* ## No test needed for internal helper function. %!assert (1) */ #undef GET_PARAM // Determine the file formats supported by GraphicsMagick. This is // called once at the beginning of imread or imwrite to determine // exactly which file formats are supported, so error messages can be // displayed properly. DEFUN_DLD (__magick_format_list__, args, , "-*- texinfo -*-\n\ @deftypefn {Function File} {} __magick_format_list__ (@var{formats})\n\ Undocumented internal function.\n\ @end deftypefn") { octave_value retval; #ifdef HAVE_MAGICK maybe_initialize_magick (); std::list<std::string> accepted_formats; if (args.length () == 1) { Cell c = args (0).cell_value (); if (! error_state) { for (octave_idx_type i = 0; i < c.nelem (); i++) { try { std::string fmt = c.elem (i).string_value (); Magick::CoderInfo info(fmt); if (info.isReadable () && info.isWritable ()) accepted_formats.push_back (fmt); } catch (Magick::Exception& e) { // Do nothing: exception here are simply missing formats. } } } else error ("__magick_format_list__: expecting a cell array of image format names"); } else print_usage (); retval = Cell (accepted_formats); #else error ("__magick_format_list__: not available in this version of Octave"); #endif return retval; } /* ## No test needed for internal helper function. %!assert (1) */