@@ -510,12 +510,11 @@ bump_to_bumpslopes(ImageBuf& dst, const ImageBuf& src,
510510 return false ;
511511 }
512512 is_height = false ;
513- } else if (Strutil::iequals (
514- bumpformat,
515- " auto" )) { // guess input bump format by analyzing channel count and component
513+ } else if (Strutil::iequals (bumpformat, " auto" )) {
514+ // guess input bump format by analyzing channel count and component
516515 if (src.spec ().nchannels > 2
517- && !ImageBufAlgo::isMonochrome (src)) // maybe it's a normal map?
518- is_height = false ;
516+ && !ImageBufAlgo::isMonochrome (src, 0 . 0f , ROI (), nthreads))
517+ is_height = false ; // maybe it's a normal map?
519518 else
520519 is_height = true ;
521520 } else {
@@ -705,6 +704,8 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
705704 ImageSpec outspec = outspec_template;
706705 outspec.set_format (outputdatatype);
707706
707+ int nthreads = configspec.get_int_attribute (" maketx:threads" );
708+
708709 // Going from float to half is prone to generating Inf values if we had
709710 // any floats that were out of the range that half can represent. Nobody
710711 // wants Inf in textures; better to clamp.
@@ -783,7 +784,8 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
783784
784785 if (clamp_half) {
785786 std::shared_ptr<ImageBuf> tmp (new ImageBuf);
786- ImageBufAlgo::clamp (*tmp, *img, -HALF_MAX, HALF_MAX, true );
787+ ImageBufAlgo::clamp (*tmp, *img, -HALF_MAX, HALF_MAX, true , ROI (),
788+ nthreads);
787789 std::swap (tmp, img);
788790 }
789791 if (!img->write (out)) {
@@ -831,7 +833,8 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
831833 std::shared_ptr<ImageBuf> t (new ImageBuf (smallspec));
832834 ImageBufAlgo::channels (*t, *small, outspec.nchannels ,
833835 cspan<int >(), cspan<float >(),
834- cspan<std::string>(), true );
836+ cspan<std::string>(), true ,
837+ nthreads);
835838 std::swap (t, small);
836839 }
837840 smallspec.tile_width = outspec.tile_width ;
@@ -863,7 +866,7 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
863866 // and pixel windows match. Don't worry, the texture
864867 // engine doesn't care what the upper MIP levels have
865868 // for the window sizes, it uses level 0 to determine
866- // the relatinship between texture 0-1 space (display
869+ // the relationship between texture 0-1 space (display
867870 // window) and the pixels.
868871 smallspec.x = 0 ;
869872 smallspec.y = 0 ;
@@ -875,12 +878,11 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
875878
876879 if (filtername == " box" && !orig_was_overscan
877880 && sharpen <= 0 .0f ) {
878- ImageBufAlgo::parallel_image (get_roi (small->spec ()),
879- std::bind (resize_block,
880- std::ref (*small),
881- std::cref (*img), _1,
882- envlatlmode,
883- allow_shift));
881+ ImageBufAlgo::parallel_image (
882+ get_roi (small->spec ()), paropt (nthreads), [&](ROI roi) {
883+ resize_block (*small, *img, roi, envlatlmode,
884+ allow_shift);
885+ });
884886 } else {
885887 Filter2D* filter = setup_filter (small->spec (), img->spec (),
886888 filtername);
@@ -901,38 +903,44 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
901903 OIIO::print (outstream, " \n " );
902904 }
903905 if (do_highlight_compensation)
904- ImageBufAlgo::rangecompress (*img, *img);
906+ ImageBufAlgo::rangecompress (*img, *img, false , ROI (),
907+ nthreads);
905908 if (sharpen > 0 .0f && sharpen_first) {
906909 std::shared_ptr<ImageBuf> sharp (new ImageBuf);
907910 bool uok = ImageBufAlgo::unsharp_mask (*sharp, *img,
908- sharpenfilt, 3.0 ,
909- sharpen, 0 .0f );
911+ sharpenfilt, 3 .0f ,
912+ sharpen, 0 .0f ,
913+ ROI (), nthreads);
910914 if (!uok)
911915 errorfmt (" {}" , sharp->geterror ());
912916 std::swap (img, sharp);
913917 }
914918 ImageBufAlgo::resize (*small, *img,
915- { make_pv (" filterptr" , filter) });
919+ { make_pv (" filterptr" , filter) },
920+ ROI (), nthreads);
916921 if (sharpen > 0 .0f && !sharpen_first) {
917922 std::shared_ptr<ImageBuf> sharp (new ImageBuf);
918923 bool uok = ImageBufAlgo::unsharp_mask (*sharp, *small,
919- sharpenfilt, 3.0 ,
920- sharpen, 0 .0f );
924+ sharpenfilt, 3 .0f ,
925+ sharpen, 0 .0f ,
926+ ROI (), nthreads);
921927 if (!uok)
922928 errorfmt (" {}" , sharp->geterror ());
923929 std::swap (small, sharp);
924930 }
925931 if (do_highlight_compensation) {
926- ImageBufAlgo::rangeexpand (*small, *small);
932+ ImageBufAlgo::rangeexpand (*small, *small, false , ROI (),
933+ nthreads);
927934 ImageBufAlgo::clamp (*small, *small, 0 .0f ,
928935 std::numeric_limits<float >::max (),
929- true );
936+ true , ROI (), nthreads );
930937 }
931938 Filter2D::destroy (filter);
932939 }
933940 }
934941 if (clamp_half)
935- ImageBufAlgo::clamp (*small, *small, -HALF_MAX, HALF_MAX, true );
942+ ImageBufAlgo::clamp (*small, *small, -HALF_MAX, HALF_MAX, true ,
943+ ROI (), nthreads);
936944
937945 double this_miptime = miptimer ();
938946 stat_miptime += this_miptime;
@@ -1093,6 +1101,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
10931101 if (!configspec.tile_depth )
10941102 configspec.tile_depth = 1 ;
10951103
1104+ int nthreads = configspec.get_int_attribute (" maketx:threads" );
1105+
10961106 bool ignore_unassoc = configspec.get_int_attribute (" maketx:ignore_unassoc" );
10971107 ImageSpec inconfig;
10981108 if (ignore_unassoc)
@@ -1257,8 +1267,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12571267 bool ok = true ;
12581268 OIIO_DISPATCH_COMMON_TYPES (ok, " lightprobe_to_envlatl" ,
12591269 lightprobe_to_envlatl, src->spec ().format ,
1260- *latlong, *src, true );
1261- // lightprobe_to_envlatl(*latlong, *src, true);
1270+ *latlong, *src, true , ROI (), nthreads);
12621271 // Carry on with the lat-long environment map from here on out
12631272 mode = ImageBufAlgo::MakeTxEnvLatl;
12641273 src = latlong;
@@ -1269,7 +1278,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12691278 if (Strutil::iequals (configspec.get_string_attribute (" maketx:bumprange" ,
12701279 " auto" ),
12711280 " auto" ))
1272- src_pixel_stats = ImageBufAlgo::computePixelStats (*src);
1281+ src_pixel_stats = ImageBufAlgo::computePixelStats (*src, ROI (),
1282+ nthreads);
12731283
12741284 ImageSpec newspec = src->spec ();
12751285 newspec.tile_width = newspec.tile_height = 0 ;
@@ -1286,7 +1296,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12861296 bool ok;
12871297 OIIO_DISPATCH_COMMON_TYPES (ok, " bump_to_bumpslopes" , bump_to_bumpslopes,
12881298 src->spec ().format , *bumpslopes, *src,
1289- configspec, src_pixel_stats, outstream);
1299+ configspec, src_pixel_stats, outstream,
1300+ ROI (), nthreads);
12901301 // bump_to_bumpslopes(*bumpslopes, *src);
12911302 mode = ImageBufAlgo::MakeTxTexture;
12921303 src = bumpslopes;
@@ -1330,7 +1341,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
13301341 std::vector<imagesize_t > hist;
13311342
13321343 for (int i = 0 ; i < channels; i++) {
1333- hist = ImageBufAlgo::histogram (*src, i, bins, 0 .0f , 1 .0f );
1344+ hist = ImageBufAlgo::histogram (*src, i, bins, 0 .0f , 1 .0f , false ,
1345+ ROI (), nthreads);
13341346
13351347 // Turn the histogram into a non-normalized CDF
13361348 for (uint64_t j = 1 ; j < bins; j++) {
@@ -1389,7 +1401,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
13891401 bool compute_stats = (constant_color_detect || opaque_detect
13901402 || compute_average_color || monochrome_detect);
13911403 if (compute_stats) {
1392- pixel_stats = ImageBufAlgo::computePixelStats (*src);
1404+ pixel_stats = ImageBufAlgo::computePixelStats (*src, ROI (), nthreads );
13931405 }
13941406 double stat_pixelstatstime = alltime.lap ();
13951407 STATUS (" pixelstats" , stat_pixelstatstime);
@@ -1420,7 +1432,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14201432 newspec.full_height = newspec.height ;
14211433 newspec.full_depth = newspec.depth ;
14221434 src->reset (newspec);
1423- ImageBufAlgo::fill (*src, constantColor);
1435+ ImageBufAlgo::fill (*src, constantColor, ROI (), nthreads );
14241436 if (verbose) {
14251437 outstream << " Constant color image detected. " ;
14261438 outstream << " Creating " << newspec.width << " x"
@@ -1441,7 +1453,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14411453 std::shared_ptr<ImageBuf> newsrc (new ImageBuf (src->spec ()));
14421454 ImageBufAlgo::channels (*newsrc, *src, src->nchannels () - 1 ,
14431455 cspan<int >(), cspan<float >(),
1444- cspan<std::string>(), true );
1456+ cspan<std::string>(), true , nthreads );
14451457 std::swap (src, newsrc); // N.B. the old src will delete
14461458 }
14471459
@@ -1455,14 +1467,14 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14551467 && src->spec ().alpha_channel < 0
14561468 && pixel_stats.avg [0 ] == pixel_stats.avg [1 ]
14571469 && pixel_stats.avg [0 ] == pixel_stats.avg [2 ]
1458- && ImageBufAlgo::isMonochrome (*src)) {
1470+ && ImageBufAlgo::isMonochrome (*src, 0 . 0f , ROI (), nthreads )) {
14591471 if (verbose)
14601472 OIIO::print (
14611473 outstream,
14621474 " Monochrome image detected. Converting to single channel texture.\n " );
14631475 std::shared_ptr<ImageBuf> newsrc (new ImageBuf (src->spec ()));
14641476 ImageBufAlgo::channels (*newsrc, *src, 1 , cspan<int >(), cspan<float >(),
1465- cspan<std::string>(), true );
1477+ cspan<std::string>(), true , nthreads );
14661478 newsrc->specmod ().default_channel_names ();
14671479 std::swap (src, newsrc);
14681480 }
@@ -1475,7 +1487,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14751487 << std::endl;
14761488 std::shared_ptr<ImageBuf> newsrc (new ImageBuf (src->spec ()));
14771489 ImageBufAlgo::channels (*newsrc, *src, nchannels, cspan<int >(),
1478- cspan<float >(), cspan<std::string>(), true );
1490+ cspan<float >(), cspan<std::string>(), true ,
1491+ nthreads);
14791492 std::swap (src, newsrc);
14801493 }
14811494
@@ -1663,7 +1676,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
16631676 && (srcspec.format .basetype == TypeDesc::FLOAT
16641677 || srcspec.format .basetype == TypeDesc::HALF
16651678 || srcspec.format .basetype == TypeDesc::DOUBLE)
1666- && !ImageBufAlgo::fixNonFinite (*src, *src, fixmode, &pixelsFixed)) {
1679+ && !ImageBufAlgo::fixNonFinite (*src, *src, fixmode, &pixelsFixed, ROI (),
1680+ nthreads)) {
16671681 errorfmt (" Error fixing nans/infs." );
16681682 return false ;
16691683 }
@@ -1677,7 +1691,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
16771691 || srcspec.format .basetype == TypeDesc::HALF
16781692 || srcspec.format .basetype == TypeDesc::DOUBLE)) {
16791693 int found_nonfinite = 0 ;
1680- ImageBufAlgo::parallel_image (get_roi (srcspec),
1694+ ImageBufAlgo::parallel_image (get_roi (srcspec), nthreads,
16811695 std::bind (check_nan_block, std::ref (*src),
16821696 _1, std::ref (found_nonfinite)));
16831697 if (found_nonfinite) {
@@ -1736,7 +1750,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
17361750 outstream << " Unpremulting image..." << std::endl;
17371751
17381752 if (!ImageBufAlgo::colorconvert (*ccSrc, *src, processor.get (),
1739- unpremult)) {
1753+ unpremult, ROI (), nthreads )) {
17401754 errorfmt (" Error applying color conversion to image." );
17411755 return false ;
17421756 }
@@ -1838,10 +1852,12 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
18381852 toplevel.reset (new ImageBuf (dstspec));
18391853 if ((resize_filter == " box" || resize_filter == " triangle" )
18401854 && !orig_was_overscan) {
1841- ImageBufAlgo::parallel_image (
1842- get_roi (dstspec),
1843- std::bind (resize_block, std::ref (*toplevel), std::cref (*src),
1844- _1, envlatlmode, allow_shift != 0 ));
1855+ ImageBufAlgo::parallel_image (get_roi (dstspec), nthreads,
1856+ [&](ROI roi) {
1857+ resize_block (*toplevel, *src, roi,
1858+ envlatlmode,
1859+ allow_shift != 0 );
1860+ });
18451861 } else {
18461862 Filter2D* filter = setup_filter (toplevel->spec (), src->spec (),
18471863 resize_filter);
@@ -1850,7 +1866,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
18501866 return false ;
18511867 }
18521868 ImageBufAlgo::resize (*toplevel, *src,
1853- { make_pv (" filterptr" , filter) });
1869+ { make_pv (" filterptr" , filter) }, ROI (),
1870+ nthreads);
18541871 Filter2D::destroy (filter);
18551872 }
18561873 }
@@ -1906,12 +1923,11 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
19061923 addlHashData << " keepaspect=1 " ;
19071924
19081925 const int sha1_blocksize = 256 ;
1909- std::string hash_digest
1910- = configspec.get_int_attribute (" maketx:hash" , 1 )
1911- ? ImageBufAlgo::computePixelHashSHA1 (*toplevel,
1912- addlHashData.str (),
1913- ROI::All (), sha1_blocksize)
1914- : " " ;
1926+ std::string hash_digest = configspec.get_int_attribute (" maketx:hash" , 1 )
1927+ ? ImageBufAlgo::computePixelHashSHA1 (
1928+ *toplevel, addlHashData.str (), ROI::All (),
1929+ sha1_blocksize, nthreads)
1930+ : " " ;
19151931 if (hash_digest.length ()) {
19161932 if (out->supports (" arbitrary_metadata" )) {
19171933 dstspec.attribute (" oiio:SHA-1" , hash_digest);
0 commit comments