[comp.sys.amiga] BitMaps

ahinds@hvrunix.UUCP (Alexander Hinds) (01/28/88)

	I've been trying to read the bit values of a BitMap in a particular
plane and store them in an array.  I've looked throught the RKM's and haven't
found anything too helpful.  Can anybody tell me how the bits are stored and
how one can read them out of memory?

	I thank you in advance.

					Sincerely,
						Alexander Hinds

USENET:ahinds@hvrford
BITNET:A_HINDS@HVRFORD

cmcmanis%pepper@Sun.COM (Chuck McManis) (01/29/88)

[ I know it's long, consider it an effort to get the technical stuff back
  into this newsgroup.]

In article <396@hvrunix.UUCP> ahinds@hvrunix.UUCP (Alexander Hinds) writes:
>	I've been trying to read the bit values of a BitMap in a particular
>plane and store them in an array.  I've looked throught the RKM's and haven't
>found anything too helpful.  Can anybody tell me how the bits are stored and
>how one can read them out of memory?

Bitmaps, being bit plane oriented, are a bit different on the Amiga :-). But
they are still pretty easy to get to. The simplest way is to initialize a
RastPort to point to a particular BitMap and use ReadPixel(). But since you
asked about the organization, here goes ...

The BitMap has an array of Planes pointers, there are 8 but the current 
Amigas only use a maximum of six. Each one is a pointer to
a bunch of Unsigned Bytes (UBYTEs). [Important note, even if the image
maybe only 17 pixels wide, it needs a integral number of WORDS per line and
you have to take this into account when allocating memory and doing 
calculations on where the bits are in memory.] Each Plane Pointer points 
to one bitplane of the image in question. So graphically for a 25 X 12 
BitMap that is two bits 'Deep' (4 colors) ...

			             0    0    1    1    2   2 Filler
			         X = 0....5....0....5....0...4 XXXXXX
Planes[0] -> 0x10 0x00 0x08 0x00  /* ...*................*........... */ Y = 0
             0x18 0x00 0x0c 0x00  /* ...**...............**.......... */ Y = 1
             0x14 0x00 0x0e 0x00  /* ...*.*..............***......... */ Y = 2
             0x12 0x00 0x0f 0x00  /* ...*..*.............****........ */ Y = 3
             0x11 0xff 0xff 0x80  /* ...*...******************....... */ Y = 4
             0x11 0xff 0xff 0x80  /* ...*...******************....... */ Y = 5
             0x12 0x00 0x0f 0x00  /* ...*..*.............****........ */ Y = 6
             0x14 0x00 0x0e 0x00  /* ...*.*..............***......... */ Y = 7
             0x18 0x00 0x0c 0x00  /* ...**...............**.......... */ Y = 8
             0x10 0x00 0x08 0x00  /* ...*................*........... */ Y = 9

			             0    0    1    1    2   2 Filler
			         X = 0....5....0....5....0...4 XXXXXX
Planes[1] -> 0x10 0x00 0x08 0x00  /* ...*................*........... */ Y = 0
             0x18 0x00 0x0c 0x00  /* ...**...............**.......... */ Y = 1
             0x1c 0x00 0x0a 0x00  /* ...***..............*.*......... */ Y = 2
             0x1e 0x00 0x09 0x00  /* ...****.............*..*........ */ Y = 3
             0x1f 0xff 0xf8 0x80  /* ...******************...*....... */ Y = 4
             0x1f 0xff 0xf8 0x80  /* ...******************...*....... */ Y = 5
             0x1e 0x00 0x09 0x00  /* ...****.............*..*........ */ Y = 6
             0x1c 0x00 0x0a 0x00  /* ...***..............*.*......... */ Y = 7
             0x18 0x00 0x0c 0x00  /* ...**...............**.......... */ Y = 8
             0x10 0x00 0x08 0x00  /* ...*................*........... */ Y = 9

The color register that a given pixel will use can be calculated by taking
one bit from each bitplane and assembling them into a byte (remember there
could be 8 bitplanes) and using the value of that byte to index into the
color map. So in our image above the Pixel at [0,0] has a 0 in bitplane
0 and and a zero in bitplane one, or graphically :

               Bitplane  Number
	       7 6 5 4 3 2 1 0
               -+-+-+-+-+-+-+-
  Pixel[ 0,0]  x x x x x x 0 0 = 0 = ColorMap[0]
  Pixel[21,2]  x x x x x x 0 1 = 1 = ColorMap[1]
  Pixel[ 4,2]  x x x x x x 1 0 = 2 = ColorMap[2]
  Pixel[10,4]  x x x x x x 1 1 = 3 = ColorMap[3]

Getting to an individual pixel in memory is a function of calculating
where it exists and then adding together all of the bits in question.
The three required parameters to find the desired bit are the width of 
the bitmap and the x and y co-ordinates. You will also need a pointer to
each of the bitplanes that make up the image.

So some C code to do this the hard way...

/* Method for finding the number of UBYTES per line in the bitplane */
#define BytesPerLine(w) (((w + 15) >> 3) & ~1) 

/* Returns a BYTE offset into the bitplane to find the required byte. */
USHORT Offset(w,x,y) 
  USHORT w,x,y;	/* Width, and Pixel co-ordinates */

{  return(((x >> 3) % BytesPerLine(w)) + (y * BytesPerLine(w))); }

/* Builds a byte with the 'value' of the pixel at x,y */
UBYTE PixelValue(planes,n,w,x,y)

UBYTE	*planes[]; 	/* An Array of pointers to the bitplanes  */
short	n;		/* Number of bitplanes 1 < n < 9	  */
USHORT 	w,x,y;		/* Width of the bitplane, and pixel coord */

{
  UBYTE  B,T;
  short	 i;
  
  B = 0; 
  for (i=0; i<n; i++) {
    /* Fetch the byte, isolate the desired bit, and shift it into Bit 0 */
    T = (*(planes[i]+Offset(x,y)) >> (7 - (x % 8))) & 1;
    /* Add it into the pixel we are building */
    B += T << i;
  }
  return(B); /* Return it to the Caller. */
}

Now, that is the tough way, but it will work. Consider that the BitMap
structure has the following definition ...

struct BitMap
{
    UWORD   BytesPerRow;
    UWORD   Rows;
    UBYTE   Flags;
    UBYTE   Depth;
    UWORD   pad;
    PLANEPTR Planes[8];
};

You can probably see how the above routines can be coalesed into one
smaller routine requiring only a pointer to a BitMap structure and the
co-ordinates of the pixel of interest. This is left as an exercise for
the reader... :-)



--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.

ahinds@hvrunix.UUCP (Alexander Hinds) (01/31/88)

In article <40367@sun.uucp>, cmcmanis%pepper@Sun.COM (Chuck McManis) writes:
> In article <396@hvrunix.UUCP> ahinds@hvrunix.UUCP (Alexander Hinds) writes:
> >	I've been trying to read the bit values of a BitMap in a particular
> >plane and store them in an array.  I've looked throught the RKM's and haven't
> >found anything too helpful.  Can anybody tell me how the bits are stored and
> >how one can read them out of memory?
> 
> Bitmaps, being bit plane oriented, are a bit different on the Amiga :-). But
> they are still pretty easy to get to. The simplest way is to initialize a
> RastPort to point to a particular BitMap and use ReadPixel(). But since you
> asked about the organization, here goes ..

	What I was trying to do was to grab the screen via Gfx->ActiView and
store the screen data.  I tried to use intuition by initializing a RastPort
and setting the BitMap pointer to the one in ActiView->ViewPort->RasInfo->BitMapThen, I tried to use ReadPixel.  And, of course, during this, I surrounded this
block of code with a Forbid() Permit().  However, the machine crashed on me
every time, most of the time with an Adrress Out of Range or an Opcode 1111
error.  I couldn't figure out why, so I stopped trying that method.  Was I
doing something wrong, or overlooking something?  Anyway, thanks for your help.
I hope I can get it to work this time!

						Alexander Hinds

USENET:ahinds@hvrford
BITNET:A_HINDS@HVRFORD