~ubuntu-branches/ubuntu/lucid/xcb-util/lucid

« back to all changes in this revision

Viewing changes to image/xcb_image.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Danjou
  • Date: 2009-02-15 12:58:13 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090215125813-fvdfqrch1341t8bd
Tags: 0.3.3-2
Add versioned link to GPL.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2007 Bart Massey
 
1
/* Copyright © 2007 Bart Massey
2
2
 *
3
3
 * Permission is hereby granted, free of charge, to any person obtaining a
4
4
 * copy of this software and associated documentation files (the "Software"),
62
62
              xcb_image_format_t format, uint8_t xpad)
63
63
{
64
64
  xcb_image_format_t  ef = effective_format(format, bpp);
65
 
  if (depth > bpp || bpp > unit)
 
65
  if (depth > bpp)
66
66
      return 0;
67
67
  switch(ef) {
68
68
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
125
125
  xcb_image_format_t  ef = effective_format(image->format, image->bpp);
126
126
  switch (ef) {
127
127
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
128
 
      image->plane_mask = xcb_mask(image->depth);
129
128
      image->stride = xcb_roundup(image->width, image->scanline_pad) >> 3;
130
129
      image->size = image->height * image->stride * image->depth;
131
130
      break;
132
131
  case XCB_IMAGE_FORMAT_Z_PIXMAP:
133
 
      image->plane_mask = 0;
134
132
      image->stride = xcb_roundup((uint32_t)image->width *
135
133
                                  (uint32_t)image->bpp,
136
134
                                  image->scanline_pad) >> 3;
229
227
  }
230
228
  if (!format_valid(depth, bpp, unit, format, xpad))
231
229
      return 0;
232
 
  image = (xcb_image_t *)malloc(sizeof(*image));
 
230
  image = malloc(sizeof(*image));
233
231
  if (image == 0)
234
232
      return 0;
235
233
  image->width = width;
239
237
  image->depth = depth;
240
238
  image->bpp = bpp;
241
239
  image->unit = unit;
 
240
  image->plane_mask = xcb_mask(depth);
242
241
  image->byte_order = byte_order;
243
242
  image->bit_order = bit_order;
244
243
  xcb_image_annotate(image);
358
357
  case XCB_IMAGE_FORMAT_Z_PIXMAP:
359
358
      image = xcb_image_create_native(conn, width, height, format,
360
359
                                      imrep->depth, imrep, bytes, data);
361
 
      if (!image)
 
360
      if (!image) {
362
361
          free(imrep);
 
362
          return 0;
 
363
      }
363
364
      break;
364
365
  default:
365
366
      assert(0);
527
528
}
528
529
 
529
530
 
 
531
static uint32_t
 
532
xy_image_byte (xcb_image_t *image, uint32_t x)
 
533
{
 
534
    x >>= 3;
 
535
    if (image->byte_order == image->bit_order)
 
536
        return x;
 
537
    switch (image->unit) {
 
538
    default:
 
539
    case 8:
 
540
        return x;
 
541
    case 16:
 
542
        return x ^ 1;
 
543
    case 32:
 
544
        return x ^ 3;
 
545
    }
 
546
}
 
547
 
 
548
static uint32_t
 
549
xy_image_bit (xcb_image_t *image, uint32_t x)
 
550
{
 
551
    x &= 7;
 
552
    if (image->bit_order == XCB_IMAGE_ORDER_MSB_FIRST)
 
553
        x = 7 - x;
 
554
    return x;
 
555
}
 
556
 
530
557
/* GetPixel/PutPixel */
531
558
 
532
559
/* XXX this is the most hideously done cut-and-paste
543
570
  if (x > image->width || y > image->height)
544
571
      return;
545
572
  row = image->data + (y * image->stride);
546
 
  switch (image->format) {
 
573
  switch (effective_format(image->format, image->bpp)) {
547
574
  case XCB_IMAGE_FORMAT_XY_BITMAP:
548
575
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
549
576
      /* block */ {
550
577
          int  p;
551
578
          uint32_t   plane_mask = image->plane_mask;
552
579
          uint8_t *  plane = row;
553
 
          uint32_t   ulog = image->bpp >> 4;
554
 
          uint32_t   unit = (x >> 3) & ~xcb_mask(ulog);
555
 
          uint32_t   byte = (x >> 3) & xcb_mask(ulog);
556
 
          uint32_t   bit = x & 7;
 
580
          uint32_t   byte = xy_image_byte(image, x);
 
581
          uint32_t   bit = xy_image_bit(image,x);
 
582
          uint8_t    mask = 1 << bit;
557
583
 
558
 
          if (image->byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
559
 
              byte = xcb_mask(ulog) - byte;
560
 
          if (image->bit_order == XCB_IMAGE_ORDER_MSB_FIRST) {
561
 
              bit = 7 - bit;
562
 
          } else {
563
 
              pixel = xcb_bit_reverse(pixel, image->bpp);
564
 
              plane_mask = xcb_bit_reverse(plane_mask, image->bpp);
565
 
          }
566
 
          for (p = 0; p < image->bpp; p++) {
567
 
              if (plane_mask & 1) {
568
 
                  uint8_t *  bp = plane + (unit | byte);
569
 
                  uint8_t    m = 1 << bit;
570
 
                  uint8_t    p = (pixel & 1) << bit;
571
 
                  *bp = (*bp & ~m) | p;
 
584
          for (p = image->bpp - 1; p >= 0; p--) {
 
585
              if ((plane_mask >> p) & 1) {
 
586
                  uint8_t *  bp = plane + byte;
 
587
                  uint8_t    this_bit = ((pixel >> p) & 1) << bit;
 
588
                  *bp = (*bp & ~mask) | this_bit;
572
589
              }
573
590
              plane += image->stride * image->height;
574
 
              pixel >>= 1;
575
 
              plane_mask >>= 1;
576
591
          }
577
592
      }
578
593
      break;
657
672
 
658
673
  assert(x < image->width && y < image->height);
659
674
  row = image->data + (y * image->stride);
660
 
  switch (image->format) {
 
675
  switch (effective_format(image->format, image->bpp)) {
661
676
  case XCB_IMAGE_FORMAT_XY_BITMAP:
662
677
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
663
678
      /* block */ {
664
679
          int  p;
665
680
          uint32_t   plane_mask = image->plane_mask;
666
681
          uint8_t *  plane = row;
667
 
          uint32_t   ulog = image->bpp >> 4;
668
 
          uint32_t   unit = (x >> 3) & ~xcb_mask(ulog);
669
 
          uint32_t   byte = (x >> 3) & xcb_mask(ulog);
670
 
          uint32_t   bit = x & 7;
 
682
          uint32_t   byte = xy_image_byte(image, x);
 
683
          uint32_t   bit = xy_image_bit(image,x);
671
684
 
672
 
          if (image->byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
673
 
              byte = xcb_mask(ulog) - byte;
674
 
          if (image->bit_order == XCB_IMAGE_ORDER_MSB_FIRST) {
675
 
              bit = 7 - bit;
676
 
          } else {
677
 
              plane_mask = xcb_bit_reverse(plane_mask, image->bpp);
678
 
          }
679
 
          for (p = 0; p < image->bpp; p++) {
 
685
          for (p = image->bpp - 1; p >= 0; p--) {
680
686
              pixel <<= 1;
681
 
              if (plane_mask & 1) {
682
 
                  uint8_t *  bp = plane + (unit | byte);
 
687
              if ((plane_mask >> p) & 1) {
 
688
                  uint8_t *  bp = plane + byte;
683
689
                  pixel |= (*bp >> bit) & 1;
684
690
              }
685
691
              plane += image->stride * image->height;
686
 
              plane_mask >>= 1;
687
692
          }
688
 
          if (image->bit_order == XCB_IMAGE_ORDER_LSB_FIRST)
689
 
              pixel = xcb_bit_reverse(pixel, image->bpp);
690
693
      }
691
694
      return pixel;
692
695
  case XCB_IMAGE_FORMAT_Z_PIXMAP:
830
833
           uint32_t          src_stride,
831
834
           uint8_t *         dst,
832
835
           uint32_t          dst_stride,
833
 
           uint8_t const *   byte_order,
834
 
           int               unit_bytes,
835
 
           uint16_t          height,
 
836
           uint32_t          height,
 
837
           uint32_t          byteswap,
836
838
           int               bitswap,
837
839
           int               nibbleswap)
838
840
{
839
841
  while (height--) {
840
 
      uint32_t    minor = 0;
841
 
      uint32_t    major = 0;
842
842
      uint32_t    s;
843
843
 
844
844
      for (s = 0; s < src_stride; s++) {
845
845
          uint8_t   b;
846
 
          uint32_t  d = major + byte_order[minor];
 
846
          uint32_t  d = s ^ byteswap;
847
847
 
848
848
          if (d > dst_stride)
849
849
              continue;
854
854
          if (nibbleswap)
855
855
              b = (b << 4) | (b >> 4);
856
856
          dst[d] = b;
857
 
 
858
 
          if (++minor == unit_bytes) 
859
 
          {
860
 
              minor = 0; 
861
 
              major += unit_bytes;
862
 
          }
863
857
      }
864
858
      src += src_stride;
865
859
      dst += dst_stride;
866
860
  }
867
861
}
868
862
 
869
 
/* Note that all of these permutations are self-inverse.
870
 
   Applying them twice yields the identity permutation, i.e p*p = i
871
 
   This means that we only have to care about the
872
 
   source and destination size and whether they mismatch, not
873
 
   the actual endiannesses. */
874
 
static uint8_t const forward_order[4] = {0, 1, 2, 3};
875
 
static uint8_t const reverse_order[4] = {3, 2, 1, 0};
876
 
static uint8_t const reverse_word_order[4] = {2, 3, 0, 1};
877
 
 
878
 
static uint8_t const *
879
 
conversion_byte_order(xcb_image_t *src, xcb_image_t *dst)
880
 
{
881
 
    uint8_t  nbytes = src->unit >> 3;
 
863
/* Which order are bytes in (low two bits), given
 
864
 * code which accesses an image one byte at a time
 
865
 */
 
866
static uint32_t
 
867
byte_order(xcb_image_t *i)
 
868
{
 
869
    uint32_t flip = i->byte_order == XCB_IMAGE_ORDER_MSB_FIRST;
 
870
 
 
871
    switch (i->bpp) {
 
872
    default:
 
873
    case 8:
 
874
        return 0;
 
875
    case 16:
 
876
        return flip;
 
877
    case 32:
 
878
        return flip | (flip << 1);
 
879
    }
 
880
}
 
881
 
 
882
static uint32_t
 
883
bit_order(xcb_image_t *i)
 
884
{
 
885
    uint32_t flip = i->byte_order != i->bit_order;
 
886
 
 
887
    switch (i->unit) {
 
888
    default:
 
889
    case 8:
 
890
        return 0;
 
891
    case 16:
 
892
        return flip;
 
893
    case 32:
 
894
        return flip | (flip << 1);
 
895
    }
 
896
}
 
897
 
 
898
/* Convert from one byte order to another by flipping the 
 
899
 * low two bits of the byte index along a scanline
 
900
 */
 
901
static uint32_t 
 
902
conversion_byte_swap(xcb_image_t *src, xcb_image_t *dst)
 
903
{
 
904
    xcb_image_format_t ef = effective_format(src->format, src->bpp);
882
905
    
883
 
    if (src->byte_order == dst->byte_order)
884
 
        return forward_order;
885
 
    if (nbytes >= 1 && nbytes <= 4)
886
 
        return &reverse_order[4 - nbytes];
887
 
    return forward_order;
888
 
}
889
 
 
890
 
 
891
 
#define R1 forward_order
892
 
#define R2 reverse_word_order
893
 
#define R4 reverse_order
894
 
#define W4 reverse_word_order
895
 
 
896
 
static uint8_t const * const bbo_reverse[3][3] =
897
 
        /* 8  16  32*/
898
 
  /*8*/ {{R1, R2, R4},
899
 
 /*16*/  {R2, R2, W4},
900
 
 /*32*/  {R4, W4, R4}};
901
 
 
902
 
static uint8_t const *
903
 
bitmap_conversion_byte_order(xcb_image_t *src, xcb_image_t *dst)
904
 
{
905
 
    uint8_t  srclog = src->unit >> 4;
906
 
    uint8_t  dstlog = dst->unit >> 4;
907
 
    int sbo = src->byte_order;
908
 
    int dbo = dst->byte_order;
909
 
 
910
 
    if (srclog == 0)
911
 
        sbo = XCB_IMAGE_ORDER_LSB_FIRST;
912
 
    if (dstlog == 0)
913
 
        dbo = XCB_IMAGE_ORDER_LSB_FIRST;
914
 
    if (dbo == sbo)
915
 
        return forward_order;
916
 
    return bbo_reverse[srclog][dstlog];
917
 
}
918
 
 
 
906
    /* src_ef == dst_ef in all callers of this function */
 
907
    if (ef == XCB_IMAGE_FORMAT_XY_PIXMAP) {
 
908
        return bit_order(src) ^ bit_order(dst);
 
909
    } else {
 
910
        /* src_bpp == dst_bpp in all callers of this function */
 
911
        return byte_order(src) ^ byte_order(dst);
 
912
    }
 
913
}
919
914
 
920
915
xcb_image_t *
921
916
xcb_image_convert (xcb_image_t *  src,
922
917
                   xcb_image_t *  dst)
923
918
{
924
 
  uint32_t            x;
925
 
  uint32_t            y;
926
 
  int                 format_compatible = 0;
927
 
  int                 bitmap = 0;
928
919
  xcb_image_format_t  ef = effective_format(src->format, src->bpp);
929
920
 
930
921
  /* Things will go horribly wrong here if a bad
932
923
     up front just to be nice. */
933
924
  assert(image_format_valid(src));
934
925
  assert(image_format_valid(dst));
935
 
  if (src->depth != dst->depth ||
936
 
      src->width != dst->width ||
 
926
  
 
927
  /* images must be the same size
 
928
   * (yes, we could copy a sub-set)
 
929
   */
 
930
  if (src->width != dst->width ||
937
931
      src->height != dst->height)
938
932
      return 0;
939
 
  switch (ef) {
940
 
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
941
 
      bitmap = src->depth == 1;
942
 
      format_compatible = src->format == dst->format || bitmap;
943
 
      /* Case: Formats are identical.  Just copy. */
944
 
      if (format_compatible &&
945
 
          src->bpp == dst->bpp &&
946
 
          src->unit == dst->unit &&
947
 
          src->scanline_pad == dst->scanline_pad &&
948
 
          src->byte_order == dst->byte_order &&
949
 
          src->bit_order == dst->bit_order) {
950
 
          memcpy(dst->data, src->data, src->size);
951
 
          return dst;
952
 
      }
953
 
      break;
954
 
  case XCB_IMAGE_FORMAT_Z_PIXMAP:
955
 
      format_compatible = src->format == dst->format;
956
 
      /* Case: Formats are identical.  Just copy. */
957
 
      if (format_compatible &&
958
 
          src->bpp == dst->bpp &&
959
 
          src->byte_order == dst->byte_order) {
960
 
          memcpy(dst->data, src->data, src->size);
961
 
          return dst;
962
 
      }
963
 
      break;
964
 
  default:
965
 
      assert(0);
966
 
  }
967
 
  /* Case: Bitmap scanline units are always compatible.  Copy and convert. */
968
 
  if (bitmap) {
969
 
      uint8_t const * const
970
 
               byte_order = bitmap_conversion_byte_order(src, dst);
971
 
      int      bitswap = src->bit_order != dst->bit_order;
972
 
      uint8_t  unit = src->unit;
973
 
      
974
 
      if (dst->unit < unit)
975
 
          unit = dst->unit;
976
 
      swap_image(src->data, src->stride,
977
 
                     dst->data, dst->stride,
978
 
                     byte_order, unit >> 3,
979
 
                     src->height, bitswap, 0);
980
 
      return dst;
981
 
  }
982
 
  /* Case: Pixmap scanline units are identical.  Copy and convert. */
983
 
  if (format_compatible && src->bpp == dst->bpp) {
984
 
      uint8_t const * const
985
 
           byte_order = conversion_byte_order(src, dst);
986
 
      int  bitswap = src->bit_order != dst->bit_order;
987
 
      int  nibbleswap = src->byte_order != dst->byte_order &&
988
 
                        src->bpp == 4;
989
 
      swap_image(src->data, src->stride,
990
 
                     dst->data, dst->stride,
991
 
                     byte_order, src->unit >> 3,
992
 
                     src->height, bitswap, nibbleswap);
993
 
      return dst;
994
 
  }
995
 
 
996
 
  /* General case: Slow pixel copy. Should we optimize
997
 
     Z24<->Z32 copies of either endianness? */
998
 
  for (y = 0; y < src->height; y++) {
999
 
      for (x = 0; x < src->width; x++) {
1000
 
          uint32_t  pixel = xcb_image_get_pixel(src, x, y);
1001
 
          xcb_image_put_pixel(dst, x, y, pixel);
1002
 
      }
 
933
 
 
934
  if (ef == effective_format(dst->format, dst->bpp) &&
 
935
      src->bpp == dst->bpp)
 
936
  {
 
937
    if (src->unit == dst->unit &&
 
938
        src->scanline_pad == dst->scanline_pad &&
 
939
        src->byte_order == dst->byte_order &&
 
940
        (ef == XCB_IMAGE_FORMAT_Z_PIXMAP ||
 
941
         src->bit_order == dst->bit_order)) {
 
942
      memcpy(dst->data, src->data, src->size);
 
943
    } else {
 
944
      int       bitswap = 0;
 
945
      int       nibbleswap = 0;
 
946
      uint32_t  byteswap = conversion_byte_swap(src, dst);
 
947
      uint32_t  height = src->height;;
 
948
 
 
949
      if (ef == XCB_IMAGE_FORMAT_Z_PIXMAP) {
 
950
        if (src->bpp == 4 && src->byte_order != dst->byte_order)
 
951
          nibbleswap = 1;
 
952
      } else {
 
953
        if (src->bit_order != dst->bit_order)
 
954
          bitswap = 1;
 
955
        height *= src->depth;
 
956
      }
 
957
      swap_image (src->data, src->stride, dst->data, dst->stride,
 
958
                  height, byteswap, bitswap, nibbleswap);
 
959
    }
 
960
  }
 
961
  else
 
962
  {
 
963
    uint32_t            x;
 
964
    uint32_t            y;
 
965
    /* General case: Slow pixel copy. Should we optimize
 
966
       Z24<->Z32 copies of either endianness? */
 
967
    for (y = 0; y < src->height; y++) {
 
968
        for (x = 0; x < src->width; x++) {
 
969
            uint32_t  pixel = xcb_image_get_pixel(src, x, y);
 
970
            xcb_image_put_pixel(dst, x, y, pixel);
 
971
        }
 
972
    }
1003
973
  }
1004
974
  return dst;
1005
975
}