@@ -721,7 +721,9 @@ class OIIO_API ImageBuf {
721721 // / @param x/y/z
722722 // / The pixel coordinates.
723723 // / @param c
724- // / The channel index to retrieve.
724+ // / The channel index to retrieve. If `c` is not in the
725+ // / valid channel range 0..nchannels-1, then `getchannel()`
726+ // / will return 0.
725727 // / @param wrap
726728 // / WrapMode that determines the behavior if the pixel
727729 // / coordinates are outside the data window: `WrapBlack`,
@@ -732,67 +734,114 @@ class OIIO_API ImageBuf {
732734 WrapMode wrap = WrapBlack) const ;
733735
734736 // / Retrieve the pixel value by x, y, z pixel indices, placing its
735- // / contents in `pixel[0..n-1]` where *n* is the smaller of
736- // / `maxchannels` the actual number of channels stored in the buffer.
737+ // / contents in `pixel[0..n-1]` where *n* is the smaller of the span's
738+ // / size and the actual number of channels stored in the buffer.
737739 // /
738740 // / @param x/y/z
739741 // / The pixel coordinates.
740742 // / @param pixel
741- // / The results are stored in `pixel[0..nchannels-1]`. It is
742- // / up to the caller to ensure that `pixel` points to enough
743- // / memory to hold the required number of channels.
744- // / @param maxchannels
745- // / Optional clamp to the number of channels retrieved.
743+ // / A span giving the location where results will be stored.
746744 // / @param wrap
747745 // / WrapMode that determines the behavior if the pixel
748746 // / coordinates are outside the data window: `WrapBlack`,
749747 // / `WrapClamp`, `WrapPeriodic`, `WrapMirror`.
750- void getpixel (int x, int y, int z, float * pixel, int maxchannels = 1000 ,
748+ void getpixel (int x, int y, int z, span< float > pixel,
751749 WrapMode wrap = WrapBlack) const ;
752750
753- // Simplified version: 2D, black wrap.
751+ // / Simplified version of getpixel(): 2D, black wrap.
752+ void getpixel (int x, int y, span<float > pixel) const
753+ {
754+ getpixel (x, y, 0 , pixel);
755+ }
756+
757+ // / Unsafe version of getpixel using raw pointer. Avoid if possible.
758+ OIIO_IB_DEPRECATE_RAW_PTR
759+ void getpixel (int x, int y, int z, float * pixel, int maxchannels = 1000 ,
760+ WrapMode wrap = WrapBlack) const
761+ {
762+ getpixel (x, y, z, make_span (pixel, size_t (maxchannels)), wrap);
763+ }
764+
765+ // / Unsafe version of getpixel using raw pointer. Avoid if possible.
766+ OIIO_IB_DEPRECATE_RAW_PTR
754767 void getpixel (int x, int y, float * pixel, int maxchannels = 1000 ) const
755768 {
756769 getpixel (x, y, 0 , pixel, maxchannels);
757770 }
758771
759772 // / Sample the image plane at pixel coordinates (x,y), using linear
760- // / interpolation between pixels, placing the result in `pixel[]`.
773+ // / interpolation between pixels, placing the result in `pixel[0..n-1]`
774+ // / where *n* is the smaller of the span's size and the actual number of
775+ // / channels stored in the buffer.
761776 // /
762777 // / @param x/y
763778 // / The pixel coordinates. Note that pixel data values
764779 // / themselves are at the pixel centers, so pixel (i,j) is
765780 // / at image plane coordinate (i+0.5, j+0.5).
766781 // / @param pixel
767- // / The results are stored in `pixel[0..nchannels-1]`. It is
768- // / up to the caller to ensure that `pixel` points to enough
769- // / memory to hold the number of channels in the image.
782+ // / A span giving the location where results will be stored.
770783 // / @param wrap
771784 // / WrapMode that determines the behavior if the pixel
772785 // / coordinates are outside the data window: `WrapBlack`,
773786 // / `WrapClamp`, `WrapPeriodic`, `WrapMirror`.
774- void interppixel (float x, float y, float * pixel,
787+ void interppixel (float x, float y, span< float > pixel,
775788 WrapMode wrap = WrapBlack) const ;
776789
790+ // / Unsafe version of interppixel using raw pointer. Avoid if possible.
791+ OIIO_IB_DEPRECATE_RAW_PTR
792+ void interppixel (float x, float y, float * pixel,
793+ WrapMode wrap = WrapBlack) const
794+ {
795+ interppixel (x, y, make_span (pixel, size_t (nchannels ())), wrap);
796+ }
797+
777798 // / Linearly interpolate at NDC coordinates (s,t), where (0,0) is
778799 // / the upper left corner of the display window, (1,1) the lower
779800 // / right corner of the display window.
780801 // /
781802 // / @note `interppixel()` uses pixel coordinates (ranging 0..resolution)
782803 // / whereas `interppixel_NDC()` uses NDC coordinates (ranging 0..1).
783- void interppixel_NDC (float s, float t, float * pixel,
804+ void interppixel_NDC (float s, float t, span< float > pixel,
784805 WrapMode wrap = WrapBlack) const ;
785806
807+ // / Unsafe version of interppixel_NDC using raw pointer. Avoid if
808+ // / possible.
809+ OIIO_IB_DEPRECATE_RAW_PTR
810+ void interppixel_NDC (float s, float t, float * pixel,
811+ WrapMode wrap = WrapBlack) const
812+ {
813+ interppixel_NDC (s, t, make_span (pixel, size_t (nchannels ())), wrap);
814+ }
815+
786816 // / Bicubic interpolation at pixel coordinates (x,y).
787- void interppixel_bicubic (float x, float y, float * pixel,
817+ void interppixel_bicubic (float x, float y, span< float > pixel,
788818 WrapMode wrap = WrapBlack) const ;
789819
820+ // / Unsafe version of interppixel_bicubic_NDC using raw pointer.
821+ // / Avoid if possible.
822+ OIIO_IB_DEPRECATE_RAW_PTR
823+ void interppixel_bicubic (float x, float y, float * pixel,
824+ WrapMode wrap = WrapBlack) const
825+ {
826+ interppixel_bicubic (x, y, make_span (pixel, size_t (nchannels ())), wrap);
827+ }
828+
790829 // / Bicubic interpolation at NDC space coordinates (s,t), where (0,0)
791830 // / is the upper left corner of the display (a.k.a. "full") window,
792831 // / (1,1) the lower right corner of the display window.
793- void interppixel_bicubic_NDC (float s, float t, float * pixel,
832+ void interppixel_bicubic_NDC (float s, float t, span< float > pixel,
794833 WrapMode wrap = WrapBlack) const ;
795834
835+ // / Unsafe version of interppixel_bicubic_NDC using raw pointer.
836+ // / Avoid if possible.
837+ OIIO_IB_DEPRECATE_RAW_PTR
838+ void interppixel_bicubic_NDC (float s, float t, float * pixel,
839+ WrapMode wrap = WrapBlack) const
840+ {
841+ interppixel_bicubic_NDC (s, t, make_span (pixel, size_t (nchannels ())),
842+ wrap);
843+ }
844+
796845
797846 // / Set the pixel with coordinates (x,y,0) to have the values in span
798847 // / `pixel[]`. The number of channels copied is the minimum of the span
@@ -805,48 +854,111 @@ class OIIO_API ImageBuf {
805854 // / Set the pixel with coordinates (x,y,z) to have the values in span
806855 // / `pixel[]`. The number of channels copied is the minimum of the span
807856 // / length and the actual number of channels in the image.
808- void setpixel (int x, int y, int z, cspan<float > pixel)
809- {
810- setpixel (x, y, z, pixel.data (), int (pixel.size ()));
811- }
857+ void setpixel (int x, int y, int z, cspan<float > pixel);
812858
813859 // / Set the `i`-th pixel value of the image (out of width*height*depth),
814860 // / from floating-point values in span `pixel[]`. The number of
815861 // / channels copied is the minimum of the span length and the actual
816862 // / number of channels in the image.
817863 void setpixel (int i, cspan<float > pixel)
818864 {
819- setpixel (i, pixel.data (), int (pixel.size ()));
865+ setpixel (spec ().x + (i % spec ().width ), spec ().y + (i / spec ().width ),
866+ pixel);
820867 }
821868
822869 // / Set the pixel with coordinates (x,y,0) to have the values in
823870 // / pixel[0..n-1]. The number of channels copied, n, is the minimum
824871 // / of maxchannels and the actual number of channels in the image.
872+ OIIO_IB_DEPRECATE_RAW_PTR
825873 void setpixel (int x, int y, const float * pixel, int maxchannels = 1000 )
826874 {
827- setpixel (x, y, 0 , pixel, maxchannels);
875+ int n = std::min (spec ().nchannels , maxchannels);
876+ setpixel (x, y, 0 , make_cspan (pixel, size_t (n)));
828877 }
829878
830879 // / Set the pixel with coordinates (x,y,z) to have the values in
831880 // / `pixel[0..n-1]`. The number of channels copied, n, is the minimum
832881 // / of `maxchannels` and the actual number of channels in the image.
882+ OIIO_IB_DEPRECATE_RAW_PTR
833883 void setpixel (int x, int y, int z, const float * pixel,
834- int maxchannels = 1000 );
884+ int maxchannels = 1000 )
885+ {
886+ int n = std::min (spec ().nchannels , maxchannels);
887+ setpixel (x, y, z, make_cspan (pixel, size_t (n)));
888+ }
835889
836890 // / Set the `i`-th pixel value of the image (out of width*height*depth),
837891 // / from floating-point values in `pixel[]`. Set at most
838892 // / `maxchannels` (will be clamped to the actual number of channels).
839- void setpixel (int i, const float * pixel, int maxchannels = 1000 );
893+ OIIO_IB_DEPRECATE_RAW_PTR
894+ void setpixel (int i, const float * pixel, int maxchannels = 1000 )
895+ {
896+ int n = std::min (spec ().nchannels , maxchannels);
897+ setpixel (i, make_cspan (pixel, size_t (n)));
898+ }
840899
841900 // / Retrieve the rectangle of pixels spanning the ROI (including
842901 // / channels) at the current subimage and MIP-map level, storing the
843- // / pixel values beginning at the address specified by result and with
844- // / the given strides (by default, AutoStride means the usual contiguous
845- // / packing of pixels) and converting into the data type described by
846- // / `format`. It is up to the caller to ensure that result points to an
847- // / area of memory big enough to accommodate the requested rectangle.
848- // / Return true if the operation could be completed, otherwise return
849- // / false.
902+ // / pixel values into the `buffer`.
903+ // /
904+ // / @param roi
905+ // / The region of interest to copy.
906+ // / @param spec
907+ // / An ImageSpec describing the image and its metadata. If
908+ // / not enough information is given to know the "shape" of
909+ // / the image (width, height, depth, channels, and data
910+ // / format), the ImageBuf will remain in an UNINITIALIZED
911+ // / state.
912+ // / @param buffer
913+ // / A span delineating the extent of the safely accessible
914+ // / memory where the results should be stored.
915+ // / @param buforigin
916+ // / In the version of the template that takes this parameter,
917+ // / it is a pointer to the first pixel of the buffer. If null,
918+ // / it will be assumed to be the beginning of the buffer.
919+ // / THis is useful if any negative strides are used to
920+ // / give an unusual layout of pixels within the buffer.
921+ // / @param xstride/ystride/zstride
922+ // / The distance in bytes between successive pixels,
923+ // / scanlines, and image planes in the buffer (or
924+ // / `AutoStride` to indicate "contiguous" data in any of
925+ // / those dimensions).
926+ // / @returns
927+ // / Return true if the operation could be completed,
928+ // / otherwise return false.
929+ // /
930+ template <typename T, OIIO_ENABLE_IF(!std::is_const_v<T>
931+ && !std::is_same_v<T, std::byte>)>
932+ bool get_pixels (ROI roi, span<T> buffer, stride_t xstride = AutoStride,
933+ stride_t ystride = AutoStride,
934+ stride_t zstride = AutoStride) const
935+ {
936+ return get_pixels (roi, TypeDescFromC<T>::value (),
937+ as_writable_bytes (buffer), buffer.data (), xstride,
938+ ystride, zstride);
939+ }
940+
941+ template <typename T, OIIO_ENABLE_IF(!std::is_const_v<T>
942+ && !std::is_same_v<T, std::byte>)>
943+ bool get_pixels (ROI roi, span<T> buffer, T* buforigin,
944+ stride_t xstride = AutoStride,
945+ stride_t ystride = AutoStride,
946+ stride_t zstride = AutoStride) const
947+ {
948+ return get_pixels (roi, TypeDescFromC<T>::value (),
949+ as_writable_bytes (buffer), buforigin, xstride,
950+ ystride, zstride);
951+ }
952+
953+ // / Base case of get_pixels: read into a span of generic bytes. The
954+ // / requested data type is supplied by `format.
955+ bool get_pixels (ROI roi, TypeDesc format, span<std::byte> buffer,
956+ void * buforigin = nullptr , stride_t xstride = AutoStride,
957+ stride_t ystride = AutoStride,
958+ stride_t zstride = AutoStride) const ;
959+
960+ // / Potentially unsafe get_pixels() using raw pointers. Use with catution!
961+ OIIO_IB_DEPRECATE_RAW_PTR
850962 bool get_pixels (ROI roi, TypeDesc format, void * result,
851963 stride_t xstride = AutoStride,
852964 stride_t ystride = AutoStride,
@@ -860,6 +972,37 @@ class OIIO_API ImageBuf {
860972 // / the data buffer is assumed to have the same resolution as the ImageBuf
861973 // / itself. Return true if the operation could be completed, otherwise
862974 // / return false.
975+ template <typename T, OIIO_ENABLE_IF(!std::is_same_v<T, std::byte>)>
976+ bool set_pixels (ROI roi, span<T> buffer, stride_t xstride = AutoStride,
977+ stride_t ystride = AutoStride,
978+ stride_t zstride = AutoStride)
979+ {
980+ return set_pixels (roi, TypeDescFromC<std::remove_const_t <T>>::value (),
981+ as_bytes (buffer), buffer.data (), xstride, ystride,
982+ zstride);
983+ }
984+
985+ template <typename T, OIIO_ENABLE_IF(!std::is_same_v<T, std::byte>)>
986+ bool set_pixels (ROI roi, span<T> buffer, const T* buforigin,
987+ stride_t xstride = AutoStride,
988+ stride_t ystride = AutoStride,
989+ stride_t zstride = AutoStride)
990+ {
991+ return set_pixels (roi, TypeDescFromC<std::remove_const_t <T>>::value (),
992+ as_bytes (buffer), buforigin, xstride, ystride,
993+ zstride);
994+ }
995+
996+ // / Base case of get_pixels: read into a span of generic bytes. The
997+ // / requested data type is supplied by `format.
998+ bool set_pixels (ROI roi, TypeDesc format, cspan<std::byte> buffer,
999+ const void * buforigin = nullptr ,
1000+ stride_t xstride = AutoStride,
1001+ stride_t ystride = AutoStride,
1002+ stride_t zstride = AutoStride);
1003+
1004+ // / Potentially unsafe set_pixels() using raw pointers. Use with catution!
1005+ OIIO_IB_DEPRECATE_RAW_PTR
8631006 bool set_pixels (ROI roi, TypeDesc format, const void * data,
8641007 stride_t xstride = AutoStride,
8651008 stride_t ystride = AutoStride,
@@ -1125,8 +1268,8 @@ class OIIO_API ImageBuf {
11251268 // / Error reporting for ImageBuf: call this with std::format style
11261269 // / formatting specification. It is not necessary to have the error
11271270 // / message contain a trailing newline.
1128- template <typename ... Args>
1129- void errorfmt (const char * fmt, const Args&... args) const
1271+ template <typename Str, typename ... Args>
1272+ void errorfmt (const Str& fmt, Args& &... args) const
11301273 {
11311274 error (Strutil::fmt::format (fmt, args...));
11321275 }
0 commit comments