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
00026
00027
00028
00029
00030
00031
00035
00036
00037 #ifndef OPENIMAGEIO_IMAGEBUF_H
00038 #define OPENIMAGEIO_IMAGEBUF_H
00039
00040 #include "imageio.h"
00041 #include "fmath.h"
00042 #include "imagecache.h"
00043
00044 #ifdef OPENIMAGEIO_NAMESPACE
00045 namespace OPENIMAGEIO_NAMESPACE {
00046 #endif
00047
00048 namespace OpenImageIO {
00049
00050
00056 class DLLPUBLIC ImageBuf {
00057 public:
00061 ImageBuf (const std::string &name = std::string(),
00062 ImageCache *imagecache = NULL);
00063
00067 ImageBuf (const std::string &name, const ImageSpec &spec);
00068
00071 virtual ~ImageBuf ();
00072
00075 virtual void clear ();
00076
00079 virtual void reset (const std::string &name = std::string(),
00080 ImageCache *imagecache = NULL);
00081
00084 virtual void reset (const std::string &name, const ImageSpec &spec);
00085
00091 virtual void alloc (const ImageSpec &spec);
00092
00098 virtual bool read (int subimage=0, bool force=false,
00099 TypeDesc convert=TypeDesc::UNKNOWN,
00100 OpenImageIO::ProgressCallback progress_callback=NULL,
00101 void *progress_callback_data=NULL);
00102
00107 virtual bool init_spec (const std::string &filename);
00108
00114 virtual bool save (const std::string &filename = std::string(),
00115 const std::string &fileformat = std::string(),
00116 OpenImageIO::ProgressCallback progress_callback=NULL,
00117 void *progress_callback_data=NULL) const;
00118
00123 virtual bool write (ImageOutput *out,
00124 OpenImageIO::ProgressCallback progress_callback=NULL,
00125 void *progress_callback_data=NULL) const;
00126
00129 std::string geterror (void) const {
00130 std::string e = m_err;
00131 m_err.clear();
00132 return e;
00133 }
00136 std::string error_message () const { return geterror (); }
00137
00140 const ImageSpec & spec () const { return m_spec; }
00141
00144 const std::string & name (void) const { return m_name.string(); }
00145
00149 const std::string & file_format_name (void) const { return m_fileformat.string(); }
00150
00153 int subimage () const { return m_current_subimage; }
00154
00157 int nsubimages () const { return m_nsubimages; }
00158
00161 int nchannels () const { return m_spec.nchannels; }
00162
00165 float getchannel (int x, int y, int c) const;
00166
00170 void getpixel (int x, int y, float *pixel, int maxchannels=1000) const;
00171
00175 void interppixel (float x, float y, float *pixel) const;
00176
00180 void interppixel_NDC (float x, float y, float *pixel) const {
00181 interppixel (spec().x + x * spec().width,
00182 spec().y + y * spec().height, pixel);
00183 }
00184
00188 void interppixel_NDC_full (float x, float y, float *pixel) const {
00189 interppixel (spec().full_x + x * spec().full_width,
00190 spec().full_y + y * spec().full_height, pixel);
00191 }
00192
00196 void setpixel (int x, int y, const float *pixel, int maxchannels=1000);
00197
00201 void setpixel (int i, const float *pixel, int maxchannels=1000);
00202
00211 bool copy_pixels (int xbegin, int xend, int ybegin, int yend,
00212 TypeDesc format, void *result) const;
00213
00222 template<typename T>
00223 bool copy_pixels (int xbegin, int xend, int ybegin, int yend,
00224 T *result) const;
00225
00232 template<typename T>
00233 bool copy_pixels (int xbegin, int xend, int ybegin, int yend,
00234 std::vector<T> &result) const
00235 {
00236 result.resize (nchannels() * ((yend-ybegin)*(xend-xbegin)));
00237 return _copy_pixels (xbegin, xend, ybegin, yend, &result[0]);
00238 }
00239
00240 int orientation () const { return m_orientation; }
00241
00242 int oriented_width () const;
00243 int oriented_height () const;
00244 int oriented_x () const;
00245 int oriented_y () const;
00246 int oriented_full_width () const;
00247 int oriented_full_height () const;
00248 int oriented_full_x () const;
00249 int oriented_full_y () const;
00250
00253 int xbegin () const { return spec().x; }
00254
00257 int xend () const { return spec().x + spec().width; }
00258
00261 int ybegin () const { return spec().y; }
00262
00265 int yend () const { return spec().y + spec().height; }
00266
00269 int xmin () const { return spec().x; }
00270
00273 int xmax () const { return spec().x + spec().width - 1; }
00274
00277 int ymin () const { return spec().y; }
00278
00281 int ymax () const { return spec().y + spec().height - 1; }
00282
00285 void zero ();
00286
00289 void fill (const float *pixel);
00290
00293 void fill (const float *pixel, int xbegin, int xend, int ybegin, int yend);
00294
00295 bool pixels_valid (void) const { return m_pixels_valid; }
00296
00297 bool localpixels () const { return m_localpixels; }
00298 ImageCache *imagecache () const { return m_imagecache; }
00299
00318 template<typename BUFT, typename USERT=float>
00319 class Iterator {
00320 public:
00323 Iterator (ImageBuf &ib)
00324 : m_ib(&ib), m_xbegin(ib.xbegin()), m_ybegin(ib.ybegin()),
00325 m_xend(ib.xend()), m_yend(ib.yend()), m_tile(NULL)
00326 { pos (m_xbegin,m_ybegin); }
00329 Iterator (ImageBuf &ib, int x, int y)
00330 : m_ib(&ib), m_xbegin(ib.xbegin()), m_ybegin(ib.ybegin()),
00331 m_xend(ib.xend()), m_yend(ib.yend()), m_tile(NULL)
00332 { pos (x, y); }
00335 Iterator (ImageBuf &ib, int xbegin, int ybegin, int xend, int yend)
00336 : m_ib(&ib), m_xbegin(std::max(xbegin,ib.xbegin())),
00337 m_ybegin(std::max(ybegin,ib.ybegin())),
00338 m_xend(std::min(xend,ib.xend())),
00339 m_yend(std::min(yend,ib.yend())), m_tile(NULL)
00340 { pos (m_xbegin, m_ybegin); }
00341 Iterator (const Iterator &i)
00342 : m_ib (i.m_ib), m_xbegin(i.m_xbegin), m_xend(i.m_xend),
00343 m_ybegin(i.m_ybegin), m_yend(i.m_yend), m_tile(NULL)
00344 {
00345 pos (i.m_x, i.m_y);
00346 }
00347 ~Iterator () {
00348 if (m_tile)
00349 m_ib->imagecache()->release_tile (m_tile);
00350 }
00351
00354 void pos (int x, int y) {
00355 if (! valid(x,y))
00356 m_proxy.set (NULL);
00357 else if (m_ib->localpixels())
00358 m_proxy.set ((BUFT *)m_ib->pixeladdr (x, y));
00359 else
00360 m_proxy.set ((BUFT *)m_ib->retile (m_ib->subimage(), x, y,
00361 m_tile, m_tilexbegin, m_tileybegin));
00362 m_x = x; m_y = y;
00363 }
00364
00367 void operator++ () {
00368 if (++m_x >= m_xend) {
00369 m_x = m_xbegin;
00370 ++m_y;
00371 }
00372 pos (m_x, m_y);
00373
00374
00375 }
00378 void operator++ (int) {
00379 (*this)++;
00380 }
00381
00384 const Iterator & operator= (const Iterator &i) {
00385 if (m_tile)
00386 m_ib->imagecache()->release_tile (m_tile);
00387 m_tile = NULL;
00388 m_ib = i.m_ib;
00389 m_xbegin = i.m_xbegin; m_xend = i.m_xend;
00390 m_ybegin = i.m_ybegin; m_yend = i.m_yend;
00391 pos (i.m_x, i.m_y);
00392 return *this;
00393 }
00394
00397 int x () const { return m_x; }
00400 int y () const { return m_y; }
00401
00405 bool valid () const {
00406 return (m_x >= m_xbegin && m_x < m_xend &&
00407 m_y >= m_ybegin && m_y < m_yend);
00408 }
00409
00413 bool valid (int x, int y) const {
00414 return (x >= m_xbegin && x < m_xend &&
00415 y >= m_ybegin && y < m_yend);
00416 }
00417
00420 DataArrayProxy<BUFT,USERT>& operator* () { return m_proxy; }
00421
00424 USERT operator[] (int i) const { return m_proxy[i]; }
00425
00429 DataProxy<BUFT,USERT> operator[] (int i) { return m_proxy[i]; }
00430
00431 void * rawptr () const { return m_proxy.get(); }
00432
00433 private:
00434 ImageBuf *m_ib;
00435 int m_xbegin, m_ybegin, m_xend, m_yend;
00436 int m_x, m_y;
00437 DataArrayProxy<BUFT,USERT> m_proxy;
00438 ImageCache::Tile *m_tile;
00439 int m_tilexbegin, m_tileybegin;
00440 };
00441
00442
00445 template<typename BUFT, typename USERT=float>
00446 class ConstIterator {
00447 public:
00450 ConstIterator (const ImageBuf &ib)
00451 : m_ib(&ib), m_xbegin(ib.xbegin()), m_xend(ib.xend()),
00452 m_ybegin(ib.ybegin()), m_yend(ib.yend()), m_tile(NULL)
00453 { pos (m_xbegin,m_ybegin); }
00456 ConstIterator (const ImageBuf &ib, int x, int y)
00457 : m_ib(&ib), m_xbegin(ib.xbegin()), m_xend(ib.xend()),
00458 m_ybegin(ib.ybegin()), m_yend(ib.yend()), m_tile(NULL)
00459 { pos (x, y); }
00462 ConstIterator (const ImageBuf &ib, int xbegin, int xend,
00463 int ybegin, int yend)
00464 : m_ib(&ib), m_xbegin(std::max(xbegin,ib.xbegin())),
00465 m_xend(std::min(xend,ib.xend())),
00466 m_ybegin(std::max(ybegin,ib.ybegin())),
00467 m_yend(std::min(yend,ib.yend())), m_tile(NULL)
00468 { pos (m_xbegin, m_ybegin); }
00469 ConstIterator (const ConstIterator &i)
00470 : m_ib (i.m_ib), m_xbegin(i.m_xbegin), m_xend(i.m_xend),
00471 m_ybegin(i.m_ybegin), m_yend(i.m_yend), m_tile(NULL)
00472 {
00473 pos (i.m_x, i.m_y);
00474 }
00475
00476 ~ConstIterator () {
00477 if (m_tile)
00478 m_ib->imagecache()->release_tile (m_tile);
00479 }
00480
00483 void pos (int x, int y) {
00484 if (! valid(x,y))
00485 m_proxy.set (NULL);
00486 else if (m_ib->localpixels())
00487 m_proxy.set ((BUFT *)m_ib->pixeladdr (x, y));
00488 else
00489 m_proxy.set ((BUFT *)m_ib->retile (m_ib->subimage(), x, y,
00490 m_tile, m_tilexbegin, m_tileybegin));
00491 m_x = x; m_y = y;
00492 }
00493
00496 void operator++ () {
00497 if (++m_x >= m_xend) {
00498 m_x = m_xbegin;
00499 ++m_y;
00500 }
00501 pos (m_x, m_y);
00502
00503
00504 }
00507 void operator++ (int) {
00508 (*this)++;
00509 }
00510
00513 const ConstIterator & operator= (const ConstIterator &i) {
00514 if (m_tile)
00515 m_ib->imagecache()->release_tile (m_tile);
00516 m_tile = NULL;
00517 m_ib = i.m_ib;
00518 m_xbegin = i.m_xbegin; m_xend = i.m_xend;
00519 m_ybegin = i.m_ybegin; m_yend = i.m_yend;
00520 pos (i.m_x, i.m_y);
00521 return *this;
00522 }
00523
00526 int x () const { return m_x; }
00529 int y () const { return m_y; }
00530
00534 bool valid () const {
00535 return (m_x >= m_xbegin && m_x < m_xend &&
00536 m_y >= m_ybegin && m_y < m_yend);
00537 }
00538
00542 bool valid (int x, int y) const {
00543 return (x >= m_xbegin && x < m_xend &&
00544 y >= m_ybegin && y < m_yend);
00545 }
00546
00549 ConstDataArrayProxy<BUFT,USERT>& operator* () const { return m_proxy; }
00550
00553 USERT operator[] (int i) const { return m_proxy[i]; }
00554
00555 const void * rawptr () const { return m_proxy.get(); }
00556
00557 private:
00558 const ImageBuf *m_ib;
00559 int m_xbegin, m_xend, m_ybegin, m_yend;
00560 int m_x, m_y;
00561 ConstDataArrayProxy<BUFT,USERT> m_proxy;
00562 ImageCache::Tile *m_tile;
00563 int m_tilexbegin, m_tileybegin;
00564 };
00565
00566
00567 protected:
00568 ustring m_name;
00569 ustring m_fileformat;
00570 int m_nsubimages;
00571 int m_current_subimage;
00572 ImageSpec m_spec;
00573 std::vector<char> m_pixels;
00574 bool m_localpixels;
00575 bool m_spec_valid;
00576 bool m_pixels_valid;
00577 bool m_badfile;
00578 mutable std::string m_err;
00579 int m_orientation;
00580 float m_pixelaspect;
00581 ImageCache *m_imagecache;
00582 TypeDesc m_cachedpixeltype;
00583
00584 void realloc ();
00585
00586
00587
00588 const void *pixeladdr (int x, int y) const;
00589
00590
00591
00592 void *pixeladdr (int x, int y);
00593
00594
00595
00596
00597 const void * retile (int subimage, int x, int y, ImageCache::Tile* &tile,
00598 int &tilexbegin, int &tileybegin) const;
00599 };
00600
00601
00602
00603 namespace ImageBufAlgo {
00604
00610
00611 bool DLLPUBLIC add (ImageBuf &dst, const ImageBuf &A, const ImageBuf &B, int options=0);
00612
00615 enum DLLPUBLIC AddOptions
00616 {
00617 ADD_DEFAULT = 0,
00618 ADD_RETAIN_DST = 1,
00619 ADD_CLEAR_DST = 0,
00620 ADD_RETAIN_WINDOWS = 2,
00621 ADD_ALIGN_WINDOWS = 0,
00622 };
00623
00624
00625
00632 bool DLLPUBLIC crop (ImageBuf &dst, const ImageBuf &src,
00633 int xbegin, int xend, int ybegin, int yend, int options);
00634
00635 enum DLLPUBLIC CropOptions
00636 {
00637 CROP_CUT,
00638 CROP_WINDOW,
00639 CROP_BLACK,
00640 CROP_WHITE,
00641 CROP_TRANS
00642 };
00643
00644
00645 };
00646
00647
00648 };
00649
00650 #ifdef OPENIMAGEIO_NAMESPACE
00651 };
00652 using namespace OPENIMAGEIO_NAMESPACE;
00653 #endif
00654
00655 #endif // OPENIMAGEIO_IMAGEBUF_H