![]() |
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; } |
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. |
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; } |
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. |
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; } } |
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; > * * * * * * } > * * * * } |
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). |
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. |
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; } |
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.