Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
116
Task/Image-convolution/D/image-convolution.d
Normal file
116
Task/Image-convolution/D/image-convolution.d
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import std.string, std.math, std.algorithm, grayscale_image;
|
||||
|
||||
struct ConvolutionFilter {
|
||||
double[][] kernel;
|
||||
double divisor, offset_;
|
||||
string name;
|
||||
}
|
||||
|
||||
|
||||
Image!Color convolve(Color)(in Image!Color im,
|
||||
in ConvolutionFilter filter)
|
||||
pure nothrow in {
|
||||
assert(im !is null);
|
||||
assert(!filter.divisor.isNaN && !filter.offset_.isNaN);
|
||||
assert(filter.divisor != 0);
|
||||
assert(filter.kernel.length > 0 && filter.kernel[0].length > 0);
|
||||
foreach (const row; filter.kernel) // Is rectangular.
|
||||
assert(row.length == filter.kernel[0].length);
|
||||
assert(filter.kernel.length % 2 == 1); // Odd sized kernel.
|
||||
assert(filter.kernel[0].length % 2 == 1);
|
||||
assert(im.ny >= filter.kernel.length);
|
||||
assert(im.nx >= filter.kernel[0].length);
|
||||
} out(result) {
|
||||
assert(result !is null);
|
||||
assert(result.nx == im.nx && result.ny == im.ny);
|
||||
} body {
|
||||
immutable knx2 = filter.kernel[0].length / 2;
|
||||
immutable kny2 = filter.kernel.length / 2;
|
||||
auto io = new Image!Color(im.nx, im.ny);
|
||||
|
||||
static if (is(Color == RGB))
|
||||
alias CT = typeof(Color.r); // Component type.
|
||||
else static if (is(typeof(Color.c)))
|
||||
alias CT = typeof(Color.c);
|
||||
else
|
||||
alias CT = Color;
|
||||
|
||||
foreach (immutable y; kny2 .. im.ny - kny2) {
|
||||
foreach (immutable x; knx2 .. im.nx - knx2) {
|
||||
static if (is(Color == RGB))
|
||||
double[3] total = 0.0;
|
||||
else
|
||||
double total = 0.0;
|
||||
|
||||
foreach (immutable sy, const kRow; filter.kernel) {
|
||||
foreach (immutable sx, immutable k; kRow) {
|
||||
immutable p = im[x + sx - knx2, y + sy - kny2];
|
||||
static if (is(Color == RGB)) {
|
||||
total[0] += p.r * k;
|
||||
total[1] += p.g * k;
|
||||
total[2] += p.b * k;
|
||||
} else {
|
||||
total += p * k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
immutable D = filter.divisor;
|
||||
immutable O = filter.offset_ * CT.max;
|
||||
static if (is(Color == RGB)) {
|
||||
io[x, y] = Color(
|
||||
cast(CT)min(max(total[0]/ D + O, CT.min), CT.max),
|
||||
cast(CT)min(max(total[1]/ D + O, CT.min), CT.max),
|
||||
cast(CT)min(max(total[2]/ D + O, CT.min), CT.max));
|
||||
} else static if (is(typeof(Color.c))) {
|
||||
io[x, y] = Color(
|
||||
cast(CT)min(max(total / D + O, CT.min), CT.max));
|
||||
} else {
|
||||
// If Color doesn't have a 'c' field, then Color is
|
||||
// assumed to be a built-in type.
|
||||
io[x, y] =
|
||||
cast(CT)min(max(total / D + O, CT.min), CT.max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
immutable ConvolutionFilter[] filters = [
|
||||
{[[-2.0, -1.0, 0.0],
|
||||
[-1.0, 1.0, 1.0],
|
||||
[ 0.0, 1.0, 2.0]], divisor:1.0, offset_:0.0, name:"Emboss"},
|
||||
|
||||
{[[-1.0, -1.0, -1.0],
|
||||
[-1.0, 9.0, -1.0],
|
||||
[-1.0, -1.0, -1.0]], divisor:1.0, 0.0, "Sharpen"},
|
||||
|
||||
{[[-1.0, -2.0, -1.0],
|
||||
[ 0.0, 0.0, 0.0],
|
||||
[ 1.0, 2.0, 1.0]], divisor:1.0, 0.5, "Sobel_emboss"},
|
||||
|
||||
{[[1.0, 1.0, 1.0],
|
||||
[1.0, 1.0, 1.0],
|
||||
[1.0, 1.0, 1.0]], divisor:9.0, 0.0, "Box_blur"},
|
||||
|
||||
{[[1, 4, 7, 4, 1],
|
||||
[4, 16, 26, 16, 4],
|
||||
[7, 26, 41, 26, 7],
|
||||
[4, 16, 26, 16, 4],
|
||||
[1, 4, 7, 4, 1]], divisor:273, 0.0, "Gaussian_blur"}];
|
||||
|
||||
Image!RGB im;
|
||||
im.loadPPM6("Lenna100.ppm");
|
||||
|
||||
foreach (immutable filter; filters)
|
||||
im.convolve(filter)
|
||||
.savePPM6(format("lenna_%s.ppm", filter.name));
|
||||
|
||||
const img = im.rgb2grayImage();
|
||||
foreach (immutable filter; filters)
|
||||
img.convolve(filter)
|
||||
.savePGM(format("lenna_gray_%s.ppm", filter.name));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue