00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029 #include <cmath>
00030
00031 #include "file-stat.h"
00032 #include "oct-env.h"
00033 #include "oct-time.h"
00034
00035 #include "defun-dld.h"
00036 #include "error.h"
00037 #include "ov-struct.h"
00038
00039 #ifdef HAVE_MAGICK
00040
00041 #include <Magick++.h>
00042 #include <clocale>
00043
00044 octave_value_list
00045 read_indexed_images (std::vector<Magick::Image>& imvec,
00046 const Array<int>& frameidx, bool wantalpha)
00047 {
00048 octave_value_list output;
00049
00050 int rows = imvec[0].baseRows ();
00051 int columns = imvec[0].baseColumns ();
00052 int nframes = frameidx.length ();
00053
00054 dim_vector idim = dim_vector ();
00055 idim.resize (4);
00056 idim(0) = rows;
00057 idim(1) = columns;
00058 idim(2) = 1;
00059 idim(3) = nframes;
00060
00061 Array<int> idx (dim_vector (4, 1));
00062
00063 Magick::ImageType type = imvec[0].type ();
00064
00065 unsigned int mapsize = imvec[0].colorMapSize ();
00066 unsigned int i = mapsize;
00067 unsigned int depth = 0;
00068 while (i >>= 1)
00069 depth++;
00070 i = 0;
00071 depth--;
00072 while (depth >>= 1)
00073 i++;
00074 depth = 1 << i;
00075
00076 switch (depth)
00077 {
00078 case 1:
00079 case 2:
00080 case 4:
00081 case 8:
00082 {
00083 uint8NDArray im = uint8NDArray (idim);
00084
00085 idx(2) = 0;
00086 for (int frame = 0; frame < nframes; frame++)
00087 {
00088 imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
00089
00090 const Magick::IndexPacket *pix
00091 = imvec[frameidx(frame)].getConstIndexes ();
00092
00093 i = 0;
00094 idx(3) = frame;
00095
00096 for (int y = 0; y < rows; y++)
00097 {
00098 idx(0) = y;
00099 for (int x = 0; x < columns; x++)
00100 {
00101 idx(1) = x;
00102 im(idx) = static_cast<octave_uint8> (pix[i++]);
00103 }
00104 }
00105 }
00106
00107 output(0) = octave_value (im);
00108 }
00109 break;
00110
00111 case 16:
00112 {
00113 uint16NDArray im = uint16NDArray (idim);
00114
00115 idx(2) = 0;
00116 for (int frame = 0; frame < nframes; frame++)
00117 {
00118 imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
00119
00120 const Magick::IndexPacket *pix
00121 = imvec[frameidx(frame)].getConstIndexes ();
00122
00123 i = 0;
00124 idx(3) = frame;
00125
00126 for (int y = 0; y < rows; y++)
00127 {
00128 idx(0) = y;
00129 for (int x = 0; x < columns; x++)
00130 {
00131 idx(1) = x;
00132 im(idx) = static_cast<octave_uint16> (pix[i++]);
00133 }
00134 }
00135 }
00136
00137 output(0) = octave_value (im);
00138 }
00139 break;
00140
00141 default:
00142 error ("__magic_read__: index depths greater than 16-bit are not supported");
00143 return octave_value_list ();
00144 }
00145
00146 Matrix map = Matrix (mapsize, 3);
00147 Matrix alpha;
00148
00149 switch (type)
00150 {
00151 case Magick::PaletteMatteType:
00152 #if 0
00153 warning ("palettematte");
00154 Matrix map (mapsize, 3);
00155 Matrix alpha (mapsize, 1);
00156 for (i = 0; i < mapsize; i++)
00157 {
00158 warning ("%d", i);
00159 Magick::ColorRGB c = imvec[0].colorMap (i);
00160 map(i,0) = c.red ();
00161 map(i,1) = c.green ();
00162 map(i,2) = c.blue ();
00163 alpha(i,1) = c.alpha ();
00164 }
00165 break;
00166 #endif
00167
00168 case Magick::PaletteType:
00169 alpha = Matrix (0, 0);
00170 for (i = 0; i < mapsize; i++)
00171 {
00172 Magick::ColorRGB c = imvec[0].colorMap (i);
00173 map(i,0) = c.red ();
00174 map(i,1) = c.green ();
00175 map(i,2) = c.blue ();
00176 }
00177 break;
00178
00179 default:
00180 error ("__magick_read__: unsupported indexed image type");
00181 return octave_value_list ();
00182 }
00183
00184 if (wantalpha)
00185 output(2) = alpha;
00186
00187 output(1) = map;
00188
00189 return output;
00190 }
00191
00192 template <class T>
00193 octave_value_list
00194 read_images (const std::vector<Magick::Image>& imvec,
00195 const Array<int>& frameidx, unsigned int depth)
00196 {
00197 typedef typename T::element_type P;
00198
00199 octave_value_list retval (3, Matrix ());
00200
00201 T im;
00202
00203 int rows = imvec[0].baseRows ();
00204 int columns = imvec[0].baseColumns ();
00205 int nframes = frameidx.length ();
00206
00207 dim_vector idim = dim_vector ();
00208 idim.resize (4);
00209 idim(0) = rows;
00210 idim(1) = columns;
00211 idim(2) = 1;
00212 idim(3) = nframes;
00213
00214 Magick::ImageType type = imvec[0].type ();
00215 const int divisor = ((uint64_t (1) << QuantumDepth) - 1) /
00216 ((uint64_t (1) << depth) - 1);
00217
00218 switch (type)
00219 {
00220 case Magick::BilevelType:
00221 case Magick::GrayscaleType:
00222 {
00223 im = T (idim);
00224 P *vec = im.fortran_vec ();
00225
00226 for (int frame = 0; frame < nframes; frame++)
00227 {
00228 const Magick::PixelPacket *pix
00229 = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
00230
00231 P *rbuf = vec;
00232 for (int y = 0; y < rows; y++)
00233 {
00234 for (int x = 0; x < columns; x++)
00235 {
00236 *rbuf = pix->red / divisor;
00237 pix++;
00238 rbuf += rows;
00239 }
00240 rbuf -= rows * columns - 1;
00241 }
00242
00243
00244 vec += rows * columns * idim(2);
00245 }
00246 }
00247 break;
00248
00249 case Magick::GrayscaleMatteType:
00250 {
00251 idim(2) = 2;
00252 im = T (idim);
00253 P *vec = im.fortran_vec ();
00254
00255 for (int frame = 0; frame < nframes; frame++)
00256 {
00257 const Magick::PixelPacket *pix
00258 = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
00259
00260 P *rbuf = vec;
00261 P *obuf = vec + rows * columns;
00262 for (int y = 0; y < rows; y++)
00263 {
00264 for (int x = 0; x < columns; x++)
00265 {
00266 *rbuf = pix->red / divisor;
00267 *obuf = pix->opacity / divisor;
00268 pix++;
00269 rbuf += rows;
00270 obuf += rows;
00271 }
00272 rbuf -= rows * columns - 1;
00273 obuf -= rows * columns - 1;
00274 }
00275
00276
00277 vec += rows * columns * idim(2);
00278 }
00279 }
00280 break;
00281
00282 case Magick::PaletteType:
00283 case Magick::TrueColorType:
00284 {
00285 idim(2) = 3;
00286 im = T (idim);
00287 P *vec = im.fortran_vec ();
00288
00289 for (int frame = 0; frame < nframes; frame++)
00290 {
00291 const Magick::PixelPacket *pix
00292 = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
00293
00294 P *rbuf = vec;
00295 P *gbuf = vec + rows * columns;
00296 P *bbuf = vec + rows * columns * 2;
00297 for (int y = 0; y < rows; y++)
00298 {
00299 for (int x = 0; x < columns; x++)
00300 {
00301 *rbuf = pix->red / divisor;
00302 *gbuf = pix->green / divisor;
00303 *bbuf = pix->blue / divisor;
00304 pix++;
00305 rbuf += rows;
00306 gbuf += rows;
00307 bbuf += rows;
00308 }
00309 rbuf -= rows * columns - 1;
00310 gbuf -= rows * columns - 1;
00311 bbuf -= rows * columns - 1;
00312 }
00313
00314
00315 vec += rows * columns * idim(2);
00316 }
00317 }
00318 break;
00319
00320 case Magick::PaletteMatteType:
00321 case Magick::TrueColorMatteType:
00322 case Magick::ColorSeparationType:
00323 {
00324 idim(2) = 4;
00325 im = T (idim);
00326 P *vec = im.fortran_vec ();
00327
00328 for (int frame = 0; frame < nframes; frame++)
00329 {
00330 const Magick::PixelPacket *pix
00331 = imvec[frameidx(frame)].getConstPixels (0, 0, columns, rows);
00332
00333 P *rbuf = vec;
00334 P *gbuf = vec + rows * columns;
00335 P *bbuf = vec + rows * columns * 2;
00336 P *obuf = vec + rows * columns * 3;
00337 for (int y = 0; y < rows; y++)
00338 {
00339 for (int x = 0; x < columns; x++)
00340 {
00341 *rbuf = pix->red / divisor;
00342 *gbuf = pix->green / divisor;
00343 *bbuf = pix->blue / divisor;
00344 *obuf = pix->opacity / divisor;
00345 pix++;
00346 rbuf += rows;
00347 gbuf += rows;
00348 bbuf += rows;
00349 obuf += rows;
00350 }
00351 rbuf -= rows * columns - 1;
00352 gbuf -= rows * columns - 1;
00353 bbuf -= rows * columns - 1;
00354 obuf -= rows * columns - 1;
00355 }
00356
00357
00358 vec += rows * columns * idim(2);
00359 }
00360 }
00361 break;
00362
00363 default:
00364 error ("__magick_read__: undefined ImageMagick image type");
00365 return retval;
00366 }
00367
00368 retval(0) = im;
00369
00370 return retval;
00371 }
00372
00373 #endif
00374
00375 static void
00376 maybe_initialize_magick (void)
00377 {
00378 #ifdef HAVE_MAGICK
00379
00380 static bool initialized = false;
00381
00382 if (! initialized)
00383 {
00384
00385 const char *static_locale = setlocale (LC_ALL, NULL);
00386 const std::string locale (static_locale);
00387
00388 std::string program_name = octave_env::get_program_invocation_name ();
00389
00390 Magick::InitializeMagick (program_name.c_str ());
00391
00392
00393 setlocale (LC_ALL, locale.c_str ());
00394
00395 if (QuantumDepth < 32)
00396 warning ("your version of %s limits images to %d bits per pixel",
00397 MagickPackageName, QuantumDepth);
00398
00399 initialized = true;
00400 }
00401 #endif
00402 }
00403
00404 DEFUN_DLD (__magick_read__, args, nargout,
00405 "-*- texinfo -*-\n\
00406 @deftypefn {Function File} {@var{m} =} __magick_read__(@var{fname}, @var{index})\n\
00407 @deftypefnx {Function File} {[@var{m}, @var{colormap}] =} __magick_read__(@var{fname}, @var{index})\n\
00408 @deftypefnx {Function File} {[@var{m}, @var{colormap}, @var{alpha}] =} __magick_read__(@var{fname}, @var{index})\n\
00409 Read images with ImageMagick++. In general you should not be using this\n\
00410 function. Instead use @code{imread}.\n\
00411 @seealso{imread}\n\
00412 @end deftypefn")
00413 {
00414 octave_value_list output;
00415
00416 #ifdef HAVE_MAGICK
00417
00418 maybe_initialize_magick ();
00419
00420 if (args.length () > 3 || args.length () < 1 || ! args(0).is_string ()
00421 || nargout > 3)
00422 {
00423 print_usage ();
00424 return output;
00425 }
00426
00427 Array<int> frameidx;
00428 bool all_frames = false;
00429
00430 if (args.length () == 2 && args(1).is_real_type ())
00431 frameidx = args(1).int_vector_value();
00432 else if (args.length () == 3 && args(1).is_string ()
00433 && args(1).string_value() == "frames")
00434 {
00435 if (args(2).is_string () && args(2).string_value() == "all")
00436 all_frames = true;
00437 else if (args(2).is_real_type ())
00438 frameidx = args(2).int_vector_value();
00439 }
00440 else
00441 {
00442 frameidx = Array<int> (dim_vector (1, 1));
00443 frameidx(0) = 1;
00444 }
00445
00446 std::vector<Magick::Image> imvec;
00447
00448 try
00449 {
00450
00451 Magick::readImages (&imvec, args(0).string_value ());
00452 }
00453 catch (Magick::Warning& w)
00454 {
00455 warning ("Magick++ warning: %s", w.what ());
00456 }
00457 catch (Magick::ErrorCoder& e)
00458 {
00459 warning ("Magick++ coder error: %s", e.what ());
00460 }
00461 catch (Magick::Exception& e)
00462 {
00463 error ("Magick++ exception: %s", e.what ());
00464 return output;
00465 }
00466
00467 int nframes = imvec.size ();
00468 if (all_frames)
00469 {
00470 frameidx = Array<int> (dim_vector (1, nframes));
00471 for (int i = 0; i < frameidx.length (); i++)
00472 frameidx(i) = i;
00473 }
00474 else
00475 {
00476 for (int i = 0; i < frameidx.length (); i++)
00477 {
00478 frameidx(i) = frameidx(i) - 1;
00479
00480 if (frameidx(i) >= nframes || frameidx(i) < 0)
00481 {
00482 error ("__magick_read__: invalid INDEX vector");
00483 return output;
00484 }
00485 }
00486 }
00487
00488 Magick::ClassType klass = imvec[0].classType ();
00489
00490 if (klass == Magick::PseudoClass && nargout > 1)
00491 output = read_indexed_images (imvec, frameidx, (nargout == 3));
00492 else
00493 {
00494 unsigned int depth = imvec[0].modulusDepth ();
00495 if (depth > 1)
00496 {
00497 --depth;
00498 int i = 1;
00499 while (depth >>= 1)
00500 i++;
00501 depth = 1 << i;
00502 }
00503
00504 switch (depth)
00505 {
00506 case 1:
00507 output = read_images<boolNDArray> (imvec, frameidx, depth);
00508 break;
00509
00510 case 2:
00511 case 4:
00512 case 8:
00513 output = read_images<uint8NDArray> (imvec, frameidx, depth) ;
00514 break;
00515
00516 case 16:
00517 output = read_images<uint16NDArray> (imvec, frameidx, depth);
00518 break;
00519
00520 case 32:
00521 case 64:
00522 default:
00523 error ("__magick_read__: image depths greater than 16-bit are not supported");
00524 }
00525 }
00526 #else
00527
00528 error ("imread: image reading capabilities were disabled when Octave was compiled");
00529
00530 #endif
00531
00532 return output;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542 #ifdef HAVE_MAGICK
00543
00544 static void
00545 jpg_settings (std::vector<Magick::Image>& imvec,
00546 const Octave_map& options,
00547 bool)
00548 {
00549 bool something_set = false;
00550
00551
00552 octave_value result;
00553 Octave_map::const_iterator p;
00554 bool found_it = false;
00555
00556 for (p = options.begin (); p != options.end (); p++)
00557 {
00558 if (options.key (p) == "Quality")
00559 {
00560 found_it = true;
00561 result = options.contents (p).elem (0);
00562 break;
00563 }
00564 }
00565
00566 if (found_it && (! result.is_empty ()))
00567 {
00568 something_set = true;
00569
00570 if (result.is_real_type ())
00571 {
00572 int qlev = result.int_value ();
00573
00574 if (qlev < 0 || qlev > 100)
00575 warning ("warning: Quality setting invalid--use default of 75");
00576 else
00577 {
00578 for (size_t fnum = 0; fnum < imvec.size (); fnum++)
00579 imvec[fnum].quality (static_cast<unsigned int>(qlev));
00580 }
00581 }
00582 else
00583 warning ("warning: Quality setting invalid--use default of 75");
00584 }
00585
00586
00587
00588 if (! something_set)
00589 warning ("__magick_write__ warning: all write parameters ignored");
00590 }
00591
00592 static void
00593 encode_bool_image (std::vector<Magick::Image>& imvec, const octave_value& img)
00594 {
00595 unsigned int nframes = 1;
00596 boolNDArray m = img.bool_array_value ();
00597
00598 dim_vector dsizes = m.dims ();
00599 if (dsizes.length () == 4)
00600 nframes = dsizes(3);
00601
00602 Array<octave_idx_type> idx (dim_vector (dsizes.length (), 1));
00603
00604 octave_idx_type rows = m.rows ();
00605 octave_idx_type columns = m.columns ();
00606
00607 for (unsigned int ii = 0; ii < nframes; ii++)
00608 {
00609 Magick::Image im(Magick::Geometry (columns, rows), "black");
00610 im.classType (Magick::DirectClass);
00611 im.depth (1);
00612
00613 for (int y = 0; y < columns; y++)
00614 {
00615 idx(1) = y;
00616
00617 for (int x = 0; x < rows; x++)
00618 {
00619 if (nframes > 1)
00620 {
00621 idx(2) = 0;
00622 idx(3) = ii;
00623 }
00624
00625 idx(0) = x;
00626
00627 if (m(idx))
00628 im.pixelColor (y, x, "white");
00629 }
00630 }
00631
00632 im.quantizeColorSpace (Magick::GRAYColorspace);
00633 im.quantizeColors (2);
00634 im.quantize ();
00635
00636 imvec.push_back (im);
00637 }
00638 }
00639
00640 template <class T>
00641 static void
00642 encode_uint_image (std::vector<Magick::Image>& imvec,
00643 const octave_value& img,
00644 bool has_map)
00645 {
00646 unsigned int bitdepth = 0;
00647 T m;
00648
00649 if (img.is_uint8_type ())
00650 {
00651 bitdepth = 8;
00652 m = img.uint8_array_value ();
00653 }
00654 else if (img.is_uint16_type ())
00655 {
00656 bitdepth = 16;
00657 m = img.uint16_array_value ();
00658 }
00659 else
00660 error ("__magick_write__: invalid image class");
00661
00662 dim_vector dsizes = m.dims ();
00663 unsigned int nframes = 1;
00664 if (dsizes.length () == 4)
00665 nframes = dsizes(3);
00666
00667 bool is_color = ((dsizes.length () > 2) && (dsizes(2) > 2));
00668 bool has_alpha = (dsizes.length () > 2 && (dsizes(2) == 2 || dsizes(2) == 4));
00669
00670 Array<octave_idx_type> idx (dim_vector (dsizes.length (), 1));
00671 octave_idx_type rows = m.rows ();
00672 octave_idx_type columns = m.columns ();
00673
00674 unsigned int div_factor = (1 << bitdepth) - 1;
00675
00676 for (unsigned int ii = 0; ii < nframes; ii++)
00677 {
00678 Magick::Image im (Magick::Geometry (columns, rows), "black");
00679
00680 im.depth (bitdepth);
00681
00682 if (has_map)
00683 im.classType (Magick::PseudoClass);
00684 else
00685 im.classType (Magick::DirectClass);
00686
00687 if (is_color)
00688 {
00689 if (has_alpha)
00690 im.type (Magick::TrueColorMatteType);
00691 else
00692 im.type (Magick::TrueColorType);
00693
00694 Magick::ColorRGB c;
00695
00696 for (int y = 0; y < columns; y++)
00697 {
00698 idx(1) = y;
00699
00700 for (int x = 0; x < rows; x++)
00701 {
00702 idx(0) = x;
00703
00704 if (nframes > 1)
00705 idx(3) = ii;
00706
00707 idx(2) = 0;
00708 c.red (static_cast<double>(m(idx)) / div_factor);
00709
00710 idx(2) = 1;
00711 c.green (static_cast<double>(m(idx)) / div_factor);
00712
00713 idx(2) = 2;
00714 c.blue (static_cast<double>(m(idx)) / div_factor);
00715
00716 if (has_alpha)
00717 {
00718 idx(2) = 3;
00719 c.alpha (static_cast<double>(m(idx)) / div_factor);
00720 }
00721
00722 im.pixelColor (y, x, c);
00723 }
00724 }
00725 }
00726 else
00727 {
00728 if (has_alpha)
00729 im.type (Magick::GrayscaleMatteType);
00730 else
00731 im.type (Magick::GrayscaleType);
00732
00733 Magick::ColorGray c;
00734
00735 for (int y = 0; y < columns; y++)
00736 {
00737 idx(1) = y;
00738
00739 for (int x=0; x < rows; x++)
00740 {
00741 idx(0) = x;
00742
00743 if (nframes > 1)
00744 {
00745 idx(2) = 0;
00746 idx(3) = ii;
00747 }
00748
00749 if (has_alpha)
00750 {
00751 idx(2) = 1;
00752 c.alpha (static_cast<double>(m(idx)) / div_factor);
00753 idx(2) = 0;
00754 }
00755
00756 c.shade (static_cast<double>(m(idx)) / div_factor);
00757
00758 im.pixelColor (y, x, c);
00759 }
00760 }
00761
00762 im.quantizeColorSpace (Magick::GRAYColorspace);
00763 im.quantizeColors (1 << bitdepth);
00764 im.quantize ();
00765 }
00766
00767 imvec.push_back (im);
00768 }
00769 }
00770
00771 static void
00772 encode_map (std::vector<Magick::Image>& imvec, const NDArray& cmap)
00773 {
00774 unsigned int mapsize = cmap.dim1 ();
00775
00776 for (size_t fnum = 0; fnum < imvec.size (); fnum++)
00777 {
00778 imvec[fnum].colorMapSize (mapsize);
00779 imvec[fnum].type (Magick::PaletteType);
00780 }
00781
00782 for (unsigned int ii = 0; ii < mapsize; ii++)
00783 {
00784 Magick::ColorRGB c (cmap(ii,0), cmap(ii,1), cmap(ii,2));
00785
00786
00787 if (cmap.dim2 () == 4)
00788 c.alpha (cmap(ii,3));
00789
00790 try
00791 {
00792 for_each (imvec.begin (), imvec.end (),
00793 Magick::colorMapImage (ii, c));
00794 }
00795 catch (Magick::Warning& w)
00796 {
00797 warning ("Magick++ warning: %s", w.what ());
00798 }
00799 catch (Magick::ErrorCoder& e)
00800 {
00801 warning ("Magick++ coder error: %s", e.what ());
00802 }
00803 catch (Magick::Exception& e)
00804 {
00805 error ("Magick++ exception: %s", e.what ());
00806 }
00807 }
00808 }
00809
00810 static void
00811 write_image (const std::string& filename, const std::string& fmt,
00812 const octave_value& img,
00813 const octave_value& map = octave_value (),
00814 const octave_value& params = octave_value ())
00815 {
00816 std::vector<Magick::Image> imvec;
00817
00818 bool has_map = map.is_defined ();
00819
00820 if (has_map)
00821 {
00822 error ("__magick_write__: direct saving of indexed images not currently supported; use ind2rgb and save converted image");
00823 return;
00824 }
00825
00826 if (img.is_bool_type ())
00827 encode_bool_image (imvec, img);
00828 else if (img.is_uint8_type ())
00829 encode_uint_image<uint8NDArray> (imvec, img, has_map);
00830 else if (img.is_uint16_type ())
00831 encode_uint_image<uint16NDArray> (imvec, img, has_map);
00832 else
00833 error ("__magick_write__: image type not supported");
00834
00835 if (! error_state && has_map)
00836 {
00837 NDArray cmap = map.array_value ();
00838
00839 if (! error_state)
00840 encode_map (imvec, cmap);
00841 }
00842
00843 if (! error_state && params.is_defined ())
00844 {
00845 Octave_map options = params.map_value ();
00846
00847
00848 if (fmt == "jpg" || fmt == "jpeg")
00849 jpg_settings (imvec, options, has_map);
00850 else
00851 warning ("warning: your parameter(s) currently not supported");
00852 }
00853
00854 try
00855 {
00856 Magick::writeImages (imvec.begin (), imvec.end (), fmt + ":" + filename);
00857 }
00858 catch (Magick::Warning& w)
00859 {
00860 warning ("Magick++ warning: %s", w.what ());
00861 }
00862 catch (Magick::ErrorCoder& e)
00863 {
00864 warning ("Magick++ coder error: %s", e.what ());
00865 }
00866 catch (Magick::Exception& e)
00867 {
00868 error ("Magick++ exception: %s", e.what ());
00869 }
00870 }
00871
00872 #endif
00873
00874 DEFUN_DLD (__magick_write__, args, ,
00875 "-*- texinfo -*-\n\
00876 @deftypefn {Function File} {} __magick_write__(@var{fname}, @var{fmt}, @var{img})\n\
00877 @deftypefnx {Function File} {} __magick_write__(@var{fname}, @var{fmt}, @var{img}, @var{map})\n\
00878 Write images with ImageMagick++. In general you should not be using this\n\
00879 function. Instead use @code{imwrite}.\n\
00880 @seealso{imread}\n\
00881 @end deftypefn")
00882 {
00883 octave_value_list retval;
00884
00885 #ifdef HAVE_MAGICK
00886 maybe_initialize_magick ();
00887
00888 int nargin = args.length ();
00889
00890 if (nargin > 2)
00891 {
00892 std::string filename = args(0).string_value ();
00893
00894 if (! error_state)
00895 {
00896 std::string fmt = args(1).string_value ();
00897
00898 if (! error_state)
00899 {
00900 if (nargin > 4)
00901 write_image (filename, fmt, args(2), args(3), args(4));
00902 else if (nargin > 3)
00903 if (args(3).is_real_type ())
00904 write_image (filename, fmt, args(2), args(3));
00905 else
00906 write_image (filename, fmt, args(2), octave_value(), args(3));
00907 else
00908 write_image (filename, fmt, args(2));
00909 }
00910 else
00911 error ("__magick_write__: FMT must be string");
00912 }
00913 else
00914 error ("__magick_write__: FNAME must be a string");
00915 }
00916 else
00917 print_usage ();
00918 #else
00919
00920 error ("__magick_write__: not available in this version of Octave");
00921
00922 #endif
00923
00924 return retval;
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934 #ifdef HAVE_MAGICK
00935
00936 template<class T>
00937 static octave_value
00938 magick_to_octave_value (const T magick)
00939 {
00940 return octave_value (magick);
00941 }
00942
00943 static octave_value
00944 magick_to_octave_value (const Magick::EndianType magick)
00945 {
00946 switch (magick)
00947 {
00948 case Magick::LSBEndian:
00949 return octave_value ("little-endian");
00950
00951 case Magick::MSBEndian:
00952 return octave_value ("big-endian");
00953
00954 default:
00955 return octave_value ("undefined");
00956 }
00957 }
00958
00959 static octave_value
00960 magick_to_octave_value (const Magick::ResolutionType magick)
00961 {
00962 switch (magick)
00963 {
00964 case Magick::PixelsPerInchResolution:
00965 return octave_value ("pixels per inch");
00966
00967 case Magick::PixelsPerCentimeterResolution:
00968 return octave_value ("pixels per centimeter");
00969
00970 default:
00971 return octave_value ("undefined");
00972 }
00973 }
00974
00975 static octave_value
00976 magick_to_octave_value (const Magick::ImageType magick)
00977 {
00978 switch (magick)
00979 {
00980 case Magick::BilevelType:
00981 case Magick::GrayscaleType:
00982 case Magick::GrayscaleMatteType:
00983 return octave_value ("grayscale");
00984
00985 case Magick::PaletteType:
00986 case Magick::PaletteMatteType:
00987 return octave_value ("indexed");
00988
00989 case Magick::TrueColorType:
00990 case Magick::TrueColorMatteType:
00991 case Magick::ColorSeparationType:
00992 return octave_value ("truecolor");
00993
00994 default:
00995 return octave_value ("undefined");
00996 }
00997 }
00998
00999
01000
01001 #define GET_PARAM(NAME, OUTNAME) \
01002 try \
01003 { \
01004 info.contents (OUTNAME)(frame,0) = magick_to_octave_value (im.NAME ()); \
01005 } \
01006 catch (Magick::Warning& w) \
01007 { \
01008 }
01009
01010 #endif
01011
01012 DEFUN_DLD (__magick_finfo__, args, ,
01013 "-*- texinfo -*-\n\
01014 @deftypefn {Loadable Function} {} __magick_finfo__(@var{fname})\n\
01015 Read image information with GraphicsMagick++. In general you should\n\
01016 not be using this function. Instead use @code{imfinfo}.\n\
01017 @seealso{imfinfo, imread}\n\
01018 @end deftypefn")
01019 {
01020 octave_value retval;
01021
01022 #ifdef HAVE_MAGICK
01023
01024 maybe_initialize_magick ();
01025
01026 if (args.length () < 1 || ! args (0).is_string ())
01027 {
01028 print_usage ();
01029 return retval;
01030 }
01031
01032 const std::string filename = args (0).string_value ();
01033
01034 try
01035 {
01036
01037 std::vector<Magick::Image> imvec;
01038 Magick::readImages (&imvec, args(0).string_value ());
01039 int nframes = imvec.size ();
01040
01041
01042
01043 static const char *fields[] =
01044 {
01045 "Filename",
01046 "FileModDate",
01047 "FileSize",
01048 "Height",
01049 "Width",
01050 "BitDepth",
01051 "Format",
01052 "LongFormat",
01053 "XResolution",
01054 "YResolution",
01055 "TotalColors",
01056 "TileName",
01057 "AnimationDelay",
01058 "AnimationIterations",
01059 "ByteOrder",
01060 "Gamma",
01061 "Matte",
01062 "ModulusDepth",
01063 "Quality",
01064 "QuantizeColors",
01065 "ResolutionUnits",
01066 "ColorType",
01067 "View",
01068 0
01069 };
01070
01071 Octave_map info (string_vector (fields), dim_vector (nframes, 1));
01072
01073 file_stat fs (filename);
01074
01075 std::string filetime;
01076
01077 if (fs)
01078 {
01079 octave_localtime mtime = fs.mtime ();
01080
01081 filetime = mtime.strftime ("%e-%b-%Y %H:%M:%S");
01082 }
01083 else
01084 {
01085 std::string msg = fs.error ();
01086
01087 error ("imfinfo: error reading '%s': %s",
01088 filename.c_str (), msg.c_str ());
01089
01090 return retval;
01091 }
01092
01093
01094
01095 for (int frame = 0; frame < nframes; frame++)
01096 {
01097 Magick::Image im = imvec[frame];
01098
01099
01100 info.contents ("Filename")(frame,0) = filename;
01101 info.contents ("FileModDate")(frame,0) = filetime;
01102
01103
01104 GET_PARAM (fileSize, "FileSize")
01105 GET_PARAM (rows, "Height")
01106 GET_PARAM (columns, "Width")
01107 GET_PARAM (depth, "BitDepth")
01108 GET_PARAM (magick, "Format")
01109 GET_PARAM (format, "LongFormat")
01110 GET_PARAM (xResolution, "XResolution")
01111 GET_PARAM (yResolution, "YResolution")
01112 GET_PARAM (totalColors, "TotalColors")
01113 GET_PARAM (tileName, "TileName")
01114 GET_PARAM (animationDelay, "AnimationDelay")
01115 GET_PARAM (animationIterations, "AnimationIterations")
01116 GET_PARAM (endian, "ByteOrder")
01117 GET_PARAM (gamma, "Gamma")
01118 GET_PARAM (matte, "Matte")
01119 GET_PARAM (modulusDepth, "ModulusDepth")
01120 GET_PARAM (quality, "Quality")
01121 GET_PARAM (quantizeColors, "QuantizeColors")
01122 GET_PARAM (resolutionUnits, "ResolutionUnits")
01123 GET_PARAM (type, "ColorType")
01124 GET_PARAM (view, "View")
01125 }
01126
01127 retval = octave_value (info);
01128 }
01129 catch (Magick::Warning& w)
01130 {
01131 warning ("Magick++ warning: %s", w.what ());
01132 }
01133 catch (Magick::ErrorCoder& e)
01134 {
01135 warning ("Magick++ coder error: %s", e.what ());
01136 }
01137 catch (Magick::Exception& e)
01138 {
01139 error ("Magick++ exception: %s", e.what ());
01140 return retval;
01141 }
01142
01143 #else
01144
01145 error ("imfinfo: not available in this version of Octave");
01146
01147 #endif
01148
01149 return retval;
01150 }
01151
01152
01153
01154
01155
01156
01157
01158
01159 #undef GET_PARAM
01160
01161
01162
01163
01164
01165
01166 DEFUN_DLD (__magick_format_list__, args, ,
01167 "-*- texinfo -*-\n\
01168 @deftypefn {Function File} {} __magick_format_list__ (@var{formats})\n\
01169 Undocumented internal function.\n\
01170 @end deftypefn")
01171 {
01172 octave_value retval;
01173
01174 #ifdef HAVE_MAGICK
01175 maybe_initialize_magick ();
01176
01177 std::list<std::string> accepted_formats;
01178
01179 if (args.length () == 1)
01180 {
01181 Cell c = args (0).cell_value ();
01182
01183 if (! error_state)
01184 {
01185 for (octave_idx_type i = 0; i < c.nelem (); i++)
01186 {
01187 try
01188 {
01189 std::string fmt = c.elem (i).string_value ();
01190
01191 Magick::CoderInfo info(fmt);
01192
01193 if (info.isReadable () && info.isWritable ())
01194 accepted_formats.push_back (fmt);
01195 }
01196 catch (Magick::Exception& e)
01197 {
01198
01199 }
01200 }
01201 }
01202 else
01203 error ("__magick_format_list__: expecting a cell array of image format names");
01204 }
01205 else
01206 print_usage ();
01207
01208 retval = Cell (accepted_formats);
01209
01210 #else
01211
01212 error ("__magick_format_list__: not available in this version of Octave");
01213
01214 #endif
01215
01216 return retval;
01217 }
01218
01219
01220
01221
01222
01223
01224