rsbx@cbmvax.commodore.com (Raymond S. Brand) (04/17/91)
Due to the number of requests, I'm posting this instead of emailing.
The request was for a way to rotate a bitmap 90 degrees without having to do
a readpixel/writepixel for each pixel in the area to rotate. What follows is
a shar file with the source (Amiga but you can understand it anyway :-) to 2
rotate functions and 2 test programs.
rsbx
------------------------------------------------------------------------
Raymond S. Brand rsbx@cbmvax.commodore.com
Commodore-Amiga Engineering ...!uunet!cbmvax!rsbx
1200 Wilson Drive (215)-431-9100
West Chester PA 19380 "Looking"
------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# readme
# rastport.c
# rotate1.c
# rotatebitmap.c
# rotatebitmap.h
# test.c
# test.lnk
# test1.c
# test1.lnk
# This archive created: Wed Apr 17 11:57:26 1991
# By: Raymond S. Brand (Commodore-Amiga Inc, West Chester, PA)
export PATH; PATH=/bin:$PATH
if test -f 'readme'
then
echo shar: will not over-write existing file "'readme'"
else
sed 's/^X//' << \HI_MOM > 'readme'
XWARNING: I use a Hedley display (big). You may need to change some sizes in
X the test/demonstration programs if you don't.
X
XThe algorithm for the rotate square is from the Smalltalk-80 book referenced
Xbelow; the rotate rectangle algorithm is a modification of the square
Xalgorithm.
X
XThe code is not recursive and makes O(log2(M)) calls to the blitter
Xfunctions where M is MAX(X_size, Y_size) of the area to rotate.
X
XIf you do something interesting with this, please let me know what you did.
X
X rsbx
X
XReferences:
X Goldberg and Robson, Smalltalk-80: The Language and Implementation,
X Addison Wesley 1983, pp 408-411.
X
X------------------------------------------------------------------------
X Raymond S. Brand rsbx@cbmvax.commodore.com
X Commodore-Amiga Engineering ...!uunet!cbmvax!rsbx
X 1200 Wilson Drive (215)-431-9100
X West Chester PA 19380 "Looking"
X------------------------------------------------------------------------
HI_MOM
fi # end of overwriting check
if test -f 'rastport.c'
then
echo shar: will not over-write existing file "'rastport.c'"
else
sed 's/^X//' << \HI_MOM > 'rastport.c'
X/*
X** $Id$
X**
X** Create and free RastPorts.
X**
X** (C) Copyright 1991 Raymond S. Brand
X** All Rights Reserved
X*/
X
X
X#include <exec/types.h>
X#include <graphics/rastport.h>
X#include <proto/graphics.h>
X#include <proto/exec.h>
X
Xstruct RastPort *NewRastPort(int x, int y, int depth)
X {
X struct RastPort *rp;
X struct BitMap *bm;
X int i;
X
X if (!(rp = AllocMem(sizeof(struct RastPort), 0)))
X {
X goto Exit1;
X }
X
X if (!(bm = AllocMem(sizeof(struct BitMap), 0)))
X {
X goto Exit2;
X }
X
X for (i = 0; i < depth; i++)
X {
X bm->Planes[i] = NULL;
X }
X
X for (i = 0; i < depth; i++)
X {
X if (!(bm->Planes[i] = AllocRaster(x, y)))
X {
X goto Exit3;
X }
X }
X
X InitBitMap(bm, depth, x, y);
X InitRastPort(rp);
X rp->BitMap = bm;
X
X return rp;
X
X
X
XExit3:
X for (i = 0; i < depth; i++)
X {
X if (bm->Planes[i])
X {
X FreeRaster(bm->Planes[i], x, y);
X }
X }
X FreeMem(bm, sizeof(struct BitMap));
XExit2:
X FreeMem(rp, sizeof(struct RastPort));
XExit1:
X return 0;
X }
X
X
Xvoid FreeRastPort(struct RastPort *rp, int x, int y, int depth)
X {
X int i;
X
X if (!rp)
X {
X return;
X }
X
X if (rp->BitMap)
X {
X for (i = 0; i < depth; i++)
X {
X if (rp->BitMap->Planes[i])
X {
X FreeRaster(rp->BitMap->Planes[i], x, y);
X }
X }
X FreeMem(rp->BitMap, sizeof(struct BitMap));
X }
X
X FreeMem(rp, sizeof(struct RastPort));
X }
HI_MOM
fi # end of overwriting check
if test -f 'rotate1.c'
then
echo shar: will not over-write existing file "'rotate1.c'"
else
sed 's/^X//' << \HI_MOM > 'rotate1.c'
X/*
X** $Id$
X**
X** Rotate a retacngular area 90 deg. to another retangular area.
X**
X** (C) Copyright 1991 Raymond S. Brand
X** All Rights Reserved
X*/
X
X
X#include <exec/types.h>
X#include <graphics/rastport.h>
X#include <proto/graphics.h>
X#include "rotatebitmap.h"
X#include <math.h>
X
X
Xextern struct RastPort *NewRastPort(int x, int y, int depth);
Xextern void FreeRastPort(struct RastPort *rp, int x, int y, int depth);
X
X
Xint Rotate(struct RastPort *src, int OsrcX, int Osrcy, struct RastPort *dst, int OdstX, int OdstY, int sizeX, int sizeY,
X struct RastPort *mask, struct RastPort *temp)
X {
X int s;
X int q;
X int a;
X int b;
X int z;
X int n;
X/*
X * struct RastPort *mask;
X * struct RastPort *temp;
X * int depth;
X */
X
X s = min(sizeX, sizeY);
X
X q = 1;
X
X while (q < s)
X {
X q <<= 1;
X }
X
X s = q >> 1;
X q = s >> 1;
X/*
X * depth = dst->BitMap->Depth;
X *
X * if (!(temp = NewRastPort(sizeX, sizeY, depth)))
X * {
X * return ERROR_NEWRASTPORT_FAILED;
X * }
X *
X * if (!(mask = NewRastPort(sizeX, sizeY, depth)))
X * {
X * FreeRastPort(temp, sizeX, sizeY, depth);
X * return ERROR_NEWRASTPORT_FAILED;
X * }
X */
X ClipBlit(mask, 0, 0, mask, 0, 0, sizeX, sizeY, OP_D_EQ_ZERO );
X
X a = b = 0;
X
X if (sizeX > sizeY)
X {
X a = sizeX - (sizeX%s);
X }
X else
X {
X b = sizeY - (sizeY%s);
X }
X
X while (q)
X {
X if ((b+s) <= sizeY)
X {
X for (z=0; z<a; z+=s)
X {
X
X ClipBlit( src, b, sizeX-z-s, dst, z, b, s, s, OP_D_EQ_S );
X
X ClipBlit(mask, z, b, mask, z, b, q, q, OP_D_EQ_ONE );
X }
X b += s;
X }
X
X if ((a+s) <= sizeX)
X {
X for (z=0; z<b; z+=s)
X {
X
X ClipBlit( src, z, sizeX-a-s, dst, a, z, s, s, OP_D_EQ_S );
X
X ClipBlit(mask, a, z, mask, a, z, q, q, OP_D_EQ_ONE );
X }
X a += s;
X }
X
X /*
X * exchange right & left halves
X */
X ClipBlit(mask, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S );
X ClipBlit(mask, 0, 0, temp, 0, q, a, b-q, OP_D_EQ_S_OR_D );
X ClipBlit( dst, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S_AND_D );
X ClipBlit(temp, 0, 0, dst, 0, 0, a, b, OP_D_EQ_S_XOR_D );
X ClipBlit( dst, q, 0, temp, 0, 0, a-q, b, OP_D_EQ_S_XOR_D );
X ClipBlit( dst, q, 0, dst, 0, 0, a-q, b, OP_D_EQ_S_OR_D );
X ClipBlit(temp, 0, 0, dst, q, 0, a-q, b, OP_D_EQ_S_XOR_D );
X
X /*
X * exchange diagonals
X */
X ClipBlit( dst, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S );
X ClipBlit( dst, q, q, temp, 0, 0, a-q, b-q, OP_D_EQ_S_XOR_D );
X ClipBlit(mask, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S_AND_D );
X ClipBlit(temp, 0, 0, dst, 0, 0, a, b, OP_D_EQ_S_XOR_D );
X ClipBlit(temp, 0, 0, dst, q, q, a-q, b-q, OP_D_EQ_S_XOR_D );
X
X
X n = q>>1;
X ClipBlit(mask, n, n, mask, 0, 0, a-n, b-n, OP_D_EQ_S_AND_D );
X ClipBlit(mask, 0, 0, mask, 0, q, a, b-q, OP_D_EQ_S_OR_D );
X ClipBlit(mask, 0, 0, mask, q, 0, a-q, b, OP_D_EQ_S_OR_D );
X
X s = q;
X q >>= 1;
X }
X
X/*
X * LINEROTATE
X */
X if (b < sizeY)
X {
X for (z=0; z<a; z++)
X {
X SetAPen(dst, ReadPixel(src, b, sizeX-z-1));
X WritePixel(dst, z, b);
X }
X b++;
X }
X
X if (a < sizeX)
X {
X for (z=0; z<b; z++)
X {
X SetAPen(dst, ReadPixel(src, z, sizeX-a-1));
X WritePixel(dst, a, z);
X }
X }
X
X/*
X * FreeRastPort(temp, sizeX, sizeY, depth);
X * FreeRastPort(mask, sizeX, sizeY, depth);
X */
X return 0;
X }
HI_MOM
fi # end of overwriting check
if test -f 'rotatebitmap.c'
then
echo shar: will not over-write existing file "'rotatebitmap.c'"
else
sed 's/^X//' << \HI_MOM > 'rotatebitmap.c'
X/*
X** $Id$
X**
X** Rotate a square, size 2^n rastport 90 deg.
X**
X** (C) Copyright 1991 Raymond S. Brand
X** All Rights Reserved
X*/
X
X
X#include <exec/types.h>
X#include <graphics/rastport.h>
X#include <proto/graphics.h>
X#include "rotatebitmap.h"
X
X
Xextern struct RastPort *NewRastPort(int x, int y, int depth);
Xextern void FreeRastPort(struct RastPort *rp, int x, int y, int depth);
X
X
Xint Rotate(struct RastPort *self, int s)
X {
X int q; /* control variable */
X int n; /* temp */
X int depth;
X struct RastPort *temp;
X struct RastPort *mask;
X
X /*
X * need to do RastPort size error checking here
X */
X
X if (s < 2)
X {
X return 0;
X }
X
X q = 1;
X
X while(q < s)
X {
X q <<= 1;
X }
X
X if (q != s)
X {
X return ERROR_SIZE_NOT_POWER_OF_TWO;
X }
X
X depth = self->BitMap->Depth;
X
X if (!(temp = NewRastPort(s, s, depth)))
X {
X return ERROR_NEWRASTPORT_FAILED;
X }
X
X if (!(mask = NewRastPort(s, s, depth)))
X {
X FreeRastPort(temp, s, s, depth);
X return ERROR_NEWRASTPORT_FAILED;
X }
X
X ClipBlit(mask, 0, 0, mask, 0, 0, s, s, OP_D_EQ_ZERO );
X ClipBlit(mask, 0, 0, mask, 0, 0, s/2, s/2, OP_D_EQ_ONE );
X
X while( q >>= 1 )
X {
X /*
X * exchange right & left halves
X */
X ClipBlit(mask, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S );
X ClipBlit(mask, 0, 0, temp, 0, q, s, s-q, OP_D_EQ_S_OR_D );
X ClipBlit(self, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S_AND_D );
X ClipBlit(temp, 0, 0, self, 0, 0, s, s, OP_D_EQ_S_XOR_D );
X ClipBlit(self, q, 0, temp, 0, 0, s-q, s, OP_D_EQ_S_XOR_D );
X ClipBlit(self, q, 0, self, 0, 0, s-q, s, OP_D_EQ_S_OR_D );
X ClipBlit(temp, 0, 0, self, q, 0, s-q, s, OP_D_EQ_S_XOR_D );
X /*
X * exchange diagonals
X */
X ClipBlit(self, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S );
X ClipBlit(self, q, q, temp, 0, 0, s-q, s-q, OP_D_EQ_S_XOR_D );
X ClipBlit(mask, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S_AND_D );
X ClipBlit(temp, 0, 0, self, 0, 0, s, s, OP_D_EQ_S_XOR_D );
X ClipBlit(temp, 0, 0, self, q, q, s-q, s-q, OP_D_EQ_S_XOR_D );
X /*
X * refine mask
X */
X n = q>>1;
X ClipBlit(mask, n, n, mask, 0, 0, s-n, s-n, OP_D_EQ_S_AND_D );
X ClipBlit(mask, 0, 0, mask, 0, q, s, s-q, OP_D_EQ_S_OR_D );
X ClipBlit(mask, 0, 0, mask, q, 0, s-q, s, OP_D_EQ_S_OR_D );
X }
X
X FreeRastPort(temp, s, s, depth);
X FreeRastPort(mask, s, s, depth);
X return 0;
X }
HI_MOM
fi # end of overwriting check
if test -f 'rotatebitmap.h'
then
echo shar: will not over-write existing file "'rotatebitmap.h'"
else
sed 's/^X//' << \HI_MOM > 'rotatebitmap.h'
X/*
X** $Id$
X**
X** Constants for RoateBitMap.c
X**
X** (C) Copyright 1991 Raymond S. Brand
X** All Rights Reserved
X*/
X
X
X#define OK 0
X#define ERROR_SIZE_NOT_POWER_OF_TWO 1
X#define ERROR_NEWRASTPORT_FAILED 2
X#define OP_D_EQ_ZERO 0x00
X#define OP_D_EQ_ONE 0xf0
X#define OP_D_EQ_S 0xc0
X#define OP_D_EQ_S_OR_D 0xe0
X#define OP_D_EQ_S_AND_D 0x80
X#define OP_D_EQ_S_XOR_D 0x60
HI_MOM
fi # end of overwriting check
if test -f 'test.c'
then
echo shar: will not over-write existing file "'test.c'"
else
sed 's/^X//' << \HI_MOM > 'test.c'
X/*
X** $Id$
X**
X** Test/demonstration program for RotateBiitMap.
X**
X** (C) Copyright 1991 Raymond S. Brand
X** All Rights Reserved
X*/
X
X
X#include <exec/types.h>
X#include <graphics/gfxbase.h>
X#include <proto/exec.h>
X#include <proto/graphics.h>
X
X#include <intuition/intuition.h>
X#include <proto/intuition.h>
X
X
X#define SIZE 512
X
X
Xint Rotate(struct RastPort *self, int s);
X
X
Xextern struct Library *SysBase;
Xstruct IntuitionBase *IntuitionBase = NULL;
Xstruct Window *win = NULL;
Xstruct GfxBase *GfxBase = NULL;
X
X
Xstruct NewWindow nw =
X {
X 0, 0, /* LeftEdge, TopEdge */
X SIZE, SIZE, /* Width, Height */
X -1, -1, /* DetailPen, BlockPen */
X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */
X WINDOWDRAG, /* Flags */
X NULL, /* FirstGadget */
X NULL, /* CheckMark */
X "Rotate BitMap Test Window", /* Title */
X NULL, NULL, /* Screen, BitMap */
X SIZE, SIZE, /* MinWidth, MinHeight */
X SIZE, SIZE, /* MaxWidth, MaxHeight */
X WBENCHSCREEN /* Type */
X };
X
X
X
Xvoid main(int argc, char **argv)
X {
X if (!( IntuitionBase = (struct IntuitionBase *)
X OpenLibrary("intuition.library", 0) ))
X {
X printf("Couldn't open Intuition.\n");
X goto Error;
X }
X
X if (!( GfxBase = (struct GfxBase *)
X OpenLibrary("graphics.library", 0) ))
X {
X printf("Couldn't open Graphics.\n");
X goto Error;
X }
X
X if (!( win = OpenWindow(&nw)))
X {
X printf("Couldn't open window.\n");
X goto Error;
X }
X
X Delay(200);
X
X Rotate(win->RPort, SIZE);
X
X Rotate(win->RPort, SIZE);
X
X Rotate(win->RPort, SIZE);
X
X Rotate(win->RPort, SIZE);
X
X Delay(200);
X
X
XError:
X if (win)
X CloseWindow(win);
X
X if (GfxBase)
X CloseLibrary(GfxBase);
X
X if (IntuitionBase)
X CloseLibrary(IntuitionBase);
X
X exit(0);
X}
HI_MOM
fi # end of overwriting check
if test -f 'test.lnk'
then
echo shar: will not over-write existing file "'test.lnk'"
else
sed 's/^X//' << \HI_MOM > 'test.lnk'
XFROM LIB:c.o+"test.o"+"rotatebitmap.o"+"rastport.o"
XTO "test"
XLIB LIB:lc.lib LIB:amiga.lib
X
HI_MOM
fi # end of overwriting check
if test -f 'test1.c'
then
echo shar: will not over-write existing file "'test1.c'"
else
sed 's/^X//' << \HI_MOM > 'test1.c'
X/*
X** $Id$
X**
X** Test/demonstration program for Rotate1.c
X**
X** (C) Copyright 1991 Raymond S. Brand
X** All Rights Reserved
X*/
X
X
X#include <exec/types.h>
X#include <graphics/gfxbase.h>
X#include <proto/exec.h>
X#include <proto/graphics.h>
X
X#include <intuition/intuition.h>
X#include <proto/intuition.h>
X
X
X#define XSIZE 255
X#define YSIZE 127
X#define SPACING 300
X
X
Xint Rotate(struct RastPort *src, int OsrcX, int Osrcy, struct RastPort *dst, int OdstX, int OdstY, int sizeX, int sizeY,
X struct RastPort *mask, struct RastPort *temp);
X
X
Xextern struct Library *SysBase;
Xstruct IntuitionBase *IntuitionBase = NULL;
Xstruct Window *win1 = NULL;
Xstruct Window *win2 = NULL;
Xstruct Window *win3 = NULL;
Xstruct Window *win4 = NULL;
Xstruct GfxBase *GfxBase = NULL;
X
X
Xstruct NewWindow nw1 =
X {
X 0, 0, /* LeftEdge, TopEdge */
X YSIZE, XSIZE, /* Width, Height */
X -1, -1, /* DetailPen, BlockPen */
X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */
X WINDOWDRAG, /* Flags */
X NULL, /* FirstGadget */
X NULL, /* CheckMark */
X "Rotate BitMap src Window", /* Title */
X NULL, NULL, /* Screen, BitMap */
X YSIZE, XSIZE, /* MinWidth, MinHeight */
X YSIZE, XSIZE, /* MaxWidth, MaxHeight */
X WBENCHSCREEN /* Type */
X };
X
Xstruct NewWindow nw2 =
X {
X SPACING, 0, /* LeftEdge, TopEdge */
X XSIZE, YSIZE, /* Width, Height */
X -1, -1, /* DetailPen, BlockPen */
X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */
X WINDOWDRAG, /* Flags */
X NULL, /* FirstGadget */
X NULL, /* CheckMark */
X "Rotate BitMap dst Window", /* Title */
X NULL, NULL, /* Screen, BitMap */
X XSIZE, YSIZE, /* MinWidth, MinHeight */
X XSIZE, YSIZE, /* MaxWidth, MaxHeight */
X WBENCHSCREEN /* Type */
X };
X
Xstruct NewWindow nw3 =
X {
X 0, SPACING, /* LeftEdge, TopEdge */
X XSIZE, YSIZE, /* Width, Height */
X -1, -1, /* DetailPen, BlockPen */
X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */
X WINDOWDRAG, /* Flags */
X NULL, /* FirstGadget */
X NULL, /* CheckMark */
X "Rotate BitMap mask Window", /* Title */
X NULL, NULL, /* Screen, BitMap */
X XSIZE, YSIZE, /* MinWidth, MinHeight */
X XSIZE, YSIZE, /* MaxWidth, MaxHeight */
X WBENCHSCREEN /* Type */
X };
X
Xstruct NewWindow nw4 =
X {
X SPACING, SPACING, /* LeftEdge, TopEdge */
X XSIZE, YSIZE, /* Width, Height */
X -1, -1, /* DetailPen, BlockPen */
X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */
X WINDOWDRAG, /* Flags */
X NULL, /* FirstGadget */
X NULL, /* CheckMark */
X "Rotate BitMap temp Window", /* Title */
X NULL, NULL, /* Screen, BitMap */
X XSIZE, YSIZE, /* MinWidth, MinHeight */
X XSIZE, YSIZE, /* MaxWidth, MaxHeight */
X WBENCHSCREEN /* Type */
X };
X
X
X
Xvoid main(int argc, char **argv)
X {
X if (!( IntuitionBase = (struct IntuitionBase *)
X OpenLibrary("intuition.library", 0) ))
X {
X printf("Couldn't open Intuition.\n");
X goto Error;
X }
X
X if (!( GfxBase = (struct GfxBase *)
X OpenLibrary("graphics.library", 0) ))
X {
X printf("Couldn't open Graphics.\n");
X goto Error;
X }
X
X if (!( win1 = OpenWindow(&nw1)))
X {
X printf("Couldn't open window.\n");
X goto Error;
X }
X
X if (!( win2 = OpenWindow(&nw2)))
X {
X printf("Couldn't open window.\n");
X goto Error;
X }
X
X if (!( win3 = OpenWindow(&nw3)))
X {
X printf("Couldn't open window.\n");
X goto Error;
X }
X
X if (!( win4 = OpenWindow(&nw4)))
X {
X printf("Couldn't open window.\n");
X goto Error;
X }
X
X Delay(200);
X
X Rotate(win1->RPort, 0, 0, win2->RPort, 0, 0, XSIZE, YSIZE, win3->RPort, win4->RPort);
X
X Delay(200);
X
X
XError:
X if (win1)
X CloseWindow(win1);
X
X if (win2)
X CloseWindow(win2);
X
X if (win3)
X CloseWindow(win3);
X
X if (win4)
X CloseWindow(win4);
X
X if (GfxBase)
X CloseLibrary(GfxBase);
X
X if (IntuitionBase)
X CloseLibrary(IntuitionBase);
X
X exit(0);
X}
HI_MOM
fi # end of overwriting check
if test -f 'test1.lnk'
then
echo shar: will not over-write existing file "'test1.lnk'"
else
sed 's/^X//' << \HI_MOM > 'test1.lnk'
XFROM LIB:c.o+"test1.o"+"rotate1.o"
XTO "test1"
XLIB LIB:lc.lib LIB:amiga.lib
XADDSYM
X
HI_MOM
fi # end of overwriting check
# End of shell archive
exit 0
------------------------------------------------------------------------
Raymond S. Brand rsbx@cbmvax.commodore.com
Commodore-Amiga Engineering ...!uunet!cbmvax!rsbx
1200 Wilson Drive (215)-431-9100
West Chester PA 19380 "Looking"
------------------------------------------------------------------------