Graphics

# Working with bitmaps and rastports

Bitmaps are low level primitives which consists of the pixel data for a graphics image. Rastports are high level objects which encapsulate bitmaps and encapsulate drawing information used with the bitmap.

## Setting drawing colors

To set drawing colors you can use the pen system or RGB colour values. RGB color values are supported only on high color or true color targets. RGB colour is set with SetRPAttrs() using RPTAG\_FgColor and RPTAG\_BgColor tags.

### RGB drawing mode

```
SetRPAttrs(rp,
 RPTAG\_PenMode, FALSE, /\* Switch pen mode off \*/
 RPTAG\_FgColor, 0xffffff, /\* Foreground color to white \*/
 RPTAG\_BgColor, 0x000000, /\* Background color to black \*/
 TAG\_DONE);

```

You need to switch pen mode off only once if you are only using RGB color triplets. Setting a rendering pen with SetAPen(), SetBPen() and SetOPen() switch the pen mode on automatically and the original rendering pen is restored.

### Pen drawing mode

Using pen mode is more complicated but it is always only way to draw primitives to palette based rastports. You should always obtain the pen using your preferred color. When terminating your rendering target you have to release the drawing pen.

```
LONG pen = ObtainBestPen(colormap, 0xffffffff, 0xffffffff, 0xffffffff, TAG\_DONE);

if (pen != -1)
{
 SetAPen(rp, pen);

 /\* drawing operations \*/

 /\* call ReleasePen() only when your render target is disposed \*/
 ReleasePen(colormap, pen);
}

```

Using drawing pens is only for advanced developers.

## Drawing operations

### Text

Here is an example how to draw test using RGB colour values:

```
void DrawText(struct RastPort \*rp)
{
 SetRPAttrs(rp, RPTAG\_PenMode, FALSE, RPTAG\_FgColor, 0xFFFFFF, TAG\_DONE); /\* Change foreground colour to black \*/
 Move(rp, 20, 25); /\* Start rendering to coordinates x=20, y=25 \*/
 Text(rp, sizeof("Hello world!"), "Hello world!");
}

```

### Drawing lines

To draw lines you set the starting point with Move() and then draw line to destination point with Draw().

```
Move(rp, x, y);
Draw(rp, x+10, y);
Draw(rp, x+10, y+10);
Draw(rp, x, y+10);
Draw(rp, x, y);

```

### Accessing single pixels

On palette based targets use ReadPixel() and WritePixel() to read/write pen values:

```
LONG ReadPixel(struct RastPort \*rp, LONG x, LONG y);
VOID WritePixel(struct RastPort \*rp, LONG x, LONG y);

```

On high color and true color targets ReadRGBPixel() and WriteRGBPixel() work with direct RGB values:

```
LONG ReadRGBPixel(struct RastPort \*rp, LONG x, LONG y);
VOID WriteRGBPixel(struct RastPort \*rp, LONG x, LONG y, ULONG rgb);

```

## Image copy operations

### Copy bitmap to bitmap

BltBitMap() is used to copy a rectangle from a source bitmap to another bitmap.

```
BltBitMap(struct BitMap \*src, UWORD src\_x, UWORD src\_y, struct BitMap \*dst, UWORD dst\_x, UWORD dst\_y, UWORD width, UWORD height, UBYTE minterm, UBYTE mask, APTR tempbuf);

```

The minterm should be always 0xc0. The mask parameter is used to select which bitmap planes are copied. This may speed up copy operation on OCS/AGA Amigas but most of time this should be set to 0xff. When copies overlap you must provide tempbuf what is large enough to store one scanline from the bitmap.

BltBitMapRastPort() is similar but the destination is rastport.

```
BltBitMapRastPort(struct BitMap \*src, UWORD src\_x, UWORD src\_y, struct BitMap \*dst, UWORD dst\_x, UWORD dst\_y, UWORD width, UWORD height, UBYTE minterm);

```

ClipBlit() is another form where both source and destinations are rastports.

```
ClipBlit(struct BitMap \*src, UWORD src\_x, UWORD src\_y, struct RastPort \*dst, UWORD dst\_x, UWORD dst\_y, UWORD width, UWORD height, UBYTE minterm);

```

When working with true color bitmaps it is possible use alpha blitting routines.

```
BltBitMapAlpha(struct BitMap \*src, UWORD src\_x, UWORD src\_y, struct BitMap \*dst, UWORD dst\_x, UWORD dst\_y, UWORD width, UWORD height, struct TagItem \*taglist);
BltBitMapRastPortAlpha(struct BitMap \*src, UWORD src\_x, UWORD src\_y, struct RastPort \*dst, UWORD dst\_x, UWORD dst\_y, UWORD width, UWORD height, struct TagItem \*taglist);

```

 BLTBMA\_USESOURCEALPHA
 BLTBMA\_GLOBALALPHA
 BLTBMA\_DESTALPHAVALUE

### Copy from bitmap to memory

To read pixel array from the bitmap you use ReadPixelArray():

```
ReadPixelArray(APTR dest, UWORD dest\_x, UWORD dest\_y, UWORD modulo, struct RastPort \*rp, UWORD x, UWORD y, UWORD width, UWORD height, UBYTE format)

```

 dest\_x
 dest\_y
 modulo
 rp
 x
 y
 width
 height
 format

### Copy from memory to bitmap

To write an array of pixels to the bitmap you use WritePixelArray() or WritePixelArrayAlpha():

```
WritePixelArray(APTR src, UWORD src\_x, UWORD src\_y, UWORD modulo, struct RastPort \*rp, UWORD x, UWORD y, UWORD width, UWORD height, UBYTE format)
WritePixelArrayAlpha(APTR dest, UWORD dest\_x, UWORD dest\_y, UWORD modulo, struct RastPort \*rp, UWORD x, UWORD y, UWORD width, UWORD height, ULONG global\_alpha)

```

 src\_x
 src\_y
 modulo
 rp
 x
 y
 width
 height
 global\_alpha

## Image scaling operations

Thee different calls are available for image scaling.

```
BitMapScale(struct BitScaleArgs \*args);
ScalePixelArray(APTR src, UWORD src\_w, UWORD src\_h, UWORD moduloe, struct RastPort \*, UWORD dest\_x, UWORD dest\_y, UWORD dest\_w, UWORD dest\_h, UBYTE pixelformat);
ScalePixelArrayAlpha(APTR src, UWORD src\_w, UWORD src\_h, UWORD moduloe, struct RastPort \*, UWORD dest\_x, UWORD dest\_y, UWORD dest\_w, UWORD dest\_h, ULONG global\_alpha);

```

Due to its complexity BitMapScale() is not covered here.

ScalePixelArrayAlpha() takes an ARGB source buffer what is scaled to a destination rastport.

# Create an offscreen bitmaps and rastports

Sometimes it is necessary to render offscreen. This section describes how to create offscreen rastports on Amiga.

## Create offscreen bitmap

Although bitmaps can be created manually (allocate some memory and call InitBitMap()) we strongly encourage to use AllocBitMap(). This ensures maximum compatibility and performance on different Amiga configurations.

```
struct BitMap \*AllocBitMap(UWORD width, UWORD height, UWORD depth, UWORD flags, struct BitMap \*reference\_bitmap);

```

When parameter reference\_bitmap is not null it will be used as a reference for newly allocated bitmap to determine the best possible pixel format. If reference bitmap is screen bitmap or bitmap with palette information this palette will be inherited to new bitmap.

 BMF\_DISPLAYABLE
 BMF\_MINPLANES
 BMF\_SPECIALFMT

## Create an offscreen rastport without clipping

To create simple offscreen rastport you only allocate some memory for rastport where you install your new pointer. These rastports are unsafe for rendering. Any drawing operation that is rendered outside the bitmap trash random memory.

```
#include <proto/exec.h>
#include <proto/graphics.h>

struct RastPort \*CreateRastPort(int width, int height, struct BitMap \*friend\_bitmap, BOOL displayable)
{
 struct RastPort \*rp = AllocMem(sizeof(\*rp), MEMF\_ANY);

 if (rp)
 {
 int depth = GetBitMapAttr(friend\_bitmap, BMA\_DEPTH);
 struct BitMap \*bm = AllocBitMap(width, height, depth, BMF\_MINPLANES | displayable ? BMF\_DISPLAYABLE : 0);

 if (bm)
 {
 InitRastPort(rp);
 rp->BitMap = bm;
 return rp;
 }

 FreeMem(rp, sizeof(\*rp);
 }

 return NULL;
}

void FreeRastPort(struct RastPort \*rp)
{
 FreeBitMap(rp->BitMap);
 FreeMem(rp, sizeof(\*rp));
}

```

## Create an offscreen rastport with clipping

To create safe rastports where rendering outside bitmap is not allowed some more advanced techniques are needed. Those rastports must be created using layers.library routines which allocate and initialize clipping structures for you.

```
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/layers.h>

struct RastPortData
{
 struct RastPort \*rp;
 struct Layer\_Info \*li;
 struct Layer \*l;
};

struct RastPortData \*CreateRastPort(int width, int height, struct BitMap \*friend\_bitmap, BOOL displayable)
{
 struct RastPortData \*rpd = AllocMem(sizeof(\*rpd), MEMF\_ANY);

 if (rpd)
 {
 int depth = GetBitMapAttr(friend\_bitmap, BMA\_DEPTH);
 struct BitMap \*bm = AllocBitMap(width, height, depth, BMF\_MINPLANES | displayable ? BMF\_DISPLAYABLE : 0);

 if (bm)
 {
 rpd->li = NewLayerInfo();

 if (rpd->li)
 {
 rpd->l = CreateUpfrontLayer(rpd->li, bm, 0, 0 width - 1, height - 1, 0, NULL);

 if (rpd->l)
 {
 rpd->rp = rpd->l->rp;
 return rpd;
 }

 DisposeLayerInfo(rpd->li);
 }

 FreeBitMap(bm);
 }

 FreeMem(rpd, sizeof(\*rpd);
 }

 return NULL;
}

void DeleteRastPort(struct RastPortData \*rpd)
{
 FreeBitMap(rpd->rp->BitMap);
 DeleteLayer (0, rpd->l);
 DisposeLayerInfo(rpd->li);
 FreeMem(rpd, sizeof(\*rpd));
}

```