# Extracting Cel Source Data from an Existing Image

One of a cel's most powerful features is the ability to use existing source data as its own source data. The most common instance of this is for a set of cels to use a single-source data file. For example, a driving game may allow the player to see other cars driving ahead. Each of those cars can be projected as a separate cel, each with its own CCB. Each CCB, however, points to the same source data file, which contains the single image of a car. Each car on the screen has the same appearance, but because each cel's CCB can specify a different location and projection quadrilateral, they appear in different sizes and spots on the screen. To help further differentiate the cars, each CCB can use a different PLUT, or it may tint the source data differently in the pixel processor so that each car cel appears with a different color as well.

Not all source data sharing is as simple as the previous example, which assumes that each cel uses the same source data dimensions, that is, each cel uses the full car as its source data image. A cel can use just part of an existing source data file, such as the wheel of a car cel. Or a cel might use a section of a bitmap to copy part of existing images on a screen. For example, a program could select a subrectangle of a photographic image on the screen and then magnify the subrectangle by projecting it as an enlarged cel. To extract a subrectangle of cel source data from an existing image, you must set the proper source data pointer in the CCB and set appropriate cel dimensions and offsets in the preamble.

## Setting a CCB for Data Extraction

When you extract cel source data from an existing image, you probably cannot use an existing preamble. If the image is in a bitmap, the preamble does not exist; and if the image is a subrectangle of another cel's source data, the preamble will not correctly define the subrectangle. Therefore, you must specify that this cel's preamble will appear at the end of the CCB. To do so, set the `CCBPRE` flag of the CCB's FLAGS word to 1. You must also specify that this cel is unpacked (you cannot extract a subrectangle from packed data) by setting the PACKED flag of FLAGS to 0.

The CCB must point to the address of the word where the first subrectangle pixel appears. To find that address within a bitmap, you can use the `GetPixelAddress()` call, which accepts bitmap coordinates of a pixel and returns the absolute address of the word where the pixel is stored. You then set the `SPABS` flag of `FLAGS` to 1, which specifies an absolute cel source data pointer, and add the address to the CCB in the `SOURCEPTR` word.

Your next task is to create the appropriate two-word preamble for the source data and store them as the `PRE0` and `PRE1` words of the CCB.

## Creating a Preamble for Extracted Data

The preamble contains the dimensions used to define the subrectangle and the offsets that skip over words and pixels between the end of one row and the beginning of the next row.

To define the width of the subrectangle, figure the number of pixels in a row do the following:

1. Subtract 1.
2. Add the number of pixels that must be skipped for alignment reasons
3. Put the result in `HPCNT` of the second preamble word.

To define the height, figure the number of rows in the subrectangle, do the following:

1. Subtract one
2. Put the result in `VCNT` of the first preamble word.

Figure 1 shows how to extract a subrectangle example. The width is 6 pixels, but one pixel is skipped for a total of 7, so `HPCNT` = 6; the height is 3 pixels, so `VCNT` = 2.

Figure 1: Extracting a subrectangle.

In Figure 1, the source data pointer in the CCB determines the starting word of the source data. You must set the `SKIPX` value in the first preamble word the number of pixels necessary to get to the first pixel of the subrectangle. If the first subrectangle pixel falls on the word boundary, you do not need to skip any pixels, and `SKIPX` = 0. If the first pixel falls after the word boundary, you need to skip one or more pixels by setting `SKIPX` appropriately. In the example in Figure 2, which uses 16-bit pixels that are stored two to a word, the subrectangle starts in the second half of a word. Setting `SKIPX` to 1 tells the cel engine to skip the first pixel within the starting word of each row so the subrectangle starts on the second pixel of the word.

Note: Pixels skipped by SKIPX are part of the HPCNT value.

The cel engine uses the dimension set with `HPCNT` to count pixels as it projects a row of pixels; when it is finished counting the row, it uses the `WOFFSET` value (in the second preamble word) to calculate the address of the beginning word of the next row, and then moves there. The cel engine uses `SKIPX` again to skip any pixels necessary within the row's first word to get to the beginning pixel.

To determine `WOFFSET`, count full words only from the beginning of one row to the beginning of the next, subtract 2, and then enter the value as `WOFFSET`. In the example in Figure 2, the word offset is 7, which is the word count from the beginning of one subrectangle row to the beginning of the next subrectangle row. (It is also the full width in words of the original source data.) After subtracting 2, `WOFFSET` = 5. For cels of 1-, 2-, 4-, and 6-bpp, use `WOFFSET`(8) to store the word offset value; for cels of 8- or 16-bpp, use `WOFFSET`(10). If you're extracting a subrectangle from a 16-bpp uncoded bitmap such as the frame buffer, you need to set `LRFORM` to 1 in the second preamble word so the cel engine can handle the left/right format of the pixels stored there.

Once you've defined a subrectangle with the source data pointer, vertical and horizontal dimensions, and the word and pixel offsets, you must make sure that the rest of the preamble data matches the format of the pixels you're using in the subrectangle. Set `UNCODED`, `REP8`, `BPP`, and other preamble values appropriately.

Note: When extracting a subrectangle from 6-bit source data, do not set `WOFFSET` to point to a word boundary that falls in the middle of a 6-bit pixel. Because the 32 bits of a word are not divided evenly by 6, some 6-bit pixels are split across word boundaries. Word beginnings and 6-bit pixel beginnings coincide every third word (word 0, word 3, word 6, word 9, and so on), so you should safely point to the beginning of a pixel as long as the CCB's pointer to the source data correctly points to a word beginning that does not divide a 6-bit pixel.