Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Writing bitmap to file allows display in window?!!

9 views
Skip to first unread message

luser- -droog

unread,
Nov 17, 2010, 11:16:42 PM11/17/10
to
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)[i] = ' ';
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)[i] = 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;
}


luserXtrog

unread,
Nov 18, 2010, 12:10:31 AM11/18/10
to
duh! XFlush()

--
egg on face

Malcolm McLean

unread,
Nov 18, 2010, 2:44:55 AM11/18/10
to
On Nov 18, 6:16 am, luser- -droog <mijo...@yahoo.com> wrote:

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

> void X11output (device *d) {

I don't have an X system so I can only guess. But probably you're not
allowed to free the GC or the pixmap whilst the X system is drawing,
which it does via some sort of asynchronous pipeline. If you introduce
a delay the GC and bitmap are still in existence whilst the pipeline
complete, if you remove it by not writing to disk the resources vanish
and it is stuck.

FredK

unread,
Nov 18, 2010, 6:11:31 PM11/18/10
to

"luser- -droog" <mij...@yahoo.com> wrote in message
news:01a6912c-52af-4c4a...@v20g2000yqb.googlegroups.com...

> 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.

Try following the copy area with XFlush(display)

luserXtrog

unread,
Nov 18, 2010, 11:20:05 PM11/18/10
to
On Nov 18, 5:11 pm, "FredK" <fred.nos...@dec.com> wrote:
> "luser- -droog" <mijo...@yahoo.com> wrote in message

Yes. It dawned on me shortly after I posted.
What's the difference between doing two things
to a piece of data and only doing it once?
Phrased this way, the answer is obvious: twice as
much data, hence buffer may or may not get filled.

--
breakfast burrito

luserXtrog

unread,
Nov 18, 2010, 11:37:20 PM11/18/10
to
On Nov 18, 1:44 am, Malcolm McLean <malcolm.mcle...@btinternet.com>
wrote:

Well, yeah partly. It's definitely an asynchronous protocol operating
either over a network or via ipc. But it is fully buffered. So the
CopyArea call should queue all the pertinent data along with the
instruction. If the window were being displayed down the street,
you wouldn't expect it to require the client to retain the source
bitmap.
On a single machine, the behavior is more difficult to model. But the
single protocol requires the system to behave "as if" the client and
server cannot readily access each other's memory.

But I think all the bitmap data gets trasmitted by the CreatePixmap
call, and CopyArea merely refers to the abstract identifier. But even
though it's all asynchronous, there is still a preservation of the
order
of the requests. The Free cannot begin until CopyArea is done despite
any communication delays.

--
chicken chimichanga

Bjarni Juliusson

unread,
Nov 19, 2010, 4:39:55 AM11/19/10
to

Except in this case, I think the difference is that XWriteBitmapFile()
requests data from the server, which involves an implicit flush.


Bjarni
--

INFORMATION WANTS TO BE FREE

0 new messages