Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Pack bitmap bytes into native-endian 32bit int

Reply
Thread Tools

Pack bitmap bytes into native-endian 32bit int

 
 
luser- -droog
Guest
Posts: n/a
 
      01-11-2011
I'm trying to convert byte-oriented bitmap data into
32bit words matching the endianness of the machine;
And I'm very confused. The crux is the triple for-loop
here.

compile with -I/usr/include/cairo -lcairo
mask.c:

#include <stdint.h>
#include <stdlib.h>

#include <cairo.h>
#include <X11/Xlib.h>
#include <cairo-xlib.h>
#include <unistd.h>

int main (int argc, char *argv[])
{
int width = 240;
int height = 230;
Display *dis;
int scr;
int depth;
Visual *vis;
XSetWindowAttributes attr;
unsigned long attrmask;
Window win;
cairo_surface_t *surface;
cairo_t *cr;

dis = XOpenDisplay(NULL);
scr = DefaultScreen(dis);
depth = DefaultDepth(dis, scr);
vis = DefaultVisual(dis, scr);
attr.background_pixel = WhitePixel(dis, scr);
attr.border_pixel = BlackPixel(dis, scr);
attr.event_mask = ExposureMask | StructureNotifyMask |
ButtonPressMask;
attrmask = CWColormap | CWBackPixel | CWBorderPixel | CWEventMask;
win = XCreateWindow(dis, RootWindow(dis, scr),
200, 10, //pos
width, height, 5, //width height border
depth,
InputOutput,
vis,
attrmask, &attr);
XMapWindow(dis, win);
surface = cairo_xlib_surface_create(dis, win, vis, width, height);
cr = cairo_create(surface);
cairo_scale(cr, 10, 10); /* make a big turkey */

cairo_set_source_rgb(cr, 0, 0, 1);

{
unsigned char samp[] = {
0x00, 0x3B, 0x00,
0x00, 0x27, 0x00,
0x00, 0x24, 0x80,
0x0E, 0x49, 0x40,
0x11, 0x49, 0x20,

0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14,

0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4,
0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2,

0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00,

0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00 };
int w = 24, h = 23, stride;
cairo_surface_t *mask;
unsigned char *data;
int i,j,k;
uint32_t u;

stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w);
data = malloc(h * stride);

#if 0
/* try to make a vertical line */
u = 16;
for (i = 0; i < h * (stride/4); i++) {
*((unsigned long *)(data + i * stride)) = u;
}
#endif

/* convert bytes to 32bit quantities matching
endianness of the machine */
for (i = 0; i < h; i++) { /* each row */
for (j = 0; j < stride/4; j++) { /* each 32bit int in row
*/
u = 0;
for (k = 0; k < w/8; k++) { /* each 8bit byte in 32bit
int */
u << 8;
u |= samp[i*(w/ + k];
}
*((uint32_t *)(data + i*stride + j*4)) = u;
}
}

mask = cairo_image_surface_create_for_data(data,
CAIRO_FORMAT_A1, w, h, stride);
cairo_mask_surface(cr, mask, 0, 0);
}

XFlush(dis);

sleep(20);

cairo_destroy(cr);
cairo_surface_destroy(surface);

return 0;
}

 
Reply With Quote
 
 
 
 
Nobody
Guest
Posts: n/a
 
      01-11-2011
On Tue, 11 Jan 2011 10:43:03 -0800, luser- -droog wrote:

> I'm trying to convert byte-oriented bitmap data into
> 32bit words matching the endianness of the machine;
> And I'm very confused. The crux is the triple for-loop
> here.


> for (i = 0; i < h; i++) { /* each row */
> for (j = 0; j < stride/4; j++) { /* each 32bit int in row */
> u = 0;
> for (k = 0; k < w/8; k++) { /* each 8bit byte in 32bit int */


This should be:

> for (k = 0; k < 4; k++) {


Otherwise, you're iterating over the columns twice.

But you also need to allow for:

1. any padding at the end of each row (i.e. if w < stride*4).

2. According to the documentation, cairo expects the *bits* to be swapped
based upon the byte order.

For 1, either:

a) use e.g. "if (j*4+k < stride)" around the code which reads the bytes,
or
b) iterate over the bytes rather than the words, then push an extra 0-3
zero bytes into the final word at the end of each row.

For 2, either:

a) change the inner loop to iterate over the individual bits, or
b) create a look-up table to reverse the bits.


 
Reply With Quote
 
 
 
 
luser- -droog
Guest
Posts: n/a
 
      01-12-2011
On Jan 11, 2:28*pm, Nobody <(E-Mail Removed)> wrote:
> On Tue, 11 Jan 2011 10:43:03 -0800, luser- -droog wrote:
> > I'm trying to convert byte-oriented bitmap data into
> > 32bit words matching the endianness of the machine;
> > And I'm very confused. The crux is the triple for-loop
> > here.
> > * * * * for (i = 0; i < h; i++) { /* each row */
> > * * * * * * for (j = 0; j < stride/4; j++) { /* each 32bit int in row */
> > * * * * * * * * u = 0;
> > * * * * * * * * for (k = 0; k < w/8; k++) { /* each 8bit byte in 32bit int */

>
> This should be:
>
> > * * * * * * * * for (k = 0; k < 4; k++) {

>
> Otherwise, you're iterating over the columns twice.


I tried that, but my sample data only has three bytes
per row.

> But you also need to allow for:
>
> 1. any padding at the end of each row (i.e. if w < stride*4).
>
> 2. According to the documentation, cairo expects the *bits* to be swapped
> based upon the byte order.
>
> For 1, either:
>
> a) use e.g. "if (j*4+k < stride)" around the code which reads the bytes,
> or
> b) iterate over the bytes rather than the words, then push an extra 0-3
> zero bytes into the final word at the end of each row.


I think I've got that issue addressed by zeroing the word
first and masking the bytes into it. The padding's already
there.

> For 2, either:
>
> a) change the inner loop to iterate over the individual bits, or
> b) create a look-up table to reverse the bits.


Thank you so much! Corrected version follows.

/* test program for cairo bit mask
makes a big blue turkey */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <cairo.h>
#include <X11/Xlib.h>
#include <cairo-xlib.h>
#include <unistd.h>

enum { little, big } endian = little;

unsigned char invertbits (unsigned char b) {
return ( ((b & 0x01)?1:0) <<7)
| ( ((b & 0x02)?1:0) <<6)
| ( ((b & 0x04)?1:0) <<5)
| ( ((b & 0x0?1:0) <<4)
| ( ((b & 0x10)?1:0) <<3)
| ( ((b & 0x20)?1:0) <<2)
| ( ((b & 0x40)?1:0) <<1)
| ( ((b & 0x80)?1:0) )
;
}

int main (int argc, char *argv[])
{
int width = 240;
int height = 230;
Display *dis;
int scr;
int depth;
Visual *vis;
XSetWindowAttributes attr;
unsigned long attrmask;
Window win;
cairo_surface_t *surface;
cairo_t *cr;

dis = XOpenDisplay(NULL);
scr = DefaultScreen(dis);
depth = DefaultDepth(dis, scr);
vis = DefaultVisual(dis, scr);
attr.background_pixel = WhitePixel(dis, scr);
attr.border_pixel = BlackPixel(dis, scr);
attr.event_mask = ExposureMask | StructureNotifyMask |
ButtonPressMask;
attrmask = CWColormap | CWBackPixel | CWBorderPixel | CWEventMask;
win = XCreateWindow(dis, RootWindow(dis, scr),
200, 10, //pos
width, height, 5, //width height border
depth,
InputOutput,
vis,
attrmask, &attr);
XMapWindow(dis, win);
surface = cairo_xlib_surface_create(dis, win, vis, width, height);
cr = cairo_create(surface);
cairo_scale(cr, 10, 10);

cairo_set_source_rgb(cr, 0, 0, 1);

{
unsigned char samp[] = {
0x00, 0x3B, 0x00,
0x00, 0x27, 0x00,
0x00, 0x24, 0x80,
0x0E, 0x49, 0x40,
0x11, 0x49, 0x20,

0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14,

0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4,
0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2,

0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00,

0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00 };
int w = 24, h = 23, stride;
cairo_surface_t *mask;
unsigned char *data;
int i,j,k;
uint32_t u;

stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w);
printf("stride = %d\n", stride);
data = malloc(h * stride);

/* convert bytes to 32bit quantities matching
endianness of the machine */
/* each row */
for (i = 0; i < h; i++) {
/* each 32bit int in row */
for (j = 0; j < stride/4; j++) {
u = 0;
/* each 8bit byte in 32bit int */
for (k = 0; k < w/8; k++) {
uint8_t b;
if (endian == big) b = samp[i*(w/ + k];
else b = samp[(i+1)*(w/ - (k+1)];
u <<= 8;
if (endian == big) u |= b;
else u |= invertbits(b);
//printf("%X\n", u);
}
//printf("%08X\n", u);
*((uint32_t *)(data + i*stride + j*4)) = u;
}
}

mask = cairo_image_surface_create_for_data(data,
CAIRO_FORMAT_A1, w, h, stride);
cairo_mask_surface(cr, mask, 0, 0);
}

XFlush(dis);

sleep(20);

cairo_destroy(cr);
cairo_surface_destroy(surface);

return 0;
}

 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      01-14-2011
On Tue, 11 Jan 2011 19:21:54 -0800, luser- -droog wrote:

>> This should be:
>>
>> > * * * * * * * * for (k = 0; k < 4; k++) {

>>
>> Otherwise, you're iterating over the columns twice.

>
> I tried that, but my sample data only has three bytes per row.


So? However much data you have, there are always 4 8-bit bytes in a
32-bit word.

As I said before:

> But you also need to allow for:
>
> 1. any padding at the end of each row (i.e. if w < stride*4).

....
> For 1, either:
>
> a) use e.g. "if (j*4+k < stride)" around the code which reads the bytes,
> or
> b) iterate over the bytes rather than the words, then push an extra 0-3
> zero bytes into the final word at the end of each row.


Either way, you need to "create" 0-3 extra zero bytes at the end of each
row. If you iterate over the words, the innermost level needs a check to
use the created zeros rather than trying to read non-existent source
bytes. If you iterate over the bytes, you need to "complete" the last word
after the loop.

 
Reply With Quote
 
luser- -droog
Guest
Posts: n/a
 
      01-14-2011
On Jan 14, 11:02*am, Nobody <(E-Mail Removed)> wrote:
> On Tue, 11 Jan 2011 19:21:54 -0800, luser- -droog wrote:
> >> This should be:

>
> >> > * * * * * * * * for (k = 0; k < 4; k++) {

>
> >> Otherwise, you're iterating over the columns twice.

>
> > I tried that, but my sample data only has three bytes per row.

>
> So? However much data you have, there are always 4 8-bit bytes in a
> 32-bit word.


Yebbut...

> As I said before:
>
>
>
> > But you also need to allow for:

>
> > 1. any padding at the end of each row (i.e. if w < stride*4).

> ...
> > For 1, either:

>
> > a) use e.g. "if (j*4+k < stride)" around the code which reads the bytes,
> > or
> > b) iterate over the bytes rather than the words, then push an extra 0-3
> > zero bytes into the final word at the end of each row.

>
> Either way, you need to "create" 0-3 extra zero bytes at the end of each
> row. If you iterate over the words, the innermost level needs a check to
> use the created zeros rather than trying to read non-existent source
> bytes. If you iterate over the bytes, you need to "complete" the last word
> after the loop.


I think I've got that covered.
I zero the word first and then mask and shift the
bytes into it. The padding is alredy there when I
copy the word into word-packed mask.

uint32_t u;

...

for (j = 0; j < stride/4; j++) {
u = 0;
/* each 8bit byte in 32bit int */
for (k = 0; k < w/8; k++) {
uint8_t b;
if (endian == big) b = samp[i*(w/ + k];
else b = samp[(i+1)*(w/ - (k+1)];
u <<= 8;
if (endian == big) u |= b;
else u |= invertbits(b);
//printf("%X\n", u);
}
//printf("%08X\n", u);
*((uint32_t *)(data + i*stride + j*4)) = u;
}
}

 
Reply With Quote
 
luser- -droog
Guest
Posts: n/a
 
      01-14-2011
On Jan 14, 11:29*am, luser- -droog <(E-Mail Removed)> wrote:
> On Jan 14, 11:02*am, Nobody <(E-Mail Removed)> wrote:
>
> > On Tue, 11 Jan 2011 19:21:54 -0800, luser- -droog wrote:
> > >> This should be:

>
> > >> > * * * * * * * * for (k = 0; k < 4; k++) {

>
> > >> Otherwise, you're iterating over the columns twice.

>
> > > I tried that, but my sample data only has three bytes per row.

>
> > So? However much data you have, there are always 4 8-bit bytes in a
> > 32-bit word.

>
> Yebbut...
>
>
>
> > As I said before:

>
> > > But you also need to allow for:

>
> > > 1. any padding at the end of each row (i.e. if w < stride*4).

> > ...
> > > For 1, either:

>
> > > a) use e.g. "if (j*4+k < stride)" around the code which reads the bytes,
> > > or
> > > b) iterate over the bytes rather than the words, then push an extra 0-3
> > > zero bytes into the final word at the end of each row.

>
> > Either way, you need to "create" 0-3 extra zero bytes at the end of each
> > row. If you iterate over the words, the innermost level needs a check to
> > use the created zeros rather than trying to read non-existent source
> > bytes. If you iterate over the bytes, you need to "complete" the last word
> > after the loop.

>
> I think I've got that covered.
> I zero the word first and then mask and shift the
> bytes into it. The padding is alredy there when I
> copy the word into word-packed mask.
>
> * * * * uint32_t u;
>
> * * * * ...
>
> * * * * * * for (j = 0; j < stride/4; j++) {
> * * * * * * * * u = 0;
> * * * * * * * * /* each 8bit byte in 32bit int */
> * * * * * * * * for (k = 0; k < w/8; k++) {
> * * * * * * * * * * uint8_t b;
> * * * * * * * * * * if (endian == big) b = samp[i*(w/ + k];
> * * * * * * * * * * else b = samp[(i+1)*(w/ - (k+1)];
> * * * * * * * * * * u <<= 8;
> * * * * * * * * * * if (endian == big) u |= b;
> * * * * * * * * * * else u |= invertbits(b);


Sorry, everyone! invertbits should really be called
reversebits. stinky red herring.

> * * * * * * * * * * //printf("%X\n", u);
> * * * * * * * * }
> * * * * * * * * //printf("%08X\n", u);
> * * * * * * * * *((uint32_t *)(data + i*stride + j*4)) = u;
> * * * * * * }
> * * * * }


 
Reply With Quote
 
Nobody
Guest
Posts: n/a
 
      01-14-2011
On Fri, 14 Jan 2011 09:29:15 -0800, luser- -droog wrote:

> for (j = 0; j < stride/4; j++) {
> u = 0;
> /* each 8bit byte in 32bit int */
> for (k = 0; k < w/8; k++) {


You're still doing (stride/4)*(w/ iterations, which is asymptotically
(w^2)/32 iterations.

This:

> for (j = 0; j < stride/4; j++) {


performs one iteration per word. The inner loop should be performed either
4 or 32 times, depending upon whether it processes bits or bytes. As it
processes bytes, it should be performed 4 times. The width of the bitmap
doesn't affect the limit of the inner loop, as it's already affecting the
width of the outer loop (stride will be w/8, rounded up to some multiple
decided according to efficiency constraints).

 
Reply With Quote
 
luser- -droog
Guest
Posts: n/a
 
      01-15-2011
On Jan 14, 2:54*pm, Nobody <(E-Mail Removed)> wrote:
> On Fri, 14 Jan 2011 09:29:15 -0800, luser- -droog wrote:
> > * * * * * * for (j = 0; j < stride/4; j++) {
> > * * * * * * * * u = 0;
> > * * * * * * * * /* each 8bit byte in 32bit int */
> > * * * * * * * * for (k = 0; k < w/8; k++) {

>
> You're still doing (stride/4)*(w/ iterations, which is asymptotically
> (w^2)/32 iterations.
>
> This:
>
> > * * * * * * for (j = 0; j < stride/4; j++) {

>
> performs one iteration per word. The inner loop should be performed either
> 4 or 32 times, depending upon whether it processes bits or bytes. As it
> processes bytes, it should be performed 4 times. The width of the bitmap
> doesn't affect the limit of the inner loop, as it's already affecting the
> width of the outer loop (stride will be w/8, rounded up to some multiple
> decided according to efficiency constraints).


Either I disagree for the reasons already stated or I still
don't understand for reasons I am unable to enunciate.
 
Reply With Quote
 
luser- -droog
Guest
Posts: n/a
 
      01-15-2011
On Jan 15, 12:13*am, luser- -droog <(E-Mail Removed)> wrote:
> On Jan 14, 2:54*pm, Nobody <(E-Mail Removed)> wrote:
>
>
>
> > On Fri, 14 Jan 2011 09:29:15 -0800, luser- -droog wrote:
> > > * * * * * * for (j = 0; j < stride/4; j++) {
> > > * * * * * * * * u = 0;
> > > * * * * * * * * /* each 8bit byte in 32bit int */
> > > * * * * * * * * for (k = 0; k < w/8; k++) {

>
> > You're still doing (stride/4)*(w/ iterations, which is asymptotically
> > (w^2)/32 iterations.

>
> > This:

>
> > > * * * * * * for (j = 0; j < stride/4; j++) {

>
> > performs one iteration per word. The inner loop should be performed either
> > 4 or 32 times, depending upon whether it processes bits or bytes. As it
> > processes bytes, it should be performed 4 times. The width of the bitmap
> > doesn't affect the limit of the inner loop, as it's already affecting the
> > width of the outer loop (stride will be w/8, rounded up to some multiple
> > decided according to efficiency constraints).

>
> Either I disagree for the reasons already stated or I still
> don't understand for reasons I am unable to enunciate.


I take it back!
Whatever it is you're trying to tell me, you're probably right.
When I doubled the width of the sample, the output is quite wrong.

/* test program for cairo bit mask
makes a big blue turkey */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <cairo.h>
#include <X11/Xlib.h>
#include <cairo-xlib.h>
#include <unistd.h>

enum { little, big } endian = little;

unsigned char reversebits (unsigned char b) {
return ( ((b & 0x01)?1:0) <<7)
| ( ((b & 0x02)?1:0) <<6)
| ( ((b & 0x04)?1:0) <<5)
| ( ((b & 0x0?1:0) <<4)
| ( ((b & 0x10)?1:0) <<3)
| ( ((b & 0x20)?1:0) <<2)
| ( ((b & 0x40)?1:0) <<1)
| ( ((b & 0x80)?1:0) )
;
}

void paintmask(cairo_t *cr, unsigned char *samp, int w, int h) {
int stride;
cairo_surface_t *mask;
unsigned char *data;
int i,j,k;
uint32_t u;

stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w);
printf("stride = %d\n", stride);
data = malloc(h * stride);

/* convert bytes to 32bit quantities matching
endianness of the machine */
/* each row */
for (i = 0; i < h; i++) {
/* each 32bit int in row */
for (j = 0; j < stride/4; j++) {
u = 0;
/* each 8bit byte in 32bit int */
for (k = 0; k < w/8; k++) {
uint8_t b;
if (endian == big) b = samp[i*(w/ + k];
else b = samp[(i+1)*(w/ - (k+1)];
u <<= 8;
if (endian == big) u |= b;
else u |= reversebits(b);
//printf("%X\n", u);
}
//printf("%08X\n", u);
*((uint32_t *)(data + i*stride + j*4)) = u;
}
}

mask = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A1,
w, h, stride);
cairo_mask_surface(cr, mask, 0, 0);
}



int main (int argc, char *argv[])
{
int width = 480;
int height = 460;
Display *dis;
int scr;
int depth;
Visual *vis;
XSetWindowAttributes attr;
unsigned long attrmask;
Window win;
cairo_surface_t *surface;
cairo_t *cr;

dis = XOpenDisplay(NULL);
scr = DefaultScreen(dis);
depth = DefaultDepth(dis, scr);
vis = DefaultVisual(dis, scr);
attr.background_pixel = WhitePixel(dis, scr);
attr.border_pixel = BlackPixel(dis, scr);
attr.event_mask = ExposureMask | StructureNotifyMask |
ButtonPressMask;
attrmask = CWColormap | CWBackPixel | CWBorderPixel | CWEventMask;
win = XCreateWindow(dis, RootWindow(dis, scr),
200, 10, //pos
width, height, 5, //width height border
depth,
InputOutput,
vis,
attrmask, &attr);
XMapWindow(dis, win);
surface = cairo_xlib_surface_create(dis, win, vis, width, height);
cr = cairo_create(surface);
cairo_scale(cr, 10, 10);

cairo_set_source_rgb(cr, 0, 0, 1);

{

unsigned char samp[] = {
0x00, 0x3B, 0x00,
0x00, 0x27, 0x00,
0x00, 0x24, 0x80,
0x0E, 0x49, 0x40,
0x11, 0x49, 0x20,

0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14,

0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4,
0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2,

0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00,

0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00 };


unsigned char samp2[] = {
0x00, 0x3B, 0x00, 0x00, 0x3B, 0x00,
0x00, 0x27, 0x00, 0x00, 0x27, 0x00,
0x00, 0x24, 0x80, 0x00, 0x24, 0x80,
0x0E, 0x49, 0x40, 0x0E, 0x49, 0x40,
0x11, 0x49, 0x20, 0x11, 0x49, 0x20,

0x14, 0xB2, 0x20, 0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50, 0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88, 0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C, 0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14, 0x17, 0x5F, 0x14,

0x1C, 0x07, 0xE2, 0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4, 0x38, 0x03, 0xC4,
0x70, 0x31, 0x82, 0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC, 0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2, 0xB2, 0xBB, 0xC2,

0xBB, 0x6F, 0x84, 0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2, 0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C, 0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00, 0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00,

0x03, 0xF8, 0x00, 0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00, 0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00, 0x1F, 0xF8, 0x00 };

//paintmask(cr, samp, 24, 23);
paintmask(cr, samp2, 48, 23);
XFlush(dis);
}
sleep(20);

cairo_destroy(cr);
cairo_surface_destroy(surface);

return 0;
}

 
Reply With Quote
 
luser- -droog
Guest
Posts: n/a
 
      01-16-2011
Alright. I finally understood what Nobody was saying.
I've reasoned through each line and it *should* work.
But something's still not right!

Since the operation of shifting should automatically
follow the natural endianness, I should always read
the bytes from most- to least-significance, right?

Then all that's necessary is to reverse the byte
before masking IFF it's little-endian, right?


/* test program for cairo bit mask
makes a big blue turkey */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <cairo.h>
#include <X11/Xlib.h>
#include <cairo-xlib.h>
#include <unistd.h>

enum { little, big } endian = little;

unsigned char reversebits (unsigned char b) {
return (b & 0x01? 0x80: 0)
| (b & 0x02? 0x40: 0)
| (b & 0x04? 0x20: 0)
| (b & 0x08? 0x10: 0)
| (b & 0x10? 0x08: 0)
| (b & 0x20? 0x04: 0)
| (b & 0x40? 0x02: 0)
| (b & 0x80? 0x01: 0)
;
}

void paintmask(cairo_t *cr, unsigned char *samp, int w, int h) {
int span; /* width in bytes */
int stride; /* width in words */
cairo_surface_t *mask;
unsigned char *data;
int i,j,k;
uint32_t u;

stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, w);
/* stride = (w/32) + (w%32 ? 1 : 0) */
span = w/8 + (w%8? 1: 0);
printf("stride = %d\n", stride);
data = malloc(h * stride);

/* convert bytes to 32bit quantities matching
endianness of the machine */
/* each row */
for (i = 0; i < h; i++) {

/* each 32bit int in row */
for (j = 0; j < stride/4; j++) {
u = 0; /* zero the word */

/* each 8bit byte in 32bit int from samples */
for (k = 0; k < 4; k++) {
uint8_t b;

u <<= 8;

if (j*4+k < span) {

/* postscript input is always big-endian */
/* so grab most-significant byte */
b = samp[i*span + j*4 + k];

if (endian == little) {
//b = samp[i*span + j*4 + (4-1-k)];
b = reversebits(b);
}

u |= b;
}
//printf("%X\n", u);
} /* k */

printf("%08X\n", u);
*((uint32_t *)(data + i*stride + j)) = u;

} /* j */
} /* i */

mask = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A1,
w, h, stride);
cairo_mask_surface(cr, mask, 0, 0);
}



int main (int argc, char *argv[])
{
int width = 480;
int height = 460;
Display *dis;
int scr;
int depth;
Visual *vis;
XSetWindowAttributes attr;
unsigned long attrmask;
Window win;
cairo_surface_t *surface;
cairo_t *cr;

dis = XOpenDisplay(NULL);
scr = DefaultScreen(dis);
depth = DefaultDepth(dis, scr);
vis = DefaultVisual(dis, scr);
attr.background_pixel = WhitePixel(dis, scr);
attr.border_pixel = BlackPixel(dis, scr);
attr.event_mask = ExposureMask | StructureNotifyMask |
ButtonPressMask;
attrmask = CWColormap | CWBackPixel | CWBorderPixel | CWEventMask;
win = XCreateWindow(dis, RootWindow(dis, scr),
200, 10, //pos
width, height, 5, //width height border
depth,
InputOutput,
vis,
attrmask, &attr);
XMapWindow(dis, win);
surface = cairo_xlib_surface_create(dis, win, vis, width, height);
cr = cairo_create(surface);
cairo_scale(cr, 10, 10);

cairo_set_source_rgb(cr, 0, 0, 1);

{

unsigned char samp[] = {
0x00, 0x3B, 0x00,
0x00, 0x27, 0x00,
0x00, 0x24, 0x80,
0x0E, 0x49, 0x40,
0x11, 0x49, 0x20,

0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14,

0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4,
0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2,

0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00,

0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00 };

/*
*/

unsigned char samp2[] = {
0x00, 0x3B, 0x00, 0x00, 0x3B, 0x00,
0x00, 0x27, 0x00, 0x00, 0x27, 0x00,
0x00, 0x24, 0x80, 0x00, 0x24, 0x80,
0x0E, 0x49, 0x40, 0x0E, 0x49, 0x40,
0x11, 0x49, 0x20, 0x11, 0x49, 0x20,

0x14, 0xB2, 0x20, 0x14, 0xB2, 0x20,
0x3C, 0xB6, 0x50, 0x3C, 0xB6, 0x50,
0x75, 0xFE, 0x88, 0x75, 0xFE, 0x88,
0x17, 0xFF, 0x8C, 0x17, 0xFF, 0x8C,
0x17, 0x5F, 0x14, 0x17, 0x5F, 0x14,

0x1C, 0x07, 0xE2, 0x1C, 0x07, 0xE2,
0x38, 0x03, 0xC4, 0x38, 0x03, 0xC4,
0x70, 0x31, 0x82, 0x70, 0x31, 0x82,
0xF8, 0xED, 0xFC, 0xF8, 0xED, 0xFC,
0xB2, 0xBB, 0xC2, 0xB2, 0xBB, 0xC2,

0xBB, 0x6F, 0x84, 0xBB, 0x6F, 0x84,
0x31, 0xBF, 0xC2, 0x31, 0xBF, 0xC2,
0x18, 0xEA, 0x3C, 0x18, 0xEA, 0x3C,
0x0E, 0x3E, 0x00, 0x0E, 0x3E, 0x00,
0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00,

0x03, 0xF8, 0x00, 0x03, 0xF8, 0x00,
0x1E, 0x18, 0x00, 0x1E, 0x18, 0x00,
0x1F, 0xF8, 0x00, 0x1F, 0xF8, 0x00 };

//paintmask(cr, samp, 24, 23);
paintmask(cr, samp2, 48, 23);
XFlush(dis);
}
sleep(20);

cairo_destroy(cr);
cairo_surface_destroy(surface);

return 0;
}

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help! How can I draw a bitmap only with BITMAP information! xqggz C++ 1 06-19-2007 03:07 PM
An int that is 4 bytes in native, and 12 bytes in .NET? Huh? BogusException C++ 7 02-06-2007 04:47 AM
Masked bitmap from bitmap Gandalf Python 0 01-29-2004 09:41 PM
int main(int argc, char *argv[] ) vs int main(int argc, char **argv ) Hal Styli C Programming 14 01-20-2004 10:00 PM
dirty stuff: f(int,int) cast to f(struct{int,int}) Schnoffos C Programming 2 06-27-2003 03:13 AM



Advertisments