рдбреА рдореЗрдВ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдЫрд╡рд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг

рдЫрд╡рд┐

рдореИрдВрдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЕрдкрдиреЗ рдбреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рдкреИрдХреЗрдЬ рдХрд╛ рдХрд╛рдо рдкреВрд░рд╛ рдХрд┐рдпрд╛ рд╣реИред Std.algorithm рдФрд░ std.range рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реЛрдХрд░, рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рдХреНрд╖реНрдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА:


рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рд╢реБрд░реВ, рдЫрд╡рд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдкреИрдХреЗрдЬ рдХреЗ рд╕рднреА рдШрдЯрдХреЛрдВ рдХреЛ рд░рдВрдЧ рдкреНрд░рдХрд╛рд░ рджреНрд╡рд╛рд░рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрд╣ рдЧреНрд░рд╛рдлрд┐рдХ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдорд╛рдирдХ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ - рд╕рдмрд╕реЗ рдЕрдореВрд░реНрдд рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреА рдЫрд╡рд┐ рдХрд╛ рд░рдВрдЧ рдУрдУрдкреА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реИ, рдпрд╛ рдмрд╕ рд╕рднреА рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдПрдХ рдПрдХрд▓ рдкрд┐рдХреНрд╕реЗрд▓ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВ, рдЬреЛ рд╡реЗ рдЖрдЧреЗ рд╕реНрдореГрддрд┐ рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдзрд┐рдХрд╛рдВрд╢ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рд╕реНрдореГрддрд┐ рдФрд░ рд╕рдордп рдХреА рдмрд░реНрдмрд╛рджреА рд╣реИ, рдЖрдорддреМрд░ рдкрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рдкрддрд╛ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЫрд╡рд┐ рдХреЛ рдХрд┐рд╕ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рдЙрди рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЬрд╣рд╛рдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдЧреНрд░рд╛рдлрд┐рдХ рдбреЗрдЯрд╛ рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЧреНрд░рд╛рдл рд╕рдВрдкрд╛рджрдХреЛрдВ)ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдореЗрд░реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд░рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рднреА рдЫрд╡рд┐ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд░рддреА рд╣реИред

рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкрд░ рдХрд╛рдо рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рд╕реЗ рдореИрдВ рдмрд╣реБрдд рдЦреБрд╢ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рдмрд┐рдВрджреБрдУрдВ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред





рдкреБрд╕реНрддрдХрд╛рд▓рдп рджреГрд╢реНрдп рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ:
///  ,    width, height ///       ///    enum isView(T) = is(typeof(T.init.w) : size_t) && // width is(typeof(T.init.h) : size_t) && // height is(typeof(T.init[0, 0]) ); // color information 


рд╕реНрдерд┐рд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдпрд╣ рддрд░реАрдХрд╛ рд╡рд╣реА рд╣реИ рдЬреЛ std.range рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, InInputRange ред OOP рдХреЗ рдЕрд░реНрде рдореЗрдВ рд╕рдорд╛рди рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, D рдореЗрдВ рд╕реНрдерд┐рд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд╕рд╢рд░реНрдд рд░реВрдк рд╕реЗ рдХреБрдЫ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ (рд▓рдЧрднрдЧ рдбрдХ рдЯрд╛рдЗрдкрд┐рдВрдЧ ) рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рддреНрдпрд╛рдкрди рд╕рдлрд▓ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рд╕рдВрдЪрд╛рд▓рди рдЬрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рд╡рд╣ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд┐рдирд╛ рд╕рдВрдХрд▓рд┐рдд рд╣реИ рдпрд╛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рд╣реИред рдЖрдорддреМрд░ рдкрд░, рдЗрд╕рдХреЗ рд▓рд┐рдП IsExpression рдпрд╛ trait compiles рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

Std.range.ElementType рдХреЗ рд╕рдорд╛рди , рд╣рдо рдкрд┐рдХреНрд╕реЗрд▓ рдХреЗ рд░рдВрдЧ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
 ///     view alias ViewColor(T) = typeof(T.init[0, 0]); 


рдЕрдЧрд▓рд╛, рд╣рдо рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛рдУрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
рдХреЛрдб
 /// Views    ///    enum isWritableView(T) = isView!T && is(typeof(T.init[0, 0] = ViewColor!T.init)); ///  view   ///    . ///  views  "direct views" enum isDirectView(T) = isView!T && is(typeof(T.init.scanline(0)) : ViewColor!T[]); 



рдлрд┐рд░, рдпрд╣ isForwardRange рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд╕рдорд╛рди рд╣реИ : рдпрд╣ рдЬрд╛рдБрдЪрдирд╛ рдХрд┐ рдкреНрд░рдХрд╛рд░ рд╕рднреА рдмреБрдирд┐рдпрд╛рджреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рдЗрд╕ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮрддрд╛ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИрдВред

рдЪреВрдВрдХрд┐ рдкрд┐рдХреНрд╕рд▓ рддрдХ рд╕реАрдзреА рдкрд╣реБрдВрдЪ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╕реНрдХреИрдирд▓рд╛рдЗрди рдкреНрд░рддреНрдпрдХреНрд╖ рджреГрд╢реНрдп рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд┐рд╢реНрд░рдг рдХреА рдШреЛрд╖рдгрд╛ рдХрд░реЗрдВ:
рдХреЛрдб
 /// ,    view ///     direct view mixin template DirectView() { alias COLOR = typeof(scanline(0)[0]); ///   view[x, y] ref COLOR opIndex(int x, int y) { return scanline(y)[x]; } ///   view[x, y] = c COLOR opIndexAssign(COLOR value, int x, int y) { return scanline(y)[x] = value; } } 



рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдЫрд╡рд┐ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ рдЬреЛ рд╕реНрдореГрддрд┐ рдореЗрдВ рдПрдХ рдЫрд╡рд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ:
рдХреЛрдб
 ///    ///      struct Image(COLOR) { int w, h; COLOR[] pixels; ///     y COLOR[] scanline(int y) { assert(y>=0 && y<h); return pixels[w*y..w*(y+1)]; } mixin DirectView; this(int w, int h) { size(w, h); } ///     void size(int w, int h) { this.w = w; this.h = h; if (pixels.length < w*h) pixels.length = w*h; } } 



рдбреА рдореЗрдВ рдПрд░рд░реНрд╕ рдХреЛ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдФрд░ рд▓рдВрдмрд╛рдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдФрд░ рдХреЗрд╡рд▓ рдореЗрдореЛрд░реА рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╕рдордп рд╡рд┐рд╕реНрддрд╛рд░ рдпрд╛ рдПрдХ рд╕рд╛рде рдЪрд┐рдкрдХреЗ рд╣реБрдП), рдЗрд╕рд▓рд┐рдП рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкрд┐рдХреНрд╕рд▓ [w * y ... w * (y + 1)] рд╕рд░рдгреА рдХреА рдПрдХ рдкреНрд░рддрд┐ рдирд╣реАрдВ рдмрдирд╛рддрд╛ рд╣реИред

рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рд╕рдВрдХрд▓рди рд╕рдордп рдкрд░ рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЫрд╡рд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ isDirectView рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рд╢рд░реНрддреЛрдВ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддреА рд╣реИ:
 unittest { static assert(isDirectView!(Image!ubyte)); } 





рддреЛ рд╣рдо рдЗрд╕ рдореЙрдбрд▓ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЙрди рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд┐рдХреНрд╕реЗрд▓ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЙрдиреНрд╣реЗрдВ рдорд╛рдВрдЧ рдкрд░ рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ:
рдХреЛрдб
 ///  view,    ///       template procedural(alias formula) { alias fun = binaryFun!(formula, "x", "y"); alias COLOR = typeof(fun(0, 0)); auto procedural(int w, int h) { struct Procedural { int w, h; auto ref COLOR opIndex(int x, int y) { return fun(x, y); } } return Procedural(w, h); } } 



рдПрдХ рд╣реА рдирд╛рдо рдХрд╛ рдпрд╣ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ (рдЬрд┐рд╕реЗ рдорд┐рд╢реНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛) рдХреЛ рдПрдХ рд╡рд┐рдзреЗрдп рдпрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐ (рд▓реИрдореНрдмреНрдбрд╛) рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП std.functional.binaryFun рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рдСрдЯреЛ рд╣реИ рдФрд░ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рдШреЛрд╖рд┐рдд рд╕рдВрд░рдЪрдирд╛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ Voldemort рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИред

рдПрдХ рд░рдВрдЧ рд╕реЗ рднрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рдЫрд╡рд┐ рдХрд╛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг:
 ///  view,   ///     auto solid(COLOR)(COLOR c, int w, int h) { return procedural!((x, y) => c)(w, h); } 


рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреИрд╕реЗ рд▓реМрдЯрд╛ рд╣реБрдЖ рджреГрд╢реНрдп рдХрд╛ рд░рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рдХрд╛рд░ c рд╕реЗ рдЕрдиреБрдорд╛рдирд┐рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рдареЛрд╕ (RGB (1, 2, 3), 10, 10) RGB рдкрд┐рдХреНрд╕реЗрд▓ рд╕реЗ рджреГрд╢реНрдп рд▓реМрдЯрд╛рдПрдЧрд╛, рднрд▓реЗ рд╣реА рдЙрд╕рдХреЗ рдкрд╛рд╕ рдкреВрд░реНрдг рд░реВрдк рд╕реЗ рдпреЛрдЧреНрдп рдирд╛рдо рди рд╣реЛред




рдЗрд╕ рдореЙрдбрд▓ рдореЗрдВ рдПрдХ рдФрд░ рдЪреАрдЬ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЛрдВ рд╕реЗ рдЕрдиреНрдп рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рд╡рд╛рд▓реЗ рд╡рд┐рдЪрд╛рд░ рдкреИрджрд╛ рдХрд░ рд░рд╣рд╛ рд╣реИред рдЖрдорддреМрд░ рдкрд░ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдорд┐рдХреНрд╕рд┐рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
рдХреЛрдб
 /// ,   view   ///  view,    ///  mixin template Warp(V) { V src; auto ref ViewColor!V opIndex(int x, int y) { warp(x, y); return src[x, y]; } static if (isWritableView!V) ViewColor!V opIndexAssign(ViewColor!V value, int x, int y) { warp(x, y); return src[x, y] = value; } } 



рдЖрдЗрдП рд╕реНрдереИрддрд┐рдХ рдХреЛ рджреЗрдЦреЗрдВ рдпрджрд┐ (isWritableView! V) рд░реЗрдЦрд╛ , рдЬреЛ рдХрд╣рддреА рд╣реИ рдХрд┐ рджреГрд╢реНрдп [x, y] = c рдХрдерди рдХреЛ рдХреЗрд╡рд▓ рддрднреА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдпрджрд┐ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рджреГрд╢реНрдп рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдХреБрд▓ рд▓рд┐рдкрдЯрд╛ рд╣реБрдЖ рджреГрд╢реНрдп рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рд╣реЛрдЧрд╛ рддрднреА рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рджреГрд╢реНрдп рднреА рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдПрдХ рдХреНрд░реЙрдкрд┐рдВрдЧ рджреГрд╢реНрдп рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рджреВрд╕рд░реЗ рджреГрд╢реНрдп рдХреЗ рдЖрдпрддрд╛рдХрд╛рд░ рдЯреБрдХрдбрд╝реЗ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ:
рдХреЛрдб
 ///  view    auto crop(V)(auto ref V src, int x0, int y0, int x1, int y1) if (isView!V) { assert( 0 <= x0 && 0 <= y0); assert(x0 < x1 && y0 < y1); assert(x1 <= src.w && y1 <= src.h); static struct Crop { mixin Warp!V; int x0, y0, x1, y1; @property int w() { return x1-x0; } @property int h() { return y1-y0; } void warp(ref int x, ref int y) { x += x0; y += y0; } static if (isDirectView!V) ViewColor!V[] scanline(int y) { return src.scanline(y0+y)[x0..x1]; } } static assert(isDirectView!V == isDirectView!Crop); return Crop(src, x0, y0, x1, y1); } 



рдЕрдЧрд░ (isView! V) рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдмрд╛рдзрд╛ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкрд╣рд▓рд╛ рддрд░реНрдХ isView рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рд╢рд░реНрддреЛрдВ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред

рдкрд╣рд▓реЗ рдХреА рддрд░рд╣, рдлрд╕рд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ .DirectView рдкрд┐рдХреНрд╕рд▓ рддрдХ рд╕реАрдзреЗ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЕрдЧрд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЫрд╡рд┐ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреА рд╣реИред рдПрдХ рд╕рдордп рдореЗрдВ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкрд┐рдХреНрд╕реЗрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдбрд╛рдпрд░реЗрдХреНрдЯ рдкрд┐рдХреНрд╕реЗрд▓ рдПрдХреНрд╕реЗрд╕ рдЙрдкрдпреЛрдЧреА рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдЕрдиреБрдХреНрд░рдорд┐рдХ рдПрдХреНрд╕реЗрд╕ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╡реГрджреНрдзрд┐ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдПрдХ рдЫрд╡рд┐ рдХреЛ рджреВрд╕рд░реЗ рдореЗрдВ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдкрд┐рдХреНрд╕реЗрд▓ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд▓рд╛рдЗрд╕ рдкреНрд░рддрд┐рдпрд╛рдВ (рдбреА рдореЗрдВ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рдореИрд╕реНрдХреИрдкреА рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрд╣реБрдд рддреЗрдЬ рд╣реЛрддрд╛ рд╣реИ:
рдХреЛрдб
 ///   view  . /// Views    . void blitTo(SRC, DST)(auto ref SRC src, auto ref DST dst) if (isView!SRC && isWritableView!DST) { assert(src.w == dst.w && src.h == dst.h, "View size mismatch"); foreach (y; 0..src.h) { static if (isDirectView!SRC && isDirectView!DST) dst.scanline(y)[] = src.scanline(y)[]; else { foreach (x; 0..src.w) dst[x, y] = src[x, y]; } } } 



рдлрд╕рд▓ рдХреЗ рд╕рдорд╛рди рд╡рд┐рдЪрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕реА рдРрд╕реЗ рджреГрд╢реНрдп рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдирд┐рдХрдЯрддрдо рдкрдбрд╝реЛрд╕реА рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд┐рд╕реА рдЕрдиреНрдп рджреГрд╢реНрдп рдпрд╛ рддрд░рд╛рдЬреВ рдХреЛ рдЯрд╛рдЗрд▓ рдХрд░рддрд╛ рд╣реИ (рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдмреЗрд╣рддрд░ рд╢реИрд▓реА рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдХреЛрдб рдмрд╣реБрдд рдлрд╕рд▓ рдХреЗ рд╕рдорд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдпрд╣рд╛рдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реВрдВред

рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рдлрд╕рд▓ рд╕реНрд░реЛрдд рдХреЛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддреА рд╣реИ, рддреЛ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЗрдЪреНрдЫрд┐рдд рдЙрдкрдпреЛрдЧ рдФрд░ рдРрд╕рд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рдпрд╣ рдореВрд▓ рджреГрд╢реНрдп рдХреА рд╡рд┐рдзрд┐ рдереА: someView.nearestNeighbor (100, 100) .tile (1000, 1000) .crop (50, 50, 950)ред 950) рд╣реИ ред рдпрд╣ рд╕рдВрднрд╛рд╡рдирд╛ "рдпреВрдирд┐рдлреЙрд░реНрдо рдлрдВрдХреНрд╢рди рдХреЙрд▓ рд╕рд┐рдВрдЯреЗрдХреНрд╕" (рдпрд╛ рдмрд╕ рдпреВрдПрдлрд╕реАрдПрд╕) рдирд╛рдордХ рднрд╛рд╖рд╛ рдХреА рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдХрд╛рд░рдг рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рдорд╕реНрддреА (рдП, рдмреА ...) рдХреЗ рдмрдЬрд╛рдп a.fun (b ...) рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рдореБрдЦреНрдп рд▓рд╛рдн рдлрд╝рд╛рдЗрдирд┐рдВрдЧ 3 (fun2 (рдлрд╝рди 1 (рдП )) рдХреЗ рдмрдЬрд╛рдп рдлрд╝рд╛рдЗрдирд┐рдВрдЧ (a.fun1 ()ред рдлрди 2 (), рдлрд╝рди 3 () рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдлрд╝реЗрдУрд╕ рдореЗрдВ рдФрд░ рдЗрд╕ рдкреИрдХреЗрдЬ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред




рд╕рд╛рдзрд╛рд░рдг рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд▓рд┐рдП, рдЬрд┐рд╕рдореЗрдВ рджреГрд╢реНрдп рдЖрдХрд╛рд░ рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рд╣рдо рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддреНрдпреЗрдХ рдкрд┐рдХреНрд╕реЗрд▓ рд╕рдордиреНрд╡рдп рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реВрддреНрд░ рдХреЗ рдЖрд╡реЗрджрди рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИ:
рдХреЛрдб
 ///  view    ///    template warp(string xExpr, string yExpr) { auto warp(V)(auto ref V src) if (isView!V) { static struct Warped { mixin Warp!V; @property int w() { return src.w; } @property int h() { return src.h; } void warp(ref int x, ref int y) { auto nx = mixin(xExpr); auto ny = mixin(yExpr); x = nx; y = ny; } private void testWarpY()() { int y; y = mixin(yExpr); } ///  x     y   ///  x,      scanlines. static if (xExpr == "x" && __traits(compiles, testWarpY()) && isDirectView!V) ViewColor!V[] scanline(int y) { return src.scanline(mixin(yExpr)); } } return Warped(src); } } 



рддрд╛рдирд╛ рдкрд╛рд░рд┐рдд рд╕реВрддреНрд░реЛрдВ рдХреЛ рдорд╛рдиреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреНрд░рд┐рдХреА рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред TestWarpY рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╢реВрдиреНрдп рдЯреЗрдореНрдкрд▓реЗрдЯ рддрд░реНрдХ рдХреЗ рд╕рд╛рдеред рдпрд╣ рд╕рдВрдХрд▓рдХ рдХреЛ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╢рд░реАрд░ рдХреЗ рд╢рдмреНрджрд╛рд░реНрде рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдЪреВрдВрдХрд┐ рдЗрд╕рдореЗрдВ рд╕реНрдХреЛрдк x рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдХреЗрд╡рд▓ рддрднреА рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм yExpr x рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ __traits (рд╕рдВрдХрд▓рди, testWrapY ()) рд╕рд┐рд░реНрдл рдпрд╣ рдЬрд╛рдВрдЪрддрд╛ рд╣реИред рдпрд╣ рд╕рдм рд╣рдореЗрдВ рдПрдХ рдкреНрд░рддреНрдпрдХреНрд╖ рджреГрд╢реНрдп рд╕реНрдХреИрдирд▓рд╛рдЗрди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХреЗрд╡рд▓ рдЕрдЧрд░ рд╣рдореЗрдВ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рд╣рдо рдЗрд╕реЗ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рдЙрджрд╛рд╣рд░рдг:
рдХреЛрдб
 ///  view    x alias hflip = warp!(q{wx-1}, q{y}); ///  view    y alias vflip = warp!(q{x}, q{hy-1}); ///  view    x  y alias flip = warp!(q{wx-1}, q{hy-1}); 



рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП q {...} рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗрд╡рд▓ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдорддреМрд░ рдкрд░ рдбреА рдХреЛрдб рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рддрдм рдХрд╣реАрдВ рдкрд░ рдорд┐рд╢реНрд░рд┐рдд рд╣реЛрддрд╛ рд╣реИред рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдорд┐рд╢реНрд░рдг рдореЗрдВ рд╕рднреА рд╡рд░реНрдгреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ - рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рддрд╛рдирд╛ рдХрд╛рд░реНрдп рдФрд░ рд▓рд┐рдкрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рддрд░реАрдХрд╛ рд╣реИред

рдЪреВрдВрдХрд┐ vflip рдПрдХ рд╕реНрдХреИрдирд▓рд╛рдЗрди рд╡рд┐рдзрд┐ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкрд╣рд▓реЗ рджреЛ рд╢рд░реНрддреЛрдВ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ, рддреЛ someView.vflip () рдПрдХ рдкреНрд░рддреНрдпрдХреНрд╖ рджреГрд╢реНрдп рд╣реЛрдЧрд╛, рдЕрдЧрд░ рдХреБрдЫ рджреГрд╢реНрдп рдПрдХ рд╣реИ ред рдФрд░ рдпрд╣ vflip рд╡рд┐рдЬреНрдЮрд╛рдкрди рдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд╕рддреНрдпрд╛рдкрди рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЪреВрдВрдХрд┐ рдЕрдореВрд░реНрдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧрддрд┐рд╢реАрд▓ рдмрд╣реБрд░реВрдкрддрд╛ рдкрд░ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд╕рдВрдХрд▓рдХ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрди рдкрд░рддреЛрдВ рдХреА рдХреЙрд▓ рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рд╣реИред рджреЛ рдмрд╛рд░ рдПрдХ рдЫрд╡рд┐ рдбрд╛рд▓рдиреЗ рд╕реЗ рдПрдХ рдСрдкрд░реЗрд╢рди рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореИрдВ [5, 5] рдФрд░ i.hipip ()ред Hflip () [5, 5] рдПрдХ рд╣реА рдорд╢реАрди рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реВрдВ ред рдПрдХ рдмреЗрд╣рддрд░ рдмреИрдХрдПрдВрдб рдХреЗ рд╕рд╛рде рдбреА рдХрдВрдкрд╛рдЗрд▓рд░ рдФрд░ рднреА рдЕрдзрд┐рдХ рдЖрдХреНрд░рд╛рдордХ рдЕрдиреБрдХреВрд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдлреНрд▓рд┐рдкрдПрдХреНрд╕рд╡рд╛рдИ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХреНрд╕ рдФрд░ рд╡рд╛рдИ рдПрдХреНрд╕рд┐рд╕ рдХреЛ рдЗрдиреНрд╡рд░реНрдЯ рдХрд░рддрд╛ рд╣реИ , рдФрд░ рд░реЛрдЯреНрд░реЗрдХреНрдЯ рдбрдмреНрд▓реНрдпреВрдбрдмреНрд▓реНрдпреВ (рдЫрд╡рд┐ 90 рдбрд┐рдЧреНрд░реА рд╡рд╛рдорд╛рд╡рд░реНрдд рдШреБрдорд╛рдПрдБ) рдХреЛ рдЖрд░рдЖрд░.рдПрдлрдПрд▓рдПрдХреНрд╕рдПрдХреНрд╕рд╡рд╛рдИрд╡рд╛рдИ () рдХреЗ рд░реВрдк рдореЗрдВред , рдлрд┐рд░ рдЕрдиреБрдХреВрд▓рди рдХреЗ рджреМрд░рд╛рди рдЪрд╛рд░ рд╕рдлрд▓ рд░реЛрдЯреИрдХрдбрдмреНрд▓реНрдпреВ рдХреЙрд▓ рдХрд╛рдЯ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред




рдЪрд▓реЛ рдкрд┐рдХреНрд╕реЗрд▓ рдкрд░ рд╕реНрд╡рдпрдВ рдСрдкрд░реЗрд╢рди рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВред Std.al рдПрд▓реНрдЧреЛрд░рд┐рдердо рдореЗрдВ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдорд╛рдирдЪрд┐рддреНрд░ рд╣реИ , рдЬреЛ рдПрдХ рд╕реАрдорд╛ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдЖрд▓рд╕реА рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реАрдорд╛ рдкрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рд╣рдорд╛рд░рд╛ colorMap рд░рдВрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:
рдХреЛрдб
 ///  view,    ///     view. template colorMap(alias pred) { alias fun = unaryFun!(pred, false, "c"); auto colorMap(V)(auto ref V src) if (isView!V) { alias OLDCOLOR = ViewColor!V; alias NEWCOLOR = typeof(fun(OLDCOLOR.init)); struct Map { V src; @property int w() { return src.w; } @property int h() { return src.h; } auto ref NEWCOLOR opIndex(int x, int y) { return fun(src[x, y]); } } return Map(src); } } 



ColorMap рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛, рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЫрд╡рд┐ рдХреЗ рд░рдВрдЧреЛрдВ рдХреЛ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХрд░рддрд╛ рд╣реИ:
 alias invert = colorMap!q{~c}; 


colorMap рдХреЛ рд╕реНрд░реЛрдд рд░рдВрдЧ рдкреНрд░рдХрд╛рд░ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЗ рдорд┐рд▓рд╛рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рд░рдВрдЧ рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ: рдкрдврд╝рд╛ ("image.bmp")ред ParseBMP! RGB (ред) ColorMap! (C => BGRX (cb, cg, cr)) BGRX рджреГрд╢реНрдп рдХреЗ рд░реВрдк рдореЗрдВ RGB рдмрд┐рдЯрдореИрдк рд▓реМрдЯрд╛рдПрдЧрд╛ред



рдЫрд╡рд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдмрд╣реБрдд рдмрд╛рд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЙрдзрд╛рд░ рджреЗрддрд╛ рд╣реИ ред std.parallelism рд╕рдорд╛рдирд╛рдВрддрд░ рдЫрд╡рд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдХрд╛рд░реНрдп рдХреЛ рддреБрдЪреНрдЫ рдмрдирд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ:
рдХреЛрдб
 ///  view    ///  fun    /// . ///   , ///    , ///  vjoin  vjoiner. template parallel(alias fun) { auto parallel(V)(auto ref V src, size_t chunkSize = 0) if (isView!V) { auto processSegment(R)(R rows) { auto y0 = rows[0]; auto y1 = y0 + rows.length; auto segment = src.crop(0, y0, src.w, y1); return fun(segment); } import std.range : iota, chunks; import std.parallelism : taskPool, parallel; if (!chunkSize) chunkSize = taskPool.defaultWorkUnitSize(src.h); auto range = src.h.iota.chunks(chunkSize); alias Result = typeof(processSegment(range.front)); auto result = new Result[range.length]; foreach (n; range.length.iota.parallel(1)) result[n] = processSegment(range[n]); return result; } } 


рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдирд╛ рдирд╛рдо рд╕рд╛рдЭрд╛ рдХрд░рддрд╛ рд╣реИ рдЬреЛ std.parallelism рдореЗрдВ рдореМрдЬреВрдж рд╣реИрдВ, рддреЛ рдХреЛрдИ рд╕рдВрдШрд░реНрд╖ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реИрдВ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

рдЗрд╕реА рд╕рдордп, рдСрдкрд░реЗрд╢рди рдХреЛ рдХрдИ рдереНрд░реЗрдбреНрд╕ рдХреЗ рдмреАрдЪ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ image.process () рдХреЛ image.parallel - (рд╕реЗрдЧрдореЗрдВрдЯ => рд╕реЗрдЧрдореЗрдВрдЯредрдкреНрд░реЛрд╕реЗрд╕рд░ ) ()) рдХреЗ рд╕рд╛рде рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред Vjoin () ред




рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЙрджрд╛рд╣рд░рдг:





рдЯреЗрдореНрдкрд▓реЗрдЯ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдмрдбрд╝реЗ рд▓рд╛рдн рдХрд╛ рд╡рд╛рджрд╛ рдХрд░рддрд╛ рд╣реИред рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ, рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕рднреА рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рдкреИрдорд╛рдиреЗ рдХреЛ 25% рддрдХ рдХрдо рдХрд░рддрд╛ рд╣реИ:
рдХреЛрдб
 import std.file; import std.path; import std.stdio; import ae.utils.graphics.color; import ae.utils.graphics.gamma; import ae.utils.graphics.image; void main() { alias BGR16 = Color!(ushort, "b", "g", "r"); auto gamma = GammaRamp!(ushort, ubyte)(2.2); foreach (de; dirEntries("input", "*.bmp", SpanMode.shallow)) { static Image!BGR scratch1; static Image!BGR16 scratch2, scratch3; de .read .parseBMP!BGR(scratch1) .parallel!(segment => segment .pix2lum(gamma) .copy(scratch2) .downscale!4(scratch3) .lum2pix(gamma) .copy )(4) .vjoin .toBMP .toFile(buildPath("output-d", de.baseName)); } } 



рдореИрдВрдиреЗ рдмрд░рд╛рдмрд░ ImageMagick рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреА рддреБрд▓рдирд╛ рдХреА:
 convert \ input/*.bmp \ -depth 16 \ -gamma 0.454545 \ -filter box \ -resize 25% \ -gamma 2.2 \ -depth 8 \ output-im/%02d.bmp 


рд╡рд░реНрдЬрди рдбреА 4-5 рдЧреБрдирд╛ рддреЗрдЬ рдЪрд▓рддрд╛ рд╣реИред рдмреЗрд╢рдХ, рдпрд╣ рдПрдХ рдЕрдиреБрдЪрд┐рдд рддреБрд▓рдирд╛ рд╣реИ: рднрд▓реЗ рд╣реА рджреЛрдиреЛрдВ 16-рдмрд┐рдЯ рд░рдВрдЧ рдЧрд╣рд░рд╛рдИ, рдЧрд╛рдорд╛ рд╕реБрдзрд╛рд░, рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╣реА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рдбреА рдкреНрд░реЛрдЧреНрд░рд╛рдо рдореЗрдВ рдХреЛрдб рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рд╣реЛрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╡рд┐рднрд┐рдиреНрди JIT рддрдХрдиреАрдХреЛрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдкреИрдХреЗрдЬ рдХреА рддреБрд▓рдирд╛ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдпреЛрдЬрди рдЫрд╡рд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рд╕реЗ рдирд╣реАрдВ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред




GitHub рдкрд░ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рдкреИрдХреЗрдЬ рдЙрдкрд▓рдмреНрдз рд╣реИ ред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдЙрдирдХреЗ рдпреЛрдЧрджрд╛рди рдХреЗ рд▓рд┐рдП рдбреЗрд╡рд┐рдб рдПрд▓реНрд╕рд╡рд░реНрде рдХрд╛ рдзрдиреНрдпрд╡рд╛рджред

Source: https://habr.com/ru/post/In218429/


All Articles