@@ -225,7 +225,9 @@ vector<Channel>
225225 return channels;
226226}
227227
228- Task<void > ImageLoader::resizeChannelsAsync (span<const Channel> srcChannels, vector<Channel>& dstChannels, int priority) {
228+ Task<void > ImageLoader::resizeChannelsAsync (
229+ span<const Channel> srcChannels, vector<Channel>& dstChannels, const optional<Box2i>& dstArea, int priority
230+ ) {
229231 TEV_ASSERT (srcChannels.size () == dstChannels.size (), " Number of source and destination channels must match." );
230232 if (srcChannels.empty ()) {
231233 co_return ;
@@ -235,23 +237,36 @@ Task<void> ImageLoader::resizeChannelsAsync(span<const Channel> srcChannels, vec
235237 const Vector2i targetSize = dstChannels.front ().size ();
236238 const int numChannels = (int )srcChannels.size ();
237239
240+ const Box2i box = dstArea.value_or (Box2i{Vector2i (0 , 0 ), targetSize});
241+
238242 for (int i = 1 ; i < numChannels; ++i) {
239243 TEV_ASSERT (srcChannels[i].size () == size, " Source channels' size must match." );
240244 TEV_ASSERT (dstChannels[i].size () == targetSize, " Destination channels' size must match." );
241245 }
242246
243247 const size_t numSamples = (size_t )targetSize.x () * targetSize.y () * numChannels;
244- const float scaleX = (float )size.x () / targetSize.x ();
245- const float scaleY = (float )size.y () / targetSize.y ();
248+
249+ const float scaleX = (float )size.x () / box.size ().x ();
250+ const float scaleY = (float )size.y () / box.size ().y ();
246251
247252 co_await ThreadPool::global ().parallelForAsync <int >(
248253 0 ,
249254 targetSize.y (),
250255 numSamples,
251256 [&](int dstY) {
252257 for (int dstX = 0 ; dstX < targetSize.x (); ++dstX) {
253- const float srcX = (dstX + 0 .5f ) * scaleX - 0 .5f ;
254- const float srcY = (dstY + 0 .5f ) * scaleY - 0 .5f ;
258+ const size_t dstIdx = dstY * (size_t )targetSize.x () + dstX;
259+
260+ if (dstX < box.min .x () || dstX >= box.max .x () || dstY < box.min .y () || dstY >= box.max .y ()) {
261+ for (int c = 0 ; c < numChannels; ++c) {
262+ dstChannels[c].setAt (dstIdx, 0 .0f );
263+ }
264+
265+ continue ;
266+ }
267+
268+ const float srcX = ((dstX - box.min .x ()) + 0 .5f ) * scaleX - 0 .5f ;
269+ const float srcY = ((dstY - box.min .y ()) + 0 .5f ) * scaleY - 0 .5f ;
255270
256271 const int x0 = std::max ((int )floor (srcX), 0 );
257272 const int y0 = std::max ((int )floor (srcY), 0 );
@@ -268,8 +283,6 @@ Task<void> ImageLoader::resizeChannelsAsync(span<const Channel> srcChannels, vec
268283 const float w10 = wx0 * wy1;
269284 const float w11 = wx1 * wy1;
270285
271- const size_t dstIdx = dstY * (size_t )targetSize.x () + dstX;
272-
273286 const size_t srcIdx00 = y0 * (size_t )size.x () + x0;
274287 const size_t srcIdx01 = y0 * (size_t )size.x () + x1;
275288 const size_t srcIdx10 = y1 * (size_t )size.x () + x0;
@@ -289,7 +302,7 @@ Task<void> ImageLoader::resizeChannelsAsync(span<const Channel> srcChannels, vec
289302 );
290303}
291304
292- Task<void > ImageLoader::resizeImageData (ImageData& resultData, const Vector2i& targetSize, int priority) {
305+ Task<void > ImageLoader::resizeImageData (ImageData& resultData, const Vector2i& targetSize, const optional<Box2i>& targetArea, int priority) {
293306 const Vector2i size = resultData.channels .front ().size ();
294307 if (size == targetSize) {
295308 co_return ;
@@ -302,7 +315,7 @@ Task<void> ImageLoader::resizeImageData(ImageData& resultData, const Vector2i& t
302315 resultData.channels .emplace_back (c.name (), targetSize, c.pixelFormat (), c.desiredPixelFormat ());
303316 }
304317
305- co_await resizeChannelsAsync (prevChannels, resultData.channels , priority);
318+ co_await resizeChannelsAsync (prevChannels, resultData.channels , targetArea, priority);
306319};
307320
308321} // namespace tev
0 commit comments