#include <TFT_eSPI.h> // TFT_eSPI automatically uses User_Setup.h
#include "Image.h"
#include <Adafruit_FT6206.h>
TFT_eSPI tft = TFT_eSPI();
Adafruit_FT6206 ts;
void Text(int x, int y, int size, int color, String msg) {
tft.setFreeFont(&FreeSerif9pt7b);
tft.setCursor(x,y);
tft.setTextSize(size);
tft.setTextColor(color);
tft.print(msg);
}
int touch_x() {
TS_Point point = ts.getPoint();
return 240-point.x;
}
int touch_y() {
TS_Point point = ts.getPoint();
return 320-point.y;
}
int checkSwipe() {
int x[6] = {0}, y[6] = {0};
int idx = 0;
while(ts.touched() && idx < 6) {
x[idx] = touch_x();
y[idx] = touch_y();
idx++; delay(10);
}
if(abs(y[5]-y[0]) > abs(x[5]-x[0])) {
if(y[5] > y[0]) {
return 3;
} else return 1;
} else {
if(x[5] > x[0]) {
if(x[0] < 5) return -1; // back
return 0;
} else {
if(x[0] > 245) return -1; // back
return 2;
}
}
return -2; // -2 means touch
}
uint16_t saturator(uint16_t color, int sat) {
int8_t r = (color >> 11) & 0x1f;
int8_t g = (color >> 5) & 0x3f;
int8_t b = color & 0x1f;
int8_t avg = (r+ 0.5*g + b)/3;
r = avg + ((r - avg) * sat)/100;
g = 2*avg + ((g - 2*avg) * sat)/100;
b = avg + ((b - avg) * sat)/100;
if(r > 0x1f) r = 0x1f;
else if(r < 0x0) r = 0x0;
if(g > 0x3f) g = 0x3f;
else if(g < 0x0) g = 0x0;
if(b > 0x1f) b = 0x1f;
else if(b < 0x0) b = 0x0;
return (r << 11) | (g << 5) | b;
}
uint16_t adjustBrightness(uint16_t color, int brightness ) {
uint16_t r = (color >> 11) & 0x1f; //0b11111;
uint16_t g = (color >> 5) & 0x3f; //0b111111;
uint16_t b = color & 0x1f; //0b11111;
r = (r * brightness)/100;
g = (g * brightness)/100;
b = (b * brightness)/100;
if(r > 0x1f) r = 0x1f;
if(g > 0x3f) g = 0x3f;
if(b > 0x1f) b = 0x1f;
return (r<<11) | (g<<5) | b;
}
uint16_t mixer(uint16_t color1, uint16_t color2, int mix) {
uint16_t frontColor = adjustBrightness(color1, 100-mix);
uint16_t r1 = (frontColor >> 11) & 0x1f;
uint16_t g1 = (frontColor >> 5) & 0x3f;
uint16_t b1 = frontColor & 0x1f;
uint16_t r2 = (color2 >> 11) & 0x1f;
uint16_t g2 = (color2 >> 5) & 0x3f;
uint16_t b2 = color2 & 0x1f;
r1 = r1 + (r2*mix)/100;
g1 = g1 + (g2*mix)/100;
b1 = b1 + (b2*mix)/100;
return (r1 << 11) | (g1 << 5) | b1;
}
void drawOption(int x, int y, uint16_t color) {
for(int i=0; i<7; i++) {
if(i==2 || i==3 || i==4) continue;
tft.drawLine(x+5, y+2+i, x+25, y+2+i, color);
}
for(int i=0; i<3; i++) {
tft.drawLine(x+10+i, y, x+10+i, y+5, color);
tft.drawLine(x+20-i, y+5, x+20-i, y+10, color);
}
Text(x,y+28, 1, color, "Edit");
}
void drawBrightnessLogo(int x, int y, uint16_t color) {
tft.drawCircle(x, y, 3, color);
for(int i=0; i<360; i+=45) {
tft.fillCircle(x + 7*cos((i*3.14)/180), y + 7*sin((i*3.14)/180), 1, color);
}
}
void drawFilterLogo(int x, int y, uint16_t color) {
tft.drawCircle(x-3, y+3, 5, color);
tft.drawCircle(x+3, y+3, 5, color);
tft.drawCircle(x, y-2, 5, color);
}
void drawMixerLogo(int x, int y, uint16_t color) {
for(int i=0; i<16; i++) {
for(int j=0; j<16; j++) {
if((i+j)%2 != 0) continue;
tft.drawPixel(x-4+j, y-8+i, color);
}
}
}
void drawSaturatorLogo(int x, int y, uint16_t color) {
for(int i=0; i<16; i++) {
if(i%3 == 0) continue;
int r = 8*sin((3.14*i)/16);
tft.drawRect(x-r, y-8+i, 2*r, 1, mixer(color, 0xffff, 60-3*i));
}
}
void drawBackKey(int x, int y, uint16_t color) {
tft.drawLine(x,y+8, x+8, y, color);
tft.drawLine(x+1,y+8, x+9, y, color);
tft.drawLine(x,y+8, x+8, y+16, color);
tft.drawLine(x+1,y+8, x+9, y+16, color);
}
void drawEditInterface(int x, int y, uint16_t color) {
drawBrightnessLogo(x-40, y, color);
drawFilterLogo(x, y, color);
drawMixerLogo(x+40, y, color);
drawSaturatorLogo(x+88, y, color);
drawBackKey(5,5, 0x0);
}
void showImage(int x, int y, int h, int w, const uint16_t *imageData) {
uint16_t tempData[w];
for(int i=0; i<h; i++) {
for(int j=0; j<w; j++) {
uint16_t color = imageData[i*w+j];
tempData[j] = (color >> 8) | (color << 8);
}
tft.pushImage(x,y+i,w,1, tempData);
}
}
void showMixedImage(int x, int y, int h, int w, int mix, const uint16_t *imageData1, const uint16_t *imageData2) {
uint16_t tempData[w];
for(int i=0; i<h; i++) {
for(int j=0; j<w; j++) {
uint16_t color = mixer(imageData1[i*w+j], imageData2[i*w+j], mix);
tempData[j] = (color >> 8) | (color << 8);
}
tft.pushImage(x,y+i,w,1, tempData);
}
}
void showFilteredImage(int x, int y, int h, int w, int mix, const uint16_t *imageData1, const uint16_t filterColor) {
uint16_t tempData[w];
for(int i=0; i<h; i++) {
for(int j=0; j<w; j++) {
uint16_t color = mixer(imageData1[i*w+j], filterColor, mix);
tempData[j] = (color >> 8) | (color << 8);
}
tft.pushImage(x,y+i,w,1, tempData);
}
}
void showSaturatedImage(int x, int y, int h, int w, int sat, const uint16_t *imageData) {
uint16_t tempData[w];
for(int i=0; i<h; i++) {
for(int j=0; j<w; j++) {
uint16_t color = saturator(imageData[i*w+j], sat);
tempData[j] = (color >> 8) | (color << 8);
}
tft.pushImage(x,y+i,w,1, tempData);
}
}
void showBrightnessAdjustedImage(int x, int y, int h, int w, int brightness, const uint16_t *imageData) {
uint16_t tempData[w];
for(int i=0; i<h; i++) {
for(int j=0; j<w; j++) {
uint16_t color = adjustBrightness(imageData[i*w+j], brightness);
tempData[j] = (color >> 8) | (color << 8);
}
tft.pushImage(x,y+i,w,1, tempData);
}
}
void drawSelectPin(int x, int y, uint32_t color) {
tft.drawPixel(x, y-3, color);
tft.fillRect(x-1, y-5, 3, 2, color);
tft.drawPixel(x, y+3, color);
tft.fillRect(x-1, y+4, 3, 2, color);
}
uint16_t rainbow(int n) {
uint16_t color = 0xf800;
uint8_t r = (color >> 11) & 0x1f; //0b11111;
uint8_t g = (color >> 5) & 0x3f; //0b111111;
uint8_t b = color & 0x1f; //0b11111;
if(n>=0 && n<32) {
return (r << 11) | ((uint8_t(2*n) + g) << 5) | b;
} else if(n>=32 && n<64) {
return ((r - uint8_t(n-32)) << 11) | ((uint8_t(63) + g) << 5) | b;
} else if(n>=64 && n<96) {
return ((r - uint8_t(31)) << 11) | ((uint8_t(63) + g) << 5) | (uint8_t(n-64) + b);
} else if(n>=96 && n<128) {
return ((r - uint8_t(31)) << 11) | ((uint8_t(2*(127-n)) + g) << 5) | uint8_t(31) + b;
} else if(n>=128 && n<160) {
return ((r - uint8_t(159-n)) << 11) | (g << 5) | uint8_t(31) + b;
} else if(n>=160 && n<192) {
return (r << 11) | (g << 5) | uint8_t(191-n) + b;
} else if(n>=192 && n<196) {
return 0xffff;
} else return 0x0;
}
void editImage(const uint16_t *image1, const uint16_t *image2) {
bool run = true;
bool selectBrightness = false;
bool selectFilter = false;
bool selectMixer = false;
bool selectSaturator = false;
int selectFilterColor = 100;
int filterStrength = 20;
uint16_t filterColor = rainbow(selectFilterColor);
int sat = 100;
int brightness = 100;
int mix = 50;
while(run) {
if(!ts.touched()) continue;
if(touch_x() > 4 && touch_x() < 14 && touch_y() > 4 && touch_y() < 22) return;
if(checkSwipe() == -1) return;
if(touch_x() > 72 && touch_x() < 88 && touch_y() > 298 && touch_y() < 315) {
tft.fillRect(4, 265, 232, 30, 0xffff);
drawEditInterface(120, 307, 0x0);
drawBrightnessLogo(80, 307, 0x1f);
for(int i=0; i<160; i++) {
tft.drawLine(i+40, 283, i+40, 285, adjustBrightness(0x421f, i+20));
}
tft.drawLine(120, 282, 120, 286, 0x421f);
drawSelectPin(20+brightness, 284, 0x0);
selectBrightness = true;
selectFilter = false;
selectMixer = false;
selectSaturator = false;
}
else if(touch_x() > 110 && touch_x() < 130 && touch_y() > 298 && touch_y() < 315) {
tft.fillRect(4, 265, 232, 30, 0xffff);
drawEditInterface(120, 307, 0x0);
drawFilterLogo(120, 307, 0x1f);
for(int i=0; i<200; i++) {
tft.drawLine(i+20, 288, i+20, 290, rainbow(i));
}
tft.fillRect(40, 270, 160, 5, 0xa51f);
tft.fillRect(40, 270, 2*filterStrength, 5, 0x1f);
drawSelectPin(20 + selectFilterColor, 289, 0x0);
selectBrightness = false;
selectFilter = true;
selectMixer = false;
selectSaturator = false;
}
else if(touch_x() > 156 && touch_x() < 172 && touch_y() > 298 && touch_y() < 315) {
tft.fillRect(4, 265, 232, 30, 0xffff);
drawEditInterface(120, 307, 0x0);
drawMixerLogo(160, 307, 0x1f);
for(int i=0; i<=200; i++) {
tft.drawLine(20+i,282, 20+i,286, mixer(0x1f, 0x7e0, i/2));
}
drawSelectPin(20 + 2*mix, 284, 0x0);
drawSelectPin(21 + 2*mix, 284, 0x0);
selectBrightness = false;
selectFilter = false;
selectMixer = true;
selectSaturator = false;
}
else if(touch_x() > 196 && touch_x() < 212 && touch_y() > 298 && touch_y() < 315) {
tft.fillRect(4, 265, 232, 30, 0xffff);
drawEditInterface(120, 307, 0x0);
drawSaturatorLogo(208, 307, 0x1f);
for(int i=0; i<=200; i++) {
tft.drawLine(20+i,283, 20+i,285, saturator(0x629f, i)); //01100 010100 11111
}
tft.drawLine(120,282, 120, 286, 0x629f);
drawSelectPin(20 + sat, 284, 0x0);
selectBrightness = false;
selectFilter = false;
selectMixer = false;
selectSaturator = true;
}
if(selectBrightness) {
if(touch_x() > 40 && touch_x() < 200 && touch_y() > 278 && touch_y() < 290) {
drawSelectPin(20+brightness, 284, 0xffff);
brightness = touch_x() - 20;
drawSelectPin(20+brightness, 284, 0x0);
showBrightnessAdjustedImage(4, 30, 232, 232, brightness, image1);
}
} else if(selectFilter) {
if(touch_x() >20 && touch_x() < 220 && touch_y() > 283 && touch_y() < 295) {
drawSelectPin(20+selectFilterColor, 289, 0xffff);
selectFilterColor = touch_x() - 20;
filterColor = rainbow(selectFilterColor);
drawSelectPin(20+selectFilterColor, 289, 0x0);
showFilteredImage(4, 30, 232, 232, filterStrength, image1, filterColor);
} else if(touch_x() >= 40 && touch_x() <= 200 && touch_y() >= 270 && touch_y() <= 275) {
tft.fillRect(40, 270, 160, 5, 0xa51f);
filterStrength = (touch_x() - 40)/2;
tft.fillRect(40, 270, 2*filterStrength, 5, 0x1f);
showFilteredImage(4, 30, 232, 232, filterStrength, image1, filterColor);
}
} else if(selectMixer) {
if(touch_x() > 20 && touch_x() < 220 && touch_y() > 280 && touch_y() < 288) {
drawSelectPin(20 + 2*mix, 284, 0xffff);
drawSelectPin(21 + 2*mix, 284, 0xffff);
mix = (touch_x() - 20) / 2;
drawSelectPin(20 + 2*mix, 284, 0x0);
drawSelectPin(21 + 2*mix, 284, 0x0);
showMixedImage(4, 30, 232, 232, mix, image1, image2);
}
} else if(selectSaturator) {
if(touch_x() > 20 && touch_x() < 220 && touch_y() > 280 && touch_y() < 288) {
drawSelectPin(20 + sat, 284, 0xffff);
sat = touch_x() - 20;
drawSelectPin(20 + sat, 284, 0x0);
showSaturatedImage(4, 30, 232, 232, sat, image1);
}
}
}
return;
}
int state = 0;
int imageSelection = 0;
bool option = false;
void setup() {
tft.init();
ts.begin();
tft.fillScreen(0xffff);
Serial.begin(9600);
}
void loop() {
if(!option) {
drawOption(105, 275, 0x0);
option = true;
}
if(state == 0) {
Text(80, 20, 1, 0xf, "Image-"+String(imageSelection+1));
if(imageSelection == 0)
showImage(4, 30, 232, 232, Image1);
else if(imageSelection == 1)
showImage(4, 30, 232, 232, Image2);
state++;
}
else if(state == 1) {
if(ts.touched()) {
if(touch_x() > 4 && touch_x() < 232+4 && touch_y() > 30 && touch_y() < 232+30) {
int swipe = checkSwipe();
Text(80, 20, 1, 0xffff, "Image-"+String(imageSelection+1));
if(swipe == 2) {
imageSelection++; if(imageSelection > 1) imageSelection = 1;
state = 0;
}
else if(swipe == 0) {
imageSelection--; if(imageSelection < 0) imageSelection = 0;
state = 0;
}
}
else if(touch_x() > 105 && touch_x() < 130 && touch_y() > 275 && touch_y() < 303) {
drawOption(105, 275, 0xffff);
drawEditInterface(120, 307, 0x0);
state++;
}
}
}
else if(state == 2) {
if(imageSelection == 0)
editImage(Image1, Image2);
else if(imageSelection == 1)
editImage(Image2, Image1);
drawBackKey(5,5, 0xffff);
tft.fillRect(4, 265, 232, 55, 0xffff);
drawOption(105, 275, 0x0);
state = 1;
}
}