NotMyFault Posted January 5, 2023 Posted January 5, 2023 Blend mode AND, OR, XOR with Affinity Photo Out of the box, you won’t find the blend modes AND, OR, XOR in Affinity Photo V1 or V2. Luckily there is the option to use the “Apply Image” filter which allows to create self-defined blend formulas. As the formulas are quite complex and long, the best way is copy the formulas into your favourite text editor, and copy/paste them into the filter one-by-one. The steps are relatively simple, but you need to follow an exact sequence of several steps to get it right. Preparation steps Have 2 pixel layers present in file, ideally of identical size (pixel x and y). I name the layers “destination” and “source” within this tutorial. The destination layer will be modified and show the result, the source layer stays unchanged. If you want to use vector layers, make a copy and rasterise them. Have text editor with formulas open parallel to Photo. There is one formula for every colour channel. The formulas are made specifically for RGB colour model. They can be adapted for any other colour model (GREY, CMYK, LAB) by search and replacing the variable names of colour channels. I leave this task as an exercise for the reader. Steps to blend 2 layers with your chosen formula (AND, OR, XOR) Select destination layer Choose Filter-> Apply Image Drag the source layer (from layer stack) into source area of the filter UI. The canvas will show the selected source area, as the default formula uses 100% of the colours from the source layer. You will change the formulas in the next step Activate box “Equations” Copy / paste the 3 formulas for the individual colour channels DR / DG / DB Click apply The destination layer shows the result Limitations Unfortunately, this filter is “destructive”, meaning it will be applied to a pixel layer and stores the result as pixel layer. As of Photo 2 V 2.0.3, there is no way to have this as non-destructive live filter. You can re-apply the filter, using the same formulas and source image, to other destination layers. If you want to use it on different source image data, you need to apply the filter again from scratch. Even worth, there is not easy way like preset to save the formulas inside Affinity. If you use the macro recorder, you will be bound to the source layer used when recording the macro. You can store the formulas as text layers within Affinity Photo, and optionally save / export them as Assets. The only advantage is having everything consolidated “inside” Photo, the workflows gets more complicated in case you try to use the text frames as source for copy/paste. Formula for AND R: (((((((irem(idiv(SR*255,128),2)*irem(idiv(DR*255,128),2)×2+irem(idiv(SR*255,64),2)*irem(idiv(DR*255,64),2))×2+irem(idiv(SR*255,32),2)*irem(idiv(DR*255,32),2))×2+irem(idiv(SR*255,16),2)*irem(idiv(DR*255,16),2))×2+irem(idiv(SR*255,8),2)*irem(idiv(DR*255,8),2))×2+irem(idiv(SR*255,4),2)*irem(idiv(DR*255,4),2))×2+irem(idiv(SR*255,2),2)*irem(idiv(DR*255,2),2))×2+irem(idiv(SR*255,1),2)*irem(idiv(DR*255,1),2))÷255 G: (((((((irem(idiv(SG*255,128),2)*irem(idiv(DG*255,128),2)×2+irem(idiv(SG*255,64),2)*irem(idiv(DG*255,64),2))×2+irem(idiv(SG*255,32),2)*irem(idiv(DG*255,32),2))×2+irem(idiv(SG*255,16),2)*irem(idiv(DG*255,16),2))×2+irem(idiv(SG*255,8),2)*irem(idiv(DG*255,8),2))×2+irem(idiv(SG*255,4),2)*irem(idiv(DG*255,4),2))×2+irem(idiv(SG*255,2),2)*irem(idiv(DG*255,2),2))×2+irem(idiv(SG*255,1),2)*irem(idiv(DG*255,1),2))÷255 B: (((((((irem(idiv(SG*255,128),2)*irem(idiv(DG*255,128),2)×2+irem(idiv(SG*255,64),2)*irem(idiv(DG*255,64),2))×2+irem(idiv(SG*255,32),2)*irem(idiv(DG*255,32),2))×2+irem(idiv(SG*255,16),2)*irem(idiv(DG*255,16),2))×2+irem(idiv(SG*255,8),2)*irem(idiv(DG*255,8),2))×2+irem(idiv(SG*255,4),2)*irem(idiv(DG*255,4),2))×2+irem(idiv(SG*255,2),2)*irem(idiv(DG*255,2),2))×2+irem(idiv(SG*255,1),2)*irem(idiv(DG*255,1),2))÷255 Formula for XOR (((((((1-abs(irem(idiv(SR*255,128),2)+irem(idiv(DR*255,128),2)-1)×2+1-abs(irem(idiv(SR*255,64),2)+irem(idiv(DR*255,64),2)-1))×2+1-abs(irem(idiv(SR*255,32),2)+irem(idiv(DR*255,32),2)-1))×2+1-abs(irem(idiv(SR*255,16),2)+irem(idiv(DR*255,16),2)-1))×2+1-abs(irem(idiv(SR*255,8),2)+irem(idiv(DR*255,8),2)-1))×2+1-abs(irem(idiv(SR*255,4),2)+irem(idiv(DR*255,4),2)-1))×2+1-abs(irem(idiv(SR*255,2),2)+irem(idiv(DR*255,2),2)-1))×2+1-abs(irem(idiv(SR*255,1),2)+irem(idiv(DR*255,1),2)-1))÷255 (((((((1-abs(irem(idiv(SG*255,128),2)+irem(idiv(DG*255,128),2)-1)×2+1-abs(irem(idiv(SG*255,64),2)+irem(idiv(DG*255,64),2)-1))×2+1-abs(irem(idiv(SG*255,32),2)+irem(idiv(DG*255,32),2)-1))×2+1-abs(irem(idiv(SG*255,16),2)+irem(idiv(DG*255,16),2)-1))×2+1-abs(irem(idiv(SG*255,8),2)+irem(idiv(DG*255,8),2)-1))×2+1-abs(irem(idiv(SG*255,4),2)+irem(idiv(DG*255,4),2)-1))×2+1-abs(irem(idiv(SG*255,2),2)+irem(idiv(DG*255,2),2)-1))×2+1-abs(irem(idiv(SG*255,1),2)+irem(idiv(DG*255,1),2)-1))÷255 (((((((1-abs(irem(idiv(SB*255,128),2)+irem(idiv(DB*255,128),2)-1)×2+1-abs(irem(idiv(SB*255,64),2)+irem(idiv(DB*255,64),2)-1))×2+1-abs(irem(idiv(SB*255,32),2)+irem(idiv(DB*255,32),2)-1))×2+1-abs(irem(idiv(SB*255,16),2)+irem(idiv(DB*255,16),2)-1))×2+1-abs(irem(idiv(SB*255,8),2)+irem(idiv(DB*255,8),2)-1))×2+1-abs(irem(idiv(SB*255,4),2)+irem(idiv(DB*255,4),2)-1))×2+1-abs(irem(idiv(SB*255,2),2)+irem(idiv(DB*255,2),2)-1))×2+1-abs(irem(idiv(SB*255,1),2)+irem(idiv(DB*255,1),2)-1))÷255 Formula for OR ((((((clamp(irem(idiv(SR*255,128),2)+irem(idiv(DR*255,128),2))×2+clamp(irem(idiv(SR*255,64),2)+irem(idiv(DR*255,64),2)))×2+clamp(irem(idiv(SR*255,32),2)+irem(idiv(DR*255,32),2)))×2+clamp(irem(idiv(SR*255,16),2)+irem(idiv(DR*255,16),2)))×2+clamp(irem(idiv(SR*255,8),2)+irem(idiv(DR*255,8),2)))×2+clamp(irem(idiv(SR*255,4),2)+irem(idiv(DR*255,4),2)))×2+clamp(irem(idiv(SR*255,2),2)+irem(idiv(DR*255,2),2)))×2+clamp(irem(idiv(SR*255,1),2)+irem(idiv(DR*255,1),2)))÷255 (((((((clamp(irem(idiv(SG*255,128),2)+irem(idiv(DG*255,128),2))×2+clamp(irem(idiv(SG*255,64),2)+irem(idiv(DG*255,64),2)))×2+clamp(irem(idiv(SG*255,32),2)+irem(idiv(DG*255,32),2)))×2+clamp(irem(idiv(SG*255,16),2)+irem(idiv(DG*255,16),2)))×2+clamp(irem(idiv(SG*255,8),2)+irem(idiv(DG*255,8),2)))×2+clamp(irem(idiv(SG*255,4),2)+irem(idiv(DG*255,4),2)))×2+clamp(irem(idiv(SG*255,2),2)+irem(idiv(DG*255,2),2)))×2+clamp(irem(idiv(SG*255,1),2)+irem(idiv(DG*255,1),2)))÷255 (((((((clamp(irem(idiv(SB*255,128),2)+irem(idiv(DB*255,128),2))×2+clamp(irem(idiv(SB*255,64),2)+irem(idiv(DB*255,64),2)))×2+clamp(irem(idiv(SB*255,32),2)+irem(idiv(DB*255,32),2)))×2+clamp(irem(idiv(SB*255,16),2)+irem(idiv(DB*255,16),2)))×2+clamp(irem(idiv(SB*255,8),2)+irem(idiv(DB*255,8),2)))×2+clamp(irem(idiv(SB*255,4),2)+irem(idiv(DB*255,4),2)))×2+clamp(irem(idiv(SB*255,2),2)+irem(idiv(DB*255,2),2)))×2+clamp(irem(idiv(SB*255,1),2)+irem(idiv(DB*255,1),2)))÷255 Source layer Destination Layer Blend Mode AND Blend Mode OR Blend Mode XOR Zero1 and Jung21 2 Quote Mac mini M1 A2348 | MBP M3 Windows 11 - AMD Ryzen 9 5900x - 32 GB RAM - Nvidia GTX 1080 LG34WK950U-W, calibrated to DCI-P3 with LG Calibration Studio / Spider 5 | Dell 27“ 4K iPad Air Gen 5 (2022) A2589 Special interest into procedural texture filter, edit alpha channel, RGB/16 and RGB/32 color formats, stacking, finding root causes for misbehaving files, finding creative solutions for unsolvable tasks, finding bugs in Apps. I use iPad screenshots and videos even in the Desktop section of the forum when I expect no relevant difference.
NotMyFault Posted January 20, 2024 Author Posted January 20, 2024 I now have an idea for a live filter version to create these blend modes. It will get messy as we need to create huge amounts of helper layers but should work: for 1 bit of color depth, you can use blend modes lighten to implement OR, and darken to implement AND. XOR based on Blend modes subtract over result from (lighten, darken) For 2 or more bit of color depth, we need to use linked layers or symbols to create one group per bit. isolate the corresponding bit from both layers, and store it as 0 or 1. Shift back the result (after blending) to the correct bit position (/ 2 ^ position) combine the results of each group using blend mode add @Ldinaare you interested into trying this as exercise? Quote Mac mini M1 A2348 | MBP M3 Windows 11 - AMD Ryzen 9 5900x - 32 GB RAM - Nvidia GTX 1080 LG34WK950U-W, calibrated to DCI-P3 with LG Calibration Studio / Spider 5 | Dell 27“ 4K iPad Air Gen 5 (2022) A2589 Special interest into procedural texture filter, edit alpha channel, RGB/16 and RGB/32 color formats, stacking, finding root causes for misbehaving files, finding creative solutions for unsolvable tasks, finding bugs in Apps. I use iPad screenshots and videos even in the Desktop section of the forum when I expect no relevant difference.
NotMyFault Posted January 20, 2024 Author Posted January 20, 2024 And here the formula for a pure live version for the bitwise blend modes: for RGB: var n1=vec3(pow(2,n)); var n255=vec3(255); irem (trunc (vec3(R,G,B)*n255 /n1), vec3(2)) *n1 /n255 Input: n (from 7 to 0) You need one high level group per pit of color depth, blend mode add. In every HL group, one group for top layer, with blend mode "lighten" or "darken" and optionally "invert adjustment" (same for all 8 groups of course in one file) one group for bottom layer, blend more "normal" a PT filter, and input n set to the bit depth. The demo file uses two symbol layers borrowed from Designer to simplify the usage as you could drop any layer content into the symbols, and resize the document to any x/y dimension. Could be extended to 16 bit color depth Could be extended to CMYK, GRAY, LAB color modes by adjusting the channel names (and using vec4 instead of vec3 for CMYK and scalars for GREY) blend mode binary OR symbol.afdesign TrentL 1 Quote Mac mini M1 A2348 | MBP M3 Windows 11 - AMD Ryzen 9 5900x - 32 GB RAM - Nvidia GTX 1080 LG34WK950U-W, calibrated to DCI-P3 with LG Calibration Studio / Spider 5 | Dell 27“ 4K iPad Air Gen 5 (2022) A2589 Special interest into procedural texture filter, edit alpha channel, RGB/16 and RGB/32 color formats, stacking, finding root causes for misbehaving files, finding creative solutions for unsolvable tasks, finding bugs in Apps. I use iPad screenshots and videos even in the Desktop section of the forum when I expect no relevant difference.
TrentL Posted January 24, 2024 Posted January 24, 2024 Thanks for the insight! It would be really nice if the equations supported some basic bitwise boolean operations. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.