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