26#if defined (HAVE_CONFIG_H)
41#if defined (HAVE_MAGICK)
53#if defined (HAVE_MAGICK)
85is_indexed (
const Magick::Image& img)
87 bool indexed = (img.classType () == Magick::PseudoClass);
92 const std::string fmt = img.magick ();
97 else if (fmt ==
"PNG")
106 const std::string color_type
107 =
const_cast<Magick::Image&
> (img).attribute (
"PNG:IHDR.color-type-orig");
108 if (! color_type.empty () && color_type !=
"3")
131get_depth (Magick::Image& img)
135 && img.channelDepth (Magick::RedChannel) == 1
136 && img.channelDepth (Magick::GreenChannel) == 1
137 && img.channelDepth (Magick::BlueChannel) == 1
138 && img.channelDepth (Magick::CyanChannel) == 1
139 && img.channelDepth (Magick::MagentaChannel) == 1
140 && img.channelDepth (Magick::YellowChannel) == 1
141 && img.channelDepth (Magick::BlackChannel) == 1
142 && img.channelDepth (Magick::OpacityChannel) == 1
143 && img.channelDepth (Magick::GrayChannel) == 1)
168 double base = array(0);
169 double limit = array(array.
numel () - 1);
170 double incr = array(1) - base;
174 error (
"__magick_read__: unknown datatype for Region option");
183 image_region () =
delete;
194 const range<double> rows = get_region_range (pixel_region (0));
195 const range<double> cols = get_region_range (pixel_region (1));
197 m_row_start = rows.base () - 1;
198 m_col_start = cols.base () - 1;
199 m_row_end = rows.max () - 1;
200 m_col_end = cols.max () - 1;
202 m_row_cache = m_row_end - m_row_start + 1;
203 m_col_cache = m_col_end - m_col_start + 1;
205 m_row_shift = m_col_cache * rows.increment ();
206 m_col_shift = m_col_cache * (m_row_cache + rows.increment () - 1) - cols.increment ();
208 m_row_out = rows.numel ();
209 m_col_out = cols.numel ();
212 OCTAVE_DEFAULT_COPY_MOVE_DELETE (image_region)
260read_maps (Magick::Image& img)
268 const Magick::ColorRGB c = img.colorMap (i);
269 cmap(i, 0) = c.red ();
270 cmap(i, 1) = c.green ();
271 cmap(i, 2) = c.blue ();
272 amap(i) = c.alpha ();
282read_indexed_images (
const std::vector<Magick::Image>& imvec,
287 typedef typename T::element_type P;
291 image_region region (options);
302 T img = T (
dim_vector (nRows, nCols, 1, nFrames));
303 P *img_fvec = img.rwdata ();
320 imvec[frameidx(frame)].getConstPixels (col_start, row_start,
321 col_cache, row_cache);
323 const Magick::IndexPacket *pix
324 = imvec[frameidx(frame)].getConstIndexes ();
330 img_fvec[idx++] =
static_cast<P
> (*pix);
347 = read_maps (
const_cast<Magick::Image&
> (imvec[frameidx(def_elem)]));
354 if (imvec[def_elem].matte ())
357 const Matrix amap = maps(1).matrix_value ();
358 const double *amap_fvec = amap.
data ();
361 double *alpha_fvec = alpha.rwdata ();
367 alpha_fvec[pix] = 1 - amap_fvec[
static_cast<int> (img_fvec[3])];
393 typedef typename T::element_type P;
397 image_region region (options);
435 if (imvec[def_elem].depth () == 32)
436 divisor = std::numeric_limits<uint32_t>::max ();
438 divisor = MaxRGB / ((uint64_t (1) << imvec[def_elem].depth ()) - 1);
447 Magick::ImageType type = imvec[def_elem].type ();
448 if (type == Magick::BilevelType && imvec[def_elem].matte ())
449 type = Magick::GrayscaleMatteType;
458 if (imvec[0].magick () ==
"PNG")
468 const std::string type_str
469 = imvec[0].attribute (
"PNG:IHDR.color-type-orig");
472 type = Magick::GrayscaleType;
473 else if (type_str ==
"2")
474 type = Magick::TrueColorType;
475 else if (type_str ==
"6")
476 type = Magick::TrueColorMatteType;
477 else if (type_str ==
"4")
478 type = Magick::GrayscaleMatteType;
484 if (imvec[0].matte ())
486 if (type == Magick::GrayscaleType)
487 type = Magick::GrayscaleMatteType;
488 else if (type == Magick::TrueColorType)
489 type = Magick::TrueColorMatteType;
499 case Magick::GrayscaleMatteType:
500 type = Magick::GrayscaleType;
503 case Magick::PaletteMatteType:
504 type = Magick::PaletteType;
507 case Magick::TrueColorMatteType:
508 type = Magick::TrueColorType;
511 case Magick::ColorSeparationMatteType:
512 type = Magick::ColorSeparationType;
525 case Magick::BilevelType:
526 case Magick::GrayscaleType:
528 img = T (
dim_vector (nRows, nCols, 1, nFrames));
529 P *img_fvec = img.rwdata ();
536 const Magick::PixelPacket *pix
537 = imvec[frameidx(frame)].getConstPixels (col_start, row_start,
538 col_cache, row_cache);
544 img_fvec[idx++] = pix->red / divisor;
553 case Magick::GrayscaleMatteType:
555 img = T (
dim_vector (nRows, nCols, 1, nFrames));
556 T alpha (
dim_vector (nRows, nCols, 1, nFrames));
557 P *img_fvec = img.rwdata ();
558 P *a_fvec = alpha.rwdata ();
565 const Magick::PixelPacket *pix
566 = imvec[frameidx(frame)].getConstPixels (col_start, row_start,
567 col_cache, row_cache);
573 img_fvec[idx] = pix->red / divisor;
574 a_fvec[idx] = (MaxRGB - pix->opacity) / divisor;
585 case Magick::PaletteType:
586 case Magick::TrueColorType:
588 img = T (
dim_vector (nRows, nCols, 3, nFrames));
589 P *img_fvec = img.rwdata ();
596 const Magick::PixelPacket *pix
597 = imvec[frameidx(frame)].getConstPixels (col_start, row_start,
598 col_cache, row_cache);
602 P *gbuf = img_fvec + color_stride;
603 P *bbuf = img_fvec + color_stride * 2;
609 rbuf[idx] = pix->red / divisor;
610 gbuf[idx] = pix->green / divisor;
611 bbuf[idx] = pix->blue / divisor;
617 img_fvec += frame_stride;
622 case Magick::PaletteMatteType:
623 case Magick::TrueColorMatteType:
625 img = T (
dim_vector (nRows, nCols, 3, nFrames));
626 T alpha (
dim_vector (nRows, nCols, 1, nFrames));
627 P *img_fvec = img.rwdata ();
628 P *a_fvec = alpha.rwdata ();
639 const Magick::PixelPacket *pix
640 = imvec[frameidx(frame)].getConstPixels (col_start, row_start,
641 col_cache, row_cache);
645 P *gbuf = img_fvec + color_stride;
646 P *bbuf = img_fvec + color_stride * 2;
652 rbuf[idx] = pix->red / divisor;
653 gbuf[idx] = pix->green / divisor;
654 bbuf[idx] = pix->blue / divisor;
655 a_fvec[a_idx++] = (MaxRGB - pix->opacity) / divisor;
661 img_fvec += frame_stride;
667 case Magick::ColorSeparationType:
669 img = T (
dim_vector (nRows, nCols, 4, nFrames));
670 P *img_fvec = img.rwdata ();
677 const Magick::PixelPacket *pix
678 = imvec[frameidx(frame)].getConstPixels (col_start, row_start,
679 col_cache, row_cache);
683 P *mbuf = img_fvec + color_stride;
684 P *ybuf = img_fvec + color_stride * 2;
685 P *kbuf = img_fvec + color_stride * 3;
691 cbuf[idx] = pix->red / divisor;
692 mbuf[idx] = pix->green / divisor;
693 ybuf[idx] = pix->blue / divisor;
694 kbuf[idx] = pix->opacity / divisor;
700 img_fvec += frame_stride;
706 case Magick::ColorSeparationMatteType:
708 img = T (
dim_vector (nRows, nCols, 4, nFrames));
709 T alpha (
dim_vector (nRows, nCols, 1, nFrames));
710 P *img_fvec = img.rwdata ();
711 P *a_fvec = alpha.rwdata ();
722 const Magick::PixelPacket *pix
723 = imvec[frameidx(frame)].getConstPixels (col_start, row_start,
724 col_cache, row_cache);
727 const Magick::IndexPacket *apix
728 = imvec[frameidx(frame)].getConstIndexes ();
732 P *mbuf = img_fvec + color_stride;
733 P *ybuf = img_fvec + color_stride * 2;
734 P *kbuf = img_fvec + color_stride * 3;
740 cbuf[idx] = pix->red / divisor;
741 mbuf[idx] = pix->green / divisor;
742 ybuf[idx] = pix->blue / divisor;
743 kbuf[idx] = pix->opacity / divisor;
744 a_fvec[a_idx++] = (MaxRGB - *apix) / divisor;
750 img_fvec += frame_stride;
757 error (
"__magick_read__: unknown Magick++ image type");
767read_file (
const std::string& filename, std::vector<Magick::Image>& imvec)
773 std::string ascii_fname = sys::get_ASCII_filename (filename,
true);
777 Magick::readImages (&imvec, ascii_fname);
779 catch (
const Magick::Warning& w)
781 warning (
"Magick++ warning: %s",
w.what ());
783 catch (
const Magick::Exception& e)
785 error (
"Magick++ exception: %s", e.what ());
790maybe_initialize_magick ()
792 static bool initialized =
false;
798 const char *static_locale = setlocale (LC_ALL,
nullptr);
799 const std::string locale = (static_locale ? static_locale :
"");
801 const std::string program_name
802 = sys::env::get_program_invocation_name ();
803 Magick::InitializeMagick (program_name.c_str ());
806 setlocale (LC_ALL, locale.c_str ());
827 if (QuantumDepth < 16)
829 "your version of %s limits images to %d bits per pixel\n",
830 MagickPackageName, QuantumDepth);
838DEFUN (__magick_read__, args, nargout,
849#if defined (HAVE_MAGICK)
851 if (args.length () != 2 || ! args(0).is_string ())
854 maybe_initialize_magick ();
857 = args(1).xscalar_map_value (
"__magick_read__: OPTIONS must be a struct");
861 std::vector<Magick::Image> imvec;
862 read_file (args(0).string_value (), imvec);
876 frameidx = indexes.
xint_vector_value (
"__magick_read__: invalid value for Index/Frame");
884 if (frameidx(i) < 0 || frameidx(i) > nFrames - 1)
889 error (
"imread: index/frames specified are outside the number of images");
899 const unsigned int nRows = imvec[frameidx(0)].rows ();
900 const unsigned int nCols = imvec[frameidx(0)].columns ();
904 if (nRows != imvec[frameidx(frame)].rows ()
905 || nCols != imvec[frameidx(frame)].columns ())
907 error (
"imread: all frames must have the same size but frame "
908 "%" OCTAVE_IDX_TYPE_FORMAT
" is different",
915 if (is_indexed (imvec[frameidx(0)]))
918 output = read_indexed_images<boolNDArray> (imvec, frameidx,
921 output = read_indexed_images<uint8NDArray> (imvec, frameidx,
923 else if (depth <= 16)
924 output = read_indexed_images<uint16NDArray> (imvec, frameidx,
927 error (
"imread: indexed images with depths greater than 16-bit are not supported");
933 output = read_images<boolNDArray> (imvec, frameidx, nargout, options);
935 output = read_images<uint8NDArray> (imvec, frameidx, nargout, options);
936 else if (depth <= 16)
937 output = read_images<uint16NDArray> (imvec, frameidx, nargout, options);
938 else if (depth <= 32)
939 output = read_images<FloatNDArray> (imvec, frameidx, nargout, options);
941 error (
"imread: reading of images with %" OCTAVE_IDX_TYPE_FORMAT
942 "-bit depth is not supported", depth);
949 octave_unused_parameter (args);
950 octave_unused_parameter (nargout);
962#if defined (HAVE_MAGICK)
966img_float2uint (
const T& img)
968 typedef typename T::element_type P;
972 const P *img_fvec = img.data ();
977 out_fvec[idx] = img_fvec[idx] *
max;
986bitdepth_from_class ()
988 typedef typename T::element_type P;
990 =
sizeof (P) * std::numeric_limits<unsigned char>::digits;
997 const Magick::ImageType& type,
998 const Magick::ClassType& klass)
1000 Magick::Image img (Magick::Geometry (nCols, nRows),
"black");
1004 img.classType (klass);
1008 img.depth (bitdepth);
1011 case Magick::GrayscaleMatteType:
1012 case Magick::TrueColorMatteType:
1013 case Magick::ColorSeparationMatteType:
1014 case Magick::PaletteMatteType:
1025template <
typename T>
1027encode_indexed_images (std::vector<Magick::Image>& imvec,
1031 typedef typename T::element_type P;
1032 const octave_idx_type nFrames = (img.ndims () < 4 ? 1 : img.dims ()(3));
1040 std::vector<Magick::ColorRGB> colormap;
1042 const double *cmap_fvec = cmap.
data ();
1046 colormap.push_back (Magick::ColorRGB (cmap_fvec[map_idx],
1047 cmap_fvec[map_idx + G_offset],
1048 cmap_fvec[map_idx + B_offset]));
1055 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1056 Magick::PaletteType,
1057 Magick::PseudoClass);
1060 m_img.colorMapSize (cmap_size);
1062 m_img.colorMap (map_idx, colormap[map_idx]);
1073 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1074 Magick::IndexPacket *ind = m_img.getIndexes ();
1075 const P *img_fvec = img.data ();
1082 ind[GM_idx] =
double (*img_fvec);
1083 pix[GM_idx] = m_img.colorMap (
double (*img_fvec));
1087 GM_idx -= nCols * nRows - 1;
1091 m_img.syncPixels ();
1092 imvec.push_back (m_img);
1097encode_bool_image (std::vector<Magick::Image>& imvec,
const boolNDArray& img)
1104 const Magick::Color white (
"white");
1106 const bool *img_fvec = img.
data ();
1116 Magick::Image m_img = init_enconde_image (nCols, nRows, 1,
1117 Magick::GrayscaleType,
1118 Magick::DirectClass);
1120 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1126 if (img_fvec[img_idx])
1127 pix[GM_idx] = white;
1132 GM_idx -= nCols * nRows - 1;
1135 m_img.syncPixels ();
1138 m_img.type (Magick::BilevelType);
1139 imvec.push_back (m_img);
1143template <
typename T>
1145encode_uint_image (std::vector<Magick::Image>& imvec,
1146 const T& img,
const T& alpha)
1148 typedef typename T::element_type P;
1149 const octave_idx_type channels = (img.ndims () < 3 ? 1 : img.dims ()(2));
1150 const octave_idx_type nFrames = (img.ndims () < 4 ? 1 : img.dims ()(3));
1155 Magick::ImageType type;
1156 const bool has_alpha = ! alpha.isempty ();
1161 type = Magick::GrayscaleMatteType;
1163 type = Magick::GrayscaleType;
1168 type = Magick::TrueColorMatteType;
1170 type = Magick::TrueColorType;
1175 type = Magick::ColorSeparationMatteType;
1177 type = Magick::ColorSeparationType;
1182 error (
"__magick_write__: wrong size on 3rd dimension");
1192 const double divisor =
static_cast<double> ((uint64_t (1) << bitdepth) - 1)
1195 const P *img_fvec = img.data ();
1196 const P *a_fvec = alpha.data ();
1199 case Magick::GrayscaleType:
1205 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1207 Magick::DirectClass);
1209 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1215 const double grey = math::round (
double (*img_fvec) / divisor);
1216 Magick::Color c (grey, grey, grey);
1221 GM_idx -= nCols * nRows - 1;
1224 m_img.syncPixels ();
1225 imvec.push_back (m_img);
1230 case Magick::GrayscaleMatteType:
1236 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1238 Magick::DirectClass);
1240 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1246 double grey = math::round (
double (*img_fvec) / divisor);
1247 Magick::Color c (grey, grey, grey,
1248 MaxRGB - math::round (
double (*a_fvec) / divisor));
1254 GM_idx -= nCols * nRows - 1;
1257 m_img.syncPixels ();
1258 imvec.push_back (m_img);
1263 case Magick::TrueColorType:
1272 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1274 Magick::DirectClass);
1276 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1282 Magick::Color c (math::round (
double (*img_fvec) / divisor),
1283 math::round (
double (img_fvec[G_offset]) / divisor),
1284 math::round (
double (img_fvec[B_offset]) / divisor));
1289 GM_idx -= nCols * nRows - 1;
1292 m_img.syncPixels ();
1293 imvec.push_back (m_img);
1294 img_fvec += B_offset;
1299 case Magick::TrueColorMatteType:
1308 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1310 Magick::DirectClass);
1312 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1318 Magick::Color c (math::round (
double (*img_fvec) / divisor),
1319 math::round (
double (img_fvec[G_offset]) / divisor),
1320 math::round (
double (img_fvec[B_offset]) / divisor),
1321 MaxRGB - math::round (
double (*a_fvec) / divisor));
1327 GM_idx -= nCols * nRows - 1;
1330 m_img.syncPixels ();
1331 imvec.push_back (m_img);
1332 img_fvec += B_offset;
1337 case Magick::ColorSeparationType:
1347 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1349 Magick::DirectClass);
1351 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1357 Magick::Color c (math::round (
double (*img_fvec) / divisor),
1358 math::round (
double (img_fvec[M_offset]) / divisor),
1359 math::round (
double (img_fvec[Y_offset]) / divisor),
1360 math::round (
double (img_fvec[K_offset]) / divisor));
1365 GM_idx -= nCols * nRows - 1;
1368 m_img.syncPixels ();
1369 imvec.push_back (m_img);
1370 img_fvec += K_offset;
1375 case Magick::ColorSeparationMatteType:
1385 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth,
1387 Magick::DirectClass);
1389 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows);
1390 Magick::IndexPacket *ind = m_img.getIndexes ();
1396 Magick::Color c (math::round (
double (*img_fvec) / divisor),
1397 math::round (
double (img_fvec[M_offset]) / divisor),
1398 math::round (
double (img_fvec[Y_offset]) / divisor),
1399 math::round (
double (img_fvec[K_offset]) / divisor));
1401 ind[GM_idx] = MaxRGB - math::round (
double (*a_fvec) / divisor);
1406 GM_idx -= nCols * nRows - 1;
1409 m_img.syncPixels ();
1410 imvec.push_back (m_img);
1411 img_fvec += K_offset;
1417 error (
"__magick_write__: unrecognized Magick::ImageType");
1424static std::map<octave_idx_type, std::string>
1425init_disposal_methods ()
1442 static std::map<octave_idx_type, std::string> methods;
1443 if (methods.empty ())
1445 methods[0] =
"doNotSpecify";
1446 methods[1] =
"leaveInPlace";
1447 methods[2] =
"restoreBG";
1448 methods[3] =
"restorePrevious";
1452static std::map<std::string, octave_idx_type>
1453init_reverse_disposal_methods ()
1455 static std::map<std::string, octave_idx_type> methods;
1456 if (methods.empty ())
1458 methods[
"donotspecify"] = 0;
1459 methods[
"leaveinplace"] = 1;
1460 methods[
"restorebg"] = 2;
1461 methods[
"restoreprevious"] = 3;
1467write_file (
const std::string& filename,
1468 const std::string& ext,
1469 std::vector<Magick::Image>& imvec)
1473 Magick::writeImages (imvec.begin (), imvec.end (), ext +
':' + filename);
1475 catch (
const Magick::Warning& w)
1477 warning (
"Magick++ warning: %s",
w.what ());
1479 catch (
const Magick::ErrorCoder& e)
1481 warning (
"Magick++ coder error: %s", e.what ());
1483 catch (
const Magick::Exception& e)
1485 error (
"Magick++ exception: %s", e.what ());
1491DEFUN (__magick_write__, args, ,
1502#if defined (HAVE_MAGICK)
1504 if (args.length () != 5 || ! args(0).is_string () || ! args(1).is_string ())
1507 maybe_initialize_magick ();
1509 const std::string filename = args(0).string_value ();
1510 const std::string ext = args(1).string_value ();
1513 = args(4).xscalar_map_value (
"__magick_write__: OPTIONS must be a struct");
1516 const Matrix cmap = args(3).xmatrix_value (
"__magick_write__: invalid MAP");
1518 std::vector<Magick::Image> imvec;
1545 clip_img = img_float2uint<FloatNDArray>
1547 clip_alpha = img_float2uint<FloatNDArray>
1552 clip_img = img_float2uint<NDArray> (img.
array_value ());
1553 clip_alpha = img_float2uint<NDArray> (alpha.
array_value ());
1555 encode_uint_image<uint32NDArray> (imvec, clip_img, clip_alpha);
1558 error (
"__magick_write__: image type not supported");
1572 error (
"__magick_write__: indexed image must be uint8, uint16 or float");
1574 static std::map<std::string, octave_idx_type> disposal_methods
1575 = init_reverse_disposal_methods ();
1586 imvec[i].quality (quality);
1587 imvec[i].animationDelay (delaytime(i));
1588 imvec[i].gifDisposeMethod (disposal_methods[disposalmethod(i)]);
1594 if (writemode ==
"append" && sys::file_exists (filename))
1596 std::vector<Magick::Image> ini_imvec;
1597 read_file (filename, ini_imvec);
1599 if (ini_imvec.size () > 0)
1601 ini_imvec.insert (ini_imvec.end (), imvec.begin (), imvec.end ());
1602 ini_imvec.swap (imvec);
1632 const std::string compression
1635#define COMPRESS_MAGICK_IMAGE_VECTOR(GM_TYPE) \
1636 for (std::vector<Magick::Image>::size_type i = 0; i < imvec.size (); i++) \
1637 imvec[i].compressType (GM_TYPE)
1639 if (compression ==
"none")
1641 else if (compression ==
"bzip")
1643 else if (compression ==
"fax3")
1645 else if (compression ==
"fax4")
1647 else if (compression ==
"jpeg")
1649 else if (compression ==
"lzw")
1651 else if (compression ==
"rle")
1653 else if (compression ==
"deflate")
1656#undef COMPRESS_MAGICK_IMAGE_VECTOR
1658 write_file (filename, ext, imvec);
1664 octave_unused_parameter (args);
1680DEFUN (__magick_ping__, args, ,
1690#if defined (HAVE_MAGICK)
1692 if (args.length () < 1 || ! args(0).is_string ())
1695 maybe_initialize_magick ();
1697 const std::string filename = args(0).string_value ();
1700 if (args.length () > 1)
1701 idx = args(1).int_value () -1;
1713 std::string ascii_fname = sys::get_ASCII_filename (filename,
true);
1717 img.ping (ascii_fname);
1719 catch (
const Magick::Warning& w)
1721 warning (
"Magick++ warning: %s", w.what ());
1723 catch (
const Magick::Exception& e)
1725 error (
"Magick++ exception: %s", e.what ());
1728 static const char *fields[] = {
"rows",
"columns",
"format",
nullptr};
1738 octave_unused_parameter (args);
1745#if defined (HAVE_MAGICK)
1748magick_to_octave_value (
const Magick::CompressionType& magick)
1752 case Magick::NoCompression:
1754 case Magick::BZipCompression:
1756 case Magick::FaxCompression:
1758 case Magick::Group4Compression:
1760 case Magick::JPEGCompression:
1762 case Magick::LZWCompression:
1764 case Magick::RLECompression:
1768 case Magick::ZipCompression:
1792magick_to_octave_value (
const Magick::EndianType& magick)
1796 case Magick::LSBEndian:
1798 case Magick::MSBEndian:
1806magick_to_octave_value (
const Magick::OrientationType& magick)
1811 case Magick::TopLeftOrientation:
1813 case Magick::TopRightOrientation:
1815 case Magick::BottomRightOrientation:
1817 case Magick::BottomLeftOrientation:
1819 case Magick::LeftTopOrientation:
1821 case Magick::RightTopOrientation:
1823 case Magick::RightBottomOrientation:
1825 case Magick::LeftBottomOrientation:
1833magick_to_octave_value (
const Magick::ResolutionType& magick)
1837 case Magick::PixelsPerInchResolution:
1839 case Magick::PixelsPerCentimeterResolution:
1847is_valid_exif (
const std::string& val)
1851 return (! val.empty () && val !=
"unknown");
1856 const std::string& key)
1858 const std::string attr = img.attribute (
"EXIF:" + key);
1859 if (is_valid_exif (attr))
1866 const std::string& key)
1868 const std::string attr = img.attribute (
"EXIF:" + key);
1869 if (is_valid_exif (attr))
1873 ColumnVector values (std::count (attr.begin (), attr.end (),
',') +1);
1875 std::istringstream sstream (attr);
1877 while (std::getline (sstream, sub,
char (
',')))
1879 if (sscanf (sub.c_str (),
"%f", &number) != 1)
1880 error (
"fill_exif_ints: failed to read EXIF value as float");
1882 values(n++) = number;
1891 const std::string& key)
1893 const std::string attr = img.attribute (
"EXIF:" + key);
1894 if (is_valid_exif (attr))
1899 ColumnVector values (std::count (attr.begin (), attr.end (),
',') +1);
1901 std::istringstream sstream (attr);
1903 while (std::getline (sstream, sub,
','))
1905 if (sscanf (sub.c_str (),
"%i/%i", &numerator, &denominator) != 2)
1906 error (
"fill_exif_floats: failed to read EXIF numerator/demoninator pair");
1908 values(n++) =
double (numerator) /
double (denominator);
1917DEFUN (__magick_finfo__, args, ,
1928#if defined (HAVE_MAGICK)
1930 if (args.length () < 1 || ! args(0).is_string ())
1933 maybe_initialize_magick ();
1935 const std::string filename = args(0).string_value ();
1937 std::vector<Magick::Image> imvec;
1938 read_file (filename, imvec);
1941 const std::string
format = imvec[0].magick ();
1961 static const char *fields[] =
2024 const sys::file_stat fs (filename);
2026 error (
"imfinfo: error reading '%s': %s", filename.c_str (),
2027 fs.error ().c_str ());
2029 const sys::localtime mtime (fs.mtime ());
2030 const std::string filetime = mtime.strftime (
"%e-%b-%Y %H:%M:%S");
2040 const Magick::Image img = imvec[frame];
2045 octave_value (get_depth (
const_cast<Magick::Image&
> (img))));
2050 std::string color_type;
2052 if (is_indexed (img))
2054 color_type =
"indexed";
2055 cmap = read_maps (
const_cast<Magick::Image&
> (img))(0).matrix_value ();
2059 switch (img.type ())
2061 case Magick::BilevelType:
2062 case Magick::GrayscaleType:
2063 case Magick::GrayscaleMatteType:
2064 color_type =
"grayscale";
2067 case Magick::TrueColorType:
2068 case Magick::TrueColorMatteType:
2069 color_type =
"truecolor";
2072 case Magick::PaletteType:
2073 case Magick::PaletteMatteType:
2075 color_type =
"indexed";
2078 case Magick::ColorSeparationType:
2079 case Magick::ColorSeparationMatteType:
2080 color_type =
"CMYK";
2084 color_type =
"undefined";
2096 double *chroma_fvec = chromaticities.
rwdata ();
2097 img.chromaWhitePoint (&chroma_fvec[0], &chroma_fvec[1]);
2098 img.chromaRedPrimary (&chroma_fvec[2], &chroma_fvec[3]);
2099 img.chromaGreenPrimary (&chroma_fvec[4], &chroma_fvec[5]);
2100 img.chromaBluePrimary (&chroma_fvec[6], &chroma_fvec[7]);
2101 if (chromaticities.
nnz () == 0)
2115 info_frame.
setfield (
"Compression",
2116 magick_to_octave_value (img.compressType ()));
2117 info_frame.
setfield (
"Orientation",
2118 magick_to_octave_value (img.orientation ()));
2119 info_frame.
setfield (
"ResolutionUnit",
2120 magick_to_octave_value (img.resolutionUnits ()));
2122 magick_to_octave_value (img.endian ()));
2128 Magick::Image& cimg =
const_cast<Magick::Image&
> (img);
2137 static const char *base_exif_str_fields[] =
2148 static const string_vector base_exif_str (base_exif_str_fields);
2152 info_frame.
setfield (base_exif_str[field],
2154 fill_exif (info_frame, cimg, base_exif_str[field]);
2159 if (! cimg.attribute (
"EXIF:ExifVersion").empty ())
2165 static const char *exif_str_fields[] =
2169 "DateTimeDigitized",
2172 "SubSecTimeOriginal",
2173 "SubSecTimeDigitized",
2180 "SpectralSensitivity",
2190 fill_exif (camera, cimg, exif_str[field]);
2193 static const char *exif_int_fields[] =
2198 "PhotographicSensitivity",
2199 "StandardOutputSensitivity",
2200 "RecommendedExposureIndex",
2202 "ISOSpeedLatitudeyyy",
2203 "ISOSpeedLatitudezzz",
2204 "FocalPlaneResolutionUnit",
2205 "FocalLengthIn35mmFilm",
2228 "SubjectDistanceRange",
2234 fill_exif_ints (camera, cimg, exif_int[field]);
2237 static const char *exif_float_fields[] =
2240 "CompressedBitsPerPixel",
2243 "ShutterSpeedValue",
2246 "ExposureBiasValue",
2251 "FocalPlaneXResolution",
2252 "FocalPlaneYResolution",
2256 "LensSpecification",
2262 fill_exif_floats (camera, cimg, exif_float[field]);
2267 if (cimg.attribute (
"EXIF:GPSInfo") !=
"unknown")
2273 static const char *gps_str_fields[] =
2283 "GPSImgDirectionRef",
2285 "GPSDestLatitudeRef",
2286 "GPSDestLongitudeRef",
2287 "GPSDestBearingRef",
2288 "GPSDestDistanceRef",
2295 fill_exif (gps, cimg, gps_str[field]);
2297 static const char *gps_int_fields[] =
2305 fill_exif_ints (gps, cimg, gps_int[field]);
2307 static const char *gps_float_fields[] =
2316 "GPSHPositioningError",
2328 fill_exif_floats (gps, cimg, gps_float[field]);
2341 static std::map<octave_idx_type, std::string> disposal_methods
2342 = init_disposal_methods ();
2345 methods[frame] = disposal_methods[imvec[frame].gifDisposeMethod ()];
2356 octave_unused_parameter (args);
2368DEFUN (__magick_formats__, args, ,
2376 if (args.length () != 1 || ! args(0).isstruct ())
2381#if defined (HAVE_MAGICK)
2383 maybe_initialize_magick ();
2393 fmt.
setfield (
"multipage", coder.isMultiFrame () ?
true :
false);
2396 if (! coder.isReadable ())
2398 if (! coder.isWritable ())
2402 catch (
const Magick::Exception&)
2417 return ovl (formats);
2425OCTAVE_END_NAMESPACE(octave)
#define COMPRESS_MAGICK_IMAGE_VECTOR(GM_TYPE)
octave_value_list read_images(std::vector< Magick::Image > &imvec, const Array< octave_idx_type > &frameidx, const octave_idx_type &nargout, const octave_scalar_map &options)
charNDArray max(char d, const charNDArray &m)
N Dimensional Array with copy-on-write semantics.
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
int ndims() const
Size of the specified dimension.
octave_idx_type nnz() const
Count nonzero elements.
octave_idx_type rows() const
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
octave_idx_type columns() const
bool isempty() const
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Vector representing the dimensions (size) of an Array.
static octave_int< T > max()
octave_scalar_map checkelem(octave_idx_type n) const
string_vector fieldnames() const
void delete_elements(const octave::idx_vector &i)
void setfield(const std::string &key, const Cell &val)
octave_idx_type numel() const
bool fast_elem_insert(octave_idx_type n, const octave_scalar_map &rhs)
void setfield(const std::string &key, const octave_value &val)
octave_value getfield(const std::string &key) const
bool is_uint32_type() const
boolNDArray bool_array_value(bool warn=false) const
uint16NDArray uint16_array_value() const
int int_value(bool req_int=false, bool frc_str_conv=false) const
bool is_scalar_type() const
Array< std::string > cellstr_value() const
bool is_single_type() const
Array< int > xint_vector_value(const char *fmt,...) const
bool is_uint8_type() const
bool is_uint16_type() const
double scalar_value(bool frc_str_conv=false) const
std::string string_value(bool force=false) const
bool is_matrix_type() const
NDArray array_value(bool frc_str_conv=false) const
uint8NDArray uint8_array_value() const
ColumnVector column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
FloatNDArray float_array_value(bool frc_str_conv=false) const
uint32NDArray uint32_array_value() const
octave::range< double > range_value() const
unsigned int uint_value(bool req_int=false, bool frc_str_conv=false) const
octave_idx_type numel() const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void warning(const char *fmt,...)
void warning_with_id(const char *id, const char *fmt,...)
void error(const char *fmt,...)
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
std::complex< double > w(std::complex< double > z, double relerr=0)
T::size_type numel(const T &str)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
std::size_t format(std::ostream &os, const char *fmt,...)