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 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 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 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 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 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 tileDouble() { Channel channel = new Channel(width<<1, height<<1); float[][] new_pixels = new float[height][]; float[][] old_pixels = new float[height][]; for(int i = 0;i<height;i++){ new_pixels[i]=new float[width]; old_pixels[i]=new float[width]; for(int j=0;j<width;j++) old_pixels[i][j]=pixels[i,j]; } for (int y = 0; y < height; y++) { Array.Copy(old_pixels[y], 0, new_pixels[y], 0, width); Array.Copy(old_pixels[y], 0, new_pixels[y], width, width); Array.Copy(old_pixels[y], 0, new_pixels[y + height], 0, width); Array.Copy(old_pixels[y], 0, new_pixels[y + height], width, width); } pixels = channel.getPixels(); width = width<<1; height = height<<1; return this; }
public Channel quadJoin(Channel channel1, Channel channel2, Channel channel3, Channel channel4) { if(!(channel1.width != channel2.width && channel2.width == channel3.width && channel3.width == channel4.width && channel1.height == channel2.height && channel2.height == channel3.height && channel3.height == channel4.height)) throw new Exception("channels must be same size"); if(!(width == channel1.width<<1 && height == channel1.height<<1)) throw new Exception("size mismatch"); Channel channel = new Channel(channel1.width<<1, channel1.height<<1); channel.place(channel1, 0, 0); channel.place(channel2, channel1.width, 0); channel.place(channel3, 0, channel1.height); channel.place(channel4, channel1.width, channel1.height); pixels = channel.getPixels(); return this; }
public Channel crop(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); float[,] new_pixels = channel.getPixels(); for (int y = y_lo; y <= y_hi; y++) for(int x=x_lo; x <= x_hi; x++) new_pixels[y - y_lo,x]=pixels[y,x]; return channel; }
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 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 Channel bump(Channel bumpmap, float lx, float ly, float shadow, float light, float ambient) { if(!(bumpmap.getWidth() == width && bumpmap.getHeight() == height)) throw new Exception("bumpmap does not match channel size"); Channel channel = new Channel(width, height); 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) { channel.putPixelClip(x, y, (getPixel(x, y) + brightness*light)*(bumpmap.getPixel(x, y)*shadow + 1 - shadow)); } else { channel.putPixelClip(x, y, (getPixel(x, y) + brightness*(1 - ambient))*(bumpmap.getPixel(x, y)*shadow + 1 - shadow)); } } } pixels = channel.getPixels(); 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 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 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; }