Affinity Photo's Procedural Texture Filter System Variables
x, y, rx, ry, w, h, pi, ox, oy, R, G, B, A, C, M, Y, K
x is the horizontal pixel coordinate position beginning with 0 at the left edge of the document and increasing toward the right by 1 for each pixel.
y is the vertical pixel coordinate position beginning with 0 at the top edge of the document and increasing downward by 1 for each pixel.
rx and ry are relative pixel coordinates. These coordinates allow repositioning of the coordinate system in two ways. Double-clicking the mouse on the document moves the origin (ox,oy) to the current position of the mouse. Click and dragging moves the coordinate system from the current position to the position you drag it to.
ox and oy are the origin coordinates that can be repositioned by double-clicking in the image or clicking and dragging.
w is the width of the document in pixels, ie 1024
h is the height of the document in pixels, ie 768
pi is the geometric constant 3.14159265...
RGBA inputs
R contains the pixel information for the red channel in the document. It is not possible to access current image pixels individually from this variable. It is possible to modify the image using the channel outputs.
G contains the pixel information for the green channel.
B contains the pixel information for the blue channel.
A contains the pixel information for the alpha channel.
If the document is in CMYK mode, the letters C, M, Y, and K represent the color pixel information for the document. Note that you won't be able to access your RGB filters if the document is set to CMYK color mode.
p cannot be used as a custom input or as a variable name. p followed by a digit may not be used as a custom input but may be used to define a var variable. This includes p1, p2a, p304, etc.
Variable names must begin with a letter may only consist of numbers and letters, and _ (underscore) characters. Upper and lower case letters are allowed and a1 is not the same variable as A1. Space is not allowed nor are other special characters.
A 1024 x 768 landscape document would have an x value ranging from 0 to 1024, with 0 just to the left of the first pixel and 1024 just to the right of the last pixel. A value of x centered on the first pixel would be .5.
Here are some additional notes on some of the more confusing functions in the PTF that I haven't had a chance to make videos on yet:
rgbtoi(S r, S g, S b) or rgbtoi(V rgb) i is intensity, converts to a grayscale that is better than just taking the RGB average. A weighted average is taken based on color perception according to the following formula: .2989*R+.587*G+.114*B
cerp(T a, T b, T c, T d, T t) Cubic interpolation b and c seem to be the values being interpolated, t is the interpolant, a and d seem to control the slope of the interpolant.
It looks like d may be controlling the slope of the interplant at the endpoint (1) so when d=0 slope=0, d=1 slope=1, d=2 slope=2.
scint(T cui) S Curve interpolant Smooths out the interpolation
x y are pixel positions relative to the upper left corner
rx ry are pixel positions relative to the origin ox oy which can be changed using the mouse
Unknown: p pc pt px
Cannot be used as custom inputs: p p0 p1 p2 p3 p4 p5 (p followed by any number) however, these can be used as variable names.
Operators
+ - * / ^ ( ) . = ; ,
Exponentiation has the same priority as multiplication and division: a*b^c =(a*b)^c not a*(b^c).
I am making a series of video tutorials for Affinity Photo's procedural texture filter. This page provides an index for the functions used in each video.
This is used for an RC racing light tree. It stays red until you push the button, then stays yellow for 1-3 seconds (randomly), then flashes all colors twice, then stays green until you push the button. Weak pull-ups are enabled on pin 5 for the button.
/* * File: RaceLightsMain.c * Author: hmikelson * * Created on June 14, 2019, 1:26 PM */ #if defined(__XC) #include <xc.h> /* XC8 General Include File */ #elif defined(HI_TECH_C) #include <htc.h> /* HiTech General Include File */ #endif #include <stdint.h> /* For uint8_t definition */ #include <stdbool.h> /* For true/false definition */ #include <stdlib.h> /*rand()*/ #pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO #define _XTAL_FREQ 4000000 uint8_t sGPIO; void init() { //Configure GPIO Port ANSEL = 0b00000000; //Configure all GPIO pins as digital TRISIO = 0b11101000; //Set GP3 & 5 as input and the rest as outputs OPTION_REGbits.nGPPU = 0; WPU = 0b00100000; //Enable weak pullups on GP5 //Configuer AD Convertor ADCON0 = 0x00; //AD disabled ADRESH = 0x00; //Init the AD Register //Configure Comparator CMCON0 = 0xFF; // Comparator is turned off CMCON1 = 0x00; // Comparator is turned off //Interrupt configuration INTCON = 0x00; //Disable all interrupts } void vdelay(int n) { int i; for (i=0;i<=n;i++) { __delay_ms(150); } } void main() { uint8_t r, db_cnt; init(); GPIO = 0b00000001; __delay_ms(100); GPIO = 0b00000010; __delay_ms(100); GPIO = 0b00000100; __delay_ms(100); GPIO = 0b00000000; while(1) { GPIO = 0b00000001; __delay_ms(200); for (db_cnt = 0; db_cnt <= 10; db_cnt++) { __delay_ms(10); if (GPIObits.GP5 == 1) db_cnt = 0; } GPIO = 0b00000010; r = rand()%15; __delay_ms(250); vdelay(r); __delay_ms(250); GPIO = 0b00000001; __delay_ms(50); GPIO = 0b00000010; __delay_ms(50); GPIO = 0b00000100; __delay_ms(50); GPIO = 0b00000001; __delay_ms(50); GPIO = 0b00000010; __delay_ms(50); GPIO = 0b00000100; __delay_ms(50); GPIO = 0b00000100; __delay_ms(200); for (db_cnt = 0; db_cnt <= 10; db_cnt++) { __delay_ms(10); if (GPIObits.GP5 == 1) db_cnt = 0; } } }
Code for autonomous robot with PIR motion detection and ultrasound distance sensor. Distance sensing decreases the chance of the robot getting stuck. Robot also plays sounds while moving.
/* * File: BackupBotMain.c * Author: hmikelson * * Created on January 12, 2019, 11:32 AM * * This program is used to control a robot with PIC16f1825 microcontroller * Uses a customized circuit board with a 1 watt amplified speaker * high intensity LED * Ultrasound sensor, and PIR sensor * Two motors: Forward, backward, right, left, stop * 6V battery power * Gear driven wheels */ #include <xc.h> #include <stdio.h> #include <stdlib.h> #pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSC #define _XTAL_FREQ 16000000 unsigned char sPORTA=0b00000000, sPORTC=0b00000000, pwmax=63; void init() { //Configure GPIO Port //RA0=BI2,RA1=BI1,RA2=Stby,RC0=AI1,RC1=AI2,RC2=PWMA&B //RC3=PIR,RC4=Trig,RC5=Echo,RA3=NA,RA4=Audio,RA5=LED //ANSELC= 0b00000000; //Must disable analog inputs to read digital in TRISA = 0b11000000; //O=all TRISC = 0b11101000; //I=3,5 OSCCONbits.IRCF = 0b1111; OSCCONbits.SCS = 0b00; //Enable analog input on C3 ANSELCbits.ANSC3 = 1; ADCON0 = 0b00011101; //Channel (CHS4:0 bits 6-2),ADON bit 1 enable Analog ADCON1bits.ADCS = 0b111; // clock select dedicated osc ADCON1bits.ADNREF = 0; //neg ref ADCON1bits.ADPREF = 0; //config + voltage with vdd ADCON1bits.ADFM = 1; //format left justified ADRESH = 0x00; //Init the AD Register } void vdelay(int n) { int i; for (i=0;i<=n;i++) { __delay_us(5); } } // Read voltage from input int read_v() { int val,v1,v2; __delay_ms(1); ADCON0bits.GO_nDONE = 1; while(ADCON0bits.GO_nDONE == 1); return (ADRESH<<8) + ADRESL; } /* * Get distance from ultra sound sensor * Sensor on pins C4 Trig, C5 Echo * */ int getdist() { int i=0; sPORTC = sPORTC & 0b11101111; PORTC = sPORTC; __delay_us(40); sPORTC = sPORTC | 0b00010000; PORTC = sPORTC; __delay_us(10); sPORTC = sPORTC & 0b11101111; PORTC = sPORTC; while((PORTCbits.RC5 == 0) && (i<5000)) //Wait but not forever { i++; } i=0; while ((PORTCbits.RC5 == 1) && (i<1000)) //Wait but not forever { i++; } return i; } // Drive robot forward void RobotFd(int time, unsigned char speed) { int i, j; for (i=0;i<time;i++) { for (j=0;j<pwmax;j++) { if (j<speed) { PORTA = 0b00111110; // LED,Aud,MCLR,En,BI2,BI1 sPORTC=0b00000110 | sPORTC; sPORTC=0b11111110 & sPORTC; PORTC = sPORTC; // Eco,Trg,PIR,PWM,AI1,AI2 vdelay(pwmax/speed); } else { PORTA = 0b00000110; sPORTC = 0b00000010 | sPORTC; sPORTC = 0b11111010 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } } } } // Move Robot backward void RobotBk(int time, unsigned char speed) { int i, j; for (i=0;i<time;i++) { for (j=0;j<pwmax;j++) { if (j<speed) { PORTA = 0b00111101; sPORTC = 0b00000101 | sPORTC; sPORTC = 0b11111101 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } else { PORTA = 0b00000101; sPORTC = 0b00000001 | sPORTC; sPORTC = 0b11111001 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } } } } // Move the robot right for time at speed. void RobotRt(int time, unsigned char speed) { int i, j; for (i=0;i<time;i++) { for (j=0;j<pwmax;j++) { if (j<speed) { PORTA = 0b00111110; sPORTC = 0b00000101 | sPORTC; sPORTC = 0b11110101 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } else { PORTA = 0b00000110; sPORTC = 0b00000001 | sPORTC; sPORTC = 0b11111001 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } } } } //Move the Robot Left for given time and speed. void RobotLt(int time, unsigned char speed) { int i, j; for (i=0;i<time;i++) { for (j=0;j<pwmax;j++) { if (j<speed) { PORTA = 0b00111101; sPORTC = 0b00000110 | sPORTC; sPORTC = 0b11111110 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } else { PORTA = 0b00000101; sPORTC = 0b00000010 | sPORTC; sPORTC = 0b11111010 & sPORTC; PORTC = sPORTC; vdelay(pwmax/speed); } } } } // Robot stops for the given amount of time void RobotSt(int time) { int i; for (i=0;i<time;i++) { PORTA = 0b00000100; sPORTC = 0b00000100 | sPORTC; sPORTC = 0b11111100 & sPORTC; PORTC = sPORTC; __delay_ms(10); } } void main() { int mt=100,dist=1000,i; unsigned char rspeed, raction, rtime, nacts=30, pir; init(); RobotFd(200,pwmax/1.5); RobotRt(200,pwmax/1.5); RobotBk(200,pwmax/1.5); RobotLt(200,pwmax/1.5); while(1) { while (nacts==0) { RobotSt(200); pir = read_v(); if (pir>50) { nacts = 30; } } dist = getdist(); if (dist<300) { RobotBk(mt,pwmax/2); RobotRt(mt,pwmax/2); } else { RobotFd(mt,pwmax/2); } nacts = nacts - 1; raction=(rand() % 5); rtime=(rand() % mt)/2+mt/2; rspeed=pwmax/((rand() % 15)+1)+pwmax/5; switch (raction) { case 1: RobotFd(rtime,rspeed); break; case 2: RobotBk(rtime,rspeed); break; case 3: RobotLt(rtime,rspeed); break; case 4: RobotRt(rtime,rspeed); break; default: RobotSt(rtime); break; } } }