123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- #include "methods.h"
- struct methods t[METHODS] = {
- { "superpos", &superpos },
- { "invert", &invert },
- { "flip", &flip },
- { "scanlines", &scanlines },
- { "burn", &burn },
- { "toon", &toon },
- { "toonextreme", &toonextreme },
- { "pinkify", &pinkify },
- { "morered", &morered },
- { "moregreen", &moregreen },
- { "moreblue", &moreblue },
- { "moreblack", &moreblack },
- { "lessred", &lessred },
- { "lessgreen", &lessgreen },
- { "lessblue", &lessblue },
- { "lessblack", &lessblack },
- { "averagered", &averagered },
- { "averagegreen", &averagegreen },
- { "averageblue", &averageblue },
- { "edge", &edge },
- //{ "gauss", &gauss },
- { "none", NULL }
- };
- void superpos(spng *png) {
- png_byte r, g, b;
- /* 235,180,93 for nixie accent */
- int accent_r = 255;
- int accent_g = 128;
- int accent_b = 255;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- r = ptr[0];
- g = ptr[1];
- b = ptr[2];
- ptr[0] = (b + ((x * 255) % 255) + y) % accent_r;
- ptr[1] = (r + ((x * 255) % 255) + y) % accent_g;
- ptr[2] = (g + ((x * 255) % 255) + y) % accent_b;
- }
- }
- }
- void invert(spng *png) {
- png_byte r, g, b;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- r = ptr[0];
- g = ptr[1];
- b = ptr[2];
- ptr[0] = 255 - r;
- ptr[1] = 255 - g;
- ptr[2] = 255 - b;
- }
- }
- }
- void flip(spng *png) {
- spng *copy = copypng(png);
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- png_byte* opp_row = copy->row_pointers[(png->height - 1) - y];
- if (y == png->height - y)
- continue;
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- png_byte *ptr2 = &(opp_row[x * png->channels]);
- ptr[0] = ptr2[0];
- ptr[1] = ptr2[1];
- ptr[2] = ptr2[2];
- }
- }
- freepng(copy);
- }
- void scanlines(spng *png) {
- /* for specific color accentuation */
- float accent_r = .911;
- float accent_g = 1.;
- float accent_b = .911;
- /* effect strength */
- float fx;
- /* scanline size */
- int size = 6;
- png_byte r, g, b;
- for (int y = 0; y < png->height; y++) {
- /* scanline relative pixel pos */
- int pos = y % size;
- /* booleans */
- if (pos >= (size / 2))
- fx = 1.;
- //else if (pos <= 1 || pos >= (size / 2) - 1)
- // fx = .75;
- else
- fx = .8;
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- r = ptr[0] * (fx * accent_r);
- g = ptr[1] * (fx * accent_g);
- b = ptr[2] * (fx * accent_b);
- ptr[0] = r;
- ptr[1] = g;
- ptr[2] = b;
- }
- }
- }
- void burn(spng *png) {
- float threshhold = .66;
- float reducer = .5;
- int biggest;
- png_byte r, g, b;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- r = ptr[0];
- g = ptr[1];
- b = ptr[2];
- biggest = r > g ? (r > b ? r : b) : (g > b ? g : b);
- if (r / 255. < threshhold && r != biggest)
- r *= reducer;
- if (g / 255. < threshhold && g != biggest)
- g *= reducer;
- if (b / 255. < threshhold && b != biggest)
- b *= reducer;
- ptr[0] = r;
- ptr[1] = g;
- ptr[2] = b;
- }
- }
- }
- void toonstep(spng *png, int step) {
- png_byte r, g, b;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- r = ptr[0];
- g = ptr[1];
- b = ptr[2];
- r -= r % step;
- g -= g % step;
- b -= b % step;
- ptr[0] = r;
- ptr[1] = g;
- ptr[2] = b;
- }
- }
- }
- void toon(spng *png) {
- toonstep(png, 16);
- }
- void toonextreme(spng *png) {
- toonstep(png, 32);
- }
- void pinkify(spng *png) {
- png_byte r, g, b;
- float r_to_g = 0.;
- float b_to_g = 0.;
- float mean_ratio = 0.;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- r = ptr[0];
- g = ptr[1];
- b = ptr[2];
- r_to_g = g / (r + 0.000001);
- b_to_g = g / (b + 0.000001);
- mean_ratio = (r_to_g + b_to_g) / 2;
- if (mean_ratio > 1)
- g *= .1;
- else
- g *= mean_ratio;
- b *= .9;
- r *= 1.4;
- ptr[0] = r > 255 ? 255 : r;
- ptr[1] = g < 0 ? 0 : g;
- ptr[2] = b;
- }
- }
- }
- void more_x(spng *png, int index) {
- // three separate color components
- png_byte c1, c2, c3;
- int o1 = (index + 1) % 3, o2 = (index + 2) % 3;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- // get three color components
- c1 = ptr[index];
- c2 = ptr[o1];
- c3 = ptr[o2];
- ptr[index] = (c1 * 1.1) > MAX_BRT ? MAX_BRT : (c1 * 1.1);
- ptr[o1] = c2;
- ptr[o2] = c3;
- }
- }
- }
- void morered(spng *png) {
- more_x(png, 0);
- }
- void moregreen(spng *png) {
- more_x(png, 1);
- }
- void moreblue(spng *png) {
- more_x(png, 2);
- }
- void moreblack(spng *png) {
- // three separate color components
- png_byte c1, c2, c3;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- // get three color components
- c1 = ptr[0];
- c2 = ptr[1];
- c3 = ptr[2];
- ptr[0] = c1 * .9;
- ptr[1] = c2 * .9;
- ptr[2] = c3 * .9;
- }
- }
- }
- void less_x(spng *png, int index) {
- // three separate color components
- png_byte c1, c2, c3;
- int o1 = (index + 1) % 3, o2 = (index + 2) % 3;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- // get three color components
- c1 = ptr[index];
- c2 = ptr[o1];
- c3 = ptr[o2];
- ptr[index] = c1 * .9;
- ptr[o1] = c2;
- ptr[o2] = c3;
- }
- }
- }
- void lessred(spng *png) {
- less_x(png, 0);
- }
- void lessgreen(spng *png) {
- less_x(png, 1);
- }
- void lessblue(spng *png) {
- less_x(png, 2);
- }
- void lessblack(spng *png) {
- // three separate color components
- png_byte c1, c2, c3;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- // get three color components
- c1 = ptr[0];
- c2 = ptr[1];
- c3 = ptr[2];
- ptr[0] = (c1 * 1.1) > MAX_BRT ? MAX_BRT : (c1 * 1.1);
- ptr[1] = (c2 * 1.1) > MAX_BRT ? MAX_BRT : (c2 * 1.1);
- ptr[2] = (c3 * 1.1) > MAX_BRT ? MAX_BRT : (c3 * 1.1);
- }
- }
- }
- void average_x(spng *png, int index) {
- // three separate color components
- png_byte c2, c3;
- int o1 = (index + 1) % 3, o2 = (index + 2) % 3;
- for (int y = 0; y < png->height; y++) {
- png_byte* row = png->row_pointers[y];
- for (int x = 0; x < png->width; x++) {
- png_byte *ptr = &(row[x * png->channels]);
- // get three color components
- c2 = ptr[o1];
- c3 = ptr[o2];
- ptr[index] = (c2 + c3) / 2.;
- }
- }
- }
- void averagered(spng *png) {
- average_x(png, 0);
- }
- void averagegreen(spng *png) {
- average_x(png, 1);
- }
- void averageblue(spng *png) {
- average_x(png, 2);
- }
- void edge(spng *png) {
- float kernel[9] = {
- -1.0, -1.0, -1.0,
- -1.0, 8.0, -1.0,
- -1.0, -1.0, -1.0
- };
- apply_kernel(png, &kernel, 9);
- }
- void gauss(spng *png) {
- float kernel[9] = {
- .0625, .125, .0625,
- .125, 4.0, .125,
- .0625, .125, .0625
- };
- apply_kernel(png, &kernel, 9);
- }
- void apply_method(spng *png, void(*method)(spng*)) {
- (*method)(png);
- }
- void apply_kernel(spng *png, float (*kernel)[], int kernel_size) {
- spng *copy = copypng(png);
- /* TODO: make all this shit generic lol */
- for (int y = 0; y < png->height; y++) {
- int prev_y = y > 0 ? (y - 1) : 0;
- int next_y = y < png->height - 1 ? (y + 1) : y;
- /* acquire 3 by 3 matrix of pixels */
- png_byte* row[3] = {
- copy->row_pointers[prev_y],
- copy->row_pointers[y],
- copy->row_pointers[next_y]
- };
- /* acquire image row of target buffer */
- png_byte* orig_row = png->row_pointers[y];
- for (int x = 1; x < png->width; x++) {
- int prev_x = x > 0 ? (x - 1) : 0;
- int next_x = x < png->width - 1 ? (x + 1) : x;
- png_byte *ptr[9] = {
- &(row[0][prev_x * png->channels]),
- &(row[0][x * png->channels]),
- &(row[0][next_x * png->channels]),
- &(row[1][prev_x * png->channels]),
- &(row[1][x * png->channels]),
- &(row[1][next_x * png->channels]),
- &(row[2][prev_x * png->channels]),
- &(row[2][x * png->channels]),
- &(row[2][next_x * png->channels])
- };
- /* acquire pixel of target buffer */
- png_byte *orig_ptr = &(orig_row[x * png->channels]);
- /* 0 1 2 */
- /* 3 4 5 */
- /* 6 7 8 */
- /* where 4 represents the local pixel */
- png_byte r[9] = {
- ptr[0][0], ptr[1][0], ptr[2][0],
- ptr[3][0], ptr[4][0], ptr[5][0],
- ptr[6][0], ptr[7][0], ptr[8][0]
- };
- png_byte g[9] = {
- ptr[0][1], ptr[1][1], ptr[2][1],
- ptr[3][1], ptr[4][1], ptr[5][1],
- ptr[6][1], ptr[7][1], ptr[8][1]
- };
- png_byte b[9] = {
- ptr[0][2], ptr[1][2], ptr[2][2],
- ptr[3][2], ptr[4][2], ptr[5][2],
- ptr[6][2], ptr[7][2], ptr[8][2]
- };
- png_byte brt[9];
- /* luminance conversion */
- /* digital ITU BT.601 */
- /* 0.299 R + 0.587 G + 0.114 B */
- for (int i = 0; i < 9; i++)
- brt[i] =
- .299 * r[i] +
- .587 * g[i] +
- .114 * b[i];
- /* TODO: */
- /* obv not every kernel operation assumes luminance input */
- /* values, needs changing to */
- int lum = mult_by_kernel(&brt, kernel, kernel_size);
- orig_ptr[0] = lum;
- orig_ptr[1] = lum;
- orig_ptr[2] = lum;
- }
- }
- freepng(copy);
- }
- int mult_by_kernel(png_byte (*src)[], float (*kernel)[], int kernel_size) {
- float sum = 0;
- for (int i = 0; i < kernel_size; i++)
- sum += (*src)[i] * (*kernel)[(kernel_size - 1) - i];
- sum = sum < 0. ? 0. : sum;
- return (int)sum;
- }
|