Pack bitmap bytes into native-endian 32bit int

Discussion in 'C Programming' started by luser- -droog, Jan 11, 2011.

  1. 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;
    }
     
    luser- -droog, Jan 11, 2011
    #1
    1. Advertising

  2. luser- -droog

    Nobody Guest

    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.
     
    Nobody, Jan 11, 2011
    #2
    1. Advertising

  3. On Jan 11, 2:28 pm, Nobody <> 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;
    }
     
    luser- -droog, Jan 12, 2011
    #3
  4. luser- -droog

    Nobody Guest

    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.
     
    Nobody, Jan 14, 2011
    #4
  5. On Jan 14, 11:02 am, Nobody <> 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, Jan 14, 2011
    #5
  6. On Jan 14, 11:29 am, luser- -droog <> wrote:
    > On Jan 14, 11:02 am, Nobody <> 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;
    >             }
    >         }
     
    luser- -droog, Jan 14, 2011
    #6
  7. luser- -droog

    Nobody Guest

    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).
     
    Nobody, Jan 14, 2011
    #7
  8. On Jan 14, 2:54 pm, Nobody <> 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, Jan 15, 2011
    #8
  9. On Jan 15, 12:13 am, luser- -droog <> wrote:
    > On Jan 14, 2:54 pm, Nobody <> 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, Jan 15, 2011
    #9
  10. 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;
    }
     
    luser- -droog, Jan 16, 2011
    #10
  11. luser- -droog <> writes:

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


    I can't answer this exactly since your code seems to have a very
    different view of endianness to the conventional one. You seem to be
    using the term to refer to bit order rather than byte order.

    Shifting is defined to be like multiplying by a power of two the answer
    seems to be "yes", but if the whole word need to be reversed (because
    the bit-order needs to be changed) then reversing the bit in each byte
    might not be enough.

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


    That's not a C question and I'm not a Cairo expert. All I can say is
    that endianness does not usually refer to bit order but to byte order.
    To know the correct transformation, one would need to know the byte and
    bit order to Postscript bit masks and the same for the 32-bit Cairo bit
    masks that you are building. I think a graphics group would get you
    more informed audience.

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Jan 16, 2011
    #11
  12. On Jan 16, 8:02 am, Ben Bacarisse <> wrote:
    > luser- -droog <> writes:
    > > 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?

    >
    > I can't answer this exactly since your code seems to have a very
    > different view of endianness to the conventional one.  You seem to be
    > using the term to refer to bit order rather than byte order.
    >
    > Shifting is defined to be like multiplying by a power of two the answer
    > seems to be "yes", but if the whole word need to be reversed (because
    > the bit-order needs to be changed) then reversing the bit in each byte
    > might not be enough.
    >
    > > Then all that's necessary is to reverse the byte
    > > before masking IFF it's little-endian, right?

    >
    > That's not a C question and I'm not a Cairo expert.  All I can say is
    > that endianness does not usually refer to bit order but to byte order.
    > To know the correct transformation, one would need to know the byte and
    > bit order to Postscript bit masks and the same for the 32-bit Cairo bit
    > masks that you are building.  I think a graphics group would get you
    > more informed audience.
    >
    > <snip>
    > --
    > Ben.


    Thanks. Hopefully, I've lurked on the Cairo list long enough to
    hazard the question there.
     
    luser- -droog, Jan 17, 2011
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. hicham
    Replies:
    2
    Views:
    9,040
    dxcoder
    Jul 2, 2003
  2. Ernst Murnleitner

    float: IEEE, big endian, little endian

    Ernst Murnleitner, Jan 13, 2004, in forum: C++
    Replies:
    0
    Views:
    881
    Ernst Murnleitner
    Jan 13, 2004
  3. Eric J.Hu
    Replies:
    3
    Views:
    853
    Alexei A. Frounze
    Aug 29, 2005
  4. Eric J.Hu
    Replies:
    7
    Views:
    543
    Jim Langston
    Sep 7, 2005
  5. BogusException
    Replies:
    7
    Views:
    340
Loading...

Share This Page