b8180d9f6d41dc708a2f249ba892cbca311e7a06 jcasper Mon Feb 27 11:38:55 2023 -0800 Adding transparency support for colors refs #30569 diff --git src/inc/memgfx.h src/inc/memgfx.h index cc08d04..4eec6b9 100644 --- src/inc/memgfx.h +++ src/inc/memgfx.h @@ -54,52 +54,54 @@ #define MG_BROWN 0xff00a0a0 #define MAKECOLOR_32_A(r,g,b,a) (((unsigned int)a<<24) | ((unsigned int)b<<16) | ((unsigned int)g << 8) | (unsigned int)r) #define MAKECOLOR_32(r,g,b) (((unsigned int)0xff<<24) | ((unsigned int)b<<16) | ((unsigned int)g << 8) | (unsigned int)r) #define COLOR_32_RED(c) ((c)&0xff) #define COLOR_32_GREEN(c) (((c)>>8)&0xff) #define COLOR_32_BLUE(c) (((c)>>16)&0xff) #define COLOR_32_ALPHA(c) (((c)>>24)&0xff) #endif #define MG_WRITE_MODE_NORMAL 0 #define MG_WRITE_MODE_MULTIPLY (1 << 0) struct rgbColor { - unsigned char r, g, b; + unsigned char r, g, b, a; }; /* HSV and HSL structs can be used for changing lightness, darkness, or * color of RGB colors. Convert RGB->HS[LV], modify hue, saturation, or * value/lightness, then convert back to RGB. * The datatypes were chosen to be fast but also give accurate conversion * back to RGB. * Hue is a float [0,360) degrees 0=red, 120=green, 240=blue * S/V/L are integers [0,1000] */ struct hsvColor { double h; unsigned short s, v; + unsigned char alpha; }; struct hslColor { double h; unsigned short s, l; + unsigned char alpha; }; extern struct rgbColor mgFixedColors[9]; /* Contains MG_WHITE - MG_GRAY */ struct memGfx { Color *pixels; int width, height; struct rgbColor colorMap[256]; int colorsUsed; int clipMinX, clipMaxX; int clipMinY, clipMaxY; struct colHash *colorHash; /* Hash for fast look up of color. */ unsigned int writeMode; unsigned int fontMethod; @@ -405,49 +407,79 @@ struct rgbColor mgRgbTransformHsv(struct rgbColor in, double h, double s, double v); /* Transform rgb 'in' value using * hue shift 'h' (0..360 degrees), * saturation scale 's', and * value scale 'v' * Returns the transformed rgb value * Use H=0, S=V=1 for identity transformation */ struct rgbColor mgColorIxToRgb(struct memGfx *mg, int colorIx); /* Return rgb value at color index. */ struct rgbColor colorIxToRgb(int colorIx); /* Return rgb value at color index. */ +INLINE void mixColor(Color *d, Color s) +/* Blend the color at s into d, respecting alpha */ +{ +int aA = COLOR_32_ALPHA(s); +int rA = COLOR_32_RED(s); +int gA = COLOR_32_GREEN(s); +int bA = COLOR_32_BLUE(s); + +int aB = COLOR_32_ALPHA(*d); +int rB = COLOR_32_RED(*d); +int gB = COLOR_32_GREEN(*d); +int bB = COLOR_32_BLUE(*d); + +double aOut = aA + (aB * (255.0 - aA) / 255); +int rOut, gOut, bOut; +if (aOut == 0) + rOut = gOut = bOut = 0; +else + { + rOut = (rA * aA + rB * aB * (255 - aA) / 255)/aOut ; + gOut = (gA * aA + gB * aB * (255 - aA) / 255)/aOut ; + bOut = (bA * aA + bB * aB * (255 - aA) / 255)/aOut ; + } +*d = MAKECOLOR_32_A(rOut,gOut,bOut,aOut); +} + INLINE void mixDot(struct memGfx *img, int x, int y, float frac, Color col) /* Puts a single dot on the image, mixing it with what is already there * based on the frac argument. */ /* Shouldn't this pay attention to the transparency of the current pixel? */ { if ((x < img->clipMinX) || (x >= img->clipMaxX) || (y < img->clipMinY) || (y >= img->clipMaxY)) return; Color *pt = _mgPixAdr(img,x,y); /* algorithm borrowed from https://en.wikipedia.org/wiki/Alpha_compositing */ int aA = frac * 255; int rA = COLOR_32_RED(col); int gA = COLOR_32_GREEN(col); int bA = COLOR_32_BLUE(col); +int tempC = MAKECOLOR_32_A(rA, gA, bA, aA); +mixColor(pt, tempC); +/* int aB = COLOR_32_ALPHA(*pt); int rB = COLOR_32_RED(*pt); int gB = COLOR_32_GREEN(*pt); int bB = COLOR_32_BLUE(*pt); double aOut = aA + (aB * (255.0 - aA) / 255); int rOut, gOut, bOut; if (aOut == 0) rOut = gOut = bOut = 0; else { rOut = (rA * aA + rB * aB * (255 - aA) / 255)/aOut ; gOut = (gA * aA + gB * aB * (255 - aA) / 255)/aOut ; bOut = (bA * aA + bB * aB * (255 - aA) / 255)/aOut ; } mgPutDot(img,x,y,MAKECOLOR_32_A(rOut,gOut,bOut,aOut)); +*/ } #endif /* MEMGFX_H */