37 #ifndef OPENIMAGEIO_IMAGEBUF_H
38 #define OPENIMAGEIO_IMAGEBUF_H
43 # pragma warning (disable : 4251)
65 int xbegin, xend, ybegin, yend, zbegin, zend;
70 ROI () : xbegin(std::numeric_limits<int>::min()) { }
74 ROI (
int xbegin,
int xend,
int ybegin,
int yend,
75 int zbegin=0,
int zend=1,
int chbegin=0,
int chend=10000)
76 : xbegin(xbegin), xend(xend), ybegin(ybegin), yend(yend),
77 zbegin(zbegin), zend(zend), chbegin(chbegin), chend(chend)
81 bool defined ()
const {
return (xbegin != std::numeric_limits<int>::min()); }
84 int width ()
const {
return xend - xbegin; }
85 int height ()
const {
return yend - ybegin; }
86 int depth ()
const {
return zend - zbegin; }
91 int nchannels ()
const {
return chend - chbegin; }
94 imagesize_t npixels ()
const {
97 imagesize_t w = width(), h = height(), d = depth();
107 static ROI All () {
return ROI(); }
110 friend bool operator== (
const ROI &a,
const ROI &b) {
111 return (a.xbegin == b.xbegin && a.xend == b.xend &&
112 a.ybegin == b.ybegin && a.yend == b.yend &&
113 a.zbegin == b.zbegin && a.zend == b.zend &&
114 a.chbegin == b.chbegin && a.chend == b.chend);
117 friend bool operator!= (
const ROI &a,
const ROI &b) {
118 return (a.xbegin != b.xbegin || a.xend != b.xend ||
119 a.ybegin != b.ybegin || a.yend != b.yend ||
120 a.zbegin != b.zbegin || a.zend != b.zend ||
121 a.chbegin != b.chbegin || a.chend != b.chend);
125 friend std::ostream & operator<< (std::ostream &out,
const ROI &roi) {
126 out << roi.xbegin <<
' ' << roi.xend <<
' ' << roi.ybegin <<
' '
127 << roi.yend <<
' ' << roi.zbegin <<
' ' << roi.zend <<
' '
128 << roi.chbegin <<
' ' << roi.chend;
135 OIIO_API ROI roi_union (
const ROI &A,
const ROI &B);
138 OIIO_API ROI roi_intersection (
const ROI &A,
const ROI &B);
141 OIIO_API ROI get_roi (
const ImageSpec &spec);
144 OIIO_API ROI get_roi_full (
const ImageSpec &spec);
148 OIIO_API
void set_roi (ImageSpec &spec,
const ROI &newroi);
152 OIIO_API
void set_roi_full (ImageSpec &spec,
const ROI &newroi);
165 class OIIO_API ImageBuf {
175 ImageBuf (
const std::string &name, ImageCache *imagecache = NULL);
180 ImageBuf (
const std::string &name,
const ImageSpec &spec);
185 ImageBuf (
const std::string &name,
const ImageSpec &spec,
void *buffer);
189 ImageBuf (
const ImageBuf &src);
201 void reset (
const std::string &name, ImageCache *imagecache = NULL);
205 void reset (
const std::string &name,
const ImageSpec &spec);
212 void alloc (
const ImageSpec &spec);
215 bool initialized ()
const;
222 bool read (
int subimage=0,
int miplevel=0,
bool force=
false,
223 TypeDesc convert=TypeDesc::UNKNOWN,
224 ProgressCallback progress_callback=NULL,
225 void *progress_callback_data=NULL);
231 bool init_spec (
const std::string &filename,
232 int subimage,
int miplevel);
238 bool save (
const std::string &filename = std::string(),
239 const std::string &fileformat = std::string(),
240 ProgressCallback progress_callback=NULL,
241 void *progress_callback_data=NULL)
const;
247 bool write (ImageOutput *out,
248 ProgressCallback progress_callback=NULL,
249 void *progress_callback_data=NULL)
const;
253 void copy_metadata (
const ImageBuf &src);
260 bool copy_pixels (
const ImageBuf &src);
276 bool copy (
const ImageBuf &src);
279 void swap (ImageBuf &other) { std::swap (m_impl, other.m_impl); }
284 TINYFORMAT_WRAP_FORMAT (
void, error,
const,
285 std::ostringstream msg;, msg, append_error(msg.str());)
289 bool has_error (
void)
const;
294 std::string geterror (
void)
const;
298 const ImageSpec & spec ()
const;
304 ImageSpec & specmod ();
311 const ImageSpec & nativespec ()
const;
315 const std::string & name (
void)
const;
320 const std::string & file_format_name (
void)
const;
324 int subimage ()
const;
328 int nsubimages ()
const;
332 int miplevel ()
const;
336 int nmiplevels ()
const;
340 int nchannels ()
const;
344 enum WrapMode { WrapDefault, WrapBlack, WrapClamp, WrapPeriodic,
345 WrapMirror, _WrapLast };
349 float getchannel (
int x,
int y,
int z,
int c, WrapMode wrap=WrapBlack)
const;
354 void getpixel (
int x,
int y,
float *pixel,
int maxchannels=1000)
const {
355 getpixel (x, y, 0, pixel, maxchannels);
361 void getpixel (
int x,
int y,
int z,
float *pixel,
int maxchannels=1000,
362 WrapMode wrap=WrapBlack)
const;
367 void interppixel (
float x,
float y,
float *pixel,
368 WrapMode wrap=WrapBlack)
const;
376 void interppixel_NDC (
float s,
float t,
float *pixel,
377 WrapMode wrap=WrapBlack)
const;
382 void interppixel_NDC_full (
float s,
float t,
float *pixel,
383 WrapMode wrap=WrapBlack)
const;
388 void setpixel (
int x,
int y,
const float *pixel,
int maxchannels=1000) {
389 setpixel (x, y, 0, pixel, maxchannels);
395 void setpixel (
int x,
int y,
int z,
396 const float *pixel,
int maxchannels=1000);
401 void setpixel (
int i,
const float *pixel,
int maxchannels=1000);
414 bool get_pixel_channels (
int xbegin,
int xend,
int ybegin,
int yend,
415 int zbegin,
int zend,
int chbegin,
int chend,
416 TypeDesc format,
void *result,
417 stride_t xstride=AutoStride,
418 stride_t ystride=AutoStride,
419 stride_t zstride=AutoStride)
const;
431 bool get_pixels (
int xbegin,
int xend,
int ybegin,
int yend,
432 int zbegin,
int zend,
433 TypeDesc format,
void *result,
434 stride_t xstride=AutoStride,
435 stride_t ystride=AutoStride,
436 stride_t zstride=AutoStride)
const;
449 bool get_pixel_channels (
int xbegin,
int xend,
int ybegin,
int yend,
450 int zbegin,
int zend,
int chbegin,
int chend,
451 T *result, stride_t xstride=AutoStride,
452 stride_t ystride=AutoStride,
453 stride_t zstride=AutoStride)
const;
456 bool get_pixels (
int xbegin,
int xend,
int ybegin,
int yend,
457 int zbegin,
int zend, T *result,
458 stride_t xstride=AutoStride, stride_t ystride=AutoStride,
459 stride_t zstride=AutoStride)
const
461 return get_pixel_channels (xbegin, xend, ybegin, yend, zbegin, zend,
462 0, nchannels(), result,
463 xstride, ystride, zstride);
473 bool get_pixels (
int xbegin_,
int xend_,
int ybegin_,
int yend_,
474 int zbegin_,
int zend_,
475 std::vector<T> &result)
const
477 result.resize (nchannels() * ((zend_-zbegin_)*(yend_-ybegin_)*(xend_-xbegin_)));
478 return get_pixels (xbegin_, xend_, ybegin_, yend_, zbegin_, zend_,
482 int orientation ()
const;
484 int oriented_width ()
const;
485 int oriented_height ()
const;
486 int oriented_x ()
const;
487 int oriented_y ()
const;
488 int oriented_full_width ()
const;
489 int oriented_full_height ()
const;
490 int oriented_full_x ()
const;
491 int oriented_full_y ()
const;
532 void set_full (
int xbegin,
int xend,
int ybegin,
int yend,
533 int zbegin,
int zend,
const float *bordercolor=NULL);
535 bool pixels_valid (
void)
const;
537 TypeDesc pixeltype ()
const;
542 void *localpixels ();
543 const void *localpixels ()
const;
547 bool cachedpixels ()
const;
549 ImageCache *imagecache ()
const;
554 const void *pixeladdr (
int x,
int y,
int z=0)
const;
559 void *pixeladdr (
int x,
int y) {
return pixeladdr (x, y, 0); }
564 void *pixeladdr (
int x,
int y,
int z);
572 int deep_samples (
int x,
int y,
int z=0)
const;
578 const void *deep_pixel_ptr (
int x,
int y,
int z,
int c)
const;
584 float deep_value (
int x,
int y,
int z,
int c,
int s)
const;
587 DeepData *deepdata ();
588 const DeepData *deepdata ()
const;
590 friend class IteratorBase;
594 IteratorBase (
const ImageBuf &ib, WrapMode wrap)
595 : m_ib(&ib), m_tile(NULL), m_proxydata(NULL)
602 IteratorBase (
const ImageBuf &ib,
const ROI &roi, WrapMode wrap)
603 : m_ib(&ib), m_tile(NULL), m_proxydata(NULL)
607 m_rng_xbegin = roi.xbegin;
608 m_rng_xend = roi.xend;
609 m_rng_ybegin = roi.ybegin;
610 m_rng_yend = roi.yend;
611 m_rng_zbegin = roi.zbegin;
612 m_rng_zend = roi.zend;
620 IteratorBase (
const ImageBuf &ib,
int xbegin,
int xend,
621 int ybegin,
int yend,
int zbegin,
int zend,
623 : m_ib(&ib), m_tile(NULL), m_proxydata(NULL)
626 m_rng_xbegin = xbegin;
628 m_rng_ybegin = ybegin;
630 m_rng_zbegin = zbegin;
634 IteratorBase (
const IteratorBase &i)
636 m_rng_xbegin(i.m_rng_xbegin), m_rng_xend(i.m_rng_xend),
637 m_rng_ybegin(i.m_rng_ybegin), m_rng_yend(i.m_rng_yend),
638 m_rng_zbegin(i.m_rng_zbegin), m_rng_zend(i.m_rng_zend),
639 m_tile(NULL), m_proxydata(i.m_proxydata)
646 m_ib->imagecache()->release_tile (m_tile);
651 const IteratorBase & assign_base (
const IteratorBase &i) {
653 m_ib->imagecache()->release_tile (m_tile);
655 m_proxydata = i.m_proxydata;
658 m_rng_xbegin = i.m_rng_xbegin; m_rng_xend = i.m_rng_xend;
659 m_rng_ybegin = i.m_rng_ybegin; m_rng_yend = i.m_rng_yend;
660 m_rng_zbegin = i.m_rng_zbegin; m_rng_zend = i.m_rng_zend;
666 int x ()
const {
return m_x; }
669 int y ()
const {
return m_y; }
672 int z ()
const {
return m_z; }
675 bool valid ()
const {
681 bool valid (
int x_,
int y_,
int z_=0)
const {
682 return (x_ >= m_rng_xbegin && x_ < m_rng_xend &&
683 y_ >= m_rng_ybegin && y_ < m_rng_yend &&
684 z_ >= m_rng_zbegin && z_ < m_rng_zend);
689 bool exists (
int x_,
int y_,
int z_=0)
const {
690 return (x_ >= m_img_xbegin && x_ < m_img_xend &&
691 y_ >= m_img_ybegin && y_ < m_img_yend &&
692 z_ >= m_img_zbegin && z_ < m_img_zend);
696 bool exists ()
const {
707 return (m_valid ==
false && m_x == m_rng_xbegin &&
708 m_y == m_rng_ybegin && m_z == m_rng_zend);
712 int deep_samples () {
return m_ib->deep_samples (m_x, m_y, m_z); }
715 WrapMode wrap ()
const {
return m_wrap; }
719 void pos (
int x_,
int y_,
int z_=0) {
720 if (x_ == m_x+1 && x_ < m_rng_xend && y_ == m_y && z_ == m_z &&
721 m_valid && m_exists) {
727 DASSERT ((x_ < m_img_xend) == m_exists);
730 bool v = valid(x_,y_,z_);
731 bool e = exists(x_,y_,z_);
734 m_x = x_; m_y = y_; m_z = z_;
735 if (m_wrap == WrapBlack) {
736 m_proxydata = (
char *)m_ib->blackpixel();
738 m_ib->do_wrap (x_, y_, z_, m_wrap);
739 m_proxydata = (
char *)m_ib->pixeladdr (x_, y_, z_);
746 m_proxydata = (
char *)m_ib->pixeladdr (x_, y_, z_);
749 m_proxydata = (
char *)m_ib->retile (x_, y_, z_, m_tile,
750 m_tilexbegin, m_tileybegin,
751 m_tilezbegin, m_tilexend,
753 m_x = x_; m_y = y_; m_z = z_;
761 if (++m_x < m_rng_xend) {
772 if (++m_y >= m_rng_yend) {
774 if (++m_z >= m_rng_zend) {
784 void operator++ (
int) {
790 return ROI (m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend,
791 m_rng_zbegin, m_rng_zend, 0, m_ib->nchannels());
795 friend class ImageBuf;
796 friend class ImageBufImpl;
797 const ImageBuf *m_ib;
798 bool m_valid, m_exists;
802 int m_img_xbegin, m_img_xend, m_img_ybegin, m_img_yend,
803 m_img_zbegin, m_img_zend;
805 int m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend,
806 m_rng_zbegin, m_rng_zend;
808 ImageCache::Tile *m_tile;
809 int m_tilexbegin, m_tileybegin, m_tilezbegin;
812 size_t m_pixel_bytes;
818 void init_ib (WrapMode wrap) {
819 const ImageSpec &spec (m_ib->spec());
821 m_localpixels = m_ib->localpixels() != NULL;
822 m_img_xbegin = spec.x; m_img_xend = spec.x+spec.width;
823 m_img_ybegin = spec.y; m_img_yend = spec.y+spec.height;
824 m_img_zbegin = spec.z; m_img_zend = spec.z+spec.depth;
825 m_nchannels = spec.nchannels;
827 m_pixel_bytes = spec.pixel_bytes();
831 m_wrap = (wrap == WrapDefault ? WrapBlack : wrap);
836 void range_is_image () {
837 m_rng_xbegin = m_img_xbegin; m_rng_xend = m_img_xend;
838 m_rng_ybegin = m_img_ybegin; m_rng_yend = m_img_yend;
839 m_rng_zbegin = m_img_zbegin; m_rng_zend = m_img_zend;
848 bool e = (m_x < m_img_xend);
852 m_proxydata += m_pixel_bytes;
855 if (m_wrap == WrapBlack) {
856 m_proxydata = (
char *)m_ib->blackpixel();
858 int x = m_x, y = m_y, z = m_z;
859 m_ib->do_wrap (x, y, z, m_wrap);
860 m_proxydata = (
char *)m_ib->pixeladdr (x, y, z);
867 if (e && m_x < m_tilexend)
869 m_proxydata += m_pixel_bytes;
871 m_proxydata = (
char *)m_ib->retile (m_x, m_y, m_z, m_tile,
872 m_tilexbegin, m_tileybegin, m_tilezbegin,
873 m_tilexend, e, m_wrap);
898 template<
typename BUFT,
typename USERT=
float>
899 class Iterator :
public IteratorBase {
903 Iterator (ImageBuf &ib, WrapMode wrap=WrapDefault)
904 : IteratorBase(ib,wrap)
906 pos (m_rng_xbegin,m_rng_ybegin,m_rng_zbegin);
910 Iterator (ImageBuf &ib,
int x,
int y,
int z=0,
911 WrapMode wrap=WrapDefault)
912 : IteratorBase(ib,wrap)
917 Iterator (ImageBuf &ib,
const ROI &roi, WrapMode wrap=WrapDefault)
918 : IteratorBase (ib, roi, wrap)
920 pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
924 Iterator (ImageBuf &ib,
int xbegin,
int xend,
925 int ybegin,
int yend,
int zbegin=0,
int zend=1,
926 WrapMode wrap=WrapDefault)
927 : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap)
929 pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
933 Iterator (Iterator &i)
934 : IteratorBase (i.m_ib, i.m_wrap)
936 pos (i.m_x, i.m_y, i.m_z);
943 const Iterator & operator= (
const Iterator &i) {
945 pos (i.m_x, i.m_y, i.m_z);
951 DataArrayProxy<BUFT,USERT>& operator* () {
952 return *(DataArrayProxy<BUFT,USERT> *)(
void *)&m_proxydata;
957 USERT operator[] (
int i)
const {
958 DataArrayProxy<BUFT,USERT> proxy((BUFT*)m_proxydata);
965 DataProxy<BUFT,USERT> operator[] (
int i) {
966 DataArrayProxy<BUFT,USERT> proxy((BUFT*)m_proxydata);
970 void * rawptr ()
const {
return m_proxydata; }
973 USERT deep_value (
int c,
int s)
const {
974 return convert_type<float,USERT>(m_ib->deep_value (m_x, m_y, m_z, c, s));
981 template<
typename BUFT,
typename USERT=
float>
982 class ConstIterator :
public IteratorBase {
986 ConstIterator (
const ImageBuf &ib, WrapMode wrap=WrapDefault)
987 : IteratorBase(ib,wrap)
989 pos (m_rng_xbegin,m_rng_ybegin,m_rng_zbegin);
993 ConstIterator (
const ImageBuf &ib,
int x_,
int y_,
int z_=0,
994 WrapMode wrap=WrapDefault)
995 : IteratorBase(ib,wrap)
1000 ConstIterator (
const ImageBuf &ib,
const ROI &roi,
1001 WrapMode wrap=WrapDefault)
1002 : IteratorBase (ib, roi, wrap)
1004 pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1008 ConstIterator (
const ImageBuf &ib,
int xbegin,
int xend,
1009 int ybegin,
int yend,
int zbegin=0,
int zend=1,
1010 WrapMode wrap=WrapDefault)
1011 : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap)
1013 pos (m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1017 ConstIterator (
const ConstIterator &i)
1020 pos (i.m_x, i.m_y, i.m_z);
1023 ~ConstIterator () { }
1027 const ConstIterator & operator= (
const ConstIterator &i) {
1029 pos (i.m_x, i.m_y, i.m_z);
1035 ConstDataArrayProxy<BUFT,USERT>& operator* ()
const {
1036 return *(ConstDataArrayProxy<BUFT,USERT> *)&m_proxydata;
1041 USERT operator[] (
int i)
const {
1042 ConstDataArrayProxy<BUFT,USERT> proxy ((BUFT*)m_proxydata);
1046 const void * rawptr ()
const {
return m_proxydata; }
1049 USERT deep_value (
int c,
int s)
const {
1050 return convert_type<float,USERT>(m_ib->deep_value (m_x, m_y, m_z, c, s));
1056 ImageBufImpl *m_impl;
1058 ImageBufImpl * impl () {
return m_impl; }
1059 const ImageBufImpl * impl ()
const {
return m_impl; }
1065 void copy_from (
const ImageBuf &src);
1070 const void * retile (
int x,
int y,
int z,
1071 ImageCache::Tile* &tile,
int &tilexbegin,
1072 int &tileybegin,
int &tilezbegin,
1073 int &tilexend,
bool exists,
1074 WrapMode wrap=WrapDefault)
const;
1076 const void *blackpixel ()
const;
1078 void do_wrap (
int &x,
int &y,
int &z, WrapMode wrap)
const;
1081 const ImageBuf& operator= (
const ImageBuf &src);
1084 void append_error (
const std::string& message)
const;
1092 #endif // OPENIMAGEIO_IMAGEBUF_H