diff --git a/uppsrc/Core/CoWork.h b/uppsrc/Core/CoWork.h index 6ca07958f..1eb7b4404 100644 --- a/uppsrc/Core/CoWork.h +++ b/uppsrc/Core/CoWork.h @@ -122,6 +122,15 @@ void CoDo_ST(Function&& fn) fn(); } +inline +void CoDo(bool co, Function&& fn) +{ + if(co) + CoDo(pick(fn)); + else + CoDo_ST(pick(fn)); +} + template void CoFor(int n, Fn iterator) { @@ -132,6 +141,22 @@ void CoFor(int n, Fn iterator) }); } +template +void CoFor_ST(int n, Fn iterator) +{ + for(int i = 0; i < n; i++) + iterator(i); +} + +template +void CoFor(bool co, int n, Fn iterator) +{ + if(co) + CoFor(n, iterator); + else + CoFor_ST(n, iterator); +} + template class CoWorkerResources { int workercount; diff --git a/uppsrc/Core/src.tpp/CoWork_en-us.tpp b/uppsrc/Core/src.tpp/CoWork_en-us.tpp index 915c37cf3..d9c85cb7e 100644 --- a/uppsrc/Core/src.tpp/CoWork_en-us.tpp +++ b/uppsrc/Core/src.tpp/CoWork_en-us.tpp @@ -209,10 +209,29 @@ unction]<[@(0.0.255) void]_()>`&`&_[*@3 fn])&] by adding `"`_ST`" text.&] [s3;%% &] [s4; &] +[s5;:Upp`:`:CoDo`(bool`,Upp`:`:Function``&`&`): [@(0.0.255) void]_[* CoDo]([@(0.0.255) b +ool]_[*@3 co], [_^Upp`:`:Function^ Function]<[@(0.0.255) void]_()>`&`&_[*@3 fn])&] +[s2;%% If [%-*@3 co] is true, calls CoDo([%-*@3 fn]), otherwise CoDo`_ST([%-*@3 fn]). +This allows to parametrize algorithms with respect to parallelization.&] +[s3;%% &] +[s4; &] [s5;:Upp`:`:CoFor`(int`,Fn`): [@(0.0.255) template]_<[@(0.0.255) typename]_[*@4 Fn]>_[@(0.0.255) v oid]_[* CoFor]([@(0.0.255) int]_[*@3 n], [*@4 Fn]_[*@3 iterator])&] [s2;%% Based on CoDo, runs in parallel [%-*@3 iterator] for values 0..[%-*@3 n] passing the value as argument.&] +[s3; &] +[s4; &] +[s5;:Upp`:`:CoFor`_ST`(int`,Fn`): [@(0.0.255) template]_<[@(0.0.255) typename]_[*@4 Fn]>_[@(0.0.255) v +oid]_[* CoFor`_ST]([@(0.0.255) int]_[*@3 n], [*@4 Fn]_[*@3 iterator])&] +[s2;%% Single threaded variant of CoFor, for diagnostics purposes.&] +[s3;%% &] +[s4; &] +[s5;:Upp`:`:CoFor`(bool`,int`,Fn`): [@(0.0.255) template]_<[@(0.0.255) typename]_[*@4 Fn]>_ +[@(0.0.255) void]_[* CoFor]([@(0.0.255) bool]_[*@3 co], [@(0.0.255) int]_[*@3 n], +[*@4 Fn]_[*@3 iterator])&] +[s2;%% Calls CoFor([%-*@3 n], [%-*@3 iterator]) if [%-*@3 co] is true, +CoFor`_ST([%-*@3 n], [%-*@3 iterator]) otherwise. This allows to +parametrize algorithms with respect to parallelization.&] [s0; &] [ {{10000@(113.42.0) [s0;%% [*@7;4 CoWorkerResources]]}}&] [s3; &] @@ -235,7 +254,7 @@ better solved by using CoDo function.&] [s5;:Upp`:`:CoWorkerResources`:`:CoWorkerResources`(`): [* CoWorkerResources]()&] [s2;%% Creates a required number of instances so that each sub`-job of CoWork has its unique instance.&] -[s3; &] +[s3;%% &] [s4; &] [s5;:Upp`:`:CoWorkerResources`:`:CoWorkerResources`(Upp`:`:Event``): [* CoWorkerR esources]([_^Upp`:`:Event^ Event]<[*@4 T][@(0.0.255) `&]>_[*@3 initializer])&] diff --git a/uppsrc/Draw/BiCubic.cpp b/uppsrc/Draw/BiCubic.cpp deleted file mode 100644 index 93874d542..000000000 --- a/uppsrc/Draw/BiCubic.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "Draw.h" - -namespace Upp { - -double BicubicKernel(double x) -{ - double r = 0; - double xp2 = x + 2; - double xp1 = x + 1; - double xm1 = x - 1; - if(xp2 > 0) - r += xp2 * xp2 * xp2; - if(xp1 > 0) - r -= 4 * xp1 * xp1 * xp1; - if(x > 0) - r += 6 * x * x * x; - if(xm1 > 0) - r -= 4 * xm1 * xm1 * xm1; - return 0.16666666666666666 * r; -} - -Image RescaleBicubic(const Image& img, Size sz, const Rect& sr, Gate progress) -{ - ASSERT(sr.top >= 0 && sr.left >= 0 && sr.right <= img.GetWidth() && sr.bottom <= img.GetHeight()); - Size isz = sr.GetSize(); - ImageBuffer ib(sz); - RGBA *t = ~ib; - double inv_cx = 1.0 / sz.cx; - for(int y = 0; y < sz.cy; y++) { - if(progress(y, sz.cy)) - return ib; - int sy = y * isz.cy / sz.cy; - double dy = y * isz.cy / (double)sz.cy - sy; - for(int x = 0; x < sz.cx; x++) { - int sx = x * isz.cx / sz.cx; - double dx = x * isz.cx * inv_cx - sx; - double red = 0; - double green = 0; - double blue = 0; - double alpha = 0; - for(int yy = -1; yy <= 2; yy++) { - double ky = BicubicKernel(yy - dy); - const RGBA *l = img[minmax(sy + yy + sr.top, sr.top, sr.bottom - 1)]; - for(int xx = -1; xx <= 2; xx++) { - const RGBA& s = l[minmax(sx + xx + sr.left, sr.left, sr.right - 1)]; - double weight = ky * BicubicKernel(xx - dx); - red += weight * s.r; - green += weight * s.g; - blue += weight * s.b; - alpha += weight * s.a; - } - } - t->r = (int)fround(red); - t->g = (int)fround(green); - t->b = (int)fround(blue); - t->a = (int)fround(alpha); - t++; - } - } - return ib; -} - -Image RescaleBicubic(const Image& img, int cx, int cy, Gate progress) -{ - return RescaleBicubic(img, Size(cx, cy), img.GetSize(), progress); -} - -Image RescaleBicubic(const Image& img, Size sz, Gate progress) -{ - return RescaleBicubic(img, sz, img.GetSize(), progress); -} - -} diff --git a/uppsrc/Draw/Draw.upp b/uppsrc/Draw/Draw.upp index 0a16ee166..99a05a8a3 100644 --- a/uppsrc/Draw/Draw.upp +++ b/uppsrc/Draw/Draw.upp @@ -42,7 +42,6 @@ file ImageOp.cpp, ImageChOp.cpp, ImageScale.cpp, - BiCubic.cpp, RescaleFilter.cpp, MakeCache.cpp, DrawRasterData.cpp, diff --git a/uppsrc/Draw/ImageOp.h b/uppsrc/Draw/ImageOp.h index 718f1b681..82ffb33e4 100644 --- a/uppsrc/Draw/ImageOp.h +++ b/uppsrc/Draw/ImageOp.h @@ -52,6 +52,8 @@ Image Contrast(const Image& img, int amount = 256); Image HorzFadeOut(int cx, int cy, Color color); Image HorzFadeOut(Size sz, Color color); +void DrawRasterData(Draw& w, int x, int y, int cx, int cy, const String& data); + class RescaleImage { Raster *src; Size tsz; @@ -85,10 +87,10 @@ class RescaleImage { public: void Create(Size sz, Raster& src, const Rect& src_rc); void Get(RGBA *line); + + Image CoRescale(Size sz, const Image& img, const Rect& src_rc); }; -void DrawRasterData(Draw& w, int x, int y, int cx, int cy, const String& data); - bool Rescale(RasterEncoder& tgt, Size sz, Raster& src, const Rect& src_rc, Gate progress = Null); Image Rescale(const Image& src, Size sz, const Rect& src_rc, Gate progress = Null); @@ -179,11 +181,14 @@ void SetMakeImageCacheMax(int m); Image MakeImagePaintOnly(const ImageMaker& m); Image RescaleFilter(const Image& img, Size sz, const Rect& sr, - double (*kernel_fn)(double x), int kernel_width, Gate progress); + double (*kernel_fn)(double x), int kernel_width, Gate progress, + bool co); Image RescaleFilter(const Image& img, Size sz, - double (*kernel_fn)(double x), int kernel_width, Gate progress); + double (*kernel_fn)(double x), int kernel_width, Gate progress, + bool co); Image RescaleFilter(const Image& img, int cx, int cy, - double (*kernel_fn)(double x), int kernel_width, Gate progress); + double (*kernel_fn)(double x), int kernel_width, Gate progress, + bool co); enum { FILTER_NEAREST = 0, @@ -198,10 +203,14 @@ enum { FILTER_LANCZOS5 = 9, }; -Image RescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate progress = Null); +Image RescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate progress = Null, bool co = false); Image RescaleFilter(const Image& img, Size sz, int filter, Gate progress = Null); Image RescaleFilter(const Image& img, int cx, int cy, int filter, Gate progress = Null); +Image CoRescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate progress = Null); +Image CoRescaleFilter(const Image& img, Size sz, int filter, Gate progress = Null); +Image CoRescaleFilter(const Image& img, int cx, int cy, int filter, Gate progress = Null); + Image CachedRescale(const Image& m, Size sz, const Rect& src, int filter = Null); Image CachedRescale(const Image& m, Size sz, int filter = Null); Image CachedRescalePaintOnly(const Image& m, Size sz, const Rect& src, int filter = Null); diff --git a/uppsrc/Draw/RescaleFilter.cpp b/uppsrc/Draw/RescaleFilter.cpp index 7bbc8c98e..f849f75ea 100644 --- a/uppsrc/Draw/RescaleFilter.cpp +++ b/uppsrc/Draw/RescaleFilter.cpp @@ -39,7 +39,7 @@ static int sGeta(int a, int src, int tgt, int& shift) Image RescaleFilter(const Image& img, Size sz, const Rect& sr, double (*kfn)(double x), int a, - Gate progress) + Gate progress, bool co) { ASSERT(Rect(img.GetSize()).Contains(sr)); Size isz = sr.GetSize(); @@ -72,78 +72,81 @@ Image RescaleFilter(const Image& img, Size sz, const Rect& sr, } ImageBuffer ib(sz); - RGBA *t = ~ib; - for(int y = 0; y < sz.cy; y++) { - if(progress(y, sz.cy)) - break; - int dy = ((y * isz.cy) << shift) / sz.cy - cr.cy; - int sy = dy >> shift; - dy -= sy << shift; - if(dy < 0) - dy = 0; - xd = ~px; + std::atomic yy(0); + CoDo(co, [&] { Buffer py(2 * ay * 2); - int *yd = py; - for(int yy = -ay + 1; yy <= ay; yy++) { - *yd++ = sGetk(kernel, ((yy << shift) - dy) * a / ay, a, shift); - *yd++ = minmax(sy + yy, 0, isz.cy - 1) + sr.top; - } - for(int x = 0; x < sz.cx; x++) { - int red = 0; - int green = 0; - int blue = 0; - int alpha = 0; - int w = 0; - yd = py; - int hasalpha = 0; - for(int yy = 2 * ay; yy-- > 0;) { - int ky = *yd++; - const RGBA *l = img[*yd++]; - for(int xx = 2 * ax; xx-- > 0;) { - const RGBA& s = l[*xd++]; - int weight = ky * *xd++; - red += weight * s.r; - green += weight * s.g; - blue += weight * s.b; - alpha += weight * s.a; - hasalpha |= s.a - 255; - w += weight; - } + for(int y = yy++; y < sz.cy; y = yy++) { + if(progress(y, sz.cy)) + break; + int dy = ((y * isz.cy) << shift) / sz.cy - cr.cy; + int sy = dy >> shift; + dy -= sy << shift; + if(dy < 0) + dy = 0; + int *xd = px; + int *yd = py; + for(int yy = -ay + 1; yy <= ay; yy++) { + *yd++ = sGetk(kernel, ((yy << shift) - dy) * a / ay, a, shift); + *yd++ = minmax(sy + yy, 0, isz.cy - 1) + sr.top; } - if(w) - if(hasalpha) { - t->a = alpha = Saturate255(alpha / w); - t->r = clamp(red / w, 0, alpha); - t->g = clamp(green / w, 0, alpha); - t->b = clamp(blue / w, 0, alpha); + RGBA *t = ib[y]; + for(int x = 0; x < sz.cx; x++) { + int red = 0; + int green = 0; + int blue = 0; + int alpha = 0; + int w = 0; + yd = py; + int hasalpha = 0; + for(int yy = 2 * ay; yy-- > 0;) { + int ky = *yd++; + const RGBA *l = img[*yd++]; + for(int xx = 2 * ax; xx-- > 0;) { + const RGBA& s = l[*xd++]; + int weight = ky * *xd++; + red += weight * s.r; + green += weight * s.g; + blue += weight * s.b; + alpha += weight * s.a; + hasalpha |= s.a - 255; + w += weight; + } } - else { - t->a = 255; - t->r = Saturate255(red / w); - t->g = Saturate255(green / w); - t->b = Saturate255(blue / w); - } - else - t->a = t->r = t->g = t->b = 0; - t++; + if(w) + if(hasalpha) { + t->a = alpha = Saturate255(alpha / w); + t->r = clamp(red / w, 0, alpha); + t->g = clamp(green / w, 0, alpha); + t->b = clamp(blue / w, 0, alpha); + } + else { + t->a = 255; + t->r = Saturate255(red / w); + t->g = Saturate255(green / w); + t->b = Saturate255(blue / w); + } + else + t->a = t->r = t->g = t->b = 0; + t++; + } } - } + }); ib.SetResolution(img.GetResolution()); return ib; } Image RescaleFilter(const Image& img, Size sz, double (*kfn)(double x), int a, - Gate progress) + Gate progress, bool co) { - return RescaleFilter(img, sz, img.GetSize(), kfn, a, progress); + return RescaleFilter(img, sz, img.GetSize(), kfn, a, progress, co); } Image RescaleFilter(const Image& img, int cx, int cy, double (*kfn)(double x), int a, - Gate progress) + Gate progress, bool co) { - return RescaleFilter(img, Size(cx, cy), img.GetSize(), kfn, a, progress); + return RescaleFilter(img, Size(cx, cy), img.GetSize(), kfn, a, progress, co); } static double sNearest(double x) @@ -224,7 +227,7 @@ static double sCostello(double x) 0; } -Image RescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate progress) +Image RescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate progress, bool co) { if(IsNull(filter)) return Rescale(img, sz, sr); @@ -241,7 +244,7 @@ Image RescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate< { sLanczos5, 5 }, }; ASSERT(filter >= FILTER_NEAREST && filter <= FILTER_LANCZOS5); - return RescaleFilter(img, sz, sr, tab[filter].a, tab[filter].b, progress); + return RescaleFilter(img, sz, sr, tab[filter].a, tab[filter].b, progress, co); } Image RescaleFilter(const Image& img, Size sz, int filter, Gate progress) @@ -254,4 +257,37 @@ Image RescaleFilter(const Image& img, int cx, int cy, int filter, Gate return RescaleFilter(img, Size(cx, cy), filter, progress); } +Image CoRescaleFilter(const Image& img, Size sz, const Rect& sr, int filter, Gate progress) +{ + return RescaleFilter(img, sz, sr, filter, progress, true); +} + +Image CoRescaleFilter(const Image& img, Size sz, int filter, Gate progress) +{ + return CoRescaleFilter(img, sz, img.GetSize(), filter, progress); +} + +Image CoRescaleFilter(const Image& img, int cx, int cy, int filter, Gate progress) +{ + return CoRescaleFilter(img, Size(cx, cy), filter, progress); +} + + +// Obsolete functions + +Image RescaleBicubic(const Image& img, Size sz, const Rect& sr, Gate progress) +{ + return RescaleFilter(img, sz, sr, FILTER_BICUBIC_MITCHELL, progress); +} + +Image RescaleBicubic(const Image& img, int cx, int cy, Gate progress) +{ + return RescaleBicubic(img, Size(cx, cy), img.GetSize(), progress); +} + +Image RescaleBicubic(const Image& img, Size sz, Gate progress) +{ + return RescaleBicubic(img, sz, img.GetSize(), progress); +} + } diff --git a/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp b/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp index 6f2d4a194..f70337709 100644 --- a/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp +++ b/uppsrc/Draw/src.tpp/ImageMaker_en-us.tpp @@ -1,5 +1,4 @@ topic "ImageMaker - image cache system"; -[2 $$0,0#00000000000000000000000000000000:Default] [i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class] [l288;2 $$2,2#27521748481378242620020725143825:desc] [0 $$3,0#96390100711032703541132217272105:end] @@ -9,6 +8,7 @@ topic "ImageMaker - image cache system"; [l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param] [i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam] [b42;2 $$9,9#13035079074754324216151401829390:normal] +[2 $$0,0#00000000000000000000000000000000:Default] [{_} [ {{10000@(113.42.0) [s0;%% [*@7;4 ImageMaker `- image cache system]]}}&] [s1;@(0.0.255)3 &] @@ -138,4 +138,8 @@ onst]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 src])&] [s2;%% Doubles the resolution of image, using smart heuristics algorithm designed for upscaling synthetic images (like icons).&] [s3;%% &] -[s0;%% ]] \ No newline at end of file +[s4; &] +[s5;:Upp`:`:Downscale2x`(const Upp`:`:Image`&`): [_^Upp`:`:Image^ Image]_[* Downscale2x]( +[@(0.0.255) const]_[_^Upp`:`:Image^ Image][@(0.0.255) `&]_[*@3 src])&] +[s2;%% Halves the resolution of image.&] +[s3;%% ]] \ No newline at end of file