public static Channel CratersAlgo(int sizeX, int sizeY, int numCraters, int seed) { Channel chan = new Channel(sizeX, sizeY); Console.WriteLine(); Random rand = new Random(seed); for (int i = 0; i < numCraters; ) { int x = rand.Next(0, sizeX); int y = rand.Next(0, sizeY); double radius = (rand.NextDouble() * 84.0) - 20; // Clamp //x=(x<0) ? 0 : ((x>size-1) ? size-1 : x); //x=(y<0) ? 0 : ((y>size-1) ? size-1 : y); //radius=(radius<20.0) ? 20.0 : ((radius>84.0) ? 84.0 : radius); Channel crater = (new Crater(sizeX, sizeY, x, y, radius)).toChannel(); if (crater.findMax() != 1.0) { continue; } //if(crater.findMin()!=0.0) //{ // Console.Write("!"); // continue; //} i++; drawTextProgressBar(i, numCraters); //crater.toLayer().saveAsPNG("../sims/crater_debug.png"); chan.channelAdd(crater.normalize(-0.01f, 0.01f)); } chan.normalize(); Console.WriteLine("\nRange [{0},{1}]", chan.findMin(), chan.findMax()); return chan; }
public static Channel HillsAlgo(int sizeX, int sizeY, int numHills, int seed) { Console.WriteLine(); Channel chan = new Channel(sizeX, sizeY); Random rand = new Random(seed); for (int i = 0; i < numHills; ) { int x = rand.Next(0, sizeX); int y = rand.Next(0, sizeY); double radius = ((rand.NextDouble() * 84.0) - 20); Channel crater = (new Hill(sizeX, sizeY, x, y, (float)radius)).toChannel(); if (crater.findMax() != 1.0) { continue; } i++; drawTextProgressBar(i, numHills); //crater.toLayer().saveAsPNG("../sims/crater_debug.png"); chan.channelAdd(crater.normalize(0f, 0.01f)); } chan.normalize(); Console.WriteLine("\nRange [{0},{1}]", chan.findMin(), chan.findMax()); return chan; }
public Layer(Channel r, Channel g, Channel b) { this.width = r.getWidth(); this.height = r.getHeight(); this.r = r; this.g = g; this.b = b; this.a = null; }
public Layer(Layer rgb, Channel a) { this.r = rgb.r; this.g = rgb.g; this.b = rgb.b; this.width = r.getWidth(); this.height = r.getHeight(); this.a = a; }
public Crater(int size,int xp,int yp,double radius) { channel = new Channel(size,size); double ratio=64f/64f; double craterdepth = 10.0f*ratio; double rimheight = 3.0f*ratio; double falloff = 60.0f*ratio; BuildCrater(xp,yp,radius,rimheight,craterdepth,falloff); }
public Layer(int width, int height) { this.width = width; this.height = height; Channel empty = new Channel(width, height); empty.fill(1f); this.r = empty; this.g = empty.copy(); this.b = empty.copy(); this.a = null; }
public RiverBuilder(Channel channel) { Directions = new int[,]{ {-1, 1},{ 0, 1},{ 1, 1}, {-1, 0}, { 1, 0}, {-1,-1},{ 0,-1},{ 1,-1} }; chan=channel; traversalCost=GetTraversalCost(); Console.WriteLine(" * River generator initialized with a {0}x{1} grid.",chan.Height,chan.Width); }
public Channel getDistance(float c1, float c2, float c3) { Channel channel = new Channel(sizeX, sizeY); for (int y = 0; y < sizeY; y++) { for (int x = 0; x < sizeX; x++) { channel.putPixel(x, y, c1*dist1.getPixel(x, y) + c2*dist2.getPixel(x, y) + c3*dist3.getPixel(x, y)); } } return channel.normalize(); }
public Layer(Channel r, Channel g, Channel b, Channel a) { this.width = r.getWidth(); this.height = r.getHeight(); if(!(g.getWidth() == width && b.getWidth() == width && g.getHeight() == height && b.getHeight() == height && (a == null || (a.getWidth() == width && a.getHeight() == height)))) throw new Exception("trying to combine channels of differing sizes"); this.r = r; this.g = g; this.b = b; this.a = a; }
public Hill(int size,int xp,int yp,float radius) { double r=(double)radius; channel = new Channel(size,size); double hill_height=5.0d*(radius/40.0d); for(int x=0;x<size;x++) { for(int y=0;y<size;y++) { double dx = (double)(yp-x); double dy = (double)(xp-y); double dist = Math.Sqrt(dx*dx + dy*dy); if(dist<radius) { double height = 1.0d-((dx*dx + dy*dy) / (r*r)); height = (height*hill_height); channel.putPixel(x,y,Convert.ToSingle(height));//$radius^2 + (($x-$hx)^2 - ($y-(256-$hy))^2); } //channel.putPixel(x,y,(radius*radius) + (((x-dx)*(x-dx)) - ((y-dy)*(y-dy)))); } } channel.normalize(); }
public Layer layerBlend(Layer rgb, Channel a) { return layerBlend(new Layer(rgb.r, rgb.g, rgb.b, a)); }
public Layer flipV() { r = r.flipV(); g = g.flipV(); b = b.flipV(); if (a != null) { a = a.flipV(); } return this; }
public Layer cropWrap(int x_lo, int y_lo, int x_hi, int y_hi) { r = r.cropWrap(x_lo, y_lo, x_hi, y_hi); g = g.cropWrap(x_lo, y_lo, x_hi, y_hi); b = b.cropWrap(x_lo, y_lo, x_hi, y_hi); if (a != null) { a = a.cropWrap(x_lo, y_lo, x_hi, y_hi); } width = r.getWidth(); height = r.getHeight(); return this; }
public Layer bumpSpecular(Channel bumpmap, float lx, float ly, float lz, float shadow, float light_r, float light_g, float light_b, int specular) { if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height)) throw new Exception("bumpmap size does not match layer size"); float lnorm = (float)Math.Sqrt(lx*lx + ly*ly + lz*lz); float nz = 4*(1f/Math.Min(width, height)); float nzlz = nz*lz; float nz2 = nz*nz; int power = 2<<specular; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float nx = bumpmap.getPixelWrap(x + 1, y) - bumpmap.getPixelWrap(x - 1, y); float ny = bumpmap.getPixelWrap(x, y + 1) - bumpmap.getPixelWrap(x, y - 1); float brightness = nx*lx + ny*ly; float costheta = (brightness + nzlz)/((float)Math.Sqrt(nx*nx + ny*ny + nz2)*lnorm); float highlight; if (costheta > 0) { highlight = (float)Math.Pow(costheta, power); } else { highlight = 0; } putPixelClip(x, y, (r.getPixel(x, y) + highlight*light_r)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow), (g.getPixel(x, y) + highlight*light_g)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow), (b.getPixel(x, y) + highlight*light_b)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow)); } } return this; }
public Layer bumpFast(Channel bumpmap, float lx, float light, float ambient) { if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height)) throw new Exception("bumpmap size does not match layer size"); ambient = 1f - ambient; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float brightness = lx*(bumpmap.getPixelWrap(x + 1, y) - bumpmap.getPixelWrap(x - 1, y)); if (brightness >= 0) { brightness = brightness*light; putPixel(x, y, r.getPixel(x, y) + brightness, g.getPixel(x, y) + brightness, b.getPixel(x, y) + brightness); } else { brightness = brightness*ambient; putPixel(x, y, r.getPixel(x, y) + brightness, g.getPixel(x, y) + brightness, b.getPixel(x, y) + brightness); } } } return this; }
private void Gen(int sizeX, int sizeY, int base_freq, float pers, long seed, int x_o, int y_o) { if (!Utils.isPowerOf2(sizeX)) throw new Exception("sizeX must be power of 2"); if (!Utils.isPowerOf2(sizeY)) throw new Exception("sizeY must be power of 2"); int iterationsX = Utils.powerOf2Log2(sizeX); int iterationsY = Utils.powerOf2Log2(sizeY); base_freq = Math.Max(base_freq, 0); base_freq = Math.Min(base_freq, iterationsX); random = new Random((int)seed); channel = new Channel(sizeX, sizeY); int x_block, y_block, x, y; if (base_freq > 0) { int block_size = sizeX>>base_freq; for (int x_b = 0; x_b < (1<<base_freq); x_b++) { for (int y_b = 0; y_b < (1<<base_freq); y_b++) { x = x_b*block_size; y = y_b*block_size; channel.putPixel(x, y, (float)random.NextDouble()); } } } float v1, v2, v3, v4, v5, v6, v7, v8, v9; for (int i = base_freq; i < iterationsX; i++) { int block_size = sizeX>>i; int block_size_half = sizeX>>(i + 1); float amp = (float)Math.Pow(pers, i - base_freq); float amp_half = 0.5f*amp; float avr; // calculate center midpoints if (i < 2) { for (x_block = 0, x = 0; x_block < (1<<i); x_block++) { for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % sizeX, y); v3 = channel.getPixel(x, (y + block_size) % sizeY); v4 = channel.getPixel((x + block_size) % sizeX, (y + block_size) % sizeY); avr = 0.25f*(v1 + v2 + v3 + v4); v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); y+= block_size; } x+= block_size; } } else { // safe blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel(x + block_size, y); v3 = channel.getPixel(x, y + block_size); v4 = channel.getPixel(x + block_size, y + block_size); avr = 0.25f*(v1 + v2 + v3 + v4); v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); y+= block_size; } x+= block_size; } // left and right edge blocks for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) { x = x_block*block_size; for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % sizeX, y); v3 = channel.getPixel(x, (y + block_size) % sizeY); v4 = channel.getPixel((x + block_size) % sizeX, (y + block_size) % sizeY); avr = 0.25f*(v1 + v2 + v3 + v4); v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); y+= block_size; } } // top and bottom edge blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) { y = y_block*block_size; v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % sizeX, y); v3 = channel.getPixel(x, (y + block_size) % sizeY); v4 = channel.getPixel((x + block_size) % sizeX, (y + block_size) % sizeY); avr = 0.25f*(v1 + v2 + v3 + v4); v5 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x + block_size_half, y + block_size_half, v5); } x+= block_size; } } // calculate left and bottom edge midpoints if (i < 2) { for (x_block = 0, x = 0; x_block < (1<<i); x_block++) { for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % sizeX, y); v3 = channel.getPixel(x, (y + block_size) % sizeY); v6 = channel.getPixel(((x - block_size_half) + sizeX) % sizeX, (y + block_size_half) % sizeY); v7 = channel.getPixel((x + block_size_half) % sizeX, ((y - block_size_half) + sizeY) % sizeY); avr = 0.25f*(v1 + v3 + v5 + v6); v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half); avr = 0.25f*(v1 + v2 + v5 + v7); v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y+= block_size; } x+= block_size; } } else { // safe blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel(x + block_size, y); v3 = channel.getPixel(x, y + block_size); v6 = channel.getPixel(x - block_size_half, y + block_size_half); v7 = channel.getPixel(x + block_size_half, y - block_size_half); avr = 0.25f*(v1 + v3 + v5 + v6); v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half); avr = 0.25f*(v1 + v2 + v5 + v7); v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y+= block_size; } x+= block_size; } // left and right edge blocks for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) { x = x_block*block_size; for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % sizeX, y); v3 = channel.getPixel(x, (y + block_size) % sizeY); v6 = channel.getPixel(((x - block_size_half) + sizeX) % sizeX, (y + block_size_half) % sizeY); v7 = channel.getPixel((x + block_size_half) % sizeX, ((y - block_size_half) + sizeY) % sizeY); avr = 0.25f*(v1 + v3 + v5 + v6); v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half); avr = 0.25f*(v1 + v2 + v5 + v7); v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y+= block_size; } } // top and bottom edge blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) { y = y_block*block_size; v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % sizeX, y); v3 = channel.getPixel(x, (y + block_size) % sizeY); v6 = channel.getPixel(((x - block_size_half) + sizeX) % sizeX, (y + block_size_half) % sizeY); v7 = channel.getPixel((x + block_size_half) % sizeX, ((y - block_size_half) + sizeY) % sizeY); avr = 0.25f*(v1 + v3 + v5 + v6); v8 = avr*(1f + (float)random.NextDouble()*amp - amp_half); avr = 0.25f*(v1 + v2 + v5 + v7); v9 = avr*(1f + (float)random.NextDouble()*amp - amp_half); channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); } x+= block_size; } } } float[] mm=channel.findMinMax(); //Console.WriteLine("Range Mountain->[{0},{1}]",mm[0],mm[1]); channel.normalize(); mm=channel.findMinMax(); //Console.WriteLine("Range Mountain->[{0},{1}]",mm[0],mm[1]); }
public Layer scaleFast(int new_width, int new_height) { r = r.scaleFast(new_width, new_height); g = g.scaleFast(new_width, new_height); b = b.scaleFast(new_width, new_height); if (a != null) { a = a.scaleFast(new_width, new_height); } width = new_width; height = new_height; return this; }
public void addAlpha() { a = new Channel(width, height); }
public Channel scaleDouble() { if(!(width == height)) throw new Exception("square images only"); // calculate filter Channel filter = new Channel(width<<1, height<<1); for (int y = 0; y < height; y++) { int y_shift = y<<1; for (int x = 0; x < width; x++) { int x_shift = x<<1; float value = 0.25f*getPixel(x, y); filter.putPixel(x_shift, y_shift, value); filter.putPixel(x_shift + 1, y_shift, value); filter.putPixel(x_shift, y_shift + 1, value); filter.putPixel(x_shift + 1, y_shift + 1, value); } } // draw image Channel channel = new Channel(width<<1, height<<1); for (int y = 1; y < (height<<1) - 1; y++) { for (int x = 1; x < (width<<1) - 1; x++) { channel.putPixel(x, y, filter.getPixel(x - 1, y) + filter.getPixel(x + 1, y) + filter.getPixel(x, y - 1) + filter.getPixel(x, y + 1)); } } // fix edges int max = (width<<1) - 1; for (int i = 0; i < max; i++) { channel.putPixel(0, i, filter.getPixelWrap(-1, i) + filter.getPixelWrap(1, i) + filter.getPixelWrap(0, i - 1) + filter.getPixelWrap(0, i + 1)); channel.putPixel(i, 0, filter.getPixelWrap(i, -1) + filter.getPixelWrap(i, 1) + filter.getPixelWrap(i - 1, 0) + filter.getPixelWrap(i + 1, 0)); channel.putPixel(max, i, filter.getPixelWrap(max - 1, i) + filter.getPixelWrap(max + 1, i) + filter.getPixelWrap(max, i - 1) + filter.getPixelWrap(max, i + 1)); channel.putPixel(i, max, filter.getPixelWrap(i, max - 1) + filter.getPixelWrap(i, max + 1) + filter.getPixelWrap(i - 1, max) + filter.getPixelWrap(i + 1, max)); } pixels = channel.getPixels(); width = width<<1; height = height<<1; return this; }
public Layer tile(int new_width, int new_height) { r = r.tile(new_width, new_height); g = g.tile(new_width, new_height); b = b.tile(new_width, new_height); if (a != null) { a = a.tile(new_width, new_height); } width = r.getWidth(); height = r.getHeight(); return this; }
public Channel rotate(int degrees) { Channel channel = null; int tmp = width; switch (degrees) { case 90: channel = new Channel(height, width); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { channel.putPixel(y, width - x - 1, getPixel(x, y)); } } width = height; height = tmp; break; case 180: channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { channel.putPixel(width - x - 1, height - y - 1, getPixel(x, y)); } } break; case 270: channel = new Channel(height, width); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { channel.putPixel(height - y - 1, x, getPixel(x, y)); } } width = height; height = tmp; break; default: throw new Exception("Rotation degrees not a multiple of 90"); } pixels = channel.getPixels(); return this; }
public Channel shear(float offset) { Channel channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { channel.putPixel(x, y, getPixelWrap((int)(x + offset*width*((float)y/height)), y)); } } pixels = channel.getPixels(); return this; }
public Layer offset(int x_offset, int y_offset) { r = r.offset(x_offset, y_offset); g = g.offset(x_offset, y_offset); b = b.offset(x_offset, y_offset); if (a != null) { a = a.offset(x_offset, y_offset); } return this; }
public void addAlpha(Channel alpha) { a = alpha; }
public Layer rotate(int degrees) { r = r.rotate(degrees); g = g.rotate(degrees); b = b.rotate(degrees); if (a != null) { a = a.rotate(degrees); } width = r.getWidth(); height = r.getHeight(); return this; }
public Layer bump(Channel bumpmap, float lx, float ly, float shadow, float light_r, float light_g, float light_b, float ambient_r, float ambient_g, float ambient_b) { if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height)) throw new Exception("bumpmap size does not match layer size"); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float nx = bumpmap.getPixelWrap(x + 1, y) - bumpmap.getPixelWrap(x - 1, y); float ny = bumpmap.getPixelWrap(x, y + 1) - bumpmap.getPixelWrap(x, y - 1); float brightness = nx*lx + ny*ly; if (brightness >= 0) { putPixelClip(x, y, (r.getPixel(x, y) + brightness*light_r)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow), (g.getPixel(x, y) + brightness*light_g)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow), (b.getPixel(x, y) + brightness*light_b)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow)); } else { putPixelClip(x, y, (r.getPixel(x, y) + brightness*(1 - ambient_r))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow), (g.getPixel(x, y) + brightness*(1 - ambient_g))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow), (b.getPixel(x, y) + brightness*(1 - ambient_b))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow)); } } } return this; }
public Layer shear(float offset) { r = r.shear(offset); g = g.shear(offset); b = b.shear(offset); if (a != null) { a = a.shear(offset); } return this; }
public Channel perturb(Channel perturb, float magnitude) { Channel channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float perturbation = magnitude*(perturb.getPixel(x, y) - 0.5f); float x_coord = x + width*perturbation; int x_coord_lo = (int)x_coord; int x_coord_hi = x_coord_lo + 1; float x_frac = x_coord - x_coord_lo; float y_coord = y + height*perturbation; int y_coord_lo = (int)y_coord; int y_coord_hi = y_coord_lo + 1; float y_frac = y_coord - y_coord_lo; float val1 = Tools.interpolateLinear(getPixelWrap(x_coord_lo, y_coord_lo), getPixelWrap(x_coord_hi, y_coord_lo), x_frac); float val2 = Tools.interpolateLinear(getPixelWrap(x_coord_lo, y_coord_hi), getPixelWrap(x_coord_hi, y_coord_hi), x_frac); channel.putPixel(x, y, Tools.interpolateLinear(val1, val2, y_frac)); } } pixels = channel.getPixels(); return this; }
public Layer tileDouble() { r = r.tileDouble(); g = g.tileDouble(); b = b.tileDouble(); if (a != null) { a = a.tileDouble(); } width = width<<1; height = height<<1; return this; }
public Midpoint(int size, int base_freq, float pers, long seed) { if(!Utils.isPowerOf2(size)) throw new Exception("size must be power of 2"); int iterations = Utils.powerOf2Log2(size); base_freq = Math.Max(base_freq, 0); base_freq = Math.Min(base_freq, iterations); random = new Random((int)seed); channel = new Channel(size, size); int x_block, y_block, x, y; if (base_freq > 0) { int block_size = size>>base_freq; for (x_block = 0; x_block < (1<<base_freq); x_block++) { for (y_block = 0; y_block < (1<<base_freq); y_block++) { x = x_block*block_size; y = y_block*block_size; channel.putPixel(x, y, (float)random.NextDouble()); } } } float v1, v2, v3, v4, v5, v6, v7, v8, v9; for (int i = base_freq; i < iterations; i++) { int block_size = size>>i; int block_size_half = size>>(i + 1); float amp = (float)Math.Pow(pers, i - base_freq); float amp_half = 0.5f*amp; // calculate center midpoints if (i < 2) { for (x_block = 0, x = 0; x_block < (1<<i); x_block++) { for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size); v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x + block_size_half, y + block_size_half, v5); y+= block_size; } x+= block_size; } } else { // safe blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel(x + block_size, y); v3 = channel.getPixel(x, y + block_size); v4 = channel.getPixel(x + block_size, y + block_size); v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x + block_size_half, y + block_size_half, v5); y+= block_size; } x+= block_size; } // left and right edge blocks for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) { x = x_block*block_size; for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size); v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x + block_size_half, y + block_size_half, v5); y+= block_size; } } // top and bottom edge blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) { y = y_block*block_size; v1 = channel.getPixel(x, y); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v4 = channel.getPixel((x + block_size) % size, (y + block_size) % size); v5 = 0.25f*(v1 + v2 + v3 + v4) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x + block_size_half, y + block_size_half, v5); } x+= block_size; } } // calculate left and bottom edge midpoints if (i < 2) { for (x_block = 0, x = 0; x_block < (1<<i); x_block++) { for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size); v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size); v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half; v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y+= block_size; } x+= block_size; } } else { // safe blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 1, y = block_size; y_block < (1<<i) - 1; y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel(x + block_size, y); v3 = channel.getPixel(x, y + block_size); v6 = channel.getPixel(x - block_size_half, y + block_size_half); v7 = channel.getPixel(x + block_size_half, y - block_size_half); v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half; v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y+= block_size; } x+= block_size; } // left and right edge blocks for (x_block = 0; x_block < (1<<i); x_block+= (1<<i) - 1) { x = x_block*block_size; for (y_block = 0, y = 0; y_block < (1<<i); y_block++) { v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size); v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size); v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half; v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); y+= block_size; } } // top and bottom edge blocks for (x_block = 1, x = block_size; x_block < (1<<i) - 1; x_block++) { for (y_block = 0; y_block < (1<<i); y_block+= (1<<i) - 1) { y = y_block*block_size; v1 = channel.getPixel(x, y); v5 = channel.getPixel(x + block_size_half, y + block_size_half); v2 = channel.getPixel((x + block_size) % size, y); v3 = channel.getPixel(x, (y + block_size) % size); v6 = channel.getPixel(((x - block_size_half) + size) % size, (y + block_size_half) % size); v7 = channel.getPixel((x + block_size_half) % size, ((y - block_size_half) + size) % size); v8 = 0.25f*(v1 + v3 + v5 + v6) + (float)random.NextDouble()*amp - amp_half; v9 = 0.25f*(v1 + v2 + v5 + v7) + (float)random.NextDouble()*amp - amp_half; channel.putPixel(x, y + block_size_half, v8); channel.putPixel(x + block_size_half, y, v9); } x+= block_size; } } } channel.normalize(); }