Skip to content

Instantly share code, notes, and snippets.

@notanimposter

notanimposter/drawlib.cs

Last active Jan 12, 2016
Embed
What would you like to do?
SE drawing library (version 2)
public class ColorUtils {
private static double oo64 = 1.0/64.0;
private static double[][] map = new double[][] {
new double[] { 0*oo64, 48*oo64, 12*oo64, 60*oo64, 3*oo64, 51*oo64, 15*oo64, 63*oo64},
new double[] {32*oo64, 16*oo64, 44*oo64, 28*oo64, 35*oo64, 19*oo64, 47*oo64, 31*oo64},
new double[] { 8*oo64, 56*oo64, 4*oo64, 52*oo64, 11*oo64, 59*oo64, 7*oo64, 55*oo64},
new double[] {40*oo64, 24*oo64, 36*oo64, 20*oo64, 43*oo64, 27*oo64, 39*oo64, 23*oo64},
new double[] { 2*oo64, 50*oo64, 14*oo64, 62*oo64, 1*oo64, 49*oo64, 13*oo64, 61*oo64},
new double[] {34*oo64, 18*oo64, 46*oo64, 30*oo64, 33*oo64, 17*oo64, 45*oo64, 29*oo64},
new double[] {10*oo64, 58*oo64, 6*oo64, 54*oo64, 9*oo64, 57*oo64, 5*oo64, 53*oo64},
new double[] {42*oo64, 26*oo64, 38*oo64, 22*oo64, 41*oo64, 25*oo64, 37*oo64, 21*oo64}
};
private static int zero = 0; //because space engineers is stupid
private static int[][] palette = new int[][] {
new int[] { 255+zero, 255+zero, zero},
new int[] { 255+zero, zero, zero},
new int[] { zero, zero, 255+zero},
new int[] { zero, 255+zero, zero},
new int[] { 255+zero, 255+zero, 255+zero},
new int[] { 97+zero, 97+zero, 97+zero},
new int[] { zero, zero, zero}
};
private static string[] colorStrings = new string[] {
"\uE004", //oh but it works fine with *strings* -_-
"\uE003",
"\uE002",
"\uE001",
"\uE007\u0458",
"\uE00D",
"\u2014\u0060"
};
//magic numbers yay
private static double dontHateBlueAsMuch = 1.5;
private static double howMuchDoWeHateGrey = 0.01; //not ideal but it seems to work okay
private static double compareColors(int r1, int g1, int b1, int r2, int g2, int b2) {
double luma1 = (r1*299 + g1*587 + b1*114) / (255.0*1000);
double luma2 = (r2*299 + g2*587 + b2*114) / (255.0*1000);
double dl = luma1-luma2;
double dr = (r1-r2)/255.0, dg = (g1-g2)/255.0, db = (b1-b2)/255.0;
return (dr*dr*0.299 + dg*dg*0.587 + db*db*0.114*dontHateBlueAsMuch)*0.75 + dl*dl;
}
private static double calcError(int[] color, int r0, int g0, int b0, int[] color1, int[] color2, double ratio) {
return compareColors(color[0], color[1], color[2], r0,g0,b0) +
compareColors(color1[0], color1[1], color1[2], color2[0], color2[1], color2[2]) * 0.1 * (Math.Abs(ratio-0.5)+0.5) +
((color1[0]==color1[1] && color1[1]==color1[2]) || (color2[0]==color2[1] && color2[1]==color2[2]) ? howMuchDoWeHateGrey : 0);
}
public static int[] createMix(int[] rgb) {
int r = rgb[0];
int g = rgb[1];
int b = rgb[2];
int[] result = new int[] { zero, zero, 1+zero, 2+zero };
double minPenalty = 99999999999999999;
for (int i = 0; i < palette.Length; i++) {
for (int j = i; j < palette.Length; j++) {
int[] color1 = palette[i];
int[] color2 = palette[j];
int r1 = color1[0];
int g1 = color1[1];
int b1 = color1[2];
int r2 = color2[0];
int g2 = color2[1];
int b2 = color2[2];
int ratio = 32;
if (r1 != r2 || g1 != g2 || b1 != b2)
ratio = ((r2 != r1 ? 299*64 * (int)(r - r1) / (int)(r2-r1) : 0) +
(g2 != g1 ? 587*64 * (int)(g - g1) / (int)(g2-g1) : 0) +
(b1 != b2 ? (int) (114*dontHateBlueAsMuch*64) * (int)(b - b1) / (int)(b2-b1) : 0))/
((r2 != r1 ? 299 : 0)+
(g2 != g1 ? 587 : 0)+
(b2 != b1 ? (int) (114*dontHateBlueAsMuch) : 0));
if (ratio < 0)
ratio = 0;
else if (ratio > 63)
ratio = 63;
int r0 = r1 + ratio * (int)(r2-r1) / 64;
int g0 = g1 + ratio * (int)(g2-g1) / 64;
int b0 = b1 + ratio * (int)(b2-b1) / 64;
double penalty = calcError(
rgb, r0,g0,b0, color1, color2,
(double)ratio/64.0);
if (penalty < minPenalty) {
minPenalty = penalty;
result[0] = i;
result[1] = j;
result[2] = ratio;
result[3] = 64;
}
}
}
return result;
}
public static string[][] genDitherPattern(int[] mix) {
string[][] dithered = new string[8][];
for (int x = 0; x < 8; x++) {
dithered[x] = new string[8];
for (int y = 0; y < 8; y++) {
double mapValue = map[y&7][x&7];
double ratio = ((double) mix[2])/((double) mix[3]);
dithered[x][y] = colorStrings[mix[ mapValue < ratio ? 1 : 0 ]];
}
}
return dithered;
}
}
public class Ascii {
public static readonly int width = 3;
public static readonly int height = 5;
private static int offset = 0x21;
//debigulate this later
private static string[] glyphs = new string[] {
" @ " +
" @ " +
" @ " +
" " +
" @ ",
"@ @" +
"@ @" +
" " +
" " +
" ",
"@ @" +
"@@@" +
"@ @" +
"@@@" +
"@ @",
" @@" +
"@@ " +
" @@" +
"@@ " +
" @ ",
"@ " +
" @" +
" @ " +
"@ " +
" @",
" @ " +
"@ @" +
" @ " +
"@ @" +
" @@",
" @ " +
" @ " +
" " +
" " +
" ",
" @" +
" @ " +
" @ " +
" @ " +
" @",
"@ " +
" @ " +
" @ " +
" @ " +
"@ ",
"@ @" +
" @ " +
"@ @" +
" " +
" ",
" " +
" @ " +
"@@@" +
" @ " +
" ",
" " +
" " +
" " +
" @ " +
"@ ",
" " +
" " +
"@@@" +
" " +
" ",
" " +
" " +
" " +
" " +
" @ ",
" " +
" @" +
" @ " +
"@ " +
" ",
"@@@" +
"@ @" +
"@ @" +
"@ @" +
"@@@",
" @ " +
"@@ " +
" @ " +
" @ " +
"@@@",
"@@ " +
" @" +
" @ " +
"@ " +
"@@@",
"@@@" +
" @" +
" @ " +
" @" +
"@@ ",
"@ @" +
"@ @" +
"@@@" +
" @" +
" @",
"@@@" +
"@ " +
"@@ " +
" @" +
"@@ ",
" @ " +
"@ " +
"@@ " +
"@ @" +
" @ ",
"@@@" +
" @" +
" @ " +
"@@@" +
" @ ",
" @ " +
"@ @" +
" @ " +
"@ @" +
" @ ",
" @ " +
"@ @" +
" @@" +
" @" +
" @ ",
" " +
" @ " +
" " +
" @ " +
" ",
" " +
" @ " +
" " +
" @ " +
"@ ",
" @" +
" @ " +
"@ " +
" @ " +
" @",
" " +
"@@@" +
" " +
"@@@" +
" ",
"@ " +
" @ " +
" @" +
" @ " +
"@ ",
"@@ " +
" @" +
" @ " +
" " +
" @ ",
" @@" +
"@ @" +
"@ @" +
"@ " +
" @@",
" @ " +
"@ @" +
"@@@" +
"@ @" +
"@ @",
"@@ " +
"@ @" +
"@@ " +
"@ @" +
"@@ ",
" @@" +
"@ " +
"@ " +
"@ " +
" @@",
"@@ " +
"@ @" +
"@ @" +
"@ @" +
"@@ ",
"@@@" +
"@ " +
"@@ " +
"@ " +
"@@@",
"@@@" +
"@ " +
"@@ " +
"@ " +
"@ ",
" @@" +
"@ " +
"@@@" +
"@ @" +
" @@",
"@ @" +
"@ @" +
"@@@" +
"@ @" +
"@ @",
"@@@" +
" @ " +
" @ " +
" @ " +
"@@@",
" @@" +
" @" +
" @" +
"@ @" +
" @ ",
"@ @" +
"@ @" +
"@@ " +
"@ @" +
"@ @",
"@ " +
"@ " +
"@ " +
"@ " +
"@@@",
"@ @" +
"@@@" +
"@@@" +
"@ @" +
"@ @",
"@@ " +
"@ @" +
"@ @" +
"@ @" +
"@ @",
" @ " +
"@ @" +
"@ @" +
"@ @" +
" @ ",
"@@ " +
"@ @" +
"@@ " +
"@ " +
"@ ",
" @ " +
"@ @" +
"@ @" +
"@@@" +
" @@",
"@@ " +
"@ @" +
"@@ " +
"@ @" +
"@ @",
" @@" +
"@ " +
" @ " +
" @" +
"@@ ",
"@@@" +
" @ " +
" @ " +
" @ " +
" @ ",
"@ @" +
"@ @" +
"@ @" +
"@ @" +
" @@",
"@ @" +
"@ @" +
"@ @" +
" @ " +
" @ ",
"@ @" +
"@ @" +
"@@@" +
"@@@" +
"@ @",
"@ @" +
"@ @" +
" @ " +
"@ @" +
"@ @",
"@ @" +
"@ @" +
" @ " +
" @ " +
" @ ",
"@@@" +
" @" +
" @ " +
"@ " +
"@@@",
" @@" +
" @ " +
" @ " +
" @ " +
" @@",
" " +
"@ " +
" @ " +
" @" +
" ",
"@@ " +
" @ " +
" @ " +
" @ " +
"@@ ",
" @ " +
"@ @" +
" " +
" " +
" ",
" " +
" " +
" " +
" " +
"@@@",
"@ " +
" @ " +
" " +
" " +
" ",
" " +
" " +
" @@" +
"@ @" +
"@@@",
"@ " +
"@ " +
"@@ " +
"@ @" +
"@@ ",
" " +
" " +
" @@" +
"@ " +
" @@",
" @" +
" @" +
" @@" +
"@ @" +
" @@",
" " +
" @ " +
"@ @" +
"@@ " +
" @@",
" @@" +
"@ " +
"@@ " +
"@ " +
"@ ",
" " +
" @@" +
"@ @" +
" @@" +
"@@ ",
"@ " +
"@ " +
"@@ " +
"@ @" +
"@ @",
" @ " +
" " +
"@@ " +
" @ " +
" @@",
" @" +
" " +
" @@" +
" @" +
"@@ ",
"@ " +
"@ " +
"@ @" +
"@@ " +
"@ @",
"@@ " +
" @ " +
" @ " +
" @ " +
" @",
" " +
" " +
"@@@" +
"@@@" +
"@ @",
" " +
" " +
"@@ " +
"@ @" +
"@ @",
" " +
" " +
" @ " +
"@ @" +
" @ ",
" " +
" @ " +
"@ @" +
"@@ " +
"@ ",
" " +
" @ " +
"@ @" +
" @@" +
" @",
" " +
" " +
" @@" +
"@ " +
"@ ",
" " +
" @@" +
"@@ " +
" @" +
"@@ ",
"@ " +
"@ " +
"@@ " +
"@ " +
" @@",
" " +
" " +
"@ @" +
"@ @" +
" @@",
" " +
" " +
"@ @" +
"@ @" +
" @ ",
" " +
" " +
"@ @" +
"@@@" +
"@@@",
" " +
" " +
"@ @" +
" @ " +
"@ @",
" " +
"@ @" +
" @@" +
" @" +
"@@ ",
" " +
"@@@" +
" @" +
" @ " +
"@@@",
" @" +
" @ " +
"@@ " +
" @ " +
" @",
" @ " +
" @ " +
" " +
" @ " +
" @ ",
"@ " +
" @ " +
" @@" +
" @ " +
"@ ",
" " +
" @@" +
"@@ " +
" " +
" "
};
public static string getGlyph(char code) {
return glyphs[code-offset];
}
}
public class Graphics {
public readonly int width;
public readonly int height;
private IMyTextPanel console;
private string[] screen;
public int[] bgc;
public int[] fgc;
private int[] fgMix;
private int[] bgMix;
private string[][] fgDither;
private string[][] bgDither;
public Graphics(int w, int h, IMyTextPanel c) {
width = w;
height = h;
console = c;
screen = new string[height*width];
setFG(255,255,255);
setBG(0,0,0);
}
public void setFG(int r, int g, int b) {
fgc = new int[3];
fgc[0] = r;
fgc[1] = g;
fgc[2] = b;
fgMix = ColorUtils.createMix(fgc);
fgDither = ColorUtils.genDitherPattern(fgMix);
}
public void setBG(int r, int g, int b) {
bgc = new int[3];
bgc[0] = r;
bgc[1] = g;
bgc[2] = b;
bgMix = ColorUtils.createMix(bgc);
bgDither = ColorUtils.genDitherPattern(bgMix);
}
public void paint() {
string[] s = new string[width*height+height-1];
int o = 0;
for (int i=0; i < width*height; i++) {
int x = i%width;
if (x == 0 && i > 0) {
s[o++] = "\n";
}
s[o++] = screen[i];
}
console.WritePublicText(string.Concat(s));
console.ShowTextureOnScreen();
console.ShowPublicTextOnScreen();
}
public void clear() {
for (int i = 0; i < width*height; i++) {
screen[i] = bgDither[(i%width)&7][(i/width)&7];
}
}
public void pixel(int x, int y) {
if (x > 0 && x < width && y > 0 && y < height) {
screen[width*y + x] = fgDither[x&7][y&7];
}
}
public void line(int x0, int y0, int x1, int y1) {
if (x0 == x1) {
for (int y = y0; y <= y1; y++) {
pixel(x0,y);
}
} else if (y0 == y1) {
for (int x = x0; x <= x1; x++) {
pixel(x,y0);
}
} else { //add a case for 45 degree lines at some point
double dy = y1 - y0;
double err = 0;
double slope = Math.Abs(dy / (x1 - x0));
int ndy = Math.Sign(dy);
int y = y0;
for (int x = x0; x <= x1; x++) {
pixel(x,y);
err = err + slope;
while (err >= 0.5) {
pixel(x,y);
y += ndy;
err--;
}
}
}
}
public void rect(string m, int xb, int yb, int w, int h) {
if (m == "line") {
line(xb, yb, xb, yb+h-1);
line(xb, yb, xb+w-1, yb);
line(xb+w-1, yb, xb+w-1, yb+h-1);
line(xb, yb+h-1, xb+w-1, yb+h-1);
} else if (m == "fill") {
for (int x = xb; x < xb+w; x++) {
for (int y = yb; y < yb+h; y++) {
pixel(x,y);
}
}
}
}
public void ellipse(string m, int cx, int cy, int rx, int ry) {
int rx2 = rx*rx;
int ry2 = ry*ry;
if (m == "fill") {
int rxsys = rx2*ry2;
pixel(cx, cy);
for (int i=1; i < rx*ry; i++) {
int x = i % rx;
int y = i / rx;
if (ry2*x*x+rx2*y*y <= rxsys) {
pixel(cx+x, cy+y);
pixel(cx-x, cy-y);
//if (x && y) { //unnecessary (prevents overdrawing pixels)
pixel(cx+x, cy-y);
pixel(cx-x, cy+y);
//}
}
}
} else if (m == "line") {
int frx2 = 4 * rx2;
int fry2 = 4 * ry2;
int s = 2*ry2+rx2*(1-2*ry);
int y = ry;
for (int x = 0; ry2*x <= rx2*y; x++) {
pixel(cx + x, cy + y);
pixel(cx - x, cy + y);
pixel(cx + x, cy - y);
pixel(cx - x, cy - y);
if (s >= 0) {
s += frx2 * (1 - y);
y--;
}
s += ry2 * ((4 * x) + 6);
}
y = 0;
s = 2*rx2+ry2*(1-2*rx);
for (int x = rx; rx2*y <= ry2*x; y++) {
pixel(cx + x, cy + y);
pixel(cx - x, cy + y);
pixel(cx + x, cy - y);
pixel(cx - x, cy - y);
if (s >= 0) {
s += fry2 * (1 - x);
x--;
}
s += rx2 * ((4 * y) + 6);
}
}
}
public void circle(string m, int cx, int cy, int r) {
if (m == "fill") {
int rr = r*r;
pixel(cx, cy);
for (int i=1; i < r*r; i++) {
int x = i % r;
int y = i / r;
if (x*x+y*y < rr) {
pixel(cx+x, cy+y);
pixel(cx-x, cy-y);
if (x>0 && y>0) {
pixel(cx+x, cy-y);
pixel(cx-x, cy+y);
}
}
}
} else if (m == "line") {
int x = r;
int y = 0;
int do2 = 1 - x;
while (y <= x) {
pixel(cx+x, cy+y);
pixel(cx+y, cy+x);
pixel(cx-x, cy+y);
pixel(cx-y, cy+x);
pixel(cx-x, cy-y);
pixel(cx-y, cy-x);
pixel(cx+x, cy-y);
pixel(cx+y, cy-x);
y++;
if (do2 <= 0) {
do2 += 2 * y + 1;
} else {
do2 += 2 * (y - --x) + 1;
}
}
}
}
public void print(int x, int y, string text) {
int x1 = x;
int y1 = y;
for (int i = 0; i < text.Length; i++) {
switch(text[i]) {
case '\n':
y1 += 6;
x1 = x;
break;
case ' ':
x1 += 4;
break;
default:
string glyph = Ascii.getGlyph(text[i]);
for (int j = 0; j < 15; j++) {
if (glyph[j] == '@') {
pixel(x1+j%3, y1-4+j/3);
}
}
x1 += 4;
break;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment