9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] libdraw and friends
@ 2006-04-19  4:53 lucio
  2006-04-19 15:26 ` Russ Cox
  0 siblings, 1 reply; 2+ messages in thread
From: lucio @ 2006-04-19  4:53 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 2424 bytes --]

I need a leg-up with my understanding of Plan 9 graphics.

Given

	i = allocimage (display, r, ARGB32, 1, 0);

and a "pixel" with 0xFFs splattered in the various bytes which I have
multiplicated as the contents of an image buffer, I seem unable to
make sense of its RGB and α meanings.  No matter how I swing that cat,
I can't get an output image that resembles what I would expect.

I know I'm getting indianness and other things confused, so perhaps
someone can point out where I'm going wrong (in fact, even where I'm
going _right_ seems to be a problem).

Here is some code I lifted from /sys/src/cmd/jpg/png.c and adjusted to
experiment with:

	initdraw (0, 0, 0);
	einit (Ekeyboard | Emouse);
	if ((m = allocimage (display, r, outchan, 1, 0)) == 0) {
		sysfatal ("No image");
	}
	if (loadimage (m, m->r, buf, size) < 0) {
		sysfatal ("Image load failed: %r");
	}
	if ((m2 = allocimage (display, r, outchan, 1, 0)) == 0) {
		sysfatal ("No backup image");
	}
	draw (m2, r, display->white, nil, ZP);
	draw (m2, m2->r, m, nil, m->r.min);
	image = m2;
	eresized(0);
	if ((ch = ekbd()) == 'q' || ch == 0x7F || ch == 0x04)
		return;
	draw (screen, screen->clipr, display->white, nil, ZP);
	image = nil;
	freeimage (m);

Having filled "buf" with the right number of "pixels", created using
something along the lines of

		ch = 15;
		pixel[R] = (ch & 0x01) ? 0xFF : 0x00;
		pixel[G] = (ch & 0x02) ? 0xFF : 0x00;
		pixel[B] = (ch & 0x04) ? 0xFF : 0x00;
		pixel[A] = (ch & 0x08) ? 0xFF : 0x00;

by modifying the "ch" value or, when the frustration got too much, the
"0xFF" value, I get white boxes, magenta boxes and cyan boxes.  Never
any othe colours.  Maybe I did get some of the arguments wrong.  but I
don't know which:

	enum {
		B = 0,
		G = 1,
		R = 2,
		A = 3,
	};

	unsigned long outchan = ARGB32;

Can I add anything to the above so someone with a fresh outlook and
better understanding can explain where I'm going wrong?

I actually have a working, improved "png" utility using code similar
to the above (APE with libpng, with a view to dropping the APE bit),
but there are some corner cases (only a few from a large collection of
maybe trivial PNG images) that fail dismally.  One seems to get by
with some shortcomings, but then one gets badly bitten, too.

Just in case, I have attached the full test program, as most recently
used.

++L

[-- Attachment #2: deep.c --]
[-- Type: text/plain, Size: 2463 bytes --]

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

enum {
	B = 0,
	G = 1,
	R = 2,
	A = 3,
};

static Image *image = nil;

enum{
	Border	= 2,
	Edge	= 5
};

void
eresized (int new) {
	Rectangle r;

	if (new && getwindow (display, Refnone) < 0) {
		sysfatal ("png: can't reattach to window");
	}
	if(image == nil)
		return;
	r = insetrect (screen->clipr, Edge + Border);
	r.max.x = r.min.x + Dx (image->r);
	r.max.y = r.min.y + Dy (image->r);
	border (screen, r, -Border, nil, ZP);
	draw (screen, r, image, nil, image->r.min);
	flushimage (display, 1);
}

void
main (int, char **) {
	Rectangle r;
	Image *m, *m2;
	int ch, size;
	char pixel[4];
	unsigned long outchan = ARGB32;
	unsigned char *buf, *bp;

	r.min = Pt (0, 0);
	r.max = Pt (160, 160);

	size = Dx (r) * Dy(r) * sizeof (pixel);
	bp = buf = (unsigned char *) malloc (size);
	ch = -1;
	while (bp < buf + size) {
		// ch = (ch + 1) % 16;
		ch = 15;
		pixel[R] = (ch & 0x01) ? 0x00 : 0x00;
		pixel[G] = (ch & 0x02) ? 0xFF : 0x00;
		pixel[B] = (ch & 0x04) ? 0xFF : 0x00;
		pixel[A] = (ch & 0x08) ? 0xFF : 0x00;
		*((unsigned long *) bp) = *((unsigned long *) pixel);
		bp += sizeof (pixel);
	}
fprint (2, "R: %#02x G: %#02x B: %#02x A: %#02x\n", pixel[R] & 0xFF, pixel[G] & 0xFF, pixel[B] & 0xFF, pixel[A] & 0xFF);
	while (bp < buf + size) {
		*((unsigned long *) bp) = *((unsigned long *) pixel);
		bp += sizeof (pixel);
	}

if (1) {
	initdraw (0, 0, 0);
	einit (Ekeyboard | Emouse);
	if ((m = allocimage (display, r, outchan, 1, 0)) == 0) {
		sysfatal ("No image");
	}
	if (loadimage (m, m->r, buf, size) < 0) {
		sysfatal ("Image load failed: %r");
	}
	if ((m2 = allocimage (display, r, outchan, 1, 0)) == 0) {
		sysfatal ("No backup image");
	}
	draw (m2, r, display->white, nil, ZP);
	draw (m2, m2->r, m, nil, m->r.min);
	image = m2;
	eresized(0);
	if ((ch = ekbd()) == 'q' || ch == 0x7F || ch == 0x04)
		return;
	draw (screen, screen->clipr, display->white, nil, ZP);
	image = nil;
	freeimage (m);
} else {
			char chan[10];
			int row, row_bytes = Dy(r) * sizeof (pixel);
			chantostr ((char *) chan, outchan);
			chan[9] = '\0';
			print ("%11s %11d %11d %11d %11d ", chan, 0, 0, Dx (r), Dy (r));
			bp = buf;
			for (row = 0; row < Dy (r); ++row) {
				if (write (1, bp, row_bytes) != row_bytes) {
					sysfatal ("Write error: %r");
				}
				bp += row_bytes;
			}
}
	return;
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [9fans] libdraw and friends
  2006-04-19  4:53 [9fans] libdraw and friends lucio
@ 2006-04-19 15:26 ` Russ Cox
  0 siblings, 0 replies; 2+ messages in thread
From: Russ Cox @ 2006-04-19 15:26 UTC (permalink / raw)
  To: 9fans

I changed your program to draw a colored ramp,
default yellow, but there are options -r (red), -g (green), -b (blue).

When writing raw bytes in preparation for loadimage,
you must always prepare them in little-endian order,
even on big-endian machines.  That's just the definition
(it coincides with what most VGA cards do).

So if you are using ARGB32 then you write B, G, R, A,
in that order.

Russ


#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

enum {
	B = 0,
	G = 1,
	R = 2,
	A = 3,
};

static Image *image = nil;

enum{
	Border	= 2,
	Edge	= 5
};

void
eresized (int new) {
	Rectangle r;

	if (new && getwindow (display, Refnone) < 0) {
		sysfatal ("png: can't reattach to window");
	}
	if(image == nil)
		return;
	r = insetrect (screen->clipr, Edge + Border);
	r.max.x = r.min.x + Dx (image->r);
	r.max.y = r.min.y + Dy (image->r);
	border (screen, r, -Border, nil, ZP);
	draw (screen, r, image, nil, image->r.min);
	flushimage (display, 1);
}

int
blend(int a, int b, int p, int q)
{
	/* f = p/q; return a*(1-f) + b*f */

	return (a*(q-p)+b*p)/q;
}


void
main (int argc, char **argv) {
	Rectangle r;
	Image *m, *m2;
	int ch, size;
	char pixel[4];
	unsigned long outchan = ARGB32;
	unsigned char *buf, *bp;
	int x, y, rgb;

	rgb = 0xFFFF00;	/* yellow */
	ARGBEGIN{
	case 'r':
		rgb = 0xFF0000;
		break;
	case 'g':
		rgb = 0x00FF00;
		break;
	case 'b':
		rgb = 0x0000FF;
		break;
	}ARGEND

	r.min = Pt (0, 0);
	r.max = Pt (160, 160);

	size = Dx (r) * Dy(r) * sizeof (pixel);
	bp = buf = (unsigned char *) malloc (size);
	for(y=0; y<Dy(r); y++){
		bp = buf+y*bytesperline(r, chantodepth(outchan));
		for(x=0; x<Dx(r); x++){
			*bp++ = blend(rgb, 255, x, Dx(r));	/* B */
			*bp++ = blend(rgb>>8, 255, x, Dx(r));	/* G */
			*bp++ = blend(rgb>>16, 255, x, Dx(r));	/* R */
			*bp++ = 0xFF;	/* A */
		}
	}

	initdraw (0, 0, 0);
	einit (Ekeyboard | Emouse);
	if ((m = allocimage (display, r, outchan, 1, 0)) == 0) {
		sysfatal ("No image");
	}
	if (loadimage (m, m->r, buf, size) < 0) {
		sysfatal ("Image load failed: %r");
	}
	if ((m2 = allocimage (display, r, outchan, 1, 0)) == 0) {
		sysfatal ("No backup image");
	}
	draw (m2, r, display->white, nil, ZP);
	draw (m2, m2->r, m, nil, m->r.min);
	image = m2;
	eresized(0);
	if ((ch = ekbd()) == 'q' || ch == 0x7F || ch == 0x04)
		return;
	draw (screen, screen->clipr, display->white, nil, ZP);
	image = nil;
	freeimage (m);
}



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2006-04-19 15:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-04-19  4:53 [9fans] libdraw and friends lucio
2006-04-19 15:26 ` Russ Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).