Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Pack bitmap bytes into native-endian 32bit int (http://www.velocityreviews.com/forums/t741857-pack-bitmap-bytes-into-native-endian-32bit-int.html)

luser- -droog 01-11-2011 06:43 PM

Pack bitmap bytes into native-endian 32bit int
 
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/8) + 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;
}


Nobody 01-11-2011 08:28 PM

Re: Pack bitmap bytes into native-endian 32bit int
 
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.



luser- -droog 01-12-2011 03:21 AM

Re: Pack bitmap bytes into native-endian 32bit int
 
On Jan 11, 2:28*pm, Nobody <nob...@nowhere.com> 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 & 0x08)?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/8) + k];
else b = samp[(i+1)*(w/8) - (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;
}


Nobody 01-14-2011 05:02 PM

Re: Pack bitmap bytes into native-endian 32bit int
 
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.


luser- -droog 01-14-2011 05:29 PM

Re: Pack bitmap bytes into native-endian 32bit int
 
On Jan 14, 11:02*am, Nobody <nob...@nowhere.com> 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/8) + k];
else b = samp[(i+1)*(w/8) - (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;
}
}


luser- -droog 01-14-2011 06:33 PM

Re: Pack bitmap bytes into native-endian 32bit int
 
On Jan 14, 11:29*am, luser- -droog <mijo...@yahoo.com> wrote:
> On Jan 14, 11:02*am, Nobody <nob...@nowhere.com> 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/8) + k];
> * * * * * * * * * * else b = samp[(i+1)*(w/8) - (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;
> * * * * * * }
> * * * * }



Nobody 01-14-2011 08:54 PM

Re: Pack bitmap bytes into native-endian 32bit int
 
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/8) 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).


luser- -droog 01-15-2011 06:13 AM

Re: Pack bitmap bytes into native-endian 32bit int
 
On Jan 14, 2:54*pm, Nobody <nob...@nowhere.com> 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/8) 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.

luser- -droog 01-15-2011 07:06 AM

Re: Pack bitmap bytes into native-endian 32bit int
 
On Jan 15, 12:13*am, luser- -droog <mijo...@yahoo.com> wrote:
> On Jan 14, 2:54*pm, Nobody <nob...@nowhere.com> 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/8) 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 & 0x08)?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/8) + k];
else b = samp[(i+1)*(w/8) - (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;
}


luser- -droog 01-16-2011 07:11 AM

Re: Pack bitmap bytes into native-endian 32bit int
 
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;
}



All times are GMT. The time now is 11:35 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57