#undef countof
#define countof(x) (sizeof((x))/sizeof((*x)))
+# undef MAX
+# undef MIN
+# define MAX(A,B) ((A)>(B)?(A):(B))
+# define MIN(A,B) ((A)<(B)?(A):(B))
+
#include "xshm.h"
#include "images/gen/bob_png.h"
THROTTLE (st->vartrend, "vartrend");
# undef THROTTLE
-
+#if 0
+ if (st->width > 2560) /* Retina displays */
+ {
+ /* #### One of these knobs must mean "make the fire be twice as tall"
+ but I can't figure out how. Changing any of the default values
+ of any of these seems to just make it all go crappy. */
+ st->ivspread = MAX (0, MIN (255, st->ivspread + 1));
+ }
+#endif
st->hspread = st->ihspread;
st->vspread = st->ivspread;
}
-static Pixmap
-double_pixmap (Display *dpy, Visual *visual, int depth, Pixmap pixmap,
- int pix_w, int pix_h)
+static XImage *
+double_ximage (Display *dpy, Visual *visual, XImage *image)
{
int x, y;
- Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
- XImage *i1 = XGetImage (dpy, pixmap, 0, 0, pix_w, pix_h, ~0L,
- (depth == 1 ? XYPixmap : ZPixmap));
- XImage *i2 = XCreateImage (dpy, visual, depth,
- (depth == 1 ? XYPixmap : ZPixmap), 0, 0,
- pix_w*2, pix_h*2, 8, 0);
- XGCValues gcv;
- GC gc = XCreateGC (dpy, p2, 0, &gcv);
- i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
- for (y = 0; y < pix_h; y++)
- for (x = 0; x < pix_w; x++)
+ XImage *out = XCreateImage (dpy, visual, image->depth, ZPixmap, 0, 0,
+ image->width * 2, image->height * 2, 8, 0);
+ out->data = (char *) malloc (out->height * out->bytes_per_line);
+ for (y = 0; y < image->width; y++)
+ for (x = 0; x < image->height; x++)
{
- unsigned long p = XGetPixel(i1, x, y);
- XPutPixel(i2, x*2, y*2, p);
- XPutPixel(i2, x*2+1, y*2, p);
- XPutPixel(i2, x*2, y*2+1, p);
- XPutPixel(i2, x*2+1, y*2+1, p);
+ unsigned long p = XGetPixel (image, x, y);
+ XPutPixel (out, x*2, y*2, p);
+ XPutPixel (out, x*2+1, y*2, p);
+ XPutPixel (out, x*2, y*2+1, p);
+ XPutPixel (out, x*2+1, y*2+1, p);
}
- free(i1->data); i1->data = 0;
- XDestroyImage(i1);
- XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
- XFreeGC (dpy, gc);
- free(i2->data); i2->data = 0;
- XDestroyImage(i2);
- XFreePixmap(dpy, pixmap);
- return p2;
+ XDestroyImage (image);
+ return out;
}
static unsigned char *
-reformat_pixmap (struct state *st, Pixmap pixmap, Pixmap mask, int *w, int *h)
+gaussian_blur (unsigned char *in, int w, int h, double r)
{
- XImage *image = 0, *mimage = 0;
- int x, y;
- unsigned char *result, *o;
- XColor colors[256];
- Bool cmap_p = has_writable_cells (st->screen, st->visual);
-
- while (*w < st->width / 10 &&
- *h < st->height / 10)
- {
- pixmap = double_pixmap (st->dpy, st->visual, st->depth, pixmap, *w, *h);
- if (mask)
- mask = double_pixmap (st->dpy, st->visual, st->depth, mask, *w, *h);
- *w *= 2;
- *h *= 2;
- }
-
- if (cmap_p)
- {
- int i;
- for (i = 0; i < countof (colors); i++)
- colors[i].pixel = i;
- XQueryColors (st->dpy, st->colormap, colors, countof (colors));
- }
-
- image = XGetImage (st->dpy, pixmap, 0, 0, *w, *h, ~0L, ZPixmap);
- XFreePixmap(st->dpy, pixmap);
+ unsigned char *out = malloc(w * h);
+ int rs = (int) ((r * 2.57) + 0.5);
+ int i, j;
- if (mask)
- {
- mimage = XGetImage (st->dpy, mask, 0, 0, *w, *h, ~0L, ZPixmap);
- XFreePixmap(st->dpy, mask);
- }
-
- result = (unsigned char *) malloc (image->width * image->height);
- o = result;
- for (y = 0; y < image->height; y++)
- for (x = 0; x < image->width; x++)
+ for (i = 0; i < h; i ++)
+ for (j = 0; j < w; j++)
{
- unsigned long rgb = XGetPixel (image, x, y);
- unsigned long a = mimage ? XGetPixel (mimage, x, y) : 1;
- unsigned long gray;
- if (!a)
- rgb = 0xFFFFFFFFL;
- if (cmap_p)
- gray = ((200 - ((((colors[rgb].red >> 8) & 0xFF) +
- ((colors[rgb].green >> 8) & 0xFF) +
- ((colors[rgb].blue >> 8) & 0xFF))
- >> 1))
- & 0xFF);
- else
- /* This is *so* not handling all the cases... */
- gray = (image->depth > 16
- ? ((((rgb >> 24) & 0xFF) +
- ((rgb >> 16) & 0xFF) +
- ((rgb >> 8) & 0xFF) +
- ((rgb ) & 0xFF)) >> 2)
- : ((((rgb >> 12) & 0x0F) +
- ((rgb >> 8) & 0x0F) +
- ((rgb >> 4) & 0x0F) +
- ((rgb ) & 0x0F)) >> 1));
-
- *o++ = 255 - gray;
+ double val = 0, wsum = 0;
+ int ix, iy;
+ for (iy = i-rs; iy<i+rs+1; iy++)
+ for (ix = j-rs; ix<j+rs+1; ix++)
+ {
+ int x = MIN(w-1, MAX(0, ix));
+ int y = MIN(h-1, MAX(0, iy));
+ int dsq = (ix-j)*(ix-j)+(iy-i)*(iy-i);
+ double wght = exp (-dsq / (2*r*r)) / (M_PI*2*r*r);
+ val += in[y*w+x] * wght;
+ wsum += wght;
+ }
+ out[i*w+j] = val/wsum;
}
- *w = image->width;
- *h = image->height;
- XDestroyImage (image);
- if (mimage)
- XDestroyImage (mimage);
-
- return result;
-
+ free (in);
+ return out;
}
static unsigned char *
-loadBitmap(struct state *st, int *w, int *h)
+loadBitmap (struct state *st)
{
+ int x, y;
+ unsigned char *result, *o;
+ int blur = 0;
+
# ifdef HAVE_JWXYZ
const char *bitmap_name = "(default)"; /* #### always use builtin */
# else
char *bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap");
# endif
- Pixmap p = 0, mask = 0;
+ XImage *image = 0;
if (!bitmap_name ||
!*bitmap_name ||
!strcmp(bitmap_name, "none"))
;
else if (!strcmp(bitmap_name, "(default)")) /* use the builtin */
- p = image_data_to_pixmap (st->dpy, st->window,
- bob_png, sizeof(bob_png),
- w, h, &mask);
- else /* load a bitmap file */
- p = file_to_pixmap (st->dpy, st->window, bitmap_name,
- &st->width, &st->height, 0);
-
- if (!p) return 0;
- return reformat_pixmap (st, p, mask, w, h);
+ image = image_data_to_ximage (st->dpy, st->visual,
+ bob_png, sizeof(bob_png));
+ else
+ image = file_to_ximage (st->dpy, st->visual, bitmap_name);
+
+ if (! image) return 0;
+
+ while (image->width < st->width / 10 &&
+ image->height < st->height / 10)
+ {
+ image = double_ximage (st->dpy, st->visual, image);
+ blur++;
+ }
+
+ result = (unsigned char *) malloc (image->width * image->height);
+ o = result;
+ for (y = 0; y < image->height; y++)
+ for (x = 0; x < image->width; x++)
+ {
+ unsigned long agbr = XGetPixel (image, x, image->height - y - 1);
+ unsigned long a = (agbr >> 24) & 0xFF;
+ unsigned long gray = (a == 0
+ ? 0xFF
+ : ((((agbr >> 16) & 0xFF) +
+ ((agbr >> 8) & 0xFF) +
+ ((agbr >> 0) & 0xFF))
+ / 3));
+ if (gray < 96) gray /= 2; /* a little more contrast */
+ *o++ = 255 - gray;
+ }
+
+ /* If we enlarged the image, file off the sharp edges. */
+ if (blur > 0)
+ result = gaussian_blur (result, image->width, image->height, blur * 1.7);
+
+ st->theimx = image->width;
+ st->theimy = image->height;
+ XDestroyImage (image);
+ return result;
}
+
static void *
xflame_init (Display *dpy, Window win)
{
GetXInfo(st);
InitColors(st);
- st->theim = loadBitmap(st, &st->theimx, &st->theimy);
+ st->theim = loadBitmap(st);
MakeImage(st);
InitFlame(st);