diff --git a/src/doc/imagebufalgo.rst b/src/doc/imagebufalgo.rst index ea2dd3f61f..8f6c3068fc 100644 --- a/src/doc/imagebufalgo.rst +++ b/src/doc/imagebufalgo.rst @@ -37,24 +37,22 @@ Most ImageBufAlgo functions that produce image data come in two forms: case, an entirely new image will be created to hold the result. In case of error, the result image returned can have any error conditions checked with `has_error()` and `geterror()`. - + .. tabs:: - - .. code-tab:: c++ - - // Method 1: Return an image result - ImageBuf dst = ImageBufAlgo::over (fg, bg); - if (dst.has_error()) - std::cout << "error: " << dst.geterror() << "\n"; - .. code-tab:: py - - # Method 1: Return an image result - fg = ImageBuf("fg.exr") - bg = ImageBuf("bg.exr") - dst = ImageBufAlgo.over (fg, bg) - if dst.has_error() : - print("error:", dst.geterror()) + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-output-error1 + :end-before: END-imagebufalgo-output-error1 + :dedent: 4 + + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-output-error1 + :end-before: END-imagebufalgo-output-error1 + :dedent: 4 2. Pass a destination ImageBuf reference as the first parameter. @@ -64,27 +62,22 @@ Most ImageBufAlgo functions that produce image data come in two forms: function succeeds or `false` if the function fails. Upon failure, the destination ImageBuf (the one that is being altered) will have an error message set. - + .. tabs:: - - .. code-tab:: c++ - - // Method 2: Write into an existing image - ImageBuf fg ("fg.exr"), bg ("bg.exr"); - ImageBuf dst; // will be the output image - bool ok = ImageBufAlgo::over (dst, fg, bg); - if (! ok) - std::cout << "error: " << dst.geterror() << "\n"; - - .. code-tab:: py - - # Method 2: Write into an existing image - fg = ImageBuf("fg.exr") - bg = ImageBuf("bg.exr") - dst = ImageBuf() # will be the output image - ok = ImageBufAlgo.over (dst, fg, bg) - if not ok : - print("error:", dst.geterror()) + + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-output-error2 + :end-before: END-imagebufalgo-output-error2 + :dedent: 4 + + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-output-error2 + :end-before: END-imagebufalgo-output-error2 + :dedent: 4 The first option (return an ImageBuf directly) is a more compact and @@ -188,58 +181,34 @@ zero() -- create a black image Examples: .. tabs:: - - .. code-tab:: c++ - - // Create a new 3-channel, 512x512 float image filled with 0.0 values. - ImageBuf zero = ImageBufAlgo::zero (ROI(0,512,0,512,0,1,0,3)); - - // Zero out an existing buffer, keeping it the same size and data type - ImageBuf A = ...; - ... - ImageBufAlgo::zero (A); - - // Zero out just the green channel, leave everything else the same - ROI roi = A.roi (); - roi.chbegin = 1; // green - roi.chend = 2; // one past the end of the channel region - ImageBufAlgo::zero (A, roi); - - // Zero out a rectangular region of an existing buffer - ImageBufAlgo::zero (A, ROI (0, 100, 0, 100)); - - .. code-tab:: py - - # Create a new 3-channel, 512x512 float image filled with 0.0 values. - zero = ImageBufAlgo.zero (ROI(0,512,0,512,0,1,0,3)) - - # Zero out an existing buffer, keeping it the same size and data type - A = ImageBuf(...) - ... - ImageBufAlgo.zero (A) - - # Zero out just the green channel, leave everything else the same - roi = A.roi - roi.chbegin = 1 # green - roi.chend = 2 # one past the end of the channel region - ImageBufAlgo.zero (A, roi) - - # Zero out a rectangular region of an existing buffer - ImageBufAlgo.zero (A, ROI (0, 100, 0, 100)) - + + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-zero + :end-before: END-imagebufalgo-zero + :dedent: 4 + + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-zero + :end-before: END-imagebufalgo-zero + :dedent: 4 + .. code-tab:: bash oiiotool - + # Create a new 3-channel, 512x512 float image filled with 0.0 values. oiiotool --create 512x512 3 -d float -o out.exr - + # Zero out an existing image, keeping it the same size and data type. # For simplicity, just scale all values by 0.0 oiiotool in.exr --mulc 0.0 -o out.exr - + # Zero out just the green channel, leave everything else the same. # Again, rely on --mulc to scale the channels oiiotool in.exr --mulc 1,0,1 -o out.exr - + # Zero out a rectangular region of an existing image oiiotool in.exr --fill:color=0,0,0 100x100+0+0 -o out.exr @@ -254,29 +223,20 @@ fill() -- fill a region with a solid color or gradient Examples: .. tabs:: - - .. code-tab:: c++ - - // Create a new 640x480 RGB image, with a top-to-bottom gradient - // from red to pink - float pink[3] = { 1, 0.7, 0.7 }; - float red[3] = { 1, 0, 0 }; - ImageBuf A = ImageBufAlgo::fill (red, pink, ROI(0, 640, 0, 480, 0, 1, 0, 3)); - - // Draw a filled red rectangle overtop existing image A. - ImageBufAlgo::fill (A, red, ROI(50, 100, 75, 175)); - .. code-tab:: py - - # Create a new 640x480 RGB image, with a top-to-bottom gradient - # from red to pink - pink = (1, 0.7, 0.7) - red = (1, 0, 0) - A = ImageBufAlgo.fill (top=red, bottom=pink, - ROI(0, 640, 0, 480, 0, 1, 0, 3)) + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-fill + :end-before: END-imagebufalgo-fill + :dedent: 4 - # Draw a filled red rectangle overtop existing image A. - ImageBufAlgo.fill (A, red, ROI(50, 100, 75, 175)) + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-fill + :end-before: END-imagebufalgo-fill + :dedent: 4 .. code-tab:: bash oiiotool @@ -307,24 +267,19 @@ checker() -- make a checker pattern .. tabs:: - .. code-tab:: c++ - - // Create a new 640x480 RGB image, fill it with a two-toned gray - // checkerboard, the checkers being 64x64 pixels each. - ImageBuf A (ImageSpec(640, 480, 3, TypeDesc::FLOAT); - float dark[3] = { 0.1, 0.1, 0.1 }; - float light[3] = { 0.4, 0.4, 0.4 }; - ImageBufAlgo::checker (A, 64, 64, 1, dark, light, 0, 0, 0); + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-checker + :end-before: END-imagebufalgo-checker + :dedent: 4 - .. code-tab:: py - - # Create a new 640x480 RGB image, fill it with a two-toned gray - # checkerboard, the checkers being 64x64 pixels each. - A = ImageBuf (ImageSpec(640, 480, 3, "float") - dark = (0.1, 0.1, 0.1) - light = (0.4, 0.4, 0.4) - A = ImageBufAlgo.checker (64, 64, 1, dark, light, - roi=ROI(0, 640, 0, 480, 0, 1, 0, 3)) + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-checker + :end-before: END-imagebufalgo-checker + :dedent: 4 .. code-tab:: bash oiiotool @@ -352,43 +307,20 @@ Noise patterns Examples: .. tabs:: - - .. code-tab:: c++ - - // Create a new 256x256 field of grayscale white noise on [0,1) - ImageBuf A = ImageBufAlgo::noise ("uniform", 0.0f /*min*/, 1.0f /*max*/, - true /*mono*/, 1 /*seed*/, ROI(0,256,0,256,0,1,0,3)); - - // Create a new 256x256 field of grayscale white noise on [0,1) - ImageBuf B = ImageBufAlgo::noise ("blue", 0.0f /*min*/, 1.0f /*max*/, - true /*mono*/, 1 /*seed*/, ROI(0,256,0,256,0,1,0,3)); - - // Add color Gaussian noise to an existing image - ImageBuf C ("tahoe.jpg"); - ImageBufAlgo::noise (C, "gaussian", 0.0f /*mean*/, 0.1f /*stddev*/, - false /*mono*/, 1 /*seed*/); - - // Use salt and pepper noise to make occasional random dropouts - ImageBuf D ("tahoe.jpg"); - ImageBufAlgo::noise (D, "salt", 0.0f /*value*/, 0.01f /*portion*/, - true /*mono*/, 1 /*seed*/); - .. code-tab:: py - - # Create a new 256x256 field of grayscale white noise on [0,1) - A = ImageBufAlgo.noise ("uniform", min=0.0, max=1.0, mono=True, seed=1, - roi = ROI(0,256,0,256,0,1,0,3)) - - # Create a new 256x256 field of grayscale blue noise on [0,1) - B = ImageBufAlgo.noise ("blue", min=0.0, max=1.0, mono=True, seed=1, - roi = ROI(0,256,0,256,0,1,0,3)) - - # Add color Gaussian noise to an existing image - C = ImageBuf ("tahoe.jpg") - ImageBufAlgo.noise (C, "gaussian", A=0.0, B=0.1, mono=False, seed=1) - - # Use salt and pepper noise to make occasional random dropouts - D = ImageBuf ("tahoe.jpg") - ImageBufAlg.noise (D, "salt", A=0.0, B=0.01, mono=True, seed=1) + + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-noise1 + :end-before: END-imagebufalgo-noise1 + :dedent: 4 + + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-noise1 + :end-before: END-imagebufalgo-noise1 + :dedent: 4 .. code-tab:: bash oiiotool @@ -432,15 +364,20 @@ Noise patterns Example: .. tabs:: - - .. code-tab:: c++ - - const ImageBuf& A = ImageBufAlgo::bluenoise_image(); - .. code-tab:: py - - A = ImageBufAlgo.bluenoise_image() + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-noise2 + :end-before: END-imagebufalgo-noise2 + :dedent: 4 + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-noise2 + :end-before: END-imagebufalgo-noise2 + :dedent: 4 Drawing shapes: points, lines, boxes @@ -452,18 +389,20 @@ Drawing shapes: points, lines, boxes Examples: .. tabs:: - - .. code-tab:: c++ - - ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); - float red[4] = { 1, 0, 0, 1 }; - ImageBufAlgo::render_point (A, 50, 100, red); - .. code-tab:: py - - A = ImageBuf(ImageSpec(640, 480, 4, "float")) - red = (1, 0, 0, 1) - ImageBufAlgo.render_point (A, 50, 100, red) + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-point + :end-before: END-imagebufalgo-point + :dedent: 4 + + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-point + :end-before: END-imagebufalgo-point + :dedent: 4 .. code-tab:: bash oiiotool @@ -478,20 +417,20 @@ Drawing shapes: points, lines, boxes Examples: .. tabs:: - - .. code-tab:: c++ - - ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); - float red[4] = { 1, 0, 0, 1 }; - ImageBufAlgo::render_line (A, 10, 60, 250, 20, red); - ImageBufAlgo::render_line (A, 250, 20, 100, 190, red, true); - .. code-tab:: py - - A = ImageBuf(ImageSpec(640, 480, 4, "float")) - red = (1, 0, 0, 1) - ImageBufAlgo.render_line (A, 10, 60, 250, 20, red); - ImageBufAlgo.render_line (A, 250, 20, 100, 190, red, True) + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-lines + :end-before: END-imagebufalgo-lines + :dedent: 4 + + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-lines + :end-before: END-imagebufalgo-lines + :dedent: 4 .. code-tab:: bash oiiotool @@ -510,21 +449,19 @@ Drawing shapes: points, lines, boxes .. tabs:: - .. code-tab:: c++ - - ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); - float cyan[4] = { 0, 1, 1, 1 }; - float yellow_transparent[4] = { 0.5, 0.5, 0, 0.5 }; - ImageBufAlgo::render_box (A, 150, 100, 240, 180, cyan); - ImageBufAlgo::render_box (A, 100, 50, 180, 140, yellow_transparent, true); - - .. code-tab:: py + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-box + :end-before: END-imagebufalgo-box + :dedent: 4 - A = ImageBuf(ImageSpec(640, 480, 4, "float")) - cyan = (0, 1, 1, 1) - yellow_transparent = (0.5, 0.5, 0, 0.5) - ImageBufAlgo.render_box (A, 150, 100, 240, 180, cyan) - ImageBufAlgo.render_box (A, 100, 50, 180, 140, yellow_transparent, fill=True) + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-box + :end-before: END-imagebufalgo-box + :dedent: 4 .. code-tab:: bash oiiotool @@ -548,29 +485,19 @@ Drawing text .. tabs:: - .. code-tab:: c++ - - ImageBufAlgo::render_text (ImgA, 50, 100, "Hello, world"); - float red[] = { 1, 0, 0, 1 }; - ImageBufAlgo::render_text (ImgA, 100, 200, "Go Big Red!", - 60, "Arial Bold", red); - - float white[] = { 1, 1, 1, 1 }; - ImageBufAlgo::render_text (ImgB, 320, 240, "Centered", - 60, "Arial Bold", white, - TextAlignX::Center, TextAlignY::Center); - - .. code-tab:: py - - ImageBufAlgo.render_text (ImgA, 50, 100, "Hello, world") - red = (1, 0, 0, 1) - ImageBufAlgo.render_text (ImgA, 100, 200, "Go Big Red!", - 60, "Arial Bold", red) + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-text1 + :end-before: END-imagebufalgo-text1 + :dedent: 4 - white = (1, 1, 1, 1) - ImageBufAlgo.render_text (ImgB, 320, 240, "Centered", - fontsize=60, fontname="Arial Bold", - color=white, alignx="center", aligny="center") + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-text1 + :end-before: END-imagebufalgo-text1 + :dedent: 4 .. code-tab:: bash oiiotool @@ -602,30 +529,19 @@ Drawing text .. tabs:: - .. code-tab:: c++ - - // Render text centered in the image, using text_size to find out - // the size we will need and adjusting the coordinates. - ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); - ROI Aroi = A.roi(); - ROI size = ImageBufAlgo::text_size ("Centered", 48, "Courier New"); - if (size.defined()) { - int x = Aroi.xbegin + Aroi.width()/2 - (size.xbegin + size.width()/2); - int y = Aroi.ybegin + Aroi.height()/2 - (size.ybegin + size.height()/2); - ImageBufAlgo::render_text (A, x, y, "Centered", 48, "Courier New"); - } - - .. code-tab:: py + .. tab:: C++ + .. literalinclude:: ../../testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp + :language: c++ + :start-after: BEGIN-imagebufalgo-text2 + :end-before: END-imagebufalgo-text2 + :dedent: 4 - # Render text centered in the image, using text_size to find out - # the size we will need and adjusting the coordinates. - A = ImageBuf (ImageSpec (640, 480, 4, "float")) - Aroi = A.roi - size = ImageBufAlgo.text_size ("Centered", 48, "Courier New") - if size.defined() : - x = Aroi.xbegin + Aroi.width//2 - (size.xbegin + size.width//2) - y = Aroi.ybegin + Aroi.height//2 - (size.ybegin + size.height//2) - ImageBufAlgo.render_text (A, x, y, "Centered", 48, "Courier New") + .. tab:: Python + .. literalinclude:: ../../testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py + :language: py + :start-after: BEGIN-imagebufalgo-text2 + :end-before: END-imagebufalgo-text2 + :dedent: 4 diff --git a/testsuite/docs-examples-cpp/ref/out.txt b/testsuite/docs-examples-cpp/ref/out.txt index c82bb6b53c..c2e31b2ba9 100644 --- a/testsuite/docs-examples-cpp/ref/out.txt +++ b/testsuite/docs-examples-cpp/ref/out.txt @@ -1,3 +1,37 @@ +error: Uninitialized input image +error: Uninitialized input image +zero1.exr : 512 x 512, 3 channel, float openexr + SHA-1: 1E5F8DEF40BB0CB0F7156B9C2BAB9EFB49CFB699 +zero2.exr : 256 x 256, 4 channel, half openexr + SHA-1: 6A521E1D2A632C26E53B83D2CC4B0EDECFC1E68C +zero3.exr : 256 x 256, 4 channel, half openexr + SHA-1: 1254F2956229777B721576B94A6A944ECB806A37 +zero4.exr : 256 x 256, 4 channel, half openexr + SHA-1: 36EB49C5102703693C078717CE82AE05D4904680 +fill.exr : 640 x 480, 3 channel, float openexr + SHA-1: D517EA07CB6DB931AE4BF6D9E9957EEF9228734E +checker.exr : 640 x 480, 3 channel, float openexr + SHA-1: 87A4424581AAFCE31E6D1134E5025B620B48BBB3 +noise1.exr : 256 x 256, 3 channel, float openexr + SHA-1: 9E9278C8F5460068363D36DBD395FA59CA5986DC +noise2.exr : 256 x 256, 3 channel, float openexr + SHA-1: 0A75E8EF38846D8DC5D8BA997EB54F7A36058288 +noise3.exr : 512 x 384, 3 channel, half openexr + SHA-1: 95EDBCA9953281CE63A3E18C7C04BCCB07CB4C8A +noise4.exr : 512 x 384, 3 channel, half openexr + SHA-1: 43BC1FDFA1F18635B635A57D71DB08BB347CBD46 +blue-noise.exr : 256 x 256, 4 channel, float openexr + SHA-1: 36F448FE29C9DE6CFA65FC0BFCF4178DC66581C4 +point.exr : 640 x 480, 4 channel, float openexr + SHA-1: A2AC7CC98AB44798EEEA76C253DE44F6E49FFB8D +lines.exr : 640 x 480, 4 channel, float openexr + SHA-1: 69C0317F92256FD30415D1FE12419DC1C514D818 +box.exr : 640 x 480, 4 channel, float openexr + SHA-1: 6CBE5E98B145C5975CB930A91BAEE981C30E6B32 +text1.exr : 640 x 480, 3 channel, float openexr + SHA-1: 014ECFC5EBF07F77DF24A592F43BC7CB101534AE +text2.exr : 640 x 480, 3 channel, float openexr + SHA-1: 53359E96A286F909A89ACC99A67A9ED3BADC4A7A cshift.exr : 256 x 256, 4 channel, half openexr SHA-1: 000F95FDC44D4DBDA8B4041C2506149C7AE28ACA Comparing "simple.tif" and "ref/simple.tif" diff --git a/testsuite/docs-examples-cpp/run.py b/testsuite/docs-examples-cpp/run.py index 65c5caeb3a..b3b02cf760 100755 --- a/testsuite/docs-examples-cpp/run.py +++ b/testsuite/docs-examples-cpp/run.py @@ -11,7 +11,8 @@ prefix = "./build/" # Prep: -command += run_app("cmake -E copy ../common/grid-small.exr grid.exr") +command += run_app("cmake -E copy " + test_source_dir + "/../common/grid-small.exr grid.exr") +command += run_app("cmake -E copy " + test_source_dir + "/../common/tahoe-small.tif tahoe.tif") # Build command += run_app("cmake -S " + test_source_dir + " -B build -DCMAKE_BUILD_TYPE=Release >> build.txt 2>&1", silent=True) @@ -26,6 +27,22 @@ # of checking in a full copy of the image if it's not needed. hashes = [ # Outputs from the ImageBufAlgo chapter: + "zero1.exr", + "zero2.exr", + "zero3.exr", + "zero4.exr", + "fill.exr", + "checker.exr", + "noise1.exr", + "noise2.exr", + "noise3.exr", + "noise4.exr", + "blue-noise.exr", + "point.exr", + "lines.exr", + "box.exr", + "text1.exr", + "text2.exr", "cshift.exr", ] for file in hashes : diff --git a/testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp b/testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp index 57a7734a5b..da3c11e391 100644 --- a/testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp +++ b/testsuite/docs-examples-cpp/src/docs-examples-imagebufalgo.cpp @@ -35,19 +35,213 @@ void example1() // Section: ImageBufAlgo common principles +void example_output_error1() +{ + ImageBuf fg, bg; + + // BEGIN-imagebufalgo-output-error1 + // Method 1: Return an image result + ImageBuf dst = ImageBufAlgo::over (fg, bg); + if (dst.has_error()) + std::cout << "error: " << dst.geterror() << "\n"; + // END-imagebufalgo-output-error1 +} + +void example_output_error2() +{ + ImageBuf fg, bg; + + // BEGIN-imagebufalgo-output-error2 + // Method 2: Write into an existing image + ImageBuf dst; // will be the output image + bool ok = ImageBufAlgo::over (dst, fg, bg); + if (! ok) + std::cout << "error: " << dst.geterror() << "\n"; + // END-imagebufalgo-output-error2 +} + // Section: Pattern Generation +void example_zero() +{ + ImageBuf A("grid.exr"); + ImageBuf B("grid.exr"); + ImageBuf C("grid.exr"); + + // BEGIN-imagebufalgo-zero + // Create a new 3-channel, 512x512 float image filled with 0.0 values. + ImageBuf zero = ImageBufAlgo::zero (ROI(0,512,0,512,0,1,0,3)); + + // Zero out an existing buffer, keeping it the same size and data type + ImageBufAlgo::zero (A); + + // Zero out just the green channel, leave everything else the same + ROI roi = B.roi (); + roi.chbegin = 1; // green + roi.chend = 2; // one past the end of the channel region + ImageBufAlgo::zero (B, roi); + + // Zero out a rectangular region of an existing buffer + ImageBufAlgo::zero (C, ROI (0, 100, 0, 100)); + // END-imagebufalgo-zero + + zero.write("zero1.exr"); + A.write("zero2.exr"); + B.write("zero3.exr"); + C.write("zero4.exr"); +} + +void example_fill() +{ + // BEGIN-imagebufalgo-fill + // Create a new 640x480 RGB image, with a top-to-bottom gradient + // from red to pink + float pink[3] = { 1, 0.7, 0.7 }; + float red[3] = { 1, 0, 0 }; + ImageBuf A = ImageBufAlgo::fill (red, pink, ROI(0, 640, 0, 480, 0, 1, 0, 3)); + + // Draw a filled red rectangle overtop existing image A. + ImageBufAlgo::fill (A, red, ROI(50, 100, 75, 175)); + // END-imagebufalgo-fill + + A.write("fill.exr"); +} + +void example_checker() +{ + // BEGIN-imagebufalgo-checker + // Create a new 640x480 RGB image, fill it with a two-toned gray + // checkerboard, the checkers being 64x64 pixels each. + ImageBuf A (ImageSpec(640, 480, 3, TypeDesc::FLOAT)); + float dark[3] = { 0.1, 0.1, 0.1 }; + float light[3] = { 0.4, 0.4, 0.4 }; + ImageBufAlgo::checker (A, 64, 64, 1, dark, light, 0, 0, 0); + // END-imagebufalgo-checker + + A.write("checker.exr"); +} + +void example_noise1() +{ + // BEGIN-imagebufalgo-noise1 + // Create a new 256x256 field of grayscale white noise on [0,1) + ImageBuf A = ImageBufAlgo::noise ("uniform", 0.0f /*min*/, 1.0f /*max*/, + true /*mono*/, 1 /*seed*/, ROI(0,256,0,256,0,1,0,3)); + + // Create a new 256x256 field of grayscale white noise on [0,1) + ImageBuf B = ImageBufAlgo::noise ("blue", 0.0f /*min*/, 1.0f /*max*/, + true /*mono*/, 1 /*seed*/, ROI(0,256,0,256,0,1,0,3)); + + // Add color Gaussian noise to an existing image + ImageBuf C ("tahoe.tif"); + ImageBufAlgo::noise (C, "gaussian", 0.0f /*mean*/, 0.1f /*stddev*/, + false /*mono*/, 1 /*seed*/); + + // Use salt and pepper noise to make occasional random dropouts + ImageBuf D ("tahoe.tif"); + ImageBufAlgo::noise (D, "salt", 0.0f /*value*/, 0.01f /*portion*/, + true /*mono*/, 1 /*seed*/); + // END-imagebufalgo-noise1 + + A.write("noise1.exr"); + B.write("noise2.exr"); + C.write("noise3.exr"); + D.write("noise4.exr"); +} + +void example_noise2() +{ + // BEGIN-imagebufalgo-noise2 + const ImageBuf& A = ImageBufAlgo::bluenoise_image(); + // END-imagebufalgo-noise2 + + A.write("blue-noise.exr"); +} + +void example_point() +{ + // BEGIN-imagebufalgo-point + ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); + float red[4] = { 1, 0, 0, 1 }; + ImageBufAlgo::render_point (A, 50, 100, red); + // END-imagebufalgo-point + + A.write("point.exr"); +} + +void example_lines() +{ + // BEGIN-imagebufalgo-lines + ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); + float red[4] = { 1, 0, 0, 1 }; + ImageBufAlgo::render_line (A, 10, 60, 250, 20, red); + ImageBufAlgo::render_line (A, 250, 20, 100, 190, red, true); + // END-imagebufalgo-lines + + A.write("lines.exr"); +} + +void example_box() +{ + // BEGIN-imagebufalgo-box + ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); + float cyan[4] = { 0, 1, 1, 1 }; + float yellow_transparent[4] = { 0.5, 0.5, 0, 0.5 }; + ImageBufAlgo::render_box (A, 150, 100, 240, 180, cyan); + ImageBufAlgo::render_box (A, 100, 50, 180, 140, yellow_transparent, true); + // END-imagebufalgo-box + + A.write("box.exr"); +} + +void example_text1() +{ + ImageBuf ImgA = ImageBufAlgo::zero(ROI(0, 640, 0, 480, 0, 1, 0, 3)); + ImageBuf ImgB = ImageBufAlgo::zero(ROI(0, 640, 0, 480, 0, 1, 0, 3)); + + // BEGIN-imagebufalgo-text1 + ImageBufAlgo::render_text (ImgA, 50, 100, "Hello, world"); + float red[] = { 1, 0, 0, 1 }; + ImageBufAlgo::render_text (ImgA, 100, 200, "Go Big Red!", + 60, "" /*font name*/, red); + + float white[] = { 1, 1, 1, 1 }; + ImageBufAlgo::render_text (ImgB, 320, 240, "Centered", + 60, "" /*font name*/, white, + ImageBufAlgo::TextAlignX::Center, + ImageBufAlgo::TextAlignY::Center); + // END-imagebufalgo-text1 + + ImgA.write("text1.exr"); + ImgB.write("text2.exr"); +} + +void example_text2() +{ + // BEGIN-imagebufalgo-text2 + // Render text centered in the image, using text_size to find out + // the size we will need and adjusting the coordinates. + ImageBuf A (ImageSpec (640, 480, 4, TypeDesc::FLOAT)); + ROI Aroi = A.roi(); + ROI size = ImageBufAlgo::text_size("Centered", 48, "Courier New"); + if (size.defined()) { + int x = Aroi.xbegin + Aroi.width()/2 - (size.xbegin + size.width()/2); + int y = Aroi.ybegin + Aroi.height()/2 - (size.ybegin + size.height()/2); + ImageBufAlgo::render_text(A, x, y, "Centered", 48, "Courier New"); + } + // END-imagebufalgo-text2 +} // Section: Image transformation and data movement void example_circular_shift() { -// BEGIN-imagebufalgo-cshift + // BEGIN-imagebufalgo-cshift ImageBuf A("grid.exr"); ImageBuf B = ImageBufAlgo::circular_shift(A, 70, 30); B.write("cshift.exr"); -// END-imagebufalgo-cshift + // END-imagebufalgo-cshift } @@ -83,8 +277,20 @@ int main(int /*argc*/, char** /*argv*/) example1(); // Section: ImageBufAlgo common principles + example_output_error1(); + example_output_error2(); // Section: Pattern Generation + example_zero(); + example_fill(); + example_checker(); + example_noise1(); + example_noise2(); + example_point(); + example_lines(); + example_box(); + example_text1(); + example_text2(); // Section: Image transformation and data movement example_circular_shift(); diff --git a/testsuite/docs-examples-python/ref/out.txt b/testsuite/docs-examples-python/ref/out.txt index c82bb6b53c..c2e31b2ba9 100644 --- a/testsuite/docs-examples-python/ref/out.txt +++ b/testsuite/docs-examples-python/ref/out.txt @@ -1,3 +1,37 @@ +error: Uninitialized input image +error: Uninitialized input image +zero1.exr : 512 x 512, 3 channel, float openexr + SHA-1: 1E5F8DEF40BB0CB0F7156B9C2BAB9EFB49CFB699 +zero2.exr : 256 x 256, 4 channel, half openexr + SHA-1: 6A521E1D2A632C26E53B83D2CC4B0EDECFC1E68C +zero3.exr : 256 x 256, 4 channel, half openexr + SHA-1: 1254F2956229777B721576B94A6A944ECB806A37 +zero4.exr : 256 x 256, 4 channel, half openexr + SHA-1: 36EB49C5102703693C078717CE82AE05D4904680 +fill.exr : 640 x 480, 3 channel, float openexr + SHA-1: D517EA07CB6DB931AE4BF6D9E9957EEF9228734E +checker.exr : 640 x 480, 3 channel, float openexr + SHA-1: 87A4424581AAFCE31E6D1134E5025B620B48BBB3 +noise1.exr : 256 x 256, 3 channel, float openexr + SHA-1: 9E9278C8F5460068363D36DBD395FA59CA5986DC +noise2.exr : 256 x 256, 3 channel, float openexr + SHA-1: 0A75E8EF38846D8DC5D8BA997EB54F7A36058288 +noise3.exr : 512 x 384, 3 channel, half openexr + SHA-1: 95EDBCA9953281CE63A3E18C7C04BCCB07CB4C8A +noise4.exr : 512 x 384, 3 channel, half openexr + SHA-1: 43BC1FDFA1F18635B635A57D71DB08BB347CBD46 +blue-noise.exr : 256 x 256, 4 channel, float openexr + SHA-1: 36F448FE29C9DE6CFA65FC0BFCF4178DC66581C4 +point.exr : 640 x 480, 4 channel, float openexr + SHA-1: A2AC7CC98AB44798EEEA76C253DE44F6E49FFB8D +lines.exr : 640 x 480, 4 channel, float openexr + SHA-1: 69C0317F92256FD30415D1FE12419DC1C514D818 +box.exr : 640 x 480, 4 channel, float openexr + SHA-1: 6CBE5E98B145C5975CB930A91BAEE981C30E6B32 +text1.exr : 640 x 480, 3 channel, float openexr + SHA-1: 014ECFC5EBF07F77DF24A592F43BC7CB101534AE +text2.exr : 640 x 480, 3 channel, float openexr + SHA-1: 53359E96A286F909A89ACC99A67A9ED3BADC4A7A cshift.exr : 256 x 256, 4 channel, half openexr SHA-1: 000F95FDC44D4DBDA8B4041C2506149C7AE28ACA Comparing "simple.tif" and "ref/simple.tif" diff --git a/testsuite/docs-examples-python/run.py b/testsuite/docs-examples-python/run.py index 542b2a00a0..8e48f26989 100755 --- a/testsuite/docs-examples-python/run.py +++ b/testsuite/docs-examples-python/run.py @@ -6,7 +6,8 @@ # Prep: -command += run_app("cmake -E copy ../common/grid-small.exr grid.exr") +command += run_app("cmake -E copy " + test_source_dir + "/../common/grid-small.exr grid.exr") +command += run_app("cmake -E copy " + test_source_dir + "/../common/tahoe-small.tif tahoe.tif") # Run the examples for each chapter for chapter in [ "imageioapi", "imageoutput", "imageinput", "writingplugins", @@ -17,6 +18,22 @@ # of checking in a full copy of the image if it's not needed. hashes = [ # Outputs from the ImageBufAlgo chapter: + "zero1.exr", + "zero2.exr", + "zero3.exr", + "zero4.exr", + "fill.exr", + "checker.exr", + "noise1.exr", + "noise2.exr", + "noise3.exr", + "noise4.exr", + "blue-noise.exr", + "point.exr", + "lines.exr", + "box.exr", + "text1.exr", + "text2.exr", "cshift.exr", ] for file in hashes : diff --git a/testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py b/testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py index 69a0623555..9590ece844 100644 --- a/testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py +++ b/testsuite/docs-examples-python/src/docs-examples-imagebufalgo.py @@ -40,9 +40,190 @@ def example1() : # Section: ImageBufAlgo common principles +def example_output_error1(): + fg = ImageBuf() + bg = ImageBuf() + + # BEGIN-imagebufalgo-output-error1 + # Method 1: Return an image result + dst = ImageBufAlgo.over(fg, bg) + if dst.has_error: + print("error:", dst.geterror()) + # END-imagebufalgo-output-error1 + + +def example_output_error2(): + fg = ImageBuf() + bg = ImageBuf() + + # BEGIN-imagebufalgo-output-error2 + # Method 2: Write into an existing image + dst = ImageBuf() # will be the output image + ok = ImageBufAlgo.over(dst, fg, bg) + if not ok: + print("error:", dst.geterror()) + # END-imagebufalgo-output-error2 + # Section: Pattern Generation +def example_zero(): + A = ImageBuf("grid.exr") + B = ImageBuf("grid.exr") + C = ImageBuf("grid.exr") + + # BEGIN-imagebufalgo-zero + # Create a new 3-channel, 512x512 float image filled with 0.0 values. + zero = ImageBufAlgo.zero(ROI(0, 512, 0, 512, 0, 1, 0, 3)) + + # Zero out an existing buffer, keeping it the same size and data type + ImageBufAlgo.zero(A) + + # Zero out just the green channel, leave everything else the same + roi = B.roi + roi.chbegin = 1 # green + roi.chend = 2 # one past the end of the channel region + ImageBufAlgo.zero(B, roi) + + # Zero out a rectangular region of an existing buffer + ImageBufAlgo.zero(C, ROI(0, 100, 0, 100)) + # END-imagebufalgo-zero + + zero.write("zero1.exr") + A.write("zero2.exr") + B.write("zero3.exr") + C.write("zero4.exr") + + +def example_fill(): + # BEGIN-imagebufalgo-fill + # Create a new 640x480 RGB image, with a top-to-bottom gradient + # from red to pink + pink = (1, 0.7, 0.7) + red = (1, 0, 0) + A = ImageBufAlgo.fill(top=red, bottom=pink, + roi=ROI(0, 640, 0, 480, 0, 1, 0, 3)) + + # Draw a filled red rectangle overtop existing image A. + ImageBufAlgo.fill(A, red, ROI(50, 100, 75, 175)) + # END-imagebufalgo-fill + + A.write("fill.exr") + + +def example_checker(): + # BEGIN-imagebufalgo-checker + # Create a new 640x480 RGB image, fill it with a two-toned gray + # checkerboard, the checkers being 64x64 pixels each. + A = ImageBuf(ImageSpec(640, 480, 3, "float")) + dark = (0.1, 0.1, 0.1) + light = (0.4, 0.4, 0.4) + A = ImageBufAlgo.checker(64, 64, 1, dark, light, + roi=ROI(0, 640, 0, 480, 0, 1, 0, 3)) + # END-imagebufalgo-checker + + A.write("checker.exr") + + +def example_noise1(): + # BEGIN-imagebufalgo-noise1 + # Create a new 256x256 field of grayscale white noise on [0,1) + A = ImageBufAlgo.noise("uniform", A=0.0, B=1.0, mono=True, seed=1, + roi=ROI(0, 256, 0, 256, 0, 1, 0, 3)) + + # Create a new 256x256 field of grayscale blue noise on [0,1) + B = ImageBufAlgo.noise("blue", A=0.0, B=1.0, mono=True, seed=1, + roi=ROI(0, 256, 0, 256, 0, 1, 0, 3)) + + # Add color Gaussian noise to an existing image + C = ImageBuf("tahoe.tif") + ImageBufAlgo.noise(C, "gaussian", A=0.0, B=0.1, mono=False, seed=1) + + # Use salt and pepper noise to make occasional random dropouts + D = ImageBuf("tahoe.tif") + ImageBufAlgo.noise(D, "salt", A=0.0, B=0.01, mono=True, seed=1) + # END-imagebufalgo-noise1 + + A.write("noise1.exr") + B.write("noise2.exr") + C.write("noise3.exr") + D.write("noise4.exr") + + +def example_noise2(): + # BEGIN-imagebufalgo-noise2 + A = ImageBufAlgo.bluenoise_image() + # END-imagebufalgo-noise2 + + A.write("blue-noise.exr") + + +def example_point(): + # BEGIN-imagebufalgo-point + A = ImageBuf(ImageSpec(640, 480, 4, "float")) + red = (1, 0, 0, 1) + ImageBufAlgo.render_point(A, 50, 100, red) + # END-imagebufalgo-point + + A.write("point.exr") + + +def example_lines(): + # BEGIN-imagebufalgo-lines + A = ImageBuf(ImageSpec(640, 480, 4, "float")) + red = (1, 0, 0, 1) + ImageBufAlgo.render_line(A, 10, 60, 250, 20, red) + ImageBufAlgo.render_line(A, 250, 20, 100, 190, red, True) + # END-imagebufalgo-lines + + A.write("lines.exr") + + +def example_box(): + # BEGIN-imagebufalgo-box + A = ImageBuf(ImageSpec(640, 480, 4, "float")) + cyan = (0, 1, 1, 1) + yellow_transparent = (0.5, 0.5, 0, 0.5) + ImageBufAlgo.render_box(A, 150, 100, 240, 180, cyan) + ImageBufAlgo.render_box(A, 100, 50, 180, 140, yellow_transparent, fill=True) + # END-imagebufalgo-box + + A.write("box.exr") + + +def example_text1(): + ImgA = ImageBufAlgo.zero(ROI(0, 640, 0, 480, 0, 1, 0, 3)) + ImgB = ImageBufAlgo.zero(ROI(0, 640, 0, 480, 0, 1, 0, 3)) + + # BEGIN-imagebufalgo-text1 + ImageBufAlgo.render_text(ImgA, 50, 100, "Hello, world") + red = (1, 0, 0, 1) + ImageBufAlgo.render_text(ImgA, 100, 200, "Go Big Red!", + fontsize=60, fontname="", textcolor=red) + + white = (1, 1, 1, 1) + ImageBufAlgo.render_text(ImgB, 320, 240, "Centered", + fontsize=60, fontname="", textcolor=white, + alignx="center", aligny="center") + # END-imagebufalgo-text1 + + ImgA.write("text1.exr") + ImgB.write("text2.exr") + + +def example_test2(): + # BEGIN-imagebufalgo-text2 + # Render text centered in the image, using text_size to find out + # the size we will need and adjusting the coordinates. + A = ImageBuf(ImageSpec(640, 480, 4, "float")) + Aroi = A.roi + size = ImageBufAlgo.text_size("Centered", 48, "Courier New") + if size.defined: + x = Aroi.xbegin + Aroi.width//2 - (size.xbegin + size.width//2) + y = Aroi.ybegin + Aroi.height//2 - (size.ybegin + size.height//2) + ImageBufAlgo.render_text(A, x, y, "Centered", 48, "Courier New") + # END-imagebufalgo-text2 + # Section: Image transformation and data movement @@ -51,7 +232,7 @@ def example_circular_shift() : A = ImageBuf("grid.exr") B = ImageBufAlgo.circular_shift(A, 70, 30) # END-imagebufalgo-cshift - B.write("cshift.exr"); + B.write("cshift.exr") # Section: Image Arithmetic @@ -85,8 +266,20 @@ def example_circular_shift() : example1() # Section: ImageBufAlgo common principles + example_output_error1() + example_output_error2() # Section: Pattern Generation + example_zero() + example_fill() + example_checker() + example_noise1() + example_noise2() + example_point() + example_lines() + example_box() + example_text1() + example_test2() # Section: Image transformation and data movement example_circular_shift()