ref: 2f61e9979e69ab014cdd44ea71fa787ea3454446
parent: f8d65f9f1c74b101cccfdc08250e31c5e554b899
author: sirjofri <[email protected]>
date: Mon Aug 26 09:25:10 EDT 2024
transparent background, filter layer/editor
--- a/blie.c
+++ b/blie.c
@@ -46,6 +46,20 @@
vdata.fontheight = p.y;
vdata.gray = allocimagemix(display, DBlack, DWhite);
+ vdata.mgray = allocmemimage(Rect(0, 0, 1, 1), GREY8);
+ memfillcolor(vdata.mgray, 0xaaaaaaff);
+ vdata.mgray->flags |= Frepl|Fbytes|Fsimple;
+
+ vdata.transparent = allocimage(display, Rect(0, 0, 50, 50), RGB24, 1, 0xccccccff);
+ draw(vdata.transparent, Rect(0, 25, 25, 50), vdata.gray, nil, ZP);
+ draw(vdata.transparent, Rect(25, 0, 50, 25), vdata.gray, nil, ZP);
+
+ vdata.mtransparent = allocmemimage(Rect(0, 0, 50, 50), RGB24);
+ vdata.mtransparent->flags |= Frepl|Fbytes;
+ memfillcolor(vdata.mtransparent, 0xccccccff);
+ vdata.mgray->clipr = vdata.mtransparent->r;
+ memimagedraw(vdata.mtransparent, Rect(0, 25, 25, 50), vdata.mgray, ZP, nil, ZP, S);
+ memimagedraw(vdata.mtransparent, Rect(25, 0, 50, 25), vdata.mgray, ZP, nil, ZP, S);
}
Vstate vstate = {
@@ -197,6 +211,8 @@
{
Memimage *img[2]; /* swapchain */
int i;
+
+ draw(panels.drawing, panels.drawing->r, vdata.transparent, nil, ZP);
if (estate.ed && estate.ed->overlay) {
if (estate.ed->overlay(estate.l, nil)) {
--- a/blie.h
+++ b/blie.h
@@ -39,7 +39,10 @@
int keyoffset; /* offset on key input */
float keyzoom; /* zoom change */
+ Image *transparent;
Image *gray;
+ Memimage *mgray;
+ Memimage *mtransparent;
};
enum {
@@ -89,6 +92,7 @@
};
extern Editor p9image;
+extern Editor efilter;
void loadeditors(void);
int addeditor(Editor*);
@@ -100,6 +104,10 @@
Memimage* ecomposite(Layer*, Memimage*);
Point scalepos(Point);
+uchar rgb2k(uchar r, uchar g, uchar b);
+uchar ilerp(uchar A, uchar B, uchar α);
+double flerp(double A, double B, double α);
+uchar imul(uchar A, uchar B);
Memimage* gencomposite(Memimage*, Memimage*, Memimage*, Drawop);
Memimage* gencanvas(Memimage*);
--- a/editor.c
+++ b/editor.c
@@ -9,6 +9,7 @@
loadeditors(void)
{
addeditor(&p9image);
+ addeditor(&efilter);
}
typedef struct Leditor Leditor;
--- a/editor.txt
+++ b/editor.txt
@@ -1,5 +1,10 @@
Editor functions and properties (blie.h:/^struct Editor)
+to add new editor:
+- add struct declaration to blie.h (blie.h:/^extern Editor)
+- add editor in loadeditors (editor.c:/^loadeditors)
+- see: p9image.c
+
PROPERTY name
short name of the editor. Works as an identifier, must be unique!
--- a/mkfile
+++ b/mkfile
@@ -11,6 +11,7 @@
db.$O\
util.$O\
p9image.$O\
+ efilter.$O\
HFILES=blie.h
--- a/p9image.c
+++ b/p9image.c
@@ -127,6 +127,14 @@
memfillcolor(tstate.colorbrush, color);
}
+static ulong
+getcurrentcolorval(void)
+{
+ if (tstate.curcolor < 0 || tstate.curcolor >= NUMCELLS)
+ return DTransparent;
+ return tstate.colordata[tstate.curcolor];
+}
+
static Memimage*
getcurrentcolor(void)
{
@@ -351,9 +359,14 @@
double m;
uchar *p;
+ if (d->imask) {
+ freememimage(d->imask);
+ d->imask = nil;
+ }
+
if (d->maskdata->value == 255) {
d->imask = allocmemimage(d->img->r, GREY8);
- memfillcolor(d->imask, 0);
+ memfillcolor(d->imask, DBlack);
memimagedraw(d->imask, d->imask->r, memwhite, ZP, d->img, ZP, SoverD);
return;
}
@@ -362,7 +375,7 @@
dx = Dx(d->img->r);
dy = Dy(d->img->r);
d->imask = allocmemimage(d->img->r, GREY8);
- memfillcolor(d->imask, 0);
+ memfillcolor(d->imask, DBlack);
memimagedraw(d->imask, d->imask->r, memwhite, ZP, d->img, ZP, SoverD);
for (y = 0; y < dy; y++) {
@@ -606,9 +619,55 @@
}
static Redrawwin
+drawalphabrush(Layer *l, Data *d, Brush *brush, ulong color, Rectangle r)
+{
+ int x, y;
+ uchar *f, *t;
+ uchar *col;
+ uchar alpha, a;
+
+ col = (uchar*)&color;
+ alpha = rgb2k(col[0], col[1], col[2]);
+
+ if (r.max.y > d->img->r.max.y)
+ r.max.y = d->img->r.max.y;
+ if (r.max.x > d->img->r.max.x)
+ r.max.x = d->img->r.max.x;
+
+ for (y = r.min.y; y < r.max.y; y++) {
+ for (x = r.min.x; x < r.max.x; x++) {
+ if (x < d->img->r.min.x)
+ continue;
+ if (y < d->img->r.min.y)
+ continue;
+ t = byteaddr(d->img, Pt(x, y));
+ f = byteaddr(brush->i, Pt(x-r.min.x, y-r.min.y));
+ a = 0;
+ switch (brush->i->chan) {
+ case GREY8:
+ a = f[0];
+ break;
+ case RGB24:
+ a = rgb2k(f[3], f[2], f[1]);
+ break;
+ case RGBA32:
+ a = f[0];
+ break;
+ }
+ t[0] = ilerp(t[0], alpha, a);
+ t[1] = imul(t[0], t[1]);
+ t[2] = imul(t[0], t[2]);
+ t[3] = imul(t[0], t[3]);
+ }
+ }
+ updateimask(d);
+ dirtylayer(l);
+ return Rdrawing;
+}
+
+static Redrawwin
drawbrush(Layer *l, int buttons, Point xy)
{
- Memimage *tgt;
Data *d;
Rectangle r;
Brush *brush;
@@ -625,28 +684,28 @@
if (!(brush && brush->i && color))
return Rnil;
- tgt = nil;
- if (tstate.drawtarget == DTimg)
- tgt = d->img;
- else if (tstate.drawtarget == DTmask)
- tgt = d->mask;
-
- if (!tgt)
- return Rnil;
-
- r = insetrect(tgt->r, -brush->r);
+ r = insetrect(d->img->r, -brush->r);
if (!ptinrect(xy, r))
return Rnil;
r = rectaddpt(brush->i->r,
subpt(
- addpt(tgt->r.min, xy),
+ addpt(d->img->r.min, xy),
Pt(brush->r, brush->r)
)
);
color->clipr = brush->i->r;
- memimagedraw(tgt, r, color, ZP, brush->i, ZP, SoverD);
+
+ if (tstate.drawtarget == DTimg)
+ goto Imgdraw;
+ if (tstate.drawtarget == DTmask)
+ return drawalphabrush(l, d, brush, getcurrentcolorval(), r);
+
+ return Rnil;
+
+Imgdraw:
+ memimagedraw(d->img, r, color, ZP, brush->i, ZP, SoverD);
updateimask(d);
setdrawingdirty(Dcontent);
dirtylayer(l);
--- a/sample.c
+++ b/sample.c
@@ -229,11 +229,12 @@
src = lastsampled;
tmi = allocmemimage(r, img->chan);
- memfillcolor(tmi, DBlack);
- memimagedraw(tmi, tmi->r, src, addpt(tmi->r.min, vstate.offset), nil, ZP, S);
+ vdata.mtransparent->clipr = tmi->r;
+ memimagedraw(tmi, tmi->r, vdata.mtransparent, ZP, nil, ZP, S);
+ memimagedraw(tmi, tmi->r, src, addpt(tmi->r.min, vstate.offset), nil, ZP, SoverD);
nw = tmi->width * tmi->r.max.y * sizeof(ulong); // tmi->r.max.y == Dy(tmi->r)
- draw(img, img->r, display->black, nil, ZP);
+ draw(img, img->r, vdata.transparent, nil, ZP);
loadimage(img, img->r, tmi->data->bdata, nw);
freememimage(tmi);
--- /dev/null
+++ b/test/img/l/filter/meta
@@ -1,0 +1,3 @@
+filter
+Filter
+SoverD
--- /dev/null
+++ b/test/img/l/filter/params
@@ -1,0 +1,1 @@
+params width=20
--- /dev/null
+++ b/test/img/l/filter/script
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+crop -i $width | crop -i -$width -b 255 0 255
binary files a/test/img/l/layerA/img b/test/img/l/layerA/img differ
binary files a/test/img/l/layerA/mask /dev/null differ
binary files a/test/img/l/layerB/img b/test/img/l/layerB/img differ
--- a/test/img/layers
+++ b/test/img/layers
@@ -1,2 +1,3 @@
layerA
layerB
+filter
--- a/util.c
+++ b/util.c
@@ -6,6 +6,32 @@
#include <keyboard.h>
#include "blie.h"
+#define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
+
+uchar
+rgb2k(uchar r, uchar g, uchar b)
+{
+ return RGB2K(r, g, b);
+}
+
+uchar
+ilerp(uchar A, uchar B, uchar α)
+{
+ return flerp((double)A / 255., (double)B / 255., (double)α / 255.) * 255;
+}
+
+uchar
+imul(uchar A, uchar B)
+{
+ return (((double)A * (double)B) / (255. * 255.)) * 255;
+}
+
+double
+flerp(double A, double B, double α)
+{
+ return (B * α) + (1.-α) * A;
+}
+
Memimage*
dupmemimage(Memimage *i)
{
@@ -19,7 +45,9 @@
Memimage*
gencanvas(Memimage *i)
{
- return allocmemimage(i->r, RGBA32);
+ i = allocmemimage(i->r, RGBA32);
+ memfillcolor(i, DTransparent);
+ return i;
}
Memimage*
--- a/words
+++ b/words
@@ -118,3 +118,13 @@
- left click to select
- right click to configure
- middle mouse to preview brush (not implemented yet)
+
+
+EDITOR filter
+
+Currently only files:
+
+- script: executable script file (or binary) to be executed
+- params: database file with parameters
+
+parameters are injected as environment variables