2007.07.11 15:13 "[Tiff] how to handle pixel vs. byte-boundary", by Oliver Geisen

2007.07.12 05:25 "Re: [Tiff] how to handle pixel vs. byte-boundary", by Bob Friesenhahn

as i try to deal with bilevel images, where 1 pixel equals 1 bit, i ran more and more into problems.

I want to place a bilevel TIFF onto another one (digital mounting). Therefore i specifiy x,y-offsets in pixels where to place the second image on the first.

But if the offset-value isn't divideable by 8 without remainder (=don't fit into byte-boundary), it seems that i had to shift ALL bytes in the scanline to fit into the new position.

It does not seem to me that you need to shift any bytes into a new position, but you will need to decode starting with the byte where the first bit is, and ending in the last byte where the last bit of the altered part of the image row is. You can invent a scheme where you decode a byte, perform any boolean operations necessary on the bits, and then re-encode the byte. This approach would avoid the need for extra buffering.

Bit shifting can indeed be slow. Some algorithms are much faster than others. Performance is very compiler and CPU sensitive. I have attached a little benchmark program that I wrote some years ago in order to test the performance of various bit shift algorithms. Maybe one of these algorithms is best for you?

Bob
======================================
Bob Friesenhahn
bfriesen@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/

#include <stdio.h>

int main ( int argc, char *argv[])
{
  register long
    bit;

  register unsigned int
    i,
    rep,
    x;

  unsigned int
    algorithm,
    reps;

  register unsigned char
    c,
    *r;

  unsigned char
    result[8];

  volatile unsigned char
    value;

  if (argc != 4)
    {
      printf("usage: %s repetitions algorithm value\n", argv[0]);
      exit(1);
    }

  reps = atoi(argv[1]);

  algorithm = atoi(argv[2]);

  value = atoi(argv[3]);

  for (rep=reps; rep > 0; rep--)
    {
      switch (algorithm)
        {
        case 1:
          for (x=reps; x > 0; x--)
            {

              r=result;
              c=value;
              for (bit=7; bit >= 0; bit--)
                *r++=((c) & (0x01 << bit) ? 0x01 : 0x00);
            }
          break;
        case 2:
          for (x=reps; x > 0; x--)
            {
              r=result;
              c=value;
              for (bit=7; bit >= 0; bit--)
                *r++=(c >> bit) & 0x01;
            }
          break;
        case 3:
          for (x=reps; x > 0; x--)
            {
              r=result;
              c=value;
              *r++=(c >> 7) ;
              *r++=(c >> 6 ) & 0x01;
              *r++=(c >> 5 ) & 0x01;
              *r++=(c >> 4 ) & 0x01;
              *r++=(c >> 3 ) & 0x01;
              *r++=(c >> 2 ) & 0x01;
              *r++=(c >> 1 ) & 0x01;
              *r++=(c) & 0x01;
            }
          break;
        case 4:
          for (x=reps; x > 0; x--)
            {
              r=result;
              c=value;
              *r++=(c & 0x80) >> 7;
              *r++=(c & 0x40) >> 6;
              *r++=(c & 0x20) >> 5;
              *r++=(c & 0x10) >> 4;
              *r++=(c & 0x08) >> 3;
              *r++=(c & 0x04) >> 2;
              *r++=(c & 0x02) >> 1;
              *r++=(c & 0x01);

            }
          break;
        default:
          {
            printf("Unsupported algorithm\n");
            exit(1);
          }
        }
    }

  r=result;
  for(i=0; i<8; i++)
    printf("%d", *r++);
  printf("\n", result);

  return 0;
}