HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
imagebuf.h
Go to the documentation of this file.
1 /*
2  Copyright 2008 Larry Gritz and the other authors and contributors.
3  All Rights Reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  * Neither the name of the software's owners nor the names of its
14  contributors may be used to endorse or promote products derived from
15  this software without specific prior written permission.
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28  (This is the Modified BSD License)
29 */
30 
31 
32 /// \file
33 /// Classes for in-memory storage and simple manipulation of whole images,
34 /// which uses ImageInput and ImageOutput underneath for the file access.
35 
36 
37 #pragma once
38 #define OPENIMAGEIO_IMAGEBUF_H
39 
40 #if defined(_MSC_VER)
41 // Ignore warnings about DLL exported classes with member variables that are template classes.
42 // This happens with the std::vector and std::string protected members of ImageBuf below.
43 # pragma warning(disable : 4251)
44 #endif
45 
46 #include <OpenImageIO/dassert.h>
47 #include <OpenImageIO/fmath.h>
48 #include <OpenImageIO/imagecache.h>
49 #include <OpenImageIO/imageio.h>
50 
51 #include <limits>
52 #include <memory>
53 
54 
56 
57 class ImageBuf;
58 
59 // Opaque type for the unique_ptr.
60 class ImageBufImpl;
62 public:
63  virtual ~ImageBufImplBase() {}
64  void operator delete(void* todel) { ::operator delete(todel); }
65 };
66 
67 
68 
69 /// Return pixel data window for this ImageSpec as a ROI.
71 get_roi(const ImageSpec& spec);
72 
73 /// Return full/display window for this ImageSpec as a ROI.
75 get_roi_full(const ImageSpec& spec);
76 
77 /// Set pixel data window for this ImageSpec to a ROI.
78 /// Does NOT change the channels of the spec, regardless of newroi.
79 OIIO_API void
80 set_roi(ImageSpec& spec, const ROI& newroi);
81 
82 /// Set full/display window for this ImageSpec to a ROI.
83 /// Does NOT change the channels of the spec, regardless of newroi.
84 OIIO_API void
85 set_roi_full(ImageSpec& spec, const ROI& newroi);
86 
87 
88 
89 
90 
91 /// An ImageBuf is a simple in-memory representation of a 2D image. It
92 /// uses ImageInput and ImageOutput underneath for its file I/O, and has
93 /// simple routines for setting and getting individual pixels, that
94 /// hides most of the details of memory layout and data representation
95 /// (translating to/from float automatically).
97 public:
98  /// Construct an empty/uninitialized ImageBuf. This is relatively
99  /// useless until you call reset().
100  ImageBuf();
101 
102  /// Construct an ImageBuf to read the named image (at the designated
103  /// subimage/MIPlevel -- but don't actually read it yet! The image
104  /// will actually be read when other methods need to access the spec
105  /// and/or pixels, or when an explicit call to init_spec() or read() is
106  /// made, whichever comes first. If a non-NULL imagecache is supplied,
107  /// it will specifiy a custom ImageCache to use; if otherwise, the
108  /// global/shared ImageCache will be used.
109  /// If 'config' is not NULL, it points to an ImageSpec giving requests
110  /// or special instructions to be passed on to the eventual
111  /// ImageInput::open() call.
112  explicit ImageBuf(string_view name, int subimage = 0, int miplevel = 0,
113  ImageCache* imagecache = NULL,
114  const ImageSpec* config = NULL);
115 
116  /// Construct an ImageBuf to read the named image -- but don't actually
117  /// read it yet! The image will actually be read when other methods
118  /// need to access the spec and/or pixels, or when an explicit call to
119  /// init_spec() or read() is made, whichever comes first. If a non-NULL
120  /// imagecache is supplied, it will specifiy a custom ImageCache to use;
121  /// if otherwise, the global/shared ImageCache will be used.
122  ImageBuf(string_view name, ImageCache* imagecache);
123 
124  /// Construct an Imagebuf given a proposed spec describing the image
125  /// size and type, and allocate storage for the pixels of the image
126  /// (whose values will be uninitialized).
127  explicit ImageBuf(const ImageSpec& spec);
128 
129  /// Construct an Imagebuf given both a name and a proposed spec
130  /// describing the image size and type, and allocate storage for
131  /// the pixels of the image (whose values will be undefined).
132  ImageBuf(string_view name, const ImageSpec& spec);
133 
134  /// Construct an ImageBuf that "wraps" a memory buffer owned by the
135  /// calling application. It can write pixels to this buffer, but
136  /// can't change its resolution or data type.
137  ImageBuf(const ImageSpec& spec, void* buffer);
138 
139  /// Construct an ImageBuf that "wraps" a memory buffer owned by the
140  /// calling application. It can write pixels to this buffer, but
141  /// can't change its resolution or data type.
142  ImageBuf(string_view name, const ImageSpec& spec, void* buffer);
143 
144  /// Construct a copy of an ImageBuf.
145  ///
146  ImageBuf(const ImageBuf& src);
147 
148  /// Move a copy of an ImageBuf.
149  ///
150  ImageBuf(ImageBuf&& src);
151 
152  /// Destructor for an ImageBuf.
153  ///
154  ~ImageBuf();
155 
156  /// Description of where the pixels live for this ImageBuf.
157  enum IBStorage {
158  UNINITIALIZED, // no pixel memory
159  LOCALBUFFER, // The IB owns the memory
160  APPBUFFER, // The IB wraps app's memory
161  IMAGECACHE // Backed by ImageCache
162  };
163 
164  /// Restore the ImageBuf to an uninitialized state.
165  ///
166  void clear();
167 
168  /// Forget all previous info, reset this ImageBuf to a new image
169  /// that is uninitialized (no pixel values, no size or spec).
170  /// If 'config' is not NULL, it points to an ImageSpec giving requests
171  /// or special instructions to be passed on to the eventual
172  /// ImageInput::open() call.
173  void reset(string_view name, int subimage, int miplevel,
174  ImageCache* imagecache = NULL, const ImageSpec* config = NULL);
175 
176  /// Forget all previous info, reset this ImageBuf to a new image
177  /// that is uninitialized (no pixel values, no size or spec).
178  void reset(string_view name, ImageCache* imagecache = NULL);
179 
180  /// Forget all previous info, reset this ImageBuf to a blank
181  /// image of the given dimensions.
182  void reset(const ImageSpec& spec);
183 
184  /// Forget all previous info, reset this ImageBuf to a blank
185  /// image of the given name and dimensions.
186  void reset(string_view name, const ImageSpec& spec);
187 
188  // Copy assignment
189  const ImageBuf& operator=(const ImageBuf& src);
190 
191  /// Move assignment
192  const ImageBuf& operator=(ImageBuf&& src);
193 
194  /// Which type of storage is being used for the pixels?
195  IBStorage storage() const;
196 
197  /// Is this ImageBuf object initialized?
198  bool initialized() const;
199 
200  /// Read the file from disk. Generally will skip the read if we've
201  /// already got a current version of the image in memory, unless
202  /// force==true. This uses ImageInput underneath, so will read any
203  /// file format for which an appropriate imageio plugin can be found.
204  /// Return value is true if all is ok, otherwise false.
205  bool read(int subimage = 0, int miplevel = 0, bool force = false,
207  ProgressCallback progress_callback = NULL,
208  void* progress_callback_data = NULL);
209 
210  /// Read the file from disk, if possible only allocating and reading a
211  /// subset of channels, [chbegin..chend-1] from disk. This can be a
212  /// performance and memory improvement if you know that any use of the
213  /// ImageBuf will only access a subset of channels from a many-channel
214  /// file. If chbegin==0 and chend is either negative or greater than the
215  /// number of channels in the file, all channels will be read. Please
216  /// note that it is "advisory" and not guaranteed to be honored by the
217  /// underlying implementation.
218  bool read(int subimage, int miplevel, int chbegin, int chend, bool force,
219  TypeDesc convert, ProgressCallback progress_callback = NULL,
220  void* progress_callback_data = NULL);
221 
222  /// Initialize this ImageBuf with the named image file, and read its
223  /// header to fill out the spec correctly. Return true if this
224  /// succeeded, false if the file could not be read. But don't
225  /// allocate or read the pixels.
226  bool init_spec(string_view filename, int subimage, int miplevel);
227 
228  /// Write the image to the named file, converted to the specified pixel
229  /// data type `dtype` (TypeUnknown signifies to use the data type of the
230  /// buffer), and file format ("" means to infer the type from the
231  /// filename extension). Return true if all went ok, false if there were
232  /// errors writing.
233  bool write(string_view filename, TypeDesc dtype = TypeUnknown,
234  string_view fileformat = string_view(),
235  ProgressCallback progress_callback = nullptr,
236  void* progress_callback_data = nullptr) const;
237  // DEPRECATED(1.9): old version did not have the data type
238  bool write(string_view filename, string_view fileformat,
239  ProgressCallback progress_callback = nullptr,
240  void* progress_callback_data = nullptr) const
241  {
242  return write(filename, TypeUnknown, fileformat, progress_callback,
243  progress_callback_data);
244  }
245 
246  /// Inform the ImageBuf what data format you'd like for any subsequent
247  /// write().
248  void set_write_format(TypeDesc format);
249 
250  /// Inform the ImageBuf what tile size (or no tiling, for 0) for
251  /// any subsequent write().
252  void set_write_tiles(int width = 0, int height = 0, int depth = 0);
253 
254  /// Write the image to the open ImageOutput 'out'. Return true if
255  /// all went ok, false if there were errors writing. It does NOT
256  /// close the file when it's done (and so may be called in a loop to
257  /// write a multi-image file).
258  bool write(ImageOutput* out, ProgressCallback progress_callback = NULL,
259  void* progress_callback_data = NULL) const;
260 
261  /// Force the ImageBuf to be writeable. That means that if it was
262  /// previously backed by ImageCache (storage was IMAGECACHE), it will
263  /// force a full read so that the whole image is in local memory. This
264  /// will invalidate any current iterators on the image. It has no effect
265  /// if the image storage not IMAGECACHE. Return true if it works
266  /// (including if no read was necessary), false if something went
267  /// horribly wrong. If keep_cache_type is true, it preserves any IC-
268  /// forced data types (you might want to do this if it is critical that
269  /// the apparent data type doesn't change, for example if you are
270  /// calling make_writeable from within a type-specialized function).
271  bool make_writeable(bool keep_cache_type = false);
272 
273  /// Copy all the metadata from src to *this (except for pixel data
274  /// resolution, channel information, and data format).
275  void copy_metadata(const ImageBuf& src);
276 
277  /// Copy the pixel data from src to *this, automatically converting
278  /// to the existing data format of *this. It only copies pixels in
279  /// the overlap regions (and channels) of the two images; pixel data
280  /// in *this that do exist in src will be set to 0, and pixel data
281  /// in src that do not exist in *this will not be copied.
282  bool copy_pixels(const ImageBuf& src);
283 
284  /// Try to copy the pixels and metadata from src to *this (optionally
285  /// with an explicit data format conversion), returning true upon
286  /// success and false upon error/failure.
287  ///
288  /// If the previous state of *this was uninitialized, owning its own
289  /// local pixel memory, or referring to a read-only image backed by
290  /// ImageCache, then local pixel memory will be allocated to hold
291  /// the new pixels and the call always succeeds unless the memory
292  /// cannot be allocated.
293  ///
294  /// If *this previously referred to an app-owned memory buffer, the
295  /// memory cannot be re-allocated, so the call will only succeed if
296  /// the app-owned buffer is already the correct resolution and
297  /// number of channels. The data type of the pixels will be
298  /// converted automatically to the data type of the app buffer.
299  bool copy(const ImageBuf& src, TypeDesc format = TypeUnknown);
300 
301  /// Return a full copy of `this` ImageBuf (optionally with an explicit
302  /// data format conversion).
303  ImageBuf copy(TypeDesc format /*= TypeDesc::UNKNOWN*/) const;
304 
305  /// Swap with another ImageBuf
306  void swap(ImageBuf& other) { std::swap(m_impl, other.m_impl); }
307 
308  /// Add simple string to the error message list for this IB.
309  void error(const std::string& message) const;
310 
311  /// Error reporting for ImageBuf: call this with Python / {fmt} /
312  /// std::format style formatting specification.
313  template<typename... Args>
314  void fmterror(const char* fmt, const Args&... args) const
315  {
316  error(Strutil::fmt::format(fmt, args...));
317  }
318 
319  /// Error reporting for ImageBuf: call this with printf-like arguments.
320  template<typename... Args>
321  void errorf(const char* fmt, const Args&... args) const
322  {
323  error(Strutil::sprintf(fmt, args...));
324  }
325 
326  /// Error reporting for ImageBuf: call this with Strutil::format
327  /// formatting conventions. Beware, this is in transition, is currently
328  /// printf-like but will someday change to python-like!
329  template<typename... Args>
330  void error(const char* fmt, const Args&... args) const
331  {
332  error(Strutil::format(fmt, args...));
333  }
334 
335  /// Return true if the IB has had an error and has an error message
336  /// to retrieve via geterror().
337  bool has_error(void) const;
338 
339  /// Return the text of all error messages issued since geterror()
340  /// was called (or an empty string if no errors are pending). This
341  /// also clears the error message for next time.
342  std::string geterror(void) const;
343 
344  /// Return a read-only (const) reference to the image spec that
345  /// describes the buffer.
346  const ImageSpec& spec() const;
347 
348  /// Return a writable reference to the image spec that describes the
349  /// buffer. Use with extreme caution! If you use this for anything
350  /// other than adding attribute metadata, you are really taking your
351  /// chances!
352  ImageSpec& specmod();
353 
354  /// Return a read-only (const) reference to the "native" image spec
355  /// (that describes the file, which may be slightly different than
356  /// the spec of the ImageBuf, particularly if the IB is backed by an
357  /// ImageCache that is imposing some particular data format or tile
358  /// size).
359  const ImageSpec& nativespec() const;
360 
361  /// Return the name of this image.
362  ///
363  string_view name(void) const;
364 
365  /// Return the name of the image file format of the disk file we
366  /// read into this image. Returns an empty string if this image
367  /// was not the result of a read().
368  string_view file_format_name(void) const;
369 
370  /// Return the index of the subimage are we currently viewing
371  ///
372  int subimage() const;
373 
374  /// Return the number of subimages in the file.
375  ///
376  int nsubimages() const;
377 
378  /// Return the index of the miplevel are we currently viewing
379  ///
380  int miplevel() const;
381 
382  /// Return the number of miplevels of the current subimage.
383  ///
384  int nmiplevels() const;
385 
386  /// Return the number of color channels in the image.
387  ///
388  int nchannels() const;
389 
390  /// Wrap mode describes what happens when an iterator points to
391  /// a value outside the usual data range of an image.
392  enum WrapMode {
398  _WrapLast
399  };
400 
401  /// Named wrap mode to enum WrapMode.
402  static WrapMode WrapMode_from_string(string_view name);
403 
404  /// Retrieve a single channel of one pixel.
405  ///
406  float getchannel(int x, int y, int z, int c,
407  WrapMode wrap = WrapBlack) const;
408 
409  /// Retrieve the pixel value by x and y pixel indices,
410  /// storing the floating point version in pixel[]. Retrieve at most
411  /// maxchannels (will be clamped to the actual number of channels).
412  void getpixel(int x, int y, float* pixel, int maxchannels = 1000) const
413  {
414  getpixel(x, y, 0, pixel, maxchannels);
415  }
416 
417  /// Retrieve the pixel value by x, y, z pixel indices,
418  /// storing the floating point version in pixel[]. Retrieve at most
419  /// maxchannels (will be clamped to the actual number of channels).
420  void getpixel(int x, int y, int z, float* pixel, int maxchannels = 1000,
421  WrapMode wrap = WrapBlack) const;
422 
423  /// Sample the image plane at coordinates (x,y), using linear
424  /// interpolation between pixels, placing the result in pixel[0..n-1]
425  /// where n is the smaller of maxchannels or the actual number of
426  /// channels stored in the buffer. It is up to the application to
427  /// ensure that pixel points to enough memory to hold the required
428  /// number of channels. Note that pixel data values themselves are at
429  /// the pixel centers, so pixel (i,j) is at image plane coordinate
430  /// (i+0.5, j+0.5).
431  void interppixel(float x, float y, float* pixel,
432  WrapMode wrap = WrapBlack) const;
433 
434  /// Linearly interpolate at NDC coordinates (s,t), where (0,0) is
435  /// the upper left corner of the display window, (1,1) the lower
436  /// right corner of the display window.
437  void interppixel_NDC(float s, float t, float* pixel,
438  WrapMode wrap = WrapBlack) const;
439 
440  /// DEPCRECATED (1.5) synonym for interppixel_NDC.
441  void interppixel_NDC_full(float s, float t, float* pixel,
442  WrapMode wrap = WrapBlack) const;
443 
444  /// Bicubic interpolation at pixel coordinates (x,y), where (0,0) is
445  /// the upper left corner, (xres,yres) the lower right corner of
446  /// the pixel data.
447  void interppixel_bicubic(float x, float y, float* pixel,
448  WrapMode wrap = WrapBlack) const;
449 
450  /// Bicubic interpolattion at NDC space coordinates (s,t), where (0,0)
451  /// is the upper left corner of the display (aka "full") window, (1,1)
452  /// the lower right corner of the display window.
453  void interppixel_bicubic_NDC(float s, float t, float* pixel,
454  WrapMode wrap = WrapBlack) const;
455 
456 
457  /// Set the pixel with coordinates (x,y,0) to have the values in
458  /// pixel[0..n-1]. The number of channels copied, n, is the minimum
459  /// of maxchannels and the actual number of channels in the image.
460  void setpixel(int x, int y, const float* pixel, int maxchannels = 1000)
461  {
462  setpixel(x, y, 0, pixel, maxchannels);
463  }
464 
465  /// Set the pixel with coordinates (x,y,z) to have the values in
466  /// pixel[0..n-1]. The number of channels copied, n, is the minimum
467  /// of maxchannels and the actual number of channels in the image.
468  void setpixel(int x, int y, int z, const float* pixel,
469  int maxchannels = 1000);
470 
471  /// Set the i-th pixel value of the image (out of width*height*depth),
472  /// from floating-point values in pixel[]. Set at most
473  /// maxchannels (will be clamped to the actual number of channels).
474  void setpixel(int i, const float* pixel, int maxchannels = 1000);
475 
476  /// Retrieve the rectangle of pixels spanning the ROI (including
477  /// channels) at the current subimage and MIP-map level, storing the
478  /// pixel values beginning at the address specified by result and with
479  /// the given strides (by default, AutoStride means the usual contiguous
480  /// packing of pixels) and converting into the data type described by
481  /// 'format'. It is up to the caller to ensure that result points to an
482  /// area of memory big enough to accommodate the requested rectangle.
483  /// Return true if the operation could be completed, otherwise return
484  /// false.
485  bool get_pixels(ROI roi, TypeDesc format, void* result,
486  stride_t xstride = AutoStride,
487  stride_t ystride = AutoStride,
488  stride_t zstride = AutoStride) const;
489 
490  /// Copy the data into the given ROI of the ImageBuf. The data points to
491  /// values specified by 'format', with layout detailed by the stride
492  /// values (in bytes, with AutoStride indicating "contiguous" layout).
493  /// It is up to the caller to ensure that data points to an area of
494  /// memory big enough to account for the ROI. Return true if the
495  /// operation could be completed, otherwise return false.
496  bool set_pixels(ROI roi, TypeDesc format, const void* data,
497  stride_t xstride = AutoStride,
498  stride_t ystride = AutoStride,
499  stride_t zstride = AutoStride);
500 
501 
502  int orientation() const;
503  void set_orientation(int orient);
504 
505  int oriented_width() const;
506  int oriented_height() const;
507  int oriented_x() const;
508  int oriented_y() const;
509  int oriented_full_width() const;
510  int oriented_full_height() const;
511  int oriented_full_x() const;
512  int oriented_full_y() const;
513 
514  /// Return the beginning (minimum) x coordinate of the defined image.
515  int xbegin() const;
516 
517  /// Return the end (one past maximum) x coordinate of the defined image.
518  int xend() const;
519 
520  /// Return the beginning (minimum) y coordinate of the defined image.
521  int ybegin() const;
522 
523  /// Return the end (one past maximum) y coordinate of the defined image.
524  int yend() const;
525 
526  /// Return the beginning (minimum) z coordinate of the defined image.
527  int zbegin() const;
528 
529  /// Return the end (one past maximum) z coordinate of the defined image.
530  int zend() const;
531 
532  /// Return the minimum x coordinate of the defined image.
533  int xmin() const;
534 
535  /// Return the maximum x coordinate of the defined image.
536  int xmax() const;
537 
538  /// Return the minimum y coordinate of the defined image.
539  int ymin() const;
540 
541  /// Return the maximum y coordinate of the defined image.
542  int ymax() const;
543 
544  /// Return the minimum z coordinate of the defined image.
545  int zmin() const;
546 
547  /// Return the maximum z coordinate of the defined image.
548  int zmax() const;
549 
550  /// Set a new origin position for the pixel data.
551  void set_origin(int x, int y, int z = 0);
552 
553  /// Set the "full" (a.k.a. display) window to [xbegin,xend) x
554  /// [ybegin,yend) x [zbegin,zend).
555  void set_full(int xbegin, int xend, int ybegin, int yend, int zbegin,
556  int zend);
557 
558  /// Return pixel data window for this ImageBuf as a ROI.
559  ROI roi() const;
560 
561  /// Return full/display window for this ImageBuf as a ROI.
562  ROI roi_full() const;
563 
564  /// Set full/display window for this ImageBuf to a ROI.
565  /// Does NOT change the channels of the spec, regardless of newroi.
566  void set_roi_full(const ROI& newroi);
567 
568  /// Is the specified roi completely contained in the data window of
569  /// this ImageBuf?
570  bool contains_roi(ROI roi) const;
571 
572  bool pixels_valid(void) const;
573 
574  TypeDesc pixeltype() const;
575 
576  /// A raw pointer to "local" pixel memory, if they are fully in RAM
577  /// and not backed by an ImageCache, or nullptr otherwise. You can
578  /// also test it like a bool to find out if pixels are local.
579  void* localpixels();
580  const void* localpixels() const;
581 
582  /// Pixel-to-pixel stride within the localpixels memory.
583  stride_t pixel_stride() const;
584  /// Scanline-to-scanline stride within the localpixels memory.
585  stride_t scanline_stride() const;
586  /// Z plane stride within the localpixels memory.
587  stride_t z_stride() const;
588 
589  /// Are the pixels backed by an ImageCache, rather than the whole
590  /// image being in RAM somewhere?
591  bool cachedpixels() const;
592 
593  ImageCache* imagecache() const;
594 
595  /// Return the address where pixel (x,y,z), channel ch, is stored in the
596  /// image buffer. Use with extreme caution! Will return nullptr if the
597  /// pixel values aren't local.
598  const void* pixeladdr(int x, int y, int z = 0, int ch = 0) const;
599 
600  /// Return the address where pixel (x,y,z), channel ch, is stored in the
601  /// image buffer. Use with extreme caution! Will return nullptr if the
602  /// pixel values aren't local.
603  void* pixeladdr(int x, int y, int z = 0, int ch = 0);
604 
605  /// Return the index of pixel (x,y,z). If check_range is true, return
606  /// -1 for an invalid coordinate that is not within the data window.
607  int pixelindex(int x, int y, int z, bool check_range = false) const;
608 
609  /// Does this ImageBuf store deep data?
610  bool deep() const;
611 
612  /// Retrieve the number of deep data samples corresponding to pixel
613  /// (x,y,z). Return 0 if not a deep image or if the pixel is out of
614  /// range or has no deep samples.
615  int deep_samples(int x, int y, int z = 0) const;
616 
617  /// Return a pointer to the raw data of pixel (x,y,z), channel c, sample
618  /// s. Return NULL if the pixel coordinates or channel number are out of
619  /// range, if the pixel/channel has no deep samples, or if the image is
620  /// not deep.
621  const void* deep_pixel_ptr(int x, int y, int z, int c, int s = 0) const;
622 
623  /// Return the value (as a float) of sample s of channel c of pixel
624  /// (x,y,z). Return 0.0 if not a deep image or if the pixel
625  /// coordinates or channel number are out of range or if it has no
626  /// deep samples.
627  float deep_value(int x, int y, int z, int c, int s) const;
628 
629  /// Retrieve deep sample value within a pixel, as an untigned int.
630  uint32_t deep_value_uint(int x, int y, int z, int c, int s) const;
631 
632  /// Set the number of deep samples for a particular pixel.
633  void set_deep_samples(int x, int y, int z, int nsamples);
634 
635  /// Set the number of deep samples for a particular pixel.
636  void deep_insert_samples(int x, int y, int z, int samplepos, int nsamples);
637 
638  /// Set the number of deep samples for a particular pixel.
639  void deep_erase_samples(int x, int y, int z, int samplepos, int nsamples);
640 
641  /// Set deep sample value within a pixel, as a float.
642  void set_deep_value(int x, int y, int z, int c, int s, float value);
643  /// Set deep sample value within a pixel, as a uint32.
644  void set_deep_value(int x, int y, int z, int c, int s, uint32_t value);
645 
646  /// Retrieve the "deep" data.
647  DeepData* deepdata();
648  const DeepData* deepdata() const;
649 
650  /// Set the current thread-spawning policy: the maximum number of
651  /// threads that may be spawned by ImagBuf internals. A value of 1
652  /// means all work will be done by the calling thread; 0 means to use
653  /// the global OIIO::attribute("threads") value.
654  void threads(int n) const;
655 
656  /// Retrieve the current thread-spawning policy of this ImageBuf.
657  int threads() const;
658 
659  friend class IteratorBase;
660 
661  class IteratorBase {
662  public:
663  IteratorBase(const ImageBuf& ib, WrapMode wrap)
664  : m_ib(&ib)
665  {
666  init_ib(wrap);
667  range_is_image();
668  }
669 
670  /// Construct valid iteration region from ImageBuf and ROI.
671  IteratorBase(const ImageBuf& ib, const ROI& roi, WrapMode wrap)
672  : m_ib(&ib)
673  {
674  init_ib(wrap);
675  if (roi.defined()) {
676  m_rng_xbegin = roi.xbegin;
677  m_rng_xend = roi.xend;
678  m_rng_ybegin = roi.ybegin;
679  m_rng_yend = roi.yend;
680  m_rng_zbegin = roi.zbegin;
681  m_rng_zend = roi.zend;
682  } else {
683  range_is_image();
684  }
685  }
686 
687  /// Construct from an ImageBuf and designated region -- iterate
688  /// over region, starting with the upper left pixel.
689  IteratorBase(const ImageBuf& ib, int xbegin, int xend, int ybegin,
690  int yend, int zbegin, int zend, WrapMode wrap)
691  : m_ib(&ib)
692  {
693  init_ib(wrap);
694  m_rng_xbegin = xbegin;
695  m_rng_xend = xend;
696  m_rng_ybegin = ybegin;
697  m_rng_yend = yend;
698  m_rng_zbegin = zbegin;
699  m_rng_zend = zend;
700  }
701 
703  : m_ib(i.m_ib)
704  , m_rng_xbegin(i.m_rng_xbegin)
705  , m_rng_xend(i.m_rng_xend)
706  , m_rng_ybegin(i.m_rng_ybegin)
707  , m_rng_yend(i.m_rng_yend)
708  , m_rng_zbegin(i.m_rng_zbegin)
709  , m_rng_zend(i.m_rng_zend)
710  , m_proxydata(i.m_proxydata)
711  {
712  init_ib(i.m_wrap);
713  }
714 
716  {
717  if (m_tile)
718  m_ib->imagecache()->release_tile(m_tile);
719  }
720 
721  /// Assign one IteratorBase to another
722  ///
724  {
725  if (m_tile)
726  m_ib->imagecache()->release_tile(m_tile);
727  m_tile = NULL;
728  m_proxydata = i.m_proxydata;
729  m_ib = i.m_ib;
730  init_ib(i.m_wrap);
731  m_rng_xbegin = i.m_rng_xbegin;
732  m_rng_xend = i.m_rng_xend;
733  m_rng_ybegin = i.m_rng_ybegin;
734  m_rng_yend = i.m_rng_yend;
735  m_rng_zbegin = i.m_rng_zbegin;
736  m_rng_zend = i.m_rng_zend;
737  return *this;
738  }
739 
740  /// Retrieve the current x location of the iterator.
741  ///
742  int x() const { return m_x; }
743  /// Retrieve the current y location of the iterator.
744  ///
745  int y() const { return m_y; }
746  /// Retrieve the current z location of the iterator.
747  ///
748  int z() const { return m_z; }
749 
750  /// Is the current location within the designated iteration range?
751  bool valid() const { return m_valid; }
752 
753  /// Is the location (x,y[,z]) within the designated iteration
754  /// range?
755  bool valid(int x_, int y_, int z_ = 0) const
756  {
757  return (x_ >= m_rng_xbegin && x_ < m_rng_xend && y_ >= m_rng_ybegin
758  && y_ < m_rng_yend && z_ >= m_rng_zbegin
759  && z_ < m_rng_zend);
760  }
761 
762  /// Is the location (x,y[,z]) within the region of the ImageBuf
763  /// that contains pixel values (sometimes called the "data window")?
764  bool exists(int x_, int y_, int z_ = 0) const
765  {
766  return (x_ >= m_img_xbegin && x_ < m_img_xend && y_ >= m_img_ybegin
767  && y_ < m_img_yend && z_ >= m_img_zbegin
768  && z_ < m_img_zend);
769  }
770  /// Does the current location exist within the ImageBuf's
771  /// data window?
772  bool exists() const { return m_exists; }
773 
774  /// Are we finished iterating over the region?
775  //
776  bool done() const
777  {
778  // We're "done" if we are both invalid and in exactly the
779  // spot that we would end up after iterating off of the last
780  // pixel in the range. (The m_valid test is just a quick
781  // early-out for when we're in the correct pixel range.)
782  return (m_valid == false && m_x == m_rng_xbegin
783  && m_y == m_rng_ybegin && m_z == m_rng_zend);
784  }
785 
786  /// Retrieve the number of deep data samples at this pixel.
787  int deep_samples() const { return m_ib->deep_samples(m_x, m_y, m_z); }
788 
789  /// Return the wrap mode
790  WrapMode wrap() const { return m_wrap; }
791 
792  /// Explicitly point the iterator. This results in an invalid
793  /// iterator if outside the previously-designated region.
794  void pos(int x_, int y_, int z_ = 0)
795  {
796  if (x_ == m_x + 1 && x_ < m_rng_xend && y_ == m_y && z_ == m_z
797  && m_valid && m_exists) {
798  // Special case for what is in effect just incrementing x
799  // within the iteration region.
800  m_x = x_;
801  pos_xincr();
802  // Not necessary? m_exists = (x_ < m_img_xend);
803  DASSERT((x_ < m_img_xend) == m_exists);
804  return;
805  }
806  bool v = valid(x_, y_, z_);
807  bool e = exists(x_, y_, z_);
808  if (m_localpixels) {
809  if (e)
810  m_proxydata = (char*)m_ib->pixeladdr(x_, y_, z_);
811  else { // pixel not in data window
812  m_x = x_;
813  m_y = y_;
814  m_z = z_;
815  if (m_wrap == WrapBlack) {
816  m_proxydata = (char*)m_ib->blackpixel();
817  } else {
818  if (m_ib->do_wrap(x_, y_, z_, m_wrap))
819  m_proxydata = (char*)m_ib->pixeladdr(x_, y_, z_);
820  else
821  m_proxydata = (char*)m_ib->blackpixel();
822  }
823  m_valid = v;
824  m_exists = e;
825  return;
826  }
827  } else if (!m_deep)
828  m_proxydata = (char*)m_ib->retile(x_, y_, z_, m_tile,
829  m_tilexbegin, m_tileybegin,
830  m_tilezbegin, m_tilexend, e,
831  m_wrap);
832  m_x = x_;
833  m_y = y_;
834  m_z = z_;
835  m_valid = v;
836  m_exists = e;
837  }
838 
839  /// Increment to the next pixel in the region.
840  ///
842  {
843  if (++m_x < m_rng_xend) {
844  // Special case: we only incremented x, didn't change y
845  // or z, and the previous position was within the data
846  // window. Call a shortcut version of pos.
847  if (m_exists) {
848  pos_xincr();
849  return;
850  }
851  } else {
852  // Wrap to the next scanline
853  m_x = m_rng_xbegin;
854  if (++m_y >= m_rng_yend) {
855  m_y = m_rng_ybegin;
856  if (++m_z >= m_rng_zend) {
857  m_valid = false; // shortcut -- finished iterating
858  return;
859  }
860  }
861  }
862  pos(m_x, m_y, m_z);
863  }
864  /// Increment to the next pixel in the region.
865  ///
866  void operator++(int) { ++(*this); }
867 
868  /// Return the iteration range
869  ROI range() const
870  {
871  return ROI(m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend,
872  m_rng_zbegin, m_rng_zend, 0, m_ib->nchannels());
873  }
874 
875  /// Reset the iteration range for this iterator and reposition to
876  /// the beginning of the range, but keep referring to the same
877  /// image.
878  void rerange(int xbegin, int xend, int ybegin, int yend, int zbegin,
879  int zend, WrapMode wrap = WrapDefault)
880  {
881  m_x = 1 << 31;
882  m_y = 1 << 31;
883  m_z = 1 << 31;
884  m_wrap = (wrap == WrapDefault ? WrapBlack : wrap);
885  m_rng_xbegin = xbegin;
886  m_rng_xend = xend;
887  m_rng_ybegin = ybegin;
888  m_rng_yend = yend;
889  m_rng_zbegin = zbegin;
890  m_rng_zend = zend;
891  pos(xbegin, ybegin, zbegin);
892  }
893 
894  protected:
895  friend class ImageBuf;
896  friend class ImageBufImpl;
897  const ImageBuf* m_ib = nullptr;
898  bool m_valid = false, m_exists = false;
899  bool m_deep = false;
900  bool m_localpixels = false;
901  // Image boundaries
902  int m_img_xbegin, m_img_xend, m_img_ybegin, m_img_yend, m_img_zbegin,
903  m_img_zend;
904  // Iteration range
905  int m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend, m_rng_zbegin,
906  m_rng_zend;
907  int m_x, m_y, m_z;
908  ImageCache::Tile* m_tile = nullptr;
909  int m_tilexbegin, m_tileybegin, m_tilezbegin;
913  char* m_proxydata = nullptr;
914  WrapMode m_wrap = WrapBlack;
915 
916  // Helper called by ctrs -- set up some locally cached values
917  // that are copied or derived from the ImageBuf.
918  void init_ib(WrapMode wrap)
919  {
920  const ImageSpec& spec(m_ib->spec());
921  m_deep = spec.deep;
922  m_localpixels = (m_ib->localpixels() != NULL);
923  m_img_xbegin = spec.x;
924  m_img_xend = spec.x + spec.width;
925  m_img_ybegin = spec.y;
926  m_img_yend = spec.y + spec.height;
927  m_img_zbegin = spec.z;
928  m_img_zend = spec.z + spec.depth;
929  m_nchannels = spec.nchannels;
930  // m_tilewidth = spec.tile_width;
931  m_pixel_bytes = spec.pixel_bytes();
932  m_x = 1 << 31;
933  m_y = 1 << 31;
934  m_z = 1 << 31;
935  m_wrap = (wrap == WrapDefault ? WrapBlack : wrap);
936  }
937 
938  // Helper called by ctrs -- make the iteration range the full
939  // image data window.
941  {
942  m_rng_xbegin = m_img_xbegin;
943  m_rng_xend = m_img_xend;
944  m_rng_ybegin = m_img_ybegin;
945  m_rng_yend = m_img_yend;
946  m_rng_zbegin = m_img_zbegin;
947  m_rng_zend = m_img_zend;
948  }
949 
950  // Helper called by pos(), but ONLY for the case where we are
951  // moving from an existing pixel to the next spot in +x.
952  // Note: called *after* m_x was incremented!
954  {
955  DASSERT(m_exists && m_valid); // precondition
956  DASSERT(valid(m_x, m_y, m_z)); // should be true by definition
957  m_proxydata += m_pixel_bytes;
958  if (m_localpixels) {
959  if (OIIO_UNLIKELY(m_x >= m_img_xend)) {
960  // Ran off the end of the row
961  m_exists = false;
962  if (m_wrap == WrapBlack) {
963  m_proxydata = (char*)m_ib->blackpixel();
964  } else {
965  int x = m_x, y = m_y, z = m_z;
966  if (m_ib->do_wrap(x, y, z, m_wrap))
967  m_proxydata = (char*)m_ib->pixeladdr(x, y, z);
968  else
969  m_proxydata = (char*)m_ib->blackpixel();
970  }
971  }
972  } else if (m_deep) {
973  m_proxydata = NULL;
974  } else {
975  // Cached image
976  bool e = m_x < m_img_xend;
977  if (OIIO_UNLIKELY(!(e && m_x < m_tilexend && m_tile))) {
978  // Crossed a tile boundary
979  m_proxydata = (char*)m_ib->retile(m_x, m_y, m_z, m_tile,
980  m_tilexbegin,
981  m_tileybegin,
982  m_tilezbegin, m_tilexend,
983  e, m_wrap);
984  m_exists = e;
985  }
986  }
987  }
988 
989  // Set to the "done" position
990  void pos_done()
991  {
992  m_valid = false;
993  m_x = m_rng_xbegin;
994  m_y = m_rng_ybegin;
995  m_z = m_rng_zend;
996  }
997 
998  // Make sure it's writeable. Use with caution!
1000  {
1001  if (!m_localpixels) {
1002  const_cast<ImageBuf*>(m_ib)->make_writeable(true);
1003  DASSERT(m_ib->storage() != IMAGECACHE);
1004  m_tile = NULL;
1005  m_proxydata = NULL;
1006  init_ib(m_wrap);
1007  }
1008  }
1009  };
1010 
1011  /// Templated class for referring to an individual pixel in an
1012  /// ImageBuf, iterating over the pixels of an ImageBuf, or iterating
1013  /// over the pixels of a specified region of the ImageBuf
1014  /// [xbegin..xend) X [ybegin..yend). It is templated on BUFT, the
1015  /// type known to be in the internal representation of the ImageBuf,
1016  /// and USERT, the type that the user wants to retrieve or set the
1017  /// data (defaulting to float). the whole idea is to allow this:
1018  /// \code
1019  /// ImageBuf img (...);
1020  /// ImageBuf::Iterator<float> pixel (img, 0, 512, 0, 512);
1021  /// for ( ; ! pixel.done(); ++pixel) {
1022  /// for (int c = 0; c < img.nchannels(); ++c) {
1023  /// float x = pixel[c];
1024  /// pixel[c] = ...;
1025  /// }
1026  /// }
1027  /// \endcode
1028  ///
1029  template<typename BUFT, typename USERT = float>
1030  class Iterator : public IteratorBase {
1031  public:
1032  /// Construct from just an ImageBuf -- iterate over the whole
1033  /// region, starting with the upper left pixel of the region.
1034  Iterator(ImageBuf& ib, WrapMode wrap = WrapDefault)
1035  : IteratorBase(ib, wrap)
1036  {
1037  make_writeable();
1038  pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1039  if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend
1040  || m_rng_zbegin == m_rng_zend)
1041  pos_done(); // make empty range look "done"
1042  }
1043  /// Construct from an ImageBuf and a specific pixel index.
1044  /// The iteration range is the full image.
1045  Iterator(ImageBuf& ib, int x, int y, int z = 0,
1046  WrapMode wrap = WrapDefault)
1047  : IteratorBase(ib, wrap)
1048  {
1049  make_writeable();
1050  pos(x, y, z);
1051  }
1052  /// Construct read-write iteration region from ImageBuf and ROI.
1053  Iterator(ImageBuf& ib, const ROI& roi, WrapMode wrap = WrapDefault)
1054  : IteratorBase(ib, roi, wrap)
1055  {
1056  make_writeable();
1057  pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1058  if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend
1059  || m_rng_zbegin == m_rng_zend)
1060  pos_done(); // make empty range look "done"
1061  }
1062  /// Construct from an ImageBuf and designated region -- iterate
1063  /// over region, starting with the upper left pixel.
1064  Iterator(ImageBuf& ib, int xbegin, int xend, int ybegin, int yend,
1065  int zbegin = 0, int zend = 1, WrapMode wrap = WrapDefault)
1066  : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap)
1067  {
1068  make_writeable();
1069  pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1070  if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend
1071  || m_rng_zbegin == m_rng_zend)
1072  pos_done(); // make empty range look "done"
1073  }
1074  /// Copy constructor.
1075  ///
1077  : IteratorBase(i.m_ib, i.m_wrap)
1078  {
1079  make_writeable();
1080  pos(i.m_x, i.m_y, i.m_z);
1081  }
1082 
1084 
1085  /// Assign one Iterator to another
1086  ///
1087  const Iterator& operator=(const Iterator& i)
1088  {
1089  assign_base(i);
1090  pos(i.m_x, i.m_y, i.m_z);
1091  return *this;
1092  }
1093 
1094  /// Dereferencing the iterator gives us a proxy for the pixel,
1095  /// which we can index for reading or assignment.
1097  {
1098  return *(DataArrayProxy<BUFT, USERT>*)(void*)&m_proxydata;
1099  }
1100 
1101  /// Array indexing retrieves the value of the i-th channel of
1102  /// the current pixel.
1103  USERT operator[](int i) const
1104  {
1105  DataArrayProxy<BUFT, USERT> proxy((BUFT*)m_proxydata);
1106  return proxy[i];
1107  }
1108 
1109  /// Array referencing retrieve a proxy (which may be "assigned
1110  /// to") of i-th channel of the current pixel, so that this
1111  /// works: me[i] = val;
1113  {
1114  DataArrayProxy<BUFT, USERT> proxy((BUFT*)m_proxydata);
1115  return proxy[i];
1116  }
1117 
1118  void* rawptr() const { return m_proxydata; }
1119 
1120  /// Set the number of deep data samples at this pixel. (Only use
1121  /// this if deep_alloc() has not yet been called on the buffer.)
1123  {
1124  return const_cast<ImageBuf*>(m_ib)->set_deep_samples(m_x, m_y, m_z,
1125  n);
1126  }
1127 
1128  /// Retrieve the deep data value of sample s of channel c.
1129  USERT deep_value(int c, int s) const
1130  {
1131  return convert_type<float, USERT>(
1132  m_ib->deep_value(m_x, m_y, m_z, c, s));
1133  }
1134  uint32_t deep_value_uint(int c, int s) const
1135  {
1136  return m_ib->deep_value_uint(m_x, m_y, m_z, c, s);
1137  }
1138 
1139  /// Set the deep data value of sample s of channel c. (Only use this
1140  /// if deep_alloc() has been called.)
1141  void set_deep_value(int c, int s, float value)
1142  {
1143  return const_cast<ImageBuf*>(m_ib)->set_deep_value(m_x, m_y, m_z, c,
1144  s, value);
1145  }
1146  void set_deep_value(int c, int s, uint32_t value)
1147  {
1148  return const_cast<ImageBuf*>(m_ib)->set_deep_value(m_x, m_y, m_z, c,
1149  s, value);
1150  }
1151  };
1152 
1153 
1154  /// Just like an ImageBuf::Iterator, except that it refers to a
1155  /// const ImageBuf.
1156  template<typename BUFT, typename USERT = float>
1157  class ConstIterator : public IteratorBase {
1158  public:
1159  /// Construct from just an ImageBuf -- iterate over the whole
1160  /// region, starting with the upper left pixel of the region.
1161  ConstIterator(const ImageBuf& ib, WrapMode wrap = WrapDefault)
1162  : IteratorBase(ib, wrap)
1163  {
1164  pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1165  if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend
1166  || m_rng_zbegin == m_rng_zend)
1167  pos_done(); // make empty range look "done"
1168  }
1169  /// Construct from an ImageBuf and a specific pixel index.
1170  /// The iteration range is the full image.
1171  ConstIterator(const ImageBuf& ib, int x_, int y_, int z_ = 0,
1172  WrapMode wrap = WrapDefault)
1173  : IteratorBase(ib, wrap)
1174  {
1175  pos(x_, y_, z_);
1176  }
1177  /// Construct read-only iteration region from ImageBuf and ROI.
1178  ConstIterator(const ImageBuf& ib, const ROI& roi,
1179  WrapMode wrap = WrapDefault)
1180  : IteratorBase(ib, roi, wrap)
1181  {
1182  pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1183  if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend
1184  || m_rng_zbegin == m_rng_zend)
1185  pos_done(); // make empty range look "done"
1186  }
1187  /// Construct from an ImageBuf and designated region -- iterate
1188  /// over region, starting with the upper left pixel.
1189  ConstIterator(const ImageBuf& ib, int xbegin, int xend, int ybegin,
1190  int yend, int zbegin = 0, int zend = 1,
1191  WrapMode wrap = WrapDefault)
1192  : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap)
1193  {
1194  pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin);
1195  if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend
1196  || m_rng_zbegin == m_rng_zend)
1197  pos_done(); // make empty range look "done"
1198  }
1199  /// Copy constructor.
1200  ///
1202  : IteratorBase(i)
1203  {
1204  pos(i.m_x, i.m_y, i.m_z);
1205  }
1206 
1208 
1209  /// Assign one ConstIterator to another
1210  ///
1212  {
1213  assign_base(i);
1214  pos(i.m_x, i.m_y, i.m_z);
1215  return *this;
1216  }
1217 
1218  /// Dereferencing the iterator gives us a proxy for the pixel,
1219  /// which we can index for reading or assignment.
1221  {
1222  return *(ConstDataArrayProxy<BUFT, USERT>*)&m_proxydata;
1223  }
1224 
1225  /// Array indexing retrieves the value of the i-th channel of
1226  /// the current pixel.
1227  USERT operator[](int i) const
1228  {
1229  ConstDataArrayProxy<BUFT, USERT> proxy((BUFT*)m_proxydata);
1230  return proxy[i];
1231  }
1232 
1233  const void* rawptr() const { return m_proxydata; }
1234 
1235  /// Retrieve the deep data value of sample s of channel c.
1236  USERT deep_value(int c, int s) const
1237  {
1238  return convert_type<float, USERT>(
1239  m_ib->deep_value(m_x, m_y, m_z, c, s));
1240  }
1241  uint32_t deep_value_uint(int c, int s) const
1242  {
1243  return m_ib->deep_value_uint(m_x, m_y, m_z, c, s);
1244  }
1245  };
1246 
1247 
1248 protected:
1249  std::unique_ptr<ImageBufImplBase> m_impl; //< PIMPL idiom
1250 
1251  ImageBufImpl* impl() { return (ImageBufImpl*)m_impl.get(); }
1252  const ImageBufImpl* impl() const
1253  {
1254  return (const ImageBufImpl*)m_impl.get();
1255  }
1256 
1257  // Reset the ImageCache::Tile * to reserve and point to the correct
1258  // tile for the given pixel, and return the ptr to the actual pixel
1259  // within the tile.
1260  const void* retile(int x, int y, int z, ImageCache::Tile*& tile,
1261  int& tilexbegin, int& tileybegin, int& tilezbegin,
1262  int& tilexend, bool exists,
1263  WrapMode wrap = WrapDefault) const;
1264 
1265  const void* blackpixel() const;
1266 
1267  // Given x,y,z known to be outside the pixel data range, and a wrap
1268  // mode, alter xyz to implement the wrap. Return true if the resulting
1269  // x,y,z is within the valid pixel data window, false if it still is
1270  // not.
1271  bool do_wrap(int& x, int& y, int& z, WrapMode wrap) const;
1272 };
1273 
1274 
GLdouble s
Definition: glew.h:1390
int nchannels
number of image channels, e.g., 4 for RGBA
Definition: imageio.h:241
const ptrdiff_t AutoStride
rst::
Definition: OpenColorIO.h:1033
std::string sprintf(const char *fmt, const Args &...args)
Definition: strutil.h:136
int xend
Definition: imageio.h:116
uint32_t deep_value_uint(int c, int s) const
Definition: imagebuf.h:1134
IteratorBase(const ImageBuf &ib, WrapMode wrap)
Definition: imagebuf.h:663
GT_API const UT_StringHolder filename
void swap(ImageBuf &other)
Swap with another ImageBuf.
Definition: imagebuf.h:306
GLenum src
Definition: glew.h:2410
GLuint const GLchar * name
Definition: glew.h:1814
#define OIIO_FORCEINLINE
Definition: platform.h:249
GLclampd zmax
Definition: glew.h:9021
ConstIterator(const ImageBuf &ib, const ROI &roi, WrapMode wrap=WrapDefault)
Construct read-only iteration region from ImageBuf and ROI.
Definition: imagebuf.h:1178
void getpixel(int x, int y, float *pixel, int maxchannels=1000) const
Definition: imagebuf.h:412
OIIO_API void set_roi(ImageSpec &spec, const ROI &newroi)
GLint GLint GLint GLint GLint GLint GLsizei width
Definition: glew.h:1252
const Args & args
Definition: printf.h:628
void pos(int x_, int y_, int z_=0)
Definition: imagebuf.h:794
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1629
OIIO_API bool exists(const std::string &path)
std::string format(const char *fmt, const Args &...args)
Definition: strutil.h:182
Iterator(ImageBuf &ib, const ROI &roi, WrapMode wrap=WrapDefault)
Construct read-write iteration region from ImageBuf and ROI.
Definition: imagebuf.h:1053
USERT operator[](int i) const
Definition: imagebuf.h:1227
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
Definition: glew.h:1252
void init_ib(WrapMode wrap)
Definition: imagebuf.h:918
int x() const
Definition: imagebuf.h:742
DataArrayProxy< BUFT, USERT > & operator*()
Definition: imagebuf.h:1096
bool valid(int x_, int y_, int z_=0) const
Definition: imagebuf.h:755
void rerange(int xbegin, int xend, int ybegin, int yend, int zbegin, int zend, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:878
ROI range() const
Return the iteration range.
Definition: imagebuf.h:869
void set_deep_value(int c, int s, float value)
Definition: imagebuf.h:1141
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glew.h:1254
const void * rawptr() const
Definition: imagebuf.h:1233
int depth
depth of pixel data, >1 indicates a "volume"
Definition: imageio.h:230
Tto convert(const Tfrom &source)
const ImageBufImpl * impl() const
Definition: imagebuf.h:1252
const GLdouble * v
Definition: glew.h:1391
constexpr bool defined() const
Is a region defined?
Definition: imageio.h:134
OIIO_API ROI get_roi(const ImageSpec &spec)
Return pixel data window for this ImageSpec as a ROI.
GLboolean reset
Definition: glew.h:4959
void read(T &in, bool &v)
Definition: ImfXdr.h:611
ConstIterator(const ImageBuf &ib, int x_, int y_, int z_=0, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:1171
int zend
Definition: imageio.h:116
void setpixel(int x, int y, const float *pixel, int maxchannels=1000)
Definition: imagebuf.h:460
void error(const char *fmt, const Args &...args) const
Definition: imagebuf.h:330
OIIO_API std::string geterror()
GLdouble GLdouble z
Definition: glew.h:1559
bool write(string_view filename, string_view fileformat, ProgressCallback progress_callback=nullptr, void *progress_callback_data=nullptr) const
Definition: imagebuf.h:238
const IteratorBase & assign_base(const IteratorBase &i)
Definition: imagebuf.h:723
OIIO_API ROI get_roi_full(const ImageSpec &spec)
Return full/display window for this ImageSpec as a ROI.
bool(* ProgressCallback)(void *opaque_data, float portion_done)
Definition: imageio.h:101
#define DASSERT(x)
Definition: dassert.h:99
int z() const
Definition: imagebuf.h:748
GLint GLint GLint GLint GLint x
Definition: glew.h:1252
IteratorBase(const ImageBuf &ib, int xbegin, int xend, int ybegin, int yend, int zbegin, int zend, WrapMode wrap)
Definition: imagebuf.h:689
Iterator(Iterator &i)
Definition: imagebuf.h:1076
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1252
GLuint buffer
Definition: glew.h:1680
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
IBStorage
Description of where the pixels live for this ImageBuf.
Definition: imagebuf.h:157
void errorf(const char *fmt, const Args &...args) const
Error reporting for ImageBuf: call this with printf-like arguments.
Definition: imagebuf.h:321
basic_string_view< char > string_view
Definition: core.h:426
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2581
GLsizei n
Definition: glew.h:4040
const GLfloat * c
Definition: glew.h:16296
bool valid() const
Is the current location within the designated iteration range?
Definition: imagebuf.h:751
const ConstIterator & operator=(const ConstIterator &i)
Definition: imagebuf.h:1211
bool deep
Contains deep data.
Definition: imageio.h:248
ptrdiff_t stride_t
Definition: imageio.h:69
int y() const
Definition: imagebuf.h:745
ConstDataArrayProxy< BUFT, USERT > & operator*() const
Definition: imagebuf.h:1220
std::unique_ptr< ImageBufImplBase > m_impl
Definition: imagebuf.h:1249
IteratorBase(const ImageBuf &ib, const ROI &roi, WrapMode wrap)
Construct valid iteration region from ImageBuf and ROI.
Definition: imagebuf.h:671
virtual ~ImageBufImplBase()
Definition: imagebuf.h:63
Iterator(ImageBuf &ib, int x, int y, int z=0, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:1045
GA_API const UT_StringHolder orient
void operator++(int)
Definition: imagebuf.h:866
OIIO_FORCEINLINE void operator++()
Definition: imagebuf.h:841
void set_deep_value(int c, int s, uint32_t value)
Definition: imagebuf.h:1146
Iterator(ImageBuf &ib, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:1034
ConstIterator(const ImageBuf &ib, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:1161
ImageBufImpl * impl()
Definition: imagebuf.h:1251
IteratorBase(const IteratorBase &i)
Definition: imagebuf.h:702
int x
Definition: imageio.h:227
bool exists(int x_, int y_, int z_=0) const
Definition: imagebuf.h:764
GLsizei const GLchar *const * string
Definition: glew.h:1844
Definition: imageio.h:115
size_t pixel_bytes(bool native=false) const
#define OIIO_UNLIKELY(x)
Definition: platform.h:234
int deep_samples() const
Retrieve the number of deep data samples at this pixel.
Definition: imagebuf.h:787
void fmterror(const char *fmt, const Args &...args) const
Definition: imagebuf.h:314
int z
origin (upper left corner) of pixel data
Definition: imageio.h:227
int xbegin
Definition: imageio.h:116
USERT operator[](int i) const
Definition: imagebuf.h:1103
int width
width of the pixel data window
Definition: imageio.h:228
ConstIterator(const ImageBuf &ib, int xbegin, int xend, int ybegin, int yend, int zbegin=0, int zend=1, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:1189
Iterator(ImageBuf &ib, int xbegin, int xend, int ybegin, int yend, int zbegin=0, int zend=1, WrapMode wrap=WrapDefault)
Definition: imagebuf.h:1064
OIIO_API bool copy(string_view from, string_view to, std::string &err)
USERT deep_value(int c, int s) const
Retrieve the deep data value of sample s of channel c.
Definition: imagebuf.h:1129
OIIO_FORCEINLINE void pos_xincr()
Definition: imagebuf.h:953
const ImageBuf * m_ib
Definition: imagebuf.h:897
USERT deep_value(int c, int s) const
Retrieve the deep data value of sample s of channel c.
Definition: imagebuf.h:1236
GLuint64EXT * result
Definition: glew.h:14007
getOption("OpenEXR.storage") storage
Definition: HDK_Image.dox:276
uint32_t deep_value_uint(int c, int s) const
Definition: imagebuf.h:1241
int height
height of the pixel data window
Definition: imageio.h:229
bool done() const
Are we finished iterating over the region?
Definition: imagebuf.h:776
const Iterator & operator=(const Iterator &i)
Definition: imagebuf.h:1087
void set_deep_samples(int n)
Definition: imagebuf.h:1122
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:66
Structure to hold "deep" data – multiple samples per pixel.
Definition: deepdata.h:47
int zbegin
Definition: imageio.h:116
int yend
Definition: imageio.h:116
ConstIterator(const ConstIterator &i)
Definition: imagebuf.h:1201
WrapMode wrap() const
Return the wrap mode.
Definition: imagebuf.h:790
void write(T &out, bool v)
Definition: ImfXdr.h:332
GLsizei const GLfloat * value
Definition: glew.h:1849
void * rawptr() const
Definition: imagebuf.h:1118
GLdouble GLdouble t
Definition: glew.h:1398
DataProxy< BUFT, USERT > operator[](int i)
Definition: imagebuf.h:1112
int ybegin
Definition: imageio.h:116
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glew.h:1254
int y
Definition: imageio.h:227
OIIO_API void set_roi_full(ImageSpec &spec, const ROI &newroi)
bool exists() const
Definition: imagebuf.h:772
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:65
#define OIIO_API
Definition: export.h:91