122 lines
7.3 KiB
Markdown
122 lines
7.3 KiB
Markdown
It would be handy to have a function that, given a base image and mask,
|
|
generates the four image and mask alignments and fills in the
|
|
**MaskedImage** structure. Listing 49.3, together with the include file
|
|
in Listing 49.4 and the system memory-to-display memory block-copy
|
|
routine in Listing 48.4 (in the previous chapter) does just that. It
|
|
would be faster if Listing 49.3 were in assembly language, but there's
|
|
no reason to think that generating aligned images needs to be
|
|
particularly fast; in such cases, I prefer to use C, for reasons of
|
|
coding speed, fewer bugs, and maintainability.
|
|
|
|
**LISTING 49.3 L49-3.C**
|
|
|
|
/* Generates all four possible mode X image/mask alignments, stores image
|
|
alignments in display memory, allocates memory for and generates mask
|
|
alignments, and fills out an AlignedMaskedImage structure. Image and mask must
|
|
both be in byte-per-pixel form, and must both be of width ImageWidth. Mask
|
|
maps isomorphically (one to one) onto image, with each 0-byte in mask masking
|
|
off corresponding image pixel (causing it not to be drawn), and each non-0-byte
|
|
allowing corresponding image pixel to be drawn. Returns 0 if failure, or # of
|
|
display memory addresses (4-pixel sets) used if success. For simplicity,
|
|
allocated memory is not deallocated in case of failure. Compiled with
|
|
Borland C++ in C compilation mode. */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "maskim.h"
|
|
|
|
extern void CopySystemToScreenX(int, int, int, int, int, int, char *,
|
|
unsigned int, int, int);
|
|
unsigned int CreateAlignedMaskedImage(MaskedImage * ImageToSet,
|
|
unsigned int DispMemStart, char * Image, int ImageWidth,
|
|
int ImageHeight, char * Mask)
|
|
{
|
|
int Align, ScanLine, BitNum, Size, TempImageWidth;
|
|
unsigned char MaskTemp;
|
|
unsigned int DispMemOffset = DispMemStart;
|
|
AlignedMaskedImage *WorkingAMImage;
|
|
char *NewMaskPtr, *OldMaskPtr;
|
|
/* Generate each of the four alignments in turn. */
|
|
for (Align = 0; Align < 4; Align++) {
|
|
/* Allocate space for the AlignedMaskedImage struct for this alignment. */
|
|
if ((WorkingAMImage = ImageToSet->Alignments[Align] =
|
|
malloc(sizeof(AlignedMaskedImage))) == NULL)
|
|
return 0;
|
|
WorkingAMImage->ImageWidth =
|
|
(ImageWidth + Align + 3) / 4; /* width in 4-pixel sets */
|
|
WorkingAMImage->ImagePtr = DispMemOffset; /* image dest */
|
|
/* Download this alignment of the image. */
|
|
CopySystemToScreenX(0, 0, ImageWidth, ImageHeight, Align, 0,
|
|
Image, DispMemOffset, ImageWidth, WorkingAMImage->ImageWidth * 4);
|
|
/* Calculate the number of bytes needed to store the mask in
|
|
nibble (Map Mask-ready) form, then allocate that space. */
|
|
Size = WorkingAMImage->ImageWidth * ImageHeight;
|
|
if ((WorkingAMImage->MaskPtr = malloc(Size)) == NULL)
|
|
return 0;
|
|
/* Generate this nibble oriented (Map Mask-ready) alignment of
|
|
the mask, one scan line at a time. */
|
|
OldMaskPtr = Mask;
|
|
NewMaskPtr = WorkingAMImage->MaskPtr;
|
|
for (ScanLine = 0; ScanLine < ImageHeight; ScanLine++) {
|
|
BitNum = Align;
|
|
MaskTemp = 0;
|
|
TempImageWidth = ImageWidth;
|
|
do {
|
|
/* Set the mask bit for next pixel according to its alignment. */
|
|
MaskTemp |= (*OldMaskPtr++ != 0) << BitNum;
|
|
if (++BitNum > 3) {
|
|
*NewMaskPtr++ = MaskTemp;
|
|
MaskTemp = BitNum = 0;
|
|
}
|
|
} while (--TempImageWidth);
|
|
/* Set any partial final mask on this scan line. */
|
|
if (BitNum != 0) *NewMaskPtr++ = MaskTemp;
|
|
}
|
|
DispMemOffset += Size; /* mark off the space we just used */
|
|
}
|
|
return DispMemOffset - DispMemStart;
|
|
}
|
|
|
|
**LISTING 49.4 MASKIM.H**
|
|
|
|
/* MASKIM.H: structures used for storing and manipulating masked
|
|
images */
|
|
|
|
/* Describes one alignment of a mask-image pair. */
|
|
typedef struct {
|
|
int ImageWidth; /* image width in addresses in display memory (also
|
|
mask width in bytes) */
|
|
unsigned int ImagePtr; /* offset of image bitmap in display mem */
|
|
char *MaskPtr; /* pointer to mask bitmap */
|
|
} AlignedMaskedImage;
|
|
|
|
/* Describes all four alignments of a mask-image pair. */
|
|
typedef struct {
|
|
AlignedMaskedImage *Alignments[4]; /* ptrs to AlignedMaskedImage
|
|
structs for four possible destination
|
|
image alignments */
|
|
} MaskedImage;
|
|
|
|
#### Notes on Masked Copying {#Heading5}
|
|
|
|
Listings 49.1 and 49.2, like all Mode X code I've presented, perform no
|
|
clipping, because clipping code would complicate the listings too much.
|
|
While clipping can be implemented directly in the low-level Mode X
|
|
routines (at the beginning of Listing 49.1, for instance), another,
|
|
potentially simpler approach would be to perform clipping at a higher
|
|
level, modifying the coordinates and dimensions passed to low-level
|
|
routines such as Listings 49.1 and 49.2 as necessary to accomplish the
|
|
desired clipping. It is for precisely this reason that the low-level
|
|
Mode X routines support programmable start coordinates in the source
|
|
images, rather than assuming (0,0); likewise for the distinction between
|
|
the width of the image and the width of the area of the image to draw.
|
|
|
|
Also, it would be more efficient to make up structures that describe the
|
|
source and destination bitmaps, with dimensions and coordinates built
|
|
in, and simply pass pointers to these structures to the low level,
|
|
rather than passing many separate parameters, as is now the case. I've
|
|
used separate parameters for simplicity and flexibility.
|
|
|
|
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
 *Be aware that as nifty as Mode X hardware-assisted masked copying is, whether or not it's actually faster than software-only masked or transparent copying depends upon the processor and the video adapter. The advantage of Mode X masked copying is the 32-bit parallelism; the disadvantages are the need to read display memory and the need to perform an **OUT** for every four pixels. (**OUT** is a slow 486/Pentium instruction, and most VGAs respond to **OUT**s much more slowly than to display memory writes.)*
|
|
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|