Writing bitmap to file allows display in window?!!


L

luser- -droog

note: crossposted to clc, cup cwx

I've encountered a problem that has me stumped.
I confess, I haven't carved a minimal program that demonstrates the
issue, but the program itself is rather
short (~200 lines). So I'll show the whole thing.
The problem manifests when I uncomment the call to
XWriteBitmapToFile from the function X11output.
I show the file with the lines in question commented
with CC+-style // comments.

With the lines uncommented, the program displays
a bitmap to stdout with # for 1 and space for 0, waits
for an enter key and then displays the same bitmap
in an X window, waits for another enter key and
terminates.

With the lines commented-out, the program displays
the ascii version fine, but shows a blank X window.
Any advice?

TIA

compile with -lm -lX11

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#define _XOPEN_SOURCE 601
#include <math.h>
#include <X11/Xlib.h>



typedef struct device {
int w,h;
void *data;
void *private;
void (*putpixel)(struct device *d, int w, int h, int col);
void (*drawline)(struct device *d, int x1, int y1, int x2, int y2,
int col);
void (*output)(struct device *d);
} device;



void ASCIIputpixel(device *d, int x, int y, int col) {
if (0 <= x && x < d->w)
if (0 <= y && y < d->h)
((unsigned char *)d->data)[d->w * y + x] = (col?'#':' ');
}

void simpleDDAdrawline(device *d, int x1, int y1, int x2, int y2, int
col) {
int len, i;
double x, y, xinc, yinc;
len = abs(x2 - x1);
if (abs(y2-y1) > len) len = abs(y2-y1);
xinc = (double)(x2-x1)/len;
yinc = (double)(y2-y1)/len;
x = x1 + 0.5;
y = y1 + 0.5;
for (i = 0; i < len; i++) {
d->putpixel(d, trunc(x), trunc(y), col);
x += xinc;
y += yinc;
}
}

void ASCIIoutput(device *d) {
int i,j;
FILE *f;
f = d->private;

for (i = 0; i < d->h; i++) {
for (j = 0; j < d->w; j++) {
fputc(((unsigned char *)d->data)[d->w*i + j], f);
}
fputc('\n',f);
}
}

device *newASCIIdevice (int w, int h, FILE *f) {
device *d;
int i;
d = malloc(sizeof *d);
d->w = w;
d->h = h;
d->data = malloc( w * h );
for (i=0; i < w * h; i++)
((unsigned char *)d->data) = ' ';
d->private = f;
d->putpixel = ASCIIputpixel;
d->drawline = simpleDDAdrawline;
d->output = ASCIIoutput;
return d;
}


typedef struct Xdata {
Display *dis;
Window win;
} Xdata;

void X11putpixel (device *d, int x, int y, int col) {
if (0 <= x && x < d->w)
if (0 <= y && y < d->h)
if (col)
((unsigned char *)d->data)[y*(int)ceil((double)d->w/8)
+ (x/8)] |= 1<<(x%8);
else
((unsigned char *)d->data)[y*(int)ceil((double)d->w/8)
+ (x/8)] &= ~(1<<(x%8));
}

void X11output (device *d) {
XGCValues values;
GC gc;
Pixmap p;
values.foreground =
WhitePixel( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) );
values.background =
BlackPixel( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) );
gc = XCreateGC(
((Xdata *)d->private)->dis,
((Xdata *)d->private)->win,
(GCForeground | GCBackground), &values);
p = XCreatePixmapFromBitmapData(
((Xdata *)d->private)->dis,
((Xdata *)d->private)->win,
d->data, d->w, d->h,
BlackPixel( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) ),
WhitePixel( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) ),
DefaultDepth( ((Xdata *)d->private)->dis,
DefaultScreen( ((Xdata *)d->private)->dis) )
);
XCopyArea(
((Xdata *)d->private)->dis,
p,
((Xdata *)d->private)->win,
gc,
0, 0, d->w, d->h, 0, 0
);

/*why would the image show up only if the data is also written to
disk?*/
// XWriteBitmapFile( ((Xdata *)d->private)->dis,
// "bmp", p, d->w, d->h, -1, -1);

XFreePixmap( ((Xdata *)d->private)->dis, p);
XFreeGC( ((Xdata *)d->private)->dis, gc);
}

device *newX11device (int w, int h) {
device *d;
XEvent ev;
int i;
d = malloc(sizeof *d);
d->w = w;
d->h = h;
d->data = malloc( ceil((double)w/8) * h);
for (i=0; i < ceil((double)w/8) * h; i++)
((unsigned char *)d->data) = 0;

d->private = malloc(sizeof(Xdata));
((Xdata *)d->private)->dis = XOpenDisplay(NULL);
((Xdata *)d->private)->win = XCreateSimpleWindow(
((Xdata *)d->private)->dis,
RootWindow( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) ),
0, 0, w, h, 0,
BlackPixel( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) ),
WhitePixel( ((Xdata *)d->private)->dis, DefaultScreen( ((Xdata
*)d->private)->dis) )
);
XMapWindow( ((Xdata *)d->private)->dis,
((Xdata *)d->private)->win );

XSelectInput(
((Xdata *)d->private)->dis,
((Xdata *)d->private)->win,
ExposureMask );

/*wait for exposure*/
do {
XNextEvent( ((Xdata *)d->private)->dis, &ev);
} while (ev.type != Expose);

d->putpixel = X11putpixel;
d->drawline = simpleDDAdrawline;
d->output = X11output;
return d;
}



int testdevice(device *d) {
int j,k;

for (j=5; j < 65; j++)
for (k=5; k < 25; k++)
d->putpixel(d, j, k, 1);

d->drawline(d, 10, 6, 50, 15, 0);
d->drawline(d, 8, 18, 45, 8, 0);
d->drawline(d, 36, 16, 31, 6, 0);
d->output(d);
fgetc(stdin);

return 0;
}

int main() {
device *d;
d = newASCIIdevice(70, 30, stdout);
testdevice(d);
d = newX11device(70, 30);
testdevice(d);
return 0;
}
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top