1 // Copyright 2008-present Contributors to the OpenImageIO project. 2 // SPDX-License-Identifier: BSD-3-Clause 3 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md 4 5 6 #pragma once 7 #define OPENIMAGEIO_IMAGEBUF_H 8 9 #if defined(_MSC_VER) 10 // Ignore warnings about DLL exported classes with member variables that are template classes. 11 // This happens with the std::vector and std::string protected members of ImageBuf below. 12 # pragma warning(disable : 4251) 13 #endif 14 15 #include <OpenImageIO/dassert.h> 16 #include <OpenImageIO/fmath.h> 17 #include <OpenImageIO/imagecache.h> 18 #include <OpenImageIO/imageio.h> 19 20 #include <limits> 21 #include <memory> 22 23 24 OIIO_NAMESPACE_BEGIN 25 26 class ImageBuf; 27 class ImageBufImpl; // Opaque type for the unique_ptr. 28 29 30 31 /// Return pixel data window for this ImageSpec as a ROI. 32 OIIO_API ROI 33 get_roi(const ImageSpec& spec); 34 35 /// Return full/display window for this ImageSpec as a ROI. 36 OIIO_API ROI 37 get_roi_full(const ImageSpec& spec); 38 39 /// Set pixel data window for this ImageSpec to a ROI. 40 /// Does NOT change the channels of the spec, regardless of newroi. 41 OIIO_API void 42 set_roi(ImageSpec& spec, const ROI& newroi); 43 44 /// Set full/display window for this ImageSpec to a ROI. 45 /// Does NOT change the channels of the spec, regardless of newroi. 46 OIIO_API void 47 set_roi_full(ImageSpec& spec, const ROI& newroi); 48 49 50 enum class InitializePixels { No = 0, Yes = 1 }; 51 52 53 54 /// An ImageBuf is a simple in-memory representation of a 2D image. It uses 55 /// ImageInput and ImageOutput underneath for its file I/O, and has simple 56 /// routines for setting and getting individual pixels, that hides most of 57 /// the details of memory layout and data representation (translating 58 /// to/from float automatically). 59 class OIIO_API ImageBuf { 60 public: 61 /// An ImageBuf can store its pixels in one of several ways (each 62 /// identified by an `IBStorage` enumerated value): 63 enum IBStorage { 64 // clang-format off 65 UNINITIALIZED, 66 ///< An ImageBuf that doesn't represent any image at all 67 /// (either because it is newly constructed with the default 68 /// constructor, or had an error during construction). 69 LOCALBUFFER, 70 ///< "Local storage" is allocated to hold the image pixels 71 /// internal to the ImageBuf. This memory will be freed when 72 /// the ImageBuf is destroyed. 73 APPBUFFER, 74 ///< The ImageBuf "wraps" pixel memory already allocated and 75 /// owned by the calling application. The caller will continue 76 /// to own that memory and be responsible for freeing it after 77 /// the ImageBuf is destroyed. 78 IMAGECACHE 79 ///< The ImageBuf is "backed" by an ImageCache, which will 80 /// automatically be used to retrieve pixels when requested, but 81 /// the ImageBuf will not allocate separate storage for it. 82 /// This brings all the advantages of the ImageCache, but can 83 /// only be used for read-only ImageBuf's that reference a 84 /// stored image file. 85 // clang-format on 86 }; 87 88 /// @{ 89 /// @name Constructing and destructing an ImageBuf. 90 91 /// Default constructor makes an empty/uninitialized ImageBuf. There 92 /// isn't much you can do with an uninitialized buffer until you call 93 /// `reset()`. The storage type of a default-constructed ImageBuf is 94 /// `IBStorage::UNINITIALIZED`. 95 ImageBuf(); 96 97 /// Destructor for an ImageBuf. 98 ~ImageBuf(); 99 100 /// Construct a read-only ImageBuf that will be used to read the named 101 /// file (at the given subimage and MIP-level, defaulting to the first 102 /// in the file). But don't read it yet! The image will actually be 103 /// read lazily, only when other methods need to access the spec and/or 104 /// pixels, or when an explicit call to `init_spec()` or `read()` is 105 /// made, whichever comes first. 106 /// 107 /// The implementation may end up either reading the entire image 108 /// internally owned memory (if so, the storage will be `LOCALBUFFER`), 109 /// or it may rely on being backed by an ImageCache (in this case, the 110 /// storage will be `IMAGECACHE`) -- depending on the image size and 111 /// other factors. 112 /// 113 /// @param name 114 /// The image to read. 115 /// @param subimage/miplevel 116 /// The subimage and MIP level to read (defaults to the 117 /// first subimage of the file, highest-res MIP level). 118 /// @param imagecache 119 /// Optionally, a particular ImageCache to use. If nullptr, 120 /// the default global/shared image cache will be used. If 121 /// a custom ImageCache (not the global/shared one), it is 122 /// important that the IC should not be destroyed while the 123 /// ImageBuf is still alive. 124 /// @param config 125 /// Optionally, a pointer to an ImageSpec whose metadata 126 /// contains configuration hints that set options related 127 /// to the opening and reading of the file. 128 /// @param ioproxy 129 /// Optional pointer to an IOProxy to use when reading from the 130 /// file. The caller retains ownership of the proxy. 131 /// 132 explicit ImageBuf(string_view name, int subimage = 0, int miplevel = 0, 133 ImageCache* imagecache = nullptr, 134 const ImageSpec* config = nullptr, 135 Filesystem::IOProxy* ioproxy = nullptr); 136 137 // Deprecated synonym for `ImageBuf(name, 0, 0, imagecache, nullptr)`. 138 ImageBuf(string_view name, ImageCache* imagecache); 139 140 /// Construct a writable ImageBuf with the given specification 141 /// (including resolution, data type, metadata, etc.). The ImageBuf will 142 /// allocate and own its own pixel memory and will free that memory 143 /// automatically upon destruction, clear(), or reset(). Upon successful 144 /// initialization, the storage will be reported as `LOCALBUFFER`. 145 /// 146 /// @param spec 147 /// An ImageSpec describing the image and its metadata. If 148 /// not enough information is given to know how much memory 149 /// to allocate (width, height, depth, channels, and data 150 /// format), the ImageBuf will remain in an UNINITIALIZED 151 /// state and will have no local pixel storage. 152 /// @param zero 153 /// After a successful allocation of the local pixel 154 /// storage, this parameter controls whether the pixels 155 /// will be initialized to hold zero (black) values 156 /// (`InitializePixels::Yes`) or if the pixel memory will 157 /// remain uninitialized (`InitializePixels::No`) and thus 158 /// may hold nonsensical values. Choosing `No` may save the 159 /// time of writing to the pixel memory if you know for sure 160 /// that you are about to overwrite it completely before you 161 /// will need to read any pixel values. 162 /// 163 explicit ImageBuf(const ImageSpec& spec, 164 InitializePixels zero = InitializePixels::Yes); 165 166 // Deprecated/useless synonym for `ImageBuf(spec,zero)` but also gives 167 // it an internal name. 168 ImageBuf(string_view name, const ImageSpec& spec, 169 InitializePixels zero = InitializePixels::Yes); 170 171 /// Construct a writable ImageBuf that "wraps" existing pixel memory 172 /// owned by the calling application. The ImageBuf does not own the 173 /// pixel storage and will will not free/delete that memory, even when 174 /// the ImageBuf is destroyed. Upon successful initialization, the 175 /// storage will be reported as `APPBUFFER`. 176 /// 177 /// @param spec 178 /// An ImageSpec describing the image and its metadata. If 179 /// not enough information is given to know the "shape" of 180 /// the image (width, height, depth, channels, and data 181 /// format), the ImageBuf will remain in an UNINITIALIZED 182 /// state. 183 /// @param buffer 184 /// A pointer to the caller-owned memory containing the 185 /// storage for the pixels. It must be already allocated 186 /// with enough space to hold a full image as described by 187 /// `spec`. 188 /// 189 ImageBuf(const ImageSpec& spec, void* buffer); 190 191 // Deprecated/useless synonym for `ImageBuf(spec,buffer)` but also gives 192 // it an internal name. 193 ImageBuf(string_view name, const ImageSpec& spec, void* buffer); 194 195 /// Construct a copy of an ImageBuf. 196 ImageBuf(const ImageBuf& src); 197 198 /// Move the contents of an ImageBuf to another ImageBuf. 199 ImageBuf(ImageBuf&& src); 200 201 // Old name for reset(). 202 void clear(); 203 204 /// Destroy any previous contents of the ImageBuf and re-initialize it 205 /// to resemble a freshly constructed ImageBuf using the default 206 /// constructor (holding no image, with storage 207 /// `IBStorage::UNINITIALIZED`). reset()208 void reset() { clear(); } 209 210 // Deprecated/useless synonym for `reset(name, 0, 0, imagecache, nullptr)` 211 void reset(string_view name, ImageCache* imagecache); 212 213 /// Destroy any previous contents of the ImageBuf and re-initialize it 214 /// as if newly constructed with the same arguments, as a read-only 215 /// representation of an existing image file. 216 void reset(string_view name, int subimage = 0, int miplevel = 0, 217 ImageCache* imagecache = nullptr, 218 const ImageSpec* config = nullptr, 219 Filesystem::IOProxy* ioproxy = nullptr); 220 221 /// Destroy any previous contents of the ImageBuf and re-initialize it 222 /// as if newly constructed with the same arguments, as a read/write 223 /// image with locally allocated storage that can hold an image as 224 /// described by `spec`. The optional `zero` parameter controls whether 225 /// the pixel values are filled with black/empty, or are left 226 /// uninitialized after being allocated. 227 /// 228 /// Note that if the ImageSpec does not contain enough information to 229 /// specify how much memory to allocate (width, height, channels, and 230 /// data format), the ImageBuf will remain uninitialized (regardless of 231 /// how `zero` is set). 232 void reset(const ImageSpec& spec, 233 InitializePixels zero = InitializePixels::Yes); 234 235 // Deprecated/useless synonym for `reset(spec, spec, zero)` and also 236 // give it an internal name. 237 void reset(string_view name, const ImageSpec& spec, 238 InitializePixels zero = InitializePixels::Yes); 239 240 /// Destroy any previous contents of the ImageBuf and re-initialize it 241 /// as if newly constructed with the same arguments, to "wrap" existing 242 /// pixel memory owned by the calling application. 243 void reset(const ImageSpec& spec, void* buffer); 244 245 /// Make the ImageBuf be writable. That means that if it was previously 246 /// backed by an ImageCache (storage was `IMAGECACHE`), it will force a 247 /// full read so that the whole image is in local memory. This will 248 /// invalidate any current iterators on the image. It has no effect if 249 /// the image storage is not `IMAGECACHE`. 250 /// 251 /// @param keep_cache_type 252 /// If true, preserve any ImageCache-forced data types (you 253 /// might want to do this if it is critical that the 254 /// apparent data type doesn't change, for example if you 255 /// are calling `make_writable()` from within a 256 /// type-specialized function). 257 /// @returns 258 /// Return `true` if it works (including if no read was 259 /// necessary), `false` if something went horribly wrong. 260 bool make_writable(bool keep_cache_type = false); 261 262 // DEPRECATED(2.2): This is an alternate, and less common, spelling. 263 // Let's standardize on "writable". We will eventually remove this. 264 bool make_writeable(bool keep_cache_type = false); 265 266 /// @} 267 268 269 /// Wrap mode describes what happens when an iterator points to 270 /// a value outside the usual data range of an image. 271 enum WrapMode { 272 WrapDefault, 273 WrapBlack, 274 WrapClamp, 275 WrapPeriodic, 276 WrapMirror, 277 _WrapLast 278 }; 279 280 281 /// @{ 282 /// @name Reading and Writing disk images 283 284 /// Read the particular subimage and MIP level of the image. Generally, 285 /// this will skip the expensive read if the file has already been read 286 /// into the ImageBuf (at the specified subimage and MIP level). It 287 /// will clear and re-allocate memory if the previously allocated space 288 /// was not appropriate for the size or data type of the image being 289 /// read. 290 /// 291 /// In general, `read()` will try not to do any I/O at the time of the 292 /// `read()` call, but rather to have the ImageBuf "backed" by an 293 /// ImageCache, which will do the file I/O on demand, as pixel values 294 /// are needed, and in that case the ImageBuf doesn't actually allocate 295 /// memory for the pixels (the data lives in the ImageCache). However, 296 /// there are several conditions for which the ImageCache will be 297 /// bypassed, the ImageBuf will allocate "local" memory, and the disk 298 /// file will be read directly into allocated buffer at the time of the 299 /// `read()` call: (a) if the `force` parameter is `true`; (b) if the 300 /// `convert` parameter requests a data format conversion to a type that 301 /// is not the native file type and also is not one of the internal 302 /// types supported by the ImageCache (specifically, `float` and 303 /// `UINT8`); (c) if the ImageBuf already has local pixel memory 304 /// allocated, or "wraps" an application buffer. 305 /// 306 /// Note that `read()` is not strictly necessary. If you are happy with 307 /// the filename, subimage and MIP level specified by the ImageBuf 308 /// constructor (or the last call to `reset()`), and you want the 309 /// storage to be backed by the ImageCache (including storing the 310 /// pixels in whatever data format that implies), then the file contents 311 /// will be automatically read the first time you make any other 312 /// ImageBuf API call that requires the spec or pixel values. The only 313 /// reason to call `read()` yourself is if you are changing the 314 /// filename, subimage, or MIP level, or if you want to use `force = 315 /// true` or a specific `convert` value to force data format conversion. 316 /// 317 /// @param subimage/miplevel 318 /// The subimage and MIP level to read. 319 /// @param force 320 /// If `true`, will force an immediate full read into 321 /// ImageBuf-owned local pixel memory (yielding a 322 /// `LOCALPIXELS` storage buffer). Otherwise, it is up to 323 /// the implementation whether to immediately read or have 324 /// the image backed by an ImageCache (storage 325 /// `IMAGECACHE`.) 326 /// @param convert 327 /// If set to a specific type (not`UNKNOWN`), the ImageBuf 328 /// memory will be allocated for that type specifically and 329 /// converted upon read. 330 /// @param progress_callback/progress_callback_data 331 /// If `progress_callback` is non-NULL, the underlying 332 /// read, if expensive, may make several calls to 333 /// `progress_callback(progress_callback_data, portion_done)` 334 /// which allows you to implement some sort of progress 335 /// meter. Note that if the ImageBuf is backed by an 336 /// ImageCache, the progress callback will never be called, 337 /// since no actual file I/O will occur at this time 338 /// (ImageCache will load tiles or scanlines on demand, as 339 /// individual pixel values are needed). 340 /// 341 /// @returns 342 /// `true` upon success, or `false` if the read failed (in 343 /// which case, you should be able to retrieve an error 344 /// message via `geterror()`). 345 /// 346 bool read(int subimage = 0, int miplevel = 0, bool force = false, 347 TypeDesc convert = TypeDesc::UNKNOWN, 348 ProgressCallback progress_callback = nullptr, 349 void* progress_callback_data = nullptr); 350 351 /// Read the file, if possible only allocating and reading a subset of 352 /// channels, `[chbegin..chend-1]`. This can be a performance and memory 353 /// improvement for some image file formats, if you know that any use of 354 /// the ImageBuf will only access a subset of channels from a 355 /// many-channel file. 356 /// 357 /// Additional parameters: 358 /// 359 /// @param chbegin/chend 360 /// The subset (a range with "exclusive end") of channels to 361 /// read, if the implementation is able to read only a 362 /// subset of channels and have a performance advantage by 363 /// doing so. If `chbegin` is 0 and `chend` is either 364 /// negative or greater than the number of channels in the 365 /// file, all channels will be read. Please note that it is 366 /// "advisory" and not guaranteed to be honored by the 367 /// underlying implementation. 368 bool read(int subimage, int miplevel, int chbegin, int chend, bool force, 369 TypeDesc convert, ProgressCallback progress_callback = nullptr, 370 void* progress_callback_data = nullptr); 371 372 /// Read the ImageSpec for the given file, subimage, and MIP level into 373 /// the ImageBuf, but will not read the pixels or allocate any local 374 /// storage (until a subsequent call to `read()`). This is helpful if 375 /// you have an ImageBuf and you need to know information about the 376 /// image, but don't want to do a full read yet, and maybe won't need to 377 /// do the full read, depending on what's found in the spec. 378 /// 379 /// Note that `init_spec()` is not strictly necessary. If you are happy 380 /// with the filename, subimage and MIP level specified by the ImageBuf 381 /// constructor (or the last call to `reset()`), then the spec will be 382 /// automatically read the first time you make any other ImageBuf API 383 /// call that requires it. The only reason to call `read()` yourself is 384 /// if you are changing the filename, subimage, or MIP level, or if you 385 /// want to use `force=true` or a specific `convert` value to force 386 /// data format conversion. 387 /// 388 /// @param filename 389 /// The filename to read from (should be the same as the 390 /// filename used when the ImageBuf was constructed or 391 /// reset.) 392 /// @param subimage/miplevel 393 /// The subimage and MIP level to read. 394 /// 395 /// @returns 396 /// `true` upon success, or `false` if the read failed (in 397 /// which case, you should be able to retrieve an error 398 /// message via `geterror()`). 399 /// 400 bool init_spec(string_view filename, int subimage, int miplevel); 401 402 /// Write the image to the named file, converted to the specified pixel 403 /// data type `dtype` (`TypeUnknown` signifies to use the data type of 404 /// the buffer), and file format (an empty `fileformat` means to infer 405 /// the type from the filename extension). 406 /// 407 /// By default, it will always try to write a scanline-oriented file, 408 /// unless the `set_write_tiles()` method has been used to override 409 /// this. 410 /// 411 /// @param filename 412 /// The filename to write to. 413 /// @param dtype 414 /// Optional override of the pixel data format to use in the 415 /// file being written. The default (`UNKNOWN`) means to try 416 /// writing the same data format that as pixels are stored 417 /// within the ImageBuf memory (or whatever type was 418 /// specified by a prior call to `set_write_format()`). In 419 /// either case, if the file format does not support that 420 /// data type, another will be automatically chosen that is 421 /// supported by the file type and loses as little precision 422 /// as possible. 423 /// @param fileformat 424 /// Optional override of the file format to write. The 425 /// default (empty string) means to infer the file format 426 /// from the extension of the `filename` (for 427 /// example, "foo.tif" will write a TIFF file). 428 /// @param progress_callback/progress_callback_data 429 /// If `progress_callback` is non-NULL, the underlying 430 /// write, if expensive, may make several calls to 431 /// `progress_callback(progress_callback_data, portion_done)` 432 /// which allows you to implement some sort of progress 433 /// meter. 434 /// 435 /// @returns 436 /// `true` upon success, or `false` if the write failed (in 437 /// which case, you should be able to retrieve an error 438 /// message via `geterror()`). 439 /// 440 441 bool write(string_view filename, TypeDesc dtype = TypeUnknown, 442 string_view fileformat = string_view(), 443 ProgressCallback progress_callback = nullptr, 444 void* progress_callback_data = nullptr) const; 445 446 #ifndef DOXYGEN_SHOULD_SKIP_THIS 447 // DEPRECATED(1.9): old version did not have the data type 448 bool write(string_view filename, string_view fileformat, 449 ProgressCallback progress_callback = nullptr, 450 void* progress_callback_data = nullptr) const 451 { 452 return write(filename, TypeUnknown, fileformat, progress_callback, 453 progress_callback_data); 454 } 455 #endif // DOXYGEN_SHOULD_SKIP_THIS 456 457 /// Set the pixel data format that will be used for subsequent `write()` 458 /// calls that do not themselves request a specific data type request. 459 /// 460 /// Note that this does not affect the variety of `write()` that takes 461 /// an open `ImageOutput*` as a parameter. 462 /// 463 /// @param format 464 /// The data type to be used for all channels. 465 void set_write_format(TypeDesc format); 466 467 /// Set the per-channel pixel data format that will be used for 468 /// subsequent `write()` calls that do not themselves request a specific 469 /// data type request. 470 /// 471 /// @param format 472 /// The type of each channel (in order). Any channel's 473 /// format specified as `TypeUnknown` will default to be 474 /// whatever type is described in the ImageSpec of the 475 /// buffer. 476 void set_write_format(cspan<TypeDesc> format); 477 478 /// Override the tile sizing for subsequent calls to the `write()` 479 /// method (the variety that does not take an open `ImageOutput*`). 480 /// Setting all three dimensions to 0 indicates that the output should 481 /// be a scanline-oriented file. 482 /// 483 /// This lets you write a tiled file from an ImageBuf that may have been 484 /// read originally from a scanline file, or change the dimensions of a 485 /// tiled file, or to force the file written to be scanline even if it 486 /// was originally read from a tiled file. 487 /// 488 /// In all cases, if the file format ultimately written does not support 489 /// tiling, or the tile dimensions requested, a suitable supported 490 /// tiling choice will be made automatically. 491 void set_write_tiles(int width = 0, int height = 0, int depth = 0); 492 493 /// Supply an IOProxy to use for a subsequent call to `write()`. 494 /// 495 /// If a proxy is set but it later turns out that the file format 496 /// selected does not support write proxies, then `write()` will fail 497 /// with an error. 498 void set_write_ioproxy(Filesystem::IOProxy* ioproxy); 499 500 /// Write the pixels of the ImageBuf to an open ImageOutput. The 501 /// ImageOutput must have already been opened with a spec that indicates 502 /// a resolution identical to that of this ImageBuf (but it may have 503 /// specified a different pixel data type, in which case data 504 /// conversions will happen automatically). This method does NOT close 505 /// the file when it's done (and so may be called in a loop to write a 506 /// multi-image file). 507 /// 508 /// Note that since this uses an already-opened `ImageOutput`, which is 509 /// too late to change how it was opened, it does not honor any prior 510 /// calls to `set_write_format` or `set_write_tiles`. 511 /// 512 /// The main application of this method is to allow an ImageBuf (which 513 /// by design may hold only a *single* image) to be used for the output 514 /// of one image of a multi-subimage and/or MIP-mapped image file. 515 /// 516 /// @param out 517 /// A pointer to an already-opened `ImageOutput` to which 518 /// the pixels of the ImageBuf will be written. 519 /// @param progress_callback/progress_callback_data 520 /// If `progress_callback` is non-NULL, the underlying 521 /// write, if expensive, may make several calls to 522 /// `progress_callback(progress_callback_data, portion_done)` 523 /// which allows you to implement some sort of progress 524 /// meter. 525 /// @returns `true` if all went ok, `false` if there were errors 526 /// writing. 527 bool write(ImageOutput* out, ProgressCallback progress_callback = nullptr, 528 void* progress_callback_data = nullptr) const; 529 530 /// @} 531 532 /// @{ 533 /// @name Copying ImageBuf's and blocks of pixels 534 535 /// Copy assignment. 536 const ImageBuf& operator=(const ImageBuf& src); 537 538 /// Move assignment. 539 const ImageBuf& operator=(ImageBuf&& src); 540 541 /// Copy all the metadata from `src` to `*this` (except for pixel data 542 /// resolution, channel types and names, and data format). 543 void copy_metadata(const ImageBuf& src); 544 545 /// Copy the pixel data from `src` to `*this`, automatically converting 546 /// to the existing data format of `*this`. It only copies pixels in 547 /// the overlap regions (and channels) of the two images; pixel data in 548 /// `*this` that do exist in `src` will be set to 0, and pixel data in 549 /// `src` that do not exist in `*this` will not be copied. 550 bool copy_pixels(const ImageBuf& src); 551 552 /// Try to copy the pixels and metadata from `src` to `*this` 553 /// (optionally with an explicit data format conversion). 554 /// 555 /// If the previous state of `*this` was uninitialized, owning its own 556 /// local pixel memory, or referring to a read-only image backed by 557 /// ImageCache, then local pixel memory will be allocated to hold the 558 /// new pixels and the call always succeeds unless the memory cannot be 559 /// allocated. In this case, the `format` parameter may request a pixel 560 /// data type that is different from that of the source buffer. 561 /// 562 /// If `*this` previously referred to an app-owned memory buffer, the 563 /// memory cannot be re-allocated, so the call will only succeed if the 564 /// app-owned buffer is already the correct resolution and number of 565 /// channels. The data type of the pixels will be converted 566 /// automatically to the data type of the app buffer. 567 /// 568 /// @param src 569 /// Another ImageBuf from which to copy the pixels and 570 /// metadata. 571 /// @param format 572 /// Optionally request the pixel data type to be used. The 573 /// default of `TypeUnknown` means to use whatever data type 574 /// is used by the `src`. If `*this` is already initialized 575 /// and has `APPBUFFER` storage ("wrapping" an application 576 /// buffer), this parameter is ignored. 577 /// @returns 578 /// `true` upon success or `false` upon error/failure. 579 bool copy(const ImageBuf& src, TypeDesc format = TypeUnknown); 580 581 /// Return a full copy of `this` ImageBuf (optionally with an explicit 582 /// data format conversion). 583 ImageBuf copy(TypeDesc format /*= TypeDesc::UNKNOWN*/) const; 584 585 /// Swap the entire contents with another ImageBuf. swap(ImageBuf & other)586 void swap(ImageBuf& other) { std::swap(m_impl, other.m_impl); } 587 588 /// @} 589 590 591 /// @{ 592 /// @name Getting and setting pixel values 593 594 /// Retrieve a single channel of one pixel. 595 /// 596 /// @param x/y/z 597 /// The pixel coordinates. 598 /// @param c 599 /// The channel index to retrieve. 600 /// @param wrap 601 /// WrapMode that determines the behavior if the pixel 602 /// coordinates are outside the data window: `WrapBlack`, 603 /// `WrapClamp`, `WrapPeriodic`, `WrapMirror`. 604 /// @returns 605 /// The data value, converted to a `float`. 606 float getchannel(int x, int y, int z, int c, 607 WrapMode wrap = WrapBlack) const; 608 609 /// Retrieve the pixel value by x, y, z pixel indices, placing its 610 /// contents in `pixel[0..n-1]` where *n* is the smaller of 611 /// `maxchannels` the actual number of channels stored in the buffer. 612 /// 613 /// @param x/y/z 614 /// The pixel coordinates. 615 /// @param pixel 616 /// The results are stored in `pixel[0..nchannels-1]`. It is 617 /// up to the caller to ensure that `pixel` points to enough 618 /// memory to hold the required number of channels. 619 /// @param maxchannels 620 /// Optional clamp to the number of channels retrieved. 621 /// @param wrap 622 /// WrapMode that determines the behavior if the pixel 623 /// coordinates are outside the data window: `WrapBlack`, 624 /// `WrapClamp`, `WrapPeriodic`, `WrapMirror`. 625 void getpixel(int x, int y, int z, float* pixel, int maxchannels = 1000, 626 WrapMode wrap = WrapBlack) const; 627 628 // Simplified version: 2D, black wrap. 629 void getpixel(int x, int y, float* pixel, int maxchannels = 1000) const 630 { 631 getpixel(x, y, 0, pixel, maxchannels); 632 } 633 634 /// Sample the image plane at pixel coordinates (x,y), using linear 635 /// interpolation between pixels, placing the result in `pixel[]`. 636 /// 637 /// @param x/y 638 /// The pixel coordinates. Note that pixel data values 639 /// themselves are at the pixel centers, so pixel (i,j) is 640 /// at image plane coordinate (i+0.5, j+0.5). 641 /// @param pixel 642 /// The results are stored in `pixel[0..nchannels-1]`. It is 643 /// up to the caller to ensure that `pixel` points to enough 644 /// memory to hold the number of channels in the image. 645 /// @param wrap 646 /// WrapMode that determines the behavior if the pixel 647 /// coordinates are outside the data window: `WrapBlack`, 648 /// `WrapClamp`, `WrapPeriodic`, `WrapMirror`. 649 void interppixel(float x, float y, float* pixel, 650 WrapMode wrap = WrapBlack) const; 651 652 /// Linearly interpolate at NDC coordinates (s,t), where (0,0) is 653 /// the upper left corner of the display window, (1,1) the lower 654 /// right corner of the display window. 655 /// 656 /// @note `interppixel()` uses pixel coordinates (ranging 0..resolution) 657 /// whereas `interppixel_NDC()` uses NDC coordinates (ranging 0..1). 658 void interppixel_NDC(float s, float t, float* pixel, 659 WrapMode wrap = WrapBlack) const; 660 661 // DEPRECATED (1.5) synonym for interppixel_NDC. 662 void interppixel_NDC_full(float s, float t, float* pixel, 663 WrapMode wrap = WrapBlack) const; 664 665 /// Bicubic interpolation at pixel coordinates (x,y). 666 void interppixel_bicubic(float x, float y, float* pixel, 667 WrapMode wrap = WrapBlack) const; 668 669 /// Bicubic interpolation at NDC space coordinates (s,t), where (0,0) 670 /// is the upper left corner of the display (a.k.a. "full") window, 671 /// (1,1) the lower right corner of the display window. 672 void interppixel_bicubic_NDC(float s, float t, float* pixel, 673 WrapMode wrap = WrapBlack) const; 674 675 676 /// Set the pixel with coordinates (x,y,0) to have the values in span 677 /// `pixel[]`. The number of channels copied is the minimum of the span 678 /// length and the actual number of channels in the image. setpixel(int x,int y,cspan<float> pixel)679 void setpixel(int x, int y, cspan<float> pixel) 680 { 681 setpixel(x, y, 0, pixel); 682 } 683 684 /// Set the pixel with coordinates (x,y,z) to have the values in span 685 /// `pixel[]`. The number of channels copied is the minimum of the span 686 /// length and the actual number of channels in the image. setpixel(int x,int y,int z,cspan<float> pixel)687 void setpixel(int x, int y, int z, cspan<float> pixel) 688 { 689 setpixel(x, y, z, pixel.data(), int(pixel.size())); 690 } 691 692 /// Set the `i`-th pixel value of the image (out of width*height*depth), 693 /// from floating-point values in span `pixel[]`. The number of 694 /// channels copied is the minimum of the span length and the actual 695 /// number of channels in the image. setpixel(int i,cspan<float> pixel)696 void setpixel(int i, cspan<float> pixel) 697 { 698 setpixel(i, pixel.data(), int(pixel.size())); 699 } 700 701 /// Set the pixel with coordinates (x,y,0) to have the values in 702 /// pixel[0..n-1]. The number of channels copied, n, is the minimum 703 /// of maxchannels and the actual number of channels in the image. 704 void setpixel(int x, int y, const float* pixel, int maxchannels = 1000) 705 { 706 setpixel(x, y, 0, pixel, maxchannels); 707 } 708 709 /// Set the pixel with coordinates (x,y,z) to have the values in 710 /// `pixel[0..n-1]`. The number of channels copied, n, is the minimum 711 /// of `maxchannels` and the actual number of channels in the image. 712 void setpixel(int x, int y, int z, const float* pixel, 713 int maxchannels = 1000); 714 715 /// Set the `i`-th pixel value of the image (out of width*height*depth), 716 /// from floating-point values in `pixel[]`. Set at most 717 /// `maxchannels` (will be clamped to the actual number of channels). 718 void setpixel(int i, const float* pixel, int maxchannels = 1000); 719 720 /// Retrieve the rectangle of pixels spanning the ROI (including 721 /// channels) at the current subimage and MIP-map level, storing the 722 /// pixel values beginning at the address specified by result and with 723 /// the given strides (by default, AutoStride means the usual contiguous 724 /// packing of pixels) and converting into the data type described by 725 /// `format`. It is up to the caller to ensure that result points to an 726 /// area of memory big enough to accommodate the requested rectangle. 727 /// Return true if the operation could be completed, otherwise return 728 /// false. 729 bool get_pixels(ROI roi, TypeDesc format, void* result, 730 stride_t xstride = AutoStride, 731 stride_t ystride = AutoStride, 732 stride_t zstride = AutoStride) const; 733 734 /// Copy the data into the given ROI of the ImageBuf. The data points to 735 /// values specified by `format`, with layout detailed by the stride 736 /// values (in bytes, with AutoStride indicating "contiguous" layout). 737 /// It is up to the caller to ensure that data points to an area of 738 /// memory big enough to account for the ROI. Return true if the 739 /// operation could be completed, otherwise return false. 740 bool set_pixels(ROI roi, TypeDesc format, const void* data, 741 stride_t xstride = AutoStride, 742 stride_t ystride = AutoStride, 743 stride_t zstride = AutoStride); 744 745 /// @} 746 747 /// @{ 748 /// @name Getting and setting information about an ImageBuf 749 750 /// Returns `true` if the ImageBuf is initialized, `false` if not yet 751 /// initialized. 752 bool initialized() const; 753 754 /// Which type of storage is being used for the pixels? Returns an 755 /// enumerated type describing the type of storage currently employed by 756 /// the ImageBuf: `UNINITIALIZED` (no storage), `LOCALBUFFER` (the 757 /// ImageBuf has allocated and owns the pixel memory), `APPBUFFER` (the 758 /// ImageBuf "wraps" memory owned by the calling application), or 759 /// `IMAGECACHE` (the image is backed by an ImageCache). 760 IBStorage storage() const; 761 762 /// Return a read-only (const) reference to the image spec that 763 /// describes the buffer. 764 const ImageSpec& spec() const; 765 766 /// Return a writable reference to the ImageSpec that describes the 767 /// buffer. It's ok to modify most of the metadata, but if you modify 768 /// the spec's `format`, `width`, `height`, or `depth` fields, you get 769 /// the pain you deserve, as the ImageBuf will no longer have correct 770 /// knowledge of its pixel memory layout. USE WITH EXTREME CAUTION. 771 ImageSpec& specmod(); 772 773 /// Return a read-only (const) reference to the "native" image spec 774 /// (that describes the file, which may be slightly different than 775 /// the spec of the ImageBuf, particularly if the IB is backed by an 776 /// ImageCache that is imposing some particular data format or tile 777 /// size). 778 /// 779 /// This may differ from `spec()` --- for example, if a data format 780 /// conversion was requested, if the buffer is backed by an ImageCache 781 /// which stores the pixels internally in a different data format than 782 /// that of the file, or if the file had differing per-channel data 783 /// formats (ImageBuf must contain a single data format for all 784 /// channels). 785 const ImageSpec& nativespec() const; 786 787 /// Returns the name of the buffer (name of the file, for an ImageBuf 788 /// read from disk). 789 string_view name(void) const; 790 791 /// Return the name of the image file format of the disk file we read 792 /// into this image, for example `"openexr"`. Returns an empty string 793 /// if this image was not the result of a read(). 794 string_view file_format_name(void) const; 795 796 /// Return the index of the subimage the ImageBuf is currently holding. 797 int subimage() const; 798 799 /// Return the number of subimages in the file. 800 int nsubimages() const; 801 802 /// Return the index of the miplevel the ImageBuf is currently holding. 803 int miplevel() const; 804 805 /// Return the number of miplevels of the current subimage. 806 int nmiplevels() const; 807 808 /// Return the number of color channels in the image. This is equivalent 809 /// to `spec().nchannels`. 810 int nchannels() const; 811 812 /// Return the beginning (minimum) x coordinate of the defined image. 813 int xbegin() const; 814 /// Return the end (one past maximum) x coordinate of the defined image. 815 int xend() const; 816 /// Return the beginning (minimum) y coordinate of the defined image. 817 int ybegin() const; 818 /// Return the end (one past maximum) y coordinate of the defined image. 819 int yend() const; 820 /// Return the beginning (minimum) z coordinate of the defined image. 821 int zbegin() const; 822 /// Return the end (one past maximum) z coordinate of the defined image. 823 int zend() const; 824 /// Return the minimum x coordinate of the defined image. 825 int xmin() const; 826 /// Return the maximum x coordinate of the defined image. 827 int xmax() const; 828 /// Return the minimum y coordinate of the defined image. 829 int ymin() const; 830 /// Return the maximum y coordinate of the defined image. 831 int ymax() const; 832 /// Return the minimum z coordinate of the defined image. 833 int zmin() const; 834 /// Return the maximum z coordinate of the defined image. 835 int zmax() const; 836 837 /// Return the current `"Orientation"` metadata for the image, per the 838 /// table in `sec-metadata-orientation`_ 839 int orientation() const; 840 841 /// Set the `"Orientation"` metadata for the image. 842 void set_orientation(int orient); 843 844 // Return the width, height, or full versions, if the image were 845 // positioned for display in its designated orientation. 846 int oriented_width() const; 847 int oriented_height() const; 848 int oriented_x() const; 849 int oriented_y() const; 850 int oriented_full_width() const; 851 int oriented_full_height() const; 852 int oriented_full_x() const; 853 int oriented_full_y() const; 854 855 /// Alters the metadata of the spec in the ImageBuf to reset the 856 /// "origin" of the pixel data window to be the specified coordinates. 857 /// This does not affect the size of the pixel data window, only its 858 /// position. 859 void set_origin(int x, int y, int z = 0); 860 861 /// Set the "full" (a.k.a. display) window to Alters the metadata of the 862 /// spec in the ImageBuf to reset the "full" image size (a.k.a. 863 /// "display window") to 864 /// 865 /// [xbegin,xend) x [ybegin,yend) x [zbegin,zend)` 866 /// 867 /// This does not affect the size of the pixel data window. 868 void set_full(int xbegin, int xend, int ybegin, int yend, int zbegin, 869 int zend); 870 871 /// Return pixel data window for this ImageBuf as a ROI. 872 ROI roi() const; 873 874 /// Return full/display window for this ImageBuf as a ROI. 875 ROI roi_full() const; 876 877 /// Set full/display window for this ImageBuf to a ROI. 878 /// Does NOT change the channels of the spec, regardless of `newroi`. 879 void set_roi_full(const ROI& newroi); 880 881 /// Is the specified roi completely contained in the data window of 882 /// this ImageBuf? 883 bool contains_roi(ROI roi) const; 884 885 bool pixels_valid(void) const; 886 887 /// The data type of the pixels stored in the buffer (equivalent to 888 /// `spec().format`). 889 TypeDesc pixeltype() const; 890 891 /// Return a raw pointer to "local" pixel memory, if they are fully in 892 /// RAM and not backed by an ImageCache, or `nullptr` otherwise. You 893 /// can also test it like a bool to find out if pixels are local. 894 void* localpixels(); 895 const void* localpixels() const; 896 897 /// Pixel-to-pixel stride within the localpixels memory. 898 stride_t pixel_stride() const; 899 /// Scanline-to-scanline stride within the localpixels memory. 900 stride_t scanline_stride() const; 901 /// Z plane stride within the localpixels memory. 902 stride_t z_stride() const; 903 904 /// Are the pixels backed by an ImageCache, rather than the whole 905 /// image being in RAM somewhere? 906 bool cachedpixels() const; 907 908 /// A pointer to the underlying ImageCache. 909 ImageCache* imagecache() const; 910 911 /// Return the address where pixel `(x,y,z)`, channel `ch`, is stored in 912 /// the image buffer. Use with extreme caution! Will return `nullptr` 913 /// if the pixel values aren't local in RAM. 914 const void* pixeladdr(int x, int y, int z = 0, int ch = 0) const; 915 void* pixeladdr(int x, int y, int z = 0, int ch = 0); 916 917 /// Return the index of pixel (x,y,z). If check_range is true, return 918 /// -1 for an invalid coordinate that is not within the data window. 919 int pixelindex(int x, int y, int z, bool check_range = false) const; 920 921 /// Set the threading policy for this ImageBuf, controlling the maximum 922 /// amount of parallelizing thread "fan-out" that might occur during 923 /// expensive operations. The default of 0 means that the global 924 /// `attribute("threads")` value should be used (which itself defaults 925 /// to using as many threads as cores). 926 /// 927 /// The main reason to change this value is to set it to 1 to indicate 928 /// that the calling thread should do all the work rather than spawning 929 /// new threads. That is probably the desired behavior in situations 930 /// where the calling application has already spawned multiple worker 931 /// threads. 932 void threads(int n) const; 933 934 /// Retrieve the current thread-spawning policy of this ImageBuf. 935 int threads() const; 936 937 /// @} 938 939 /// @{ 940 /// @name Error handling 941 942 /// Add simple string to the error message list for this IB. 943 void error(const std::string& message) const; 944 945 /// Error reporting for ImageBuf: call this with Python / {fmt} / 946 /// std::format style formatting specification. 947 template<typename... Args> errorfmt(const char * fmt,const Args &...args)948 void errorfmt(const char* fmt, const Args&... args) const 949 { 950 error(Strutil::fmt::format(fmt, args...)); 951 } 952 953 /// Error reporting for ImageBuf: call this with printf-like arguments 954 /// to report an error. 955 template<typename... Args> errorf(const char * fmt,const Args &...args)956 void errorf(const char* fmt, const Args&... args) const 957 { 958 error(Strutil::sprintf(fmt, args...)); 959 } 960 961 /// Error reporting for ImageBuf: call this with Strutil::format 962 /// formatting conventions. Beware, this is in transition, is currently 963 /// printf-like but will someday change to python-like! 964 template<typename... Args> error(const char * fmt,const Args &...args)965 void error(const char* fmt, const Args&... args) const 966 { 967 error(Strutil::format(fmt, args...)); 968 } 969 970 // Error reporting for ImageBuf: call this with Python / {fmt} / 971 // std::format style formatting specification. 972 template<typename... Args> 973 OIIO_DEPRECATED("use `errorfmt` instead") fmterror(const char * fmt,const Args &...args)974 void fmterror(const char* fmt, const Args&... args) const 975 { 976 error(Strutil::fmt::format(fmt, args...)); 977 } 978 979 /// Returns `true` if the ImageBuf has had an error and has an error 980 /// message ready to retrieve via `geterror()`. 981 bool has_error(void) const; 982 983 /// Return the text of all error messages issued since `geterror()` was 984 /// called (or an empty string if no errors are pending). This also 985 /// clears the error message for next time. 986 std::string geterror(void) const; 987 988 /// @} 989 990 /// @{ 991 /// @name Deep data in an ImageBuf 992 993 /// Does this ImageBuf store deep data? Returns `true` if the ImageBuf 994 /// holds a "deep" image, `false` if the ImageBuf holds an ordinary 995 /// pixel-based image. 996 bool deep() const; 997 998 /// Retrieve the number of deep data samples corresponding to pixel 999 /// (x,y,z). Return 0 if not a deep image, or if the pixel is outside 1000 /// of the data window, or if the designated pixel has no deep samples. 1001 int deep_samples(int x, int y, int z = 0) const; 1002 1003 /// Return a pointer to the raw data of pixel `(x,y,z)`, channel `c`, 1004 /// sample `s`. Return `nullptr` if the pixel coordinates or channel 1005 /// number are out of range, if the pixel/channel has no deep samples, 1006 /// or if the image is not deep. Use with caution --- these pointers may 1007 /// be invalidated by calls that adjust the number of samples in any 1008 /// pixel. 1009 const void* deep_pixel_ptr(int x, int y, int z, int c, int s = 0) const; 1010 1011 /// Return the value (as a `float`) of sample `s` of channel `c` of 1012 /// pixel `(x,y,z)`. Return 0 if not a deep image or if the pixel 1013 /// coordinates or channel number are out of range or if that pixel has 1014 /// no deep samples. 1015 float deep_value(int x, int y, int z, int c, int s) const; 1016 1017 /// Return the value (as a `uint32_t`) of sample `s` of channel `c` of 1018 /// pixel `(x,y,z)`. Return 0 if not a deep image or if the pixel 1019 /// coordinates or channel number are out of range or if that pixel has 1020 /// no deep samples. 1021 uint32_t deep_value_uint(int x, int y, int z, int c, int s) const; 1022 1023 /// Set the number of deep samples for pixel (x,y,z). If data has 1024 /// already been allocated, this is equivalent to inserting or erasing 1025 /// samples. 1026 void set_deep_samples(int x, int y, int z, int nsamples); 1027 1028 /// Insert `nsamples` new samples, starting at position `samplepos` of 1029 /// pixel (x,y,z). 1030 void deep_insert_samples(int x, int y, int z, int samplepos, int nsamples); 1031 1032 /// Remove `nsamples` samples, starting at position `samplepos` of pixel 1033 /// (x,y,z). 1034 void deep_erase_samples(int x, int y, int z, int samplepos, int nsamples); 1035 1036 /// Set the value of sample `s` of channel `c` of pixel `(x,y,z)` to a 1037 /// `float` value (it is expected that channel `c` is a floating point 1038 /// type). 1039 void set_deep_value(int x, int y, int z, int c, int s, float value); 1040 1041 /// Set the value of sample `s` of channel `c` of pixel `(x,y,z)` to a 1042 /// `uint32_t` value (it is expected that channel `c` is an integer 1043 /// type). 1044 void set_deep_value(int x, int y, int z, int c, int s, uint32_t value); 1045 1046 /// Copy a deep pixel from another ImageBuf -- it is required to have 1047 /// the same channels. 1048 bool copy_deep_pixel(int x, int y, int z, const ImageBuf& src, int srcx, 1049 int srcy, int srcz); 1050 1051 /// Retrieve the "deep" data. 1052 DeepData* deepdata(); 1053 const DeepData* deepdata() const; 1054 1055 /// @} 1056 1057 /// Return the `WrapMode` corresponding to the name (`"default"`, 1058 /// `"black"`, `"clamp"`, `"periodic"`, `"mirror"`). For an unknown 1059 /// name, this will return `WrapDefault`. 1060 static WrapMode WrapMode_from_string(string_view name); 1061 1062 1063 friend class IteratorBase; 1064 1065 class IteratorBase { 1066 public: IteratorBase(const ImageBuf & ib,WrapMode wrap)1067 IteratorBase(const ImageBuf& ib, WrapMode wrap) 1068 : m_ib(&ib) 1069 { 1070 init_ib(wrap); 1071 range_is_image(); 1072 } 1073 1074 /// Construct valid iteration region from ImageBuf and ROI. IteratorBase(const ImageBuf & ib,const ROI & roi,WrapMode wrap)1075 IteratorBase(const ImageBuf& ib, const ROI& roi, WrapMode wrap) 1076 : m_ib(&ib) 1077 { 1078 init_ib(wrap); 1079 if (roi.defined()) { 1080 m_rng_xbegin = roi.xbegin; 1081 m_rng_xend = roi.xend; 1082 m_rng_ybegin = roi.ybegin; 1083 m_rng_yend = roi.yend; 1084 m_rng_zbegin = roi.zbegin; 1085 m_rng_zend = roi.zend; 1086 } else { 1087 range_is_image(); 1088 } 1089 } 1090 1091 /// Construct from an ImageBuf and designated region -- iterate 1092 /// over region, starting with the upper left pixel. IteratorBase(const ImageBuf & ib,int xbegin,int xend,int ybegin,int yend,int zbegin,int zend,WrapMode wrap)1093 IteratorBase(const ImageBuf& ib, int xbegin, int xend, int ybegin, 1094 int yend, int zbegin, int zend, WrapMode wrap) 1095 : m_ib(&ib) 1096 { 1097 init_ib(wrap); 1098 m_rng_xbegin = xbegin; 1099 m_rng_xend = xend; 1100 m_rng_ybegin = ybegin; 1101 m_rng_yend = yend; 1102 m_rng_zbegin = zbegin; 1103 m_rng_zend = zend; 1104 } 1105 IteratorBase(const IteratorBase & i)1106 IteratorBase(const IteratorBase& i) 1107 : m_ib(i.m_ib) 1108 , m_rng_xbegin(i.m_rng_xbegin) 1109 , m_rng_xend(i.m_rng_xend) 1110 , m_rng_ybegin(i.m_rng_ybegin) 1111 , m_rng_yend(i.m_rng_yend) 1112 , m_rng_zbegin(i.m_rng_zbegin) 1113 , m_rng_zend(i.m_rng_zend) 1114 , m_proxydata(i.m_proxydata) 1115 { 1116 init_ib(i.m_wrap); 1117 } 1118 ~IteratorBase()1119 ~IteratorBase() 1120 { 1121 if (m_tile) 1122 m_ib->imagecache()->release_tile(m_tile); 1123 } 1124 1125 /// Assign one IteratorBase to another 1126 /// assign_base(const IteratorBase & i)1127 const IteratorBase& assign_base(const IteratorBase& i) 1128 { 1129 if (m_tile) 1130 m_ib->imagecache()->release_tile(m_tile); 1131 m_tile = nullptr; 1132 m_proxydata = i.m_proxydata; 1133 m_ib = i.m_ib; 1134 init_ib(i.m_wrap); 1135 m_rng_xbegin = i.m_rng_xbegin; 1136 m_rng_xend = i.m_rng_xend; 1137 m_rng_ybegin = i.m_rng_ybegin; 1138 m_rng_yend = i.m_rng_yend; 1139 m_rng_zbegin = i.m_rng_zbegin; 1140 m_rng_zend = i.m_rng_zend; 1141 return *this; 1142 } 1143 1144 /// Retrieve the current x location of the iterator. 1145 /// x()1146 int x() const { return m_x; } 1147 /// Retrieve the current y location of the iterator. 1148 /// y()1149 int y() const { return m_y; } 1150 /// Retrieve the current z location of the iterator. 1151 /// z()1152 int z() const { return m_z; } 1153 1154 /// Is the current location within the designated iteration range? valid()1155 bool valid() const { return m_valid; } 1156 1157 /// Is the location (x,y[,z]) within the designated iteration 1158 /// range? 1159 bool valid(int x_, int y_, int z_ = 0) const 1160 { 1161 return (x_ >= m_rng_xbegin && x_ < m_rng_xend && y_ >= m_rng_ybegin 1162 && y_ < m_rng_yend && z_ >= m_rng_zbegin 1163 && z_ < m_rng_zend); 1164 } 1165 1166 /// Is the location (x,y[,z]) within the region of the ImageBuf 1167 /// that contains pixel values (sometimes called the "data window")? 1168 bool exists(int x_, int y_, int z_ = 0) const 1169 { 1170 return (x_ >= m_img_xbegin && x_ < m_img_xend && y_ >= m_img_ybegin 1171 && y_ < m_img_yend && z_ >= m_img_zbegin 1172 && z_ < m_img_zend); 1173 } 1174 /// Does the current location exist within the ImageBuf's 1175 /// data window? exists()1176 bool exists() const { return m_exists; } 1177 1178 /// Are we finished iterating over the region? 1179 // done()1180 bool done() const 1181 { 1182 // We're "done" if we are both invalid and in exactly the 1183 // spot that we would end up after iterating off of the last 1184 // pixel in the range. (The m_valid test is just a quick 1185 // early-out for when we're in the correct pixel range.) 1186 return (m_valid == false && m_x == m_rng_xbegin 1187 && m_y == m_rng_ybegin && m_z == m_rng_zend); 1188 } 1189 1190 /// Retrieve the number of deep data samples at this pixel. deep_samples()1191 int deep_samples() const { return m_ib->deep_samples(m_x, m_y, m_z); } 1192 1193 /// Return the wrap mode wrap()1194 WrapMode wrap() const { return m_wrap; } 1195 1196 /// Explicitly point the iterator. This results in an invalid 1197 /// iterator if outside the previously-designated region. 1198 void pos(int x_, int y_, int z_ = 0) 1199 { 1200 if (x_ == m_x + 1 && x_ < m_rng_xend && y_ == m_y && z_ == m_z 1201 && m_valid && m_exists) { 1202 // Special case for what is in effect just incrementing x 1203 // within the iteration region. 1204 m_x = x_; 1205 pos_xincr(); 1206 // Not necessary? m_exists = (x_ < m_img_xend); 1207 OIIO_DASSERT((x_ < m_img_xend) == m_exists); 1208 return; 1209 } 1210 bool v = valid(x_, y_, z_); 1211 bool e = exists(x_, y_, z_); 1212 if (m_localpixels) { 1213 if (e) 1214 m_proxydata = (char*)m_ib->pixeladdr(x_, y_, z_); 1215 else { // pixel not in data window 1216 m_x = x_; 1217 m_y = y_; 1218 m_z = z_; 1219 if (m_wrap == WrapBlack) { 1220 m_proxydata = (char*)m_ib->blackpixel(); 1221 } else { 1222 if (m_ib->do_wrap(x_, y_, z_, m_wrap)) 1223 m_proxydata = (char*)m_ib->pixeladdr(x_, y_, z_); 1224 else 1225 m_proxydata = (char*)m_ib->blackpixel(); 1226 } 1227 m_valid = v; 1228 m_exists = e; 1229 return; 1230 } 1231 } else if (!m_deep) 1232 m_proxydata = (char*)m_ib->retile(x_, y_, z_, m_tile, 1233 m_tilexbegin, m_tileybegin, 1234 m_tilezbegin, m_tilexend, e, 1235 m_wrap); 1236 m_x = x_; 1237 m_y = y_; 1238 m_z = z_; 1239 m_valid = v; 1240 m_exists = e; 1241 } 1242 1243 /// Increment to the next pixel in the region. 1244 /// 1245 OIIO_FORCEINLINE void operator++() 1246 { 1247 if (++m_x < m_rng_xend) { 1248 // Special case: we only incremented x, didn't change y 1249 // or z, and the previous position was within the data 1250 // window. Call a shortcut version of pos. 1251 if (m_exists) { 1252 pos_xincr(); 1253 return; 1254 } 1255 } else { 1256 // Wrap to the next scanline 1257 m_x = m_rng_xbegin; 1258 if (++m_y >= m_rng_yend) { 1259 m_y = m_rng_ybegin; 1260 if (++m_z >= m_rng_zend) { 1261 m_valid = false; // shortcut -- finished iterating 1262 return; 1263 } 1264 } 1265 } 1266 pos(m_x, m_y, m_z); 1267 } 1268 /// Increment to the next pixel in the region. 1269 /// 1270 void operator++(int) { ++(*this); } 1271 1272 /// Return the iteration range range()1273 ROI range() const 1274 { 1275 return ROI(m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend, 1276 m_rng_zbegin, m_rng_zend, 0, m_ib->nchannels()); 1277 } 1278 1279 /// Reset the iteration range for this iterator and reposition to 1280 /// the beginning of the range, but keep referring to the same 1281 /// image. 1282 void rerange(int xbegin, int xend, int ybegin, int yend, int zbegin, 1283 int zend, WrapMode wrap = WrapDefault) 1284 { 1285 m_x = 1 << 31; 1286 m_y = 1 << 31; 1287 m_z = 1 << 31; 1288 m_wrap = (wrap == WrapDefault ? WrapBlack : wrap); 1289 m_rng_xbegin = xbegin; 1290 m_rng_xend = xend; 1291 m_rng_ybegin = ybegin; 1292 m_rng_yend = yend; 1293 m_rng_zbegin = zbegin; 1294 m_rng_zend = zend; 1295 pos(xbegin, ybegin, zbegin); 1296 } 1297 1298 protected: 1299 friend class ImageBuf; 1300 friend class ImageBufImpl; 1301 const ImageBuf* m_ib = nullptr; 1302 bool m_valid = false, m_exists = false; 1303 bool m_deep = false; 1304 bool m_localpixels = false; 1305 // Image boundaries 1306 int m_img_xbegin, m_img_xend, m_img_ybegin, m_img_yend, m_img_zbegin, 1307 m_img_zend; 1308 // Iteration range 1309 int m_rng_xbegin, m_rng_xend, m_rng_ybegin, m_rng_yend, m_rng_zbegin, 1310 m_rng_zend; 1311 int m_x, m_y, m_z; 1312 ImageCache::Tile* m_tile = nullptr; 1313 int m_tilexbegin, m_tileybegin, m_tilezbegin; 1314 int m_tilexend; 1315 int m_nchannels; 1316 size_t m_pixel_bytes; 1317 char* m_proxydata = nullptr; 1318 WrapMode m_wrap = WrapBlack; 1319 1320 // Helper called by ctrs -- set up some locally cached values 1321 // that are copied or derived from the ImageBuf. init_ib(WrapMode wrap)1322 void init_ib(WrapMode wrap) 1323 { 1324 const ImageSpec& spec(m_ib->spec()); 1325 m_deep = spec.deep; 1326 m_localpixels = (m_ib->localpixels() != nullptr); 1327 m_img_xbegin = spec.x; 1328 m_img_xend = spec.x + spec.width; 1329 m_img_ybegin = spec.y; 1330 m_img_yend = spec.y + spec.height; 1331 m_img_zbegin = spec.z; 1332 m_img_zend = spec.z + spec.depth; 1333 m_nchannels = spec.nchannels; 1334 // m_tilewidth = spec.tile_width; 1335 m_pixel_bytes = spec.pixel_bytes(); 1336 m_x = 1 << 31; 1337 m_y = 1 << 31; 1338 m_z = 1 << 31; 1339 m_wrap = (wrap == WrapDefault ? WrapBlack : wrap); 1340 } 1341 1342 // Helper called by ctrs -- make the iteration range the full 1343 // image data window. range_is_image()1344 void range_is_image() 1345 { 1346 m_rng_xbegin = m_img_xbegin; 1347 m_rng_xend = m_img_xend; 1348 m_rng_ybegin = m_img_ybegin; 1349 m_rng_yend = m_img_yend; 1350 m_rng_zbegin = m_img_zbegin; 1351 m_rng_zend = m_img_zend; 1352 } 1353 1354 // Helper called by pos(), but ONLY for the case where we are 1355 // moving from an existing pixel to the next spot in +x. 1356 // Note: called *after* m_x was incremented! pos_xincr()1357 OIIO_FORCEINLINE void pos_xincr() 1358 { 1359 OIIO_DASSERT(m_exists && m_valid); // precondition 1360 OIIO_DASSERT(valid(m_x, m_y, m_z)); // should be true by definition 1361 m_proxydata += m_pixel_bytes; 1362 if (m_localpixels) { 1363 if (OIIO_UNLIKELY(m_x >= m_img_xend)) { 1364 // Ran off the end of the row 1365 m_exists = false; 1366 if (m_wrap == WrapBlack) { 1367 m_proxydata = (char*)m_ib->blackpixel(); 1368 } else { 1369 int x = m_x, y = m_y, z = m_z; 1370 if (m_ib->do_wrap(x, y, z, m_wrap)) 1371 m_proxydata = (char*)m_ib->pixeladdr(x, y, z); 1372 else 1373 m_proxydata = (char*)m_ib->blackpixel(); 1374 } 1375 } 1376 } else if (m_deep) { 1377 m_proxydata = nullptr; 1378 } else { 1379 // Cached image 1380 bool e = m_x < m_img_xend; 1381 if (OIIO_UNLIKELY(!(e && m_x < m_tilexend && m_tile))) { 1382 // Crossed a tile boundary 1383 m_proxydata = (char*)m_ib->retile(m_x, m_y, m_z, m_tile, 1384 m_tilexbegin, 1385 m_tileybegin, 1386 m_tilezbegin, m_tilexend, 1387 e, m_wrap); 1388 m_exists = e; 1389 } 1390 } 1391 } 1392 1393 // Set to the "done" position pos_done()1394 void pos_done() 1395 { 1396 m_valid = false; 1397 m_x = m_rng_xbegin; 1398 m_y = m_rng_ybegin; 1399 m_z = m_rng_zend; 1400 } 1401 1402 // Make sure it's writable. Use with caution! make_writable()1403 void make_writable() 1404 { 1405 if (!m_localpixels) { 1406 const_cast<ImageBuf*>(m_ib)->make_writable(true); 1407 OIIO_DASSERT(m_ib->storage() != IMAGECACHE); 1408 m_tile = nullptr; 1409 m_proxydata = nullptr; 1410 init_ib(m_wrap); 1411 } 1412 } 1413 }; 1414 1415 /// Templated class for referring to an individual pixel in an 1416 /// ImageBuf, iterating over the pixels of an ImageBuf, or iterating 1417 /// over the pixels of a specified region of the ImageBuf 1418 /// [xbegin..xend) X [ybegin..yend). It is templated on BUFT, the 1419 /// type known to be in the internal representation of the ImageBuf, 1420 /// and USERT, the type that the user wants to retrieve or set the 1421 /// data (defaulting to float). the whole idea is to allow this: 1422 /// \code 1423 /// ImageBuf img (...); 1424 /// ImageBuf::Iterator<float> pixel (img, 0, 512, 0, 512); 1425 /// for ( ; ! pixel.done(); ++pixel) { 1426 /// for (int c = 0; c < img.nchannels(); ++c) { 1427 /// float x = pixel[c]; 1428 /// pixel[c] = ...; 1429 /// } 1430 /// } 1431 /// \endcode 1432 /// 1433 template<typename BUFT, typename USERT = float> 1434 class Iterator : public IteratorBase { 1435 public: 1436 /// Construct from just an ImageBuf -- iterate over the whole 1437 /// region, starting with the upper left pixel of the region. 1438 Iterator(ImageBuf& ib, WrapMode wrap = WrapDefault) IteratorBase(ib,wrap)1439 : IteratorBase(ib, wrap) 1440 { 1441 make_writable(); 1442 pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); 1443 if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend 1444 || m_rng_zbegin == m_rng_zend) 1445 pos_done(); // make empty range look "done" 1446 } 1447 /// Construct from an ImageBuf and a specific pixel index. 1448 /// The iteration range is the full image. 1449 Iterator(ImageBuf& ib, int x, int y, int z = 0, 1450 WrapMode wrap = WrapDefault) IteratorBase(ib,wrap)1451 : IteratorBase(ib, wrap) 1452 { 1453 make_writable(); 1454 pos(x, y, z); 1455 } 1456 /// Construct read-write iteration region from ImageBuf and ROI. 1457 Iterator(ImageBuf& ib, const ROI& roi, WrapMode wrap = WrapDefault) IteratorBase(ib,roi,wrap)1458 : IteratorBase(ib, roi, wrap) 1459 { 1460 make_writable(); 1461 pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); 1462 if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend 1463 || m_rng_zbegin == m_rng_zend) 1464 pos_done(); // make empty range look "done" 1465 } 1466 /// Construct from an ImageBuf and designated region -- iterate 1467 /// over region, starting with the upper left pixel. 1468 Iterator(ImageBuf& ib, int xbegin, int xend, int ybegin, int yend, 1469 int zbegin = 0, int zend = 1, WrapMode wrap = WrapDefault) IteratorBase(ib,xbegin,xend,ybegin,yend,zbegin,zend,wrap)1470 : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap) 1471 { 1472 make_writable(); 1473 pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); 1474 if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend 1475 || m_rng_zbegin == m_rng_zend) 1476 pos_done(); // make empty range look "done" 1477 } 1478 /// Copy constructor. 1479 /// Iterator(Iterator & i)1480 Iterator(Iterator& i) 1481 : IteratorBase(i.m_ib, i.m_wrap) 1482 { 1483 make_writable(); 1484 pos(i.m_x, i.m_y, i.m_z); 1485 } 1486 ~Iterator()1487 ~Iterator() {} 1488 1489 /// Assign one Iterator to another 1490 /// 1491 const Iterator& operator=(const Iterator& i) 1492 { 1493 assign_base(i); 1494 pos(i.m_x, i.m_y, i.m_z); 1495 return *this; 1496 } 1497 1498 /// Dereferencing the iterator gives us a proxy for the pixel, 1499 /// which we can index for reading or assignment. 1500 DataArrayProxy<BUFT, USERT>& operator*() 1501 { 1502 return *(DataArrayProxy<BUFT, USERT>*)(void*)&m_proxydata; 1503 } 1504 1505 /// Array indexing retrieves the value of the i-th channel of 1506 /// the current pixel. 1507 USERT operator[](int i) const 1508 { 1509 DataArrayProxy<BUFT, USERT> proxy((BUFT*)m_proxydata); 1510 return proxy[i]; 1511 } 1512 1513 /// Array referencing retrieve a proxy (which may be "assigned 1514 /// to") of i-th channel of the current pixel, so that this 1515 /// works: me[i] = val; 1516 DataProxy<BUFT, USERT> operator[](int i) 1517 { 1518 DataArrayProxy<BUFT, USERT> proxy((BUFT*)m_proxydata); 1519 return proxy[i]; 1520 } 1521 rawptr()1522 void* rawptr() const { return m_proxydata; } 1523 1524 /// Set the number of deep data samples at this pixel. (Only use 1525 /// this if deep_alloc() has not yet been called on the buffer.) set_deep_samples(int n)1526 void set_deep_samples(int n) 1527 { 1528 return const_cast<ImageBuf*>(m_ib)->set_deep_samples(m_x, m_y, m_z, 1529 n); 1530 } 1531 1532 /// Retrieve the deep data value of sample s of channel c. deep_value(int c,int s)1533 USERT deep_value(int c, int s) const 1534 { 1535 return convert_type<float, USERT>( 1536 m_ib->deep_value(m_x, m_y, m_z, c, s)); 1537 } deep_value_uint(int c,int s)1538 uint32_t deep_value_uint(int c, int s) const 1539 { 1540 return m_ib->deep_value_uint(m_x, m_y, m_z, c, s); 1541 } 1542 1543 /// Set the deep data value of sample s of channel c. (Only use this 1544 /// if deep_alloc() has been called.) set_deep_value(int c,int s,float value)1545 void set_deep_value(int c, int s, float value) 1546 { 1547 return const_cast<ImageBuf*>(m_ib)->set_deep_value(m_x, m_y, m_z, c, 1548 s, value); 1549 } set_deep_value(int c,int s,uint32_t value)1550 void set_deep_value(int c, int s, uint32_t value) 1551 { 1552 return const_cast<ImageBuf*>(m_ib)->set_deep_value(m_x, m_y, m_z, c, 1553 s, value); 1554 } 1555 }; 1556 1557 1558 /// Just like an ImageBuf::Iterator, except that it refers to a 1559 /// const ImageBuf. 1560 template<typename BUFT, typename USERT = float> 1561 class ConstIterator : public IteratorBase { 1562 public: 1563 /// Construct from just an ImageBuf -- iterate over the whole 1564 /// region, starting with the upper left pixel of the region. 1565 ConstIterator(const ImageBuf& ib, WrapMode wrap = WrapDefault) IteratorBase(ib,wrap)1566 : IteratorBase(ib, wrap) 1567 { 1568 pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); 1569 if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend 1570 || m_rng_zbegin == m_rng_zend) 1571 pos_done(); // make empty range look "done" 1572 } 1573 /// Construct from an ImageBuf and a specific pixel index. 1574 /// The iteration range is the full image. 1575 ConstIterator(const ImageBuf& ib, int x_, int y_, int z_ = 0, 1576 WrapMode wrap = WrapDefault) IteratorBase(ib,wrap)1577 : IteratorBase(ib, wrap) 1578 { 1579 pos(x_, y_, z_); 1580 } 1581 /// Construct read-only iteration region from ImageBuf and ROI. 1582 ConstIterator(const ImageBuf& ib, const ROI& roi, 1583 WrapMode wrap = WrapDefault) IteratorBase(ib,roi,wrap)1584 : IteratorBase(ib, roi, wrap) 1585 { 1586 pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); 1587 if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend 1588 || m_rng_zbegin == m_rng_zend) 1589 pos_done(); // make empty range look "done" 1590 } 1591 /// Construct from an ImageBuf and designated region -- iterate 1592 /// over region, starting with the upper left pixel. 1593 ConstIterator(const ImageBuf& ib, int xbegin, int xend, int ybegin, 1594 int yend, int zbegin = 0, int zend = 1, 1595 WrapMode wrap = WrapDefault) IteratorBase(ib,xbegin,xend,ybegin,yend,zbegin,zend,wrap)1596 : IteratorBase(ib, xbegin, xend, ybegin, yend, zbegin, zend, wrap) 1597 { 1598 pos(m_rng_xbegin, m_rng_ybegin, m_rng_zbegin); 1599 if (m_rng_xbegin == m_rng_xend || m_rng_ybegin == m_rng_yend 1600 || m_rng_zbegin == m_rng_zend) 1601 pos_done(); // make empty range look "done" 1602 } 1603 /// Copy constructor. 1604 /// ConstIterator(const ConstIterator & i)1605 ConstIterator(const ConstIterator& i) 1606 : IteratorBase(i) 1607 { 1608 pos(i.m_x, i.m_y, i.m_z); 1609 } 1610 ~ConstIterator()1611 ~ConstIterator() {} 1612 1613 /// Assign one ConstIterator to another 1614 /// 1615 const ConstIterator& operator=(const ConstIterator& i) 1616 { 1617 assign_base(i); 1618 pos(i.m_x, i.m_y, i.m_z); 1619 return *this; 1620 } 1621 1622 /// Dereferencing the iterator gives us a proxy for the pixel, 1623 /// which we can index for reading or assignment. 1624 ConstDataArrayProxy<BUFT, USERT>& operator*() const 1625 { 1626 return *(ConstDataArrayProxy<BUFT, USERT>*)&m_proxydata; 1627 } 1628 1629 /// Array indexing retrieves the value of the i-th channel of 1630 /// the current pixel. 1631 USERT operator[](int i) const 1632 { 1633 ConstDataArrayProxy<BUFT, USERT> proxy((BUFT*)m_proxydata); 1634 return proxy[i]; 1635 } 1636 rawptr()1637 const void* rawptr() const { return m_proxydata; } 1638 1639 /// Retrieve the deep data value of sample s of channel c. deep_value(int c,int s)1640 USERT deep_value(int c, int s) const 1641 { 1642 return convert_type<float, USERT>( 1643 m_ib->deep_value(m_x, m_y, m_z, c, s)); 1644 } deep_value_uint(int c,int s)1645 uint32_t deep_value_uint(int c, int s) const 1646 { 1647 return m_ib->deep_value_uint(m_x, m_y, m_z, c, s); 1648 } 1649 }; 1650 1651 1652 protected: 1653 // PIMPL idiom 1654 static void impl_deleter(ImageBufImpl*); 1655 std::unique_ptr<ImageBufImpl, decltype(&impl_deleter)> m_impl; 1656 1657 // Reset the ImageCache::Tile * to reserve and point to the correct 1658 // tile for the given pixel, and return the ptr to the actual pixel 1659 // within the tile. 1660 const void* retile(int x, int y, int z, ImageCache::Tile*& tile, 1661 int& tilexbegin, int& tileybegin, int& tilezbegin, 1662 int& tilexend, bool exists, 1663 WrapMode wrap = WrapDefault) const; 1664 1665 const void* blackpixel() const; 1666 1667 // Given x,y,z known to be outside the pixel data range, and a wrap 1668 // mode, alter xyz to implement the wrap. Return true if the resulting 1669 // x,y,z is within the valid pixel data window, false if it still is 1670 // not. 1671 bool do_wrap(int& x, int& y, int& z, WrapMode wrap) const; 1672 }; 1673 1674 1675 OIIO_NAMESPACE_END 1676