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 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 static Channel erode3(Channel channel, Channel rain_map, float vaporization, int rain_freq, int iterations) { Channel vapor_map = rain_map.copy().multiply(0.5f); Channel height_map_diff = new Channel(channel.width, channel.height).fill(0f); Channel water_map = new Channel(channel.width, channel.height).fill(0f); Channel water_map_diff = new Channel(channel.width, channel.height).fill(0f); Channel sediment_map = new Channel(channel.width, channel.height).fill(0f); Channel sediment_map_diff = new Channel(channel.width, channel.height).fill(0f); Console.Write("Hydraulic erosion 3: "); for (int i = 0; i < iterations; i++) { Console.Write("."); // save frames /* if (channel.width > 128 && i%8 == 0) { if (i < 10) { channel.toLayer().saveAsPNG("erosion00" + i); } else if (i < 100) { channel.toLayer().saveAsPNG("erosion0" + i); } else { channel.toLayer().saveAsPNG("erosion" + i); } } */ // rain if (i%rain_freq == 0) { water_map.channelAdd(rain_map); } // water and sediment transport for (int y = 1; y < channel.height - 1; y++) { for (int x = 1; x < channel.width - 1; x++) { // calculate total heights and height differences float h = channel.getPixel(x, y) + water_map.getPixel(x, y); float h1 = channel.getPixel(x, y + 1) + water_map.getPixel(x, y + 1) + sediment_map.getPixel(x, y + 1); float h2 = channel.getPixel(x - 1, y) + water_map.getPixel(x - 1, y) + sediment_map.getPixel(x - 1, y); float h3 = channel.getPixel(x + 1, y) + water_map.getPixel(x + 1, y) + sediment_map.getPixel(x + 1, y); float h4 = channel.getPixel(x, y - 1) + water_map.getPixel(x, y - 1) + sediment_map.getPixel(x, y - 1); float d1 = h - h1; float d2 = h - h2; float d3 = h - h3; float d4 = h - h4; // calculate amount of water and sediment to transport float total_height = 0; float total_height_diff = 0; int cells = 1; if (d1 > 0) { total_height_diff+= d1; total_height+= h1; cells++; } if (d2 > 0) { total_height_diff+= d2; total_height+= h2; cells++; } if (d3 > 0) { total_height_diff+= d3; total_height+= h3; cells++; } if (d4 > 0) { total_height_diff+= d4; total_height+= h4; cells++; } if (cells == 1) { continue; } float avr_height = total_height/cells; float water_amount = Math.Min(water_map.getPixel(x, y), h - avr_height); water_map_diff.putPixel(x, y, water_map_diff.getPixel(x, y) - water_amount); float water_inv = water_amount/total_height_diff; float sediment_amount = sediment_map.getPixel(x, y); sediment_map_diff.putPixel(x, y, sediment_map_diff.getPixel(x, y) - sediment_amount); float sediment_inv = sediment_amount/total_height_diff; float dissolve; // transport water and sediment and dissolve more material if (d1 > 0) { water_map_diff.putPixel(x, y + 1, water_map_diff.getPixel(x, y + 1) + d1*water_inv); dissolve = 10f*d1*water_amount; sediment_map_diff.putPixel(x, y + 1, sediment_map_diff.getPixel(x, y + 1) + d1*sediment_inv + dissolve); height_map_diff.putPixel(x, y + 1, height_map_diff.getPixel(x, y + 1) - dissolve); } if (d2 > 0) { water_map_diff.putPixel(x - 1, y, water_map_diff.getPixel(x - 1, y) + d2*water_inv); dissolve = 10f*d2*water_amount; sediment_map_diff.putPixel(x - 1, y, sediment_map_diff.getPixel(x - 1, y) + d2*sediment_inv + dissolve); height_map_diff.putPixel(x - 1, y, height_map_diff.getPixel(x - 1, y) - dissolve); } if (d3 > 0) { water_map_diff.putPixel(x + 1, y, water_map_diff.getPixel(x + 1, y) + d3*water_inv); dissolve = 10f*d3*water_amount; sediment_map_diff.putPixel(x + 1, y, sediment_map_diff.getPixel(x + 1, y) + d3*sediment_inv + dissolve); height_map_diff.putPixel(x + 1, y, height_map_diff.getPixel(x + 1, y) - dissolve); } if (d4 > 0) { water_map_diff.putPixel(x, y - 1, water_map_diff.getPixel(x, y - 1) + d4*water_inv); dissolve = 10f*d4*water_amount; sediment_map_diff.putPixel(x, y - 1, sediment_map_diff.getPixel(x, y - 1) + d4*sediment_inv + dissolve); height_map_diff.putPixel(x, y - 1, height_map_diff.getPixel(x, y - 1) - dissolve); } } } // apply changes to water map water_map.channelAddNoClip(water_map_diff); // apply changes to sediment map sediment_map.channelAddNoClip(sediment_map_diff); // apply changes to height map channel.channelAddNoClip(height_map_diff); // water vaporization water_map.addClip(-vaporization); // sedimentation sediment_map_diff = sediment_map.copy().channelSubtract(water_map); sediment_map.channelSubtract(sediment_map_diff); channel.channelAddNoClip(sediment_map_diff); // clear diff maps water_map_diff.fill(0f); height_map_diff.fill(0f); sediment_map_diff.fill(0f); } // force evaporation of remaining water //channel.channelAdd(water_map.multiply(0.5f)); Console.WriteLine("DONE"); return channel; }
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 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 scaleFast(int new_width, int new_height) { if (width == new_width && height == new_height) { return this; } Channel channel = new Channel(new_width, new_height); int x_coord = 0; int y_coord = 0; for (int y = 0; y < new_height; y++) { for (int x = 0; x < new_width; x++) { x_coord = x*width/new_width; y_coord = y*height/new_height; channel.putPixel(x, y, getPixel(x_coord, y_coord)); } } pixels = channel.getPixels(); width = new_width; height = new_height; return this; }
public Channel offset(int x_offset, int y_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(x - x_offset, y - y_offset)); } } pixels = channel.getPixels(); return this; }
public Channel cropWrap(int x_lo, int y_lo, int x_hi, int y_hi) { int new_width = x_hi - x_lo + 1; int new_height = y_hi - y_lo + 1; Channel channel = new Channel(new_width, new_height); for (int y = 0; y < new_height; y++) { int y_old = y + y_lo; for (int x = 0; x < new_width; x++) { int x_old = x + x_lo; if (x_old < 0 || x_old >= width || y_old < 0 || y_old >= height) { channel.putPixel(x, y, getPixelWrap(x_old, y_old)); } else { channel.putPixel(x, y, getPixel(x_old, y_old)); } } } return channel; }
public Channel smooth(int radius, Channel mask) { radius = Math.Max(1, radius); Channel filter = new Channel(width, height); float factor = 1f/((2*radius + 1)*(2*radius + 1)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { filter.putPixel(x, y, factor*getPixel(x, y)); } } for (int x = radius; x < width - radius; x++) { int y = radius; float sum = 0f; for (int i = -radius; i < radius + 1; i++) { for (int j = -radius; j < radius + 1; j++) { sum += filter.getPixel(x + j, y + i); } } for (y++; y < height - radius; y++) { float alpha = mask.getPixel(x, y); if (alpha > 0) { for (int j = -radius; j < radius + 1; j++) { sum -= filter.getPixel(x + j, y - radius - 1); sum += filter.getPixel(x + j, y + radius); } putPixel(x, y, alpha*sum + (1f - alpha)*getPixel(x, y)); } } } return this; }
public Channel smoothWrap(int radius) { radius = Math.Max(1, radius); Channel filter = new Channel(width, height); float factor = 1f/((2*radius + 1)*(2*radius + 1)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { filter.putPixel(x, y, factor*getPixel(x, y)); } } for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { float sum = 0f; for (int i = -radius; i < radius + 1; i++) { for (int j = -radius; j < radius + 1; j++) { sum += filter.getPixelWrap(x + j, y + i); } } putPixel(x, y, sum); } } return this; }
public Channel smoothFast() { Channel filter = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { filter.putPixel(x, y, 0.25f*getPixel(x, y)); } } for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { putPixel(x, y, filter.getPixelWrap(x - 1, y) + filter.getPixelWrap(x + 1, y) + filter.getPixelWrap(x, y - 1) + filter.getPixelWrap(x, y + 1)); } } return this; }
public Channel flipH() { Channel channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { channel.putPixel(x, y, getPixel(width - x - 1, y)); } } pixels = channel.getPixels(); return this; }
public static Channel LoadTerrain(String file) { using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)) { Bitmap bitmap = new Bitmap(stream); try { Channel terrain = new Channel(bitmap.Width, bitmap.Height); Console.WriteLine("LOADED {0}x{1} BITMAP!", bitmap.Height, bitmap.Width); for (int x = 0; x < bitmap.Width; x++) { for (int y = 0; y < bitmap.Height; y++) { terrain.putPixel(x, y, bitmap.GetPixel(x, y).GetBrightness()); } } Console.WriteLine("LOADED {0}x{1} CHANNEL!", terrain.getHeight(), terrain.getWidth()); return terrain;//.invert(); } catch (IOException) { Console.WriteLine("Cannot find " + file + ", using blank channel."); return new Channel(256, 256); } } }
public static Channel erode5(Channel channel, Channel rain, float erosion_water, float erosion_flow, float evaporation, float water_threshold, float solulibility, int ipr, int iterations) { Channel w = new Channel(channel.width, channel.height); // water map Channel dw = new Channel(channel.width, channel.height); // delta water map Channel s = new Channel(channel.width, channel.height); // sediment map Channel ds = new Channel(channel.width, channel.height); // delta sediment map Console.Write("Hydraulic erosion 5: "); for (int i = 0; i < iterations; i++) { Console.Write("."); // save frames /* if (channel.width > 128 && i%10 == 0) { if (i < 10) { channel.toLayer().saveAsPNG("erosion00" + i); } else if (i < 100) { channel.toLayer().saveAsPNG("erosion0" + i); } else { channel.toLayer().saveAsPNG("erosion" + i); } } */ // water is added according to rain map if (i%ipr == 0) { w.channelAdd(rain); } // the presence of water dissolves material channel.channelSubtract(w.copy().multiply(erosion_water)); s.channelAdd(w.copy().multiply(erosion_water)); // water and sediment are transported float h, h1, h2, h3, h4, d1, d2, d3, d4, total_height, total_height_diff, total_height_diff_inv, avr_height, water_amount; int cells; for (int y = 0; y < channel.height; y++) { for (int x = 0; x < channel.width; x++) { // water transport // calculate total heights and height differences h = channel.getPixel(x, y) + w.getPixel(x, y) + s.getPixel(x, y); h1 = channel.getPixelWrap(x , y + 1) + w.getPixelWrap(x , y + 1) + s.getPixelWrap(x , y + 1); h2 = channel.getPixelWrap(x - 1, y ) + w.getPixelWrap(x - 1, y ) + s.getPixelWrap(x - 1, y ); h3 = channel.getPixelWrap(x + 1, y ) + w.getPixelWrap(x + 1, y ) + s.getPixelWrap(x + 1, y ); h4 = channel.getPixelWrap(x , y - 1) + w.getPixelWrap(x , y - 1) + s.getPixelWrap(x , y - 1); d1 = h - h1; d2 = h - h2; d3 = h - h3; d4 = h - h4; // calculate amount of water to transport total_height = 0f; total_height_diff = 0f; cells = 1; if (d1 > 0) { total_height_diff+= d1; total_height+= h1; cells++; } if (d2 > 0) { total_height_diff+= d2; total_height+= h2; cells++; } if (d3 > 0) { total_height_diff+= d3; total_height+= h3; cells++; } if (d4 > 0) { total_height_diff+= d4; total_height+= h4; cells++; } if (cells == 1) { continue; } avr_height = total_height/cells; water_amount = Math.Min(w.getPixel(x, y), h - avr_height); dw.putPixel(x, y, dw.getPixel(x, y) - water_amount); total_height_diff_inv = water_amount/total_height_diff; // transport water if (d1 > 0) { dw.putPixelWrap(x, y + 1, dw.getPixelWrap(x, y + 1) + d1*total_height_diff_inv); } if (d2 > 0) { dw.putPixelWrap(x - 1, y, dw.getPixelWrap(x - 1, y) + d2*total_height_diff_inv); } if (d3 > 0) { dw.putPixelWrap(x + 1, y, dw.getPixelWrap(x + 1, y) + d3*total_height_diff_inv); } if (d4 > 0) { dw.putPixelWrap(x, y - 1, dw.getPixelWrap(x, y - 1) + d4*total_height_diff_inv); } // sediment transport /* h = s.getPixel(x, y); h1 = s.getPixelWrap(x , y + 1); h2 = s.getPixelWrap(x - 1, y ); h3 = s.getPixelWrap(x + 1, y ); h4 = s.getPixelWrap(x , y - 1); d1 = h - h1; d2 = h - h2; d3 = h - h3; d4 = h - h4; // calculate amount of sediment to transport total_height = 0f; total_height_diff = 0f; cells = 1; if (d1 > 0) { total_height_diff+= d1; total_height+= h1; cells++; } if (d2 > 0) { total_height_diff+= d2; total_height+= h2; cells++; } if (d3 > 0) { total_height_diff+= d3; total_height+= h3; cells++; } if (d4 > 0) { total_height_diff+= d4; total_height+= h4; cells++; } if (cells == 1) { continue; } avr_height = total_height/cells; sediment_amount = Math.Min(s.getPixel(x, y), h - avr_height); ds.putPixel(x, y, ds.getPixel(x, y) - sediment_amount); total_height_diff_inv = sediment_amount/total_height_diff; // transport sediment if (d1 > 0) { ds.putPixelWrap(x, y + 1, ds.getPixelWrap(x, y + 1) + d1*total_height_diff_inv); } if (d2 > 0) { ds.putPixelWrap(x - 1, y, ds.getPixelWrap(x - 1, y) + d2*total_height_diff_inv); } if (d3 > 0) { ds.putPixelWrap(x + 1, y, ds.getPixelWrap(x + 1, y) + d3*total_height_diff_inv); } if (d4 > 0) { ds.putPixelWrap(x, y - 1, ds.getPixelWrap(x, y - 1) + d4*total_height_diff_inv); } */ } } // more sediment is dissolved according to amount of water flow /* channel.channelSubtract(dw.copy().fill(0f, Float.MIN_VALUE, 0f).multiply(erosion_flow)); s.channelAdd(dw.copy().fill(0f, Float.MIN_VALUE, 0f).multiply(erosion_flow)); */ // apply water and sediment delta maps w.channelAdd(dw); //w.fill(0f, Float.MIN_VALUE, water_threshold); // remove water below threshold amount s.channelAdd(ds); dw.fill(0f); ds.fill(0f); // water evaporates w.multiply(evaporation); // sediment is deposited for (int y = 0; y < channel.height; y++) { for (int x = 0; x < channel.width; x++) { float deposition = s.getPixel(x, y) - w.getPixel(x, y)*solulibility; if (deposition > 0) { s.putPixel(x, y, s.getPixel(x, y) - deposition); channel.putPixel(x, y, channel.getPixel(x, y) + deposition); } } } } Console.WriteLine("DONE"); return channel; }
public static Channel erode4(Channel channel, float rain_amount, float vaporization, int rain_freq, int iterations) { Channel water_map = new Channel(channel.width, channel.height).fill(0f); Channel water_map_diff = new Channel(channel.width, channel.height).fill(0f); Channel height_map_diff = new Channel(channel.width, channel.height).fill(0f); Console.Write("Hydraulic erosion 4: "); for (int i = 0; i < iterations; i++) { Console.Write("."); // save frames /* if (channel.width > 128 && i%10 == 0) { if (i < 10) { channel.toLayer().saveAsPNG("erosion00" + i); } else if (i < 100) { channel.toLayer().saveAsPNG("erosion0" + i); } else { channel.toLayer().saveAsPNG("erosion" + i); } } */ // rain erodes the underlying terrain if (i%rain_freq == 0) { water_map.channelAdd(channel.copy().multiply(rain_amount)); } // water and sediment transport for (int y = 1; y < channel.height - 1; y++) { for (int x = 1; x < channel.width - 1; x++) { // calculate total heights and height differences float h = channel.getPixel(x, y) + water_map.getPixel(x, y); float h1 = channel.getPixel(x, y + 1) + water_map.getPixel(x, y + 1); float h2 = channel.getPixel(x - 1, y) + water_map.getPixel(x - 1, y); float h3 = channel.getPixel(x + 1, y) + water_map.getPixel(x + 1, y); float h4 = channel.getPixel(x, y - 1) + water_map.getPixel(x, y - 1); float d1 = h - h1; float d2 = h - h2; float d3 = h - h3; float d4 = h - h4; // calculate amount of water to transport float total_height = 0; float total_height_diff = 0; int cells = 1; if (d1 > 0) { total_height_diff+= d1; total_height+= h1; cells++; } if (d2 > 0) { total_height_diff+= d2; total_height+= h2; cells++; } if (d3 > 0) { total_height_diff+= d3; total_height+= h3; cells++; } if (d4 > 0) { total_height_diff+= d4; total_height+= h4; cells++; } if (cells == 1) { continue; } float avr_height = total_height/cells; float water_amount = Math.Min(water_map.getPixel(x, y), h - avr_height); water_map_diff.putPixel(x, y, water_map_diff.getPixel(x, y) - water_amount); float total_height_diff_inv = water_amount/total_height_diff; // transport water if (d1 > 0) { water_amount = d1*total_height_diff_inv; water_map_diff.putPixel(x, y + 1, water_map_diff.getPixel(x, y + 1) + water_amount); height_map_diff.putPixel(x, y + 1, height_map_diff.getPixel(x, y + 1) - 0.1f*water_amount); } if (d2 > 0) { water_amount = d2*total_height_diff_inv; water_map_diff.putPixel(x - 1, y, water_map_diff.getPixel(x - 1, y) + water_amount); height_map_diff.putPixel(x - 1, y, height_map_diff.getPixel(x - 1, y) - 0.1f*water_amount); } if (d3 > 0) { water_amount = d3*total_height_diff_inv; water_map_diff.putPixel(x + 1, y, water_map_diff.getPixel(x + 1, y) + water_amount); height_map_diff.putPixel(x + 1, y, height_map_diff.getPixel(x + 1, y) - 0.1f*water_amount); } if (d4 > 0) { water_amount = d4*total_height_diff_inv; water_map_diff.putPixel(x, y - 1, water_map_diff.getPixel(x, y - 1) + water_amount); height_map_diff.putPixel(x, y - 1, height_map_diff.getPixel(x, y - 1) - 0.1f*water_amount); } } } // apply changes to water map water_map.channelAddNoClip(water_map_diff); water_map_diff.fill(0f); // apply changes to height map channel.channelAddNoClip(height_map_diff); height_map_diff.fill(0f); // vaporize water channel.channelAddNoClip(water_map.copy().channelSubtract(water_map.addClip(-vaporization)).multiply(0.5f)); } // force evaporation of remaining water channel.channelAdd(water_map.multiply(0.5f)); Console.WriteLine("DONE"); return channel; }
public Channel[] fft() { if(!(width == height)) throw new Exception("square images only"); int size = width; if(!(Utils.isPowerOf2(size))) throw new Exception("size must be power of 2"); // convert channel to complex number array float[] a = new float[size*size*2 + 1]; int n = 1; for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { a[n] = getPixel(x, y); n += 2; } } // perform fast fourier transform fastFourierTransform(a, size, 1); // convert complex number array to channels n = 1; Channel magnitude = new Channel(size, size); Channel phase = new Channel(size, size); float real, imag; for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { real = a[n++]; imag = a[n++]; magnitude.putPixel(x, y, (float)Math.Sqrt(real*real + imag*imag)); if (imag == 0 && real >= 0) { phase.putPixel(x, y, (float)Math.PI/2f); } else if (imag == 0 && real < 0) { phase.putPixel(x, y, (float)Math.PI/-2f); } else { phase.putPixel(x, y, (float)Math.Atan(real/imag)); } } } // return magnitude and phase channels return new Channel[]{magnitude.offset(size>>1, size>>1), phase}; }
public Channel copy() { Channel channel = new Channel(width, height); for(int x =0;x<this.getWidth();x++) for(int y =0;y<this.getWidth();y++) channel.putPixel(x,y,pixels[y,x]); return channel; }
public Channel sharpen(int radius) { radius = Math.Max(1, radius); Channel channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float value = 0; for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { if (i == 0 && j == 0) { value += (2*radius + 1)*(2*radius + 1)*getPixel(x, y); } else { value -= getPixelWrap(x + i, y + j); } } } channel.putPixel(x, y, value); } } pixels = channel.getPixels(); return this; }
public Channel tile(int new_width, int new_height) { Channel channel = new Channel(new_width, new_height); for (int y = 0; y < new_height; y++) { for (int x = 0; x < new_width; x++) { if (x < width && y < height) { channel.putPixel(x, y, getPixel(x, y)); } else { channel.putPixel(x, y, getPixelWrap(x, y)); } } } pixels = channel.getPixels(); width = new_width; height = new_height; return this; }
public Channel convolution(float[][] filter, float divisor, float offset) { int radius = (filter.GetLength(0) - 1)/2; Channel channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { float value = 0; for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { value += filter[i + radius][j + radius] * getPixelWrap(x + i, y + j); } } value = value/divisor + offset; channel.putPixel(x, y, value); } } pixels = channel.getPixels(); return this; }
public Channel scaleCubic(int new_width, int new_height) { if (width == new_width && height == new_height) { return this; } Channel channel = new Channel(new_width, new_height); float x_coord, y_coord; float val0, val1, val2, val3; float height_ratio = (float)height/new_height; float width_ratio = (float)width/new_width; float x_diff, y_diff; int x_coord_lo, x_coord_lolo, x_coord_hi, x_coord_hihi, y_coord_lo, y_coord_lolo, y_coord_hi, y_coord_hihi; for (int y = 0; y < new_height; y++) { y_coord = y*height_ratio - 0.5f; y_coord_lo = (int)y_coord; y_coord_lolo = y_coord_lo - 1; y_coord_hi = y_coord_lo + 1; y_coord_hihi = y_coord_hi + 1; y_diff = y_coord - y_coord_lo; for (int x = 0; x < new_width; x++) { x_coord = x*width_ratio - 0.5f; x_coord_lo = (int)x_coord; x_coord_lolo = x_coord_lo - 1; x_coord_hi = x_coord_lo + 1; x_coord_hihi = x_coord_hi + 1; x_diff = x_coord - x_coord_lo; val0 = Tools.interpolateCubic( getPixelWrap(x_coord_lolo, y_coord_lolo), getPixelWrap(x_coord_lolo, y_coord_lo), getPixelWrap(x_coord_lolo, y_coord_hi), getPixelWrap(x_coord_lolo, y_coord_hihi), y_diff); val1 = Tools.interpolateCubic( getPixelWrap(x_coord_lo, y_coord_lolo), getPixelWrap(x_coord_lo, y_coord_lo), getPixelWrap(x_coord_lo, y_coord_hi), getPixelWrap(x_coord_lo, y_coord_hihi), y_diff); val2 = Tools.interpolateCubic( getPixelWrap(x_coord_hi, y_coord_lolo), getPixelWrap(x_coord_hi, y_coord_lo), getPixelWrap(x_coord_hi, y_coord_hi), getPixelWrap(x_coord_hi, y_coord_hihi), y_diff); val3 = Tools.interpolateCubic( getPixelWrap(x_coord_hihi, y_coord_lolo), getPixelWrap(x_coord_hihi, y_coord_lo), getPixelWrap(x_coord_hihi, y_coord_hi), getPixelWrap(x_coord_hihi, y_coord_hihi), y_diff); channel.putPixel(x, y, Math.Max(Math.Min(Tools.interpolateCubic(val0, val1, val2, val3, x_diff), 1f), 0f)); } } pixels = channel.getPixels(); width = new_width; height = new_height; return this; }
public Channel largestConnected(float value) { Channel tmp = this.copy(); Channel fillmap = new Channel(width, height); int[] fillcoords = tmp.findFirst(value); int max_count = 0; while (fillcoords[0] != -1) { // while reachable pixels remain int count = 0; int init_x = fillcoords[0]; int init_y = fillcoords[1]; fillmap.fill(0f); // flood fill bool[,] marked = new bool[width,height]; marked[init_x,init_y] = true; Stack list = new Stack(); list.Push(new int[]{init_x, init_y}); while (list.ToArray().Length > 0) { int[] coords = (int[])list.Pop(); int x = coords[0]; int y = coords[1]; tmp.putPixel(x, y, -1f); fillmap.putPixel(x, y, 1f); count++; if (x > 0 && tmp.getPixel(x - 1, y) == 1f && !marked[x - 1,y]) { marked[x - 1,y] = true; list.Push(new int[]{x - 1, y}); } if (x < width - 1 && tmp.getPixel(x + 1, y) == 1f && !marked[x + 1,y]) { marked[x + 1,y] = true; list.Push(new int[]{x + 1, y}); } if (y > 0 && tmp.getPixel(x, y - 1) == 1f && !marked[x,y - 1]) { marked[x,y - 1] = true; list.Push(new int[]{x, y - 1}); } if (y < height - 1 && tmp.getPixel(x, y + 1) == 1f && !marked[x,y + 1]) { marked[x,y + 1] = true; list.Push(new int[]{x, y + 1}); } } if (count > max_count) { pixels = fillmap.copy().pixels; max_count = count; } fillcoords = tmp.findFirst(value); } return this; }
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 Channel squareFit(float value, int size) { Channel channel = new Channel(width, height); bool match; for (int y = 0; y <= height - size; y++) { for (int x = 0; x <= width - size; x++) { match = true; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { match = match && (getPixel(x + i, y + j) == value); if (!match) break; } } if (match) { channel.putPixel(x, y, value); } } } pixels = channel.copy().pixels; 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 Channel boxFit(float value, int width, int height) { Channel channel = new Channel(this.width, this.height); bool match; for (int y = 0; y <= this.height - height; y++) { for (int x = 0; x <= this.width - width; x++) { match = true; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { match = match && (getPixel(x + i, y + j) == value); if (!match) break; } } if (match) { channel.putPixel(x, y, value); } } } pixels = channel.copy().pixels; 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 Channel lineart() { Channel channel = new Channel(width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { channel.putPixel(x, y, Math.Max( Math.Max( Math.Abs(getPixelWrap(x, y) - getPixelWrap(x - 1, y)), Math.Abs(getPixelWrap(x, y) - getPixelWrap(x + 1, y))), Math.Max( Math.Abs(getPixelWrap(x, y) - getPixelWrap(x, y - 1)), Math.Abs(getPixelWrap(x, y) - getPixelWrap(x, y + 1))) )); } } pixels = channel.getPixels(); 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(); }
public Channel relativeIntensity(int radius) { radius = Math.Max(1, radius); Channel relint = new Channel(width, height); float factor = 1f/((2*radius + 1)*(2*radius + 1)); float sum, avr; for (int x = 0; x < width; x++) { int y = 0; sum = 0f; for (int i = -radius; i < radius + 1; i++) { for (int j = -radius; j < radius + 1; j++) { sum += getPixelWrap(x + j, y + i); } } for (; y < height; y++) { if (y > 0) { for (int j = -radius; j < radius + 1; j++) { sum -= getPixelWrap(x + j, y - radius - 1); sum += getPixelWrap(x + j, y + radius); } } avr = sum*factor; relint.putPixel(x, y, getPixel(x, y) - avr); } } return relint.add(0.5f); }