LineIt & CharIt

By Chris Dewhurst

Originally published in EUG #64

LineIt and CharIt are two graphics compression utilities designed to convert images such as shapes and large fonts into a series of lines or graphics characters which can then be quickly redrawn in any screen mode with shadow, rotation, multiheight, etc, effects.

Theory behind LINEIT

LineIt works by scanning an image horizontally or vertically making a note of the co-ordinate of a non-black pixel and the length of the line between this and the next black pixel. Only one co-ordinate is needed, the y co-ordinate in vertical scanning or x co-ordinate in horizontal scanning. This is because the replotting works on the principle that if the next co-ordinate is smaller than the previous co-ordinate plus line length then the line must be adjacent to the previous line.

Although this method results in very compact data, there are two limitations with it. Firstly, there must not be any horizontal gaps (completely blank lines) in images scaned vertically, or any vertical gaps in vertically scanned images. This is not a problem when scanning large letters horizontally because (Think about it) there are no horizontal gaps in our Latin characters. However, you wouldn't use vertical scanning because there are usually gaps *between* letters, and the result would be joined up characters. Unless, of course, this is exactly the effect you are after!

Secondly, LineIt stores co-ordinates in one byte - graphics co-ordinates divided by the number of graphics units per pixel. This means the image must not exceed 256 by 256 pixels. While the full height of the screen can be scanned because there are four units per pixel in all modes, the lateral extent depends on the resolution. This isn't a problem in Modes 2 and 5, where there are 160 pixels across the screen, but in Modes 1 and 4 there are 320 pixels so only 4/5ths of the width of the screen can be scanned. However, LineIt was designed with small images in mind so this limitation shouldn't be a problem.

Using LINEIT

It is assumed that you have a screen image (from an Art Package for example) which - or parts of which - you want to convert into lines. If you haven't, use the example Mode 4 screen called PHANA. The program needs to know the graphics mode in which the image was created. Enter 0, 1, 2, 4 or 5 in response to the "Source Mode" (4 for the example screen).

Image Filename: Enter the name by which the image was saved on disc - the example screen is called PHANA.

Output Mode: The mode in which you want to see the image replotted. The source and output modes don't have to be of the same memory size so you can scan an image in Mode 1 and plot it in Mode 5 for example.

Scan Colour: Only pixels of the colour number entered are scanned. This will always be 1 for two-colour Modes but you might have a Mode 1 screen image and only wish to scan the yellow areas of it, in which case enter 2 and press RETURN.

Vertical or Horizontal scanning: Enter the most appropriate scanning method. If you aren't sure which orientation you want, try horizontal scanning first then vertical scanning to see which takes up less memory.

Spool DATA statements, *SAVE data, or View: If you want to create DATA lines to *EXEC onto a BASIC program enter 1. Option 2 will save the block of memory containing the data points. Enter 3 if you just want to see how the image looks - you can aways rerun the program with different options.

The screen changes to the chosen source mode and the image loaded in. In the top left is a small square which can be dragged around and enlarged to cover the area you want to scan:

Cursor keys: Move rectangle by one pixel
Shift & Cursors:Move rectangle to next 8-pixel boundary
Ctrl & Cursors:Enlarge/reduce rectangle by one pixel
Shift, Ctrl & Cursors:Enlarge/reduce rectangle to next mutiple of 8 pixels.
RETURN:Begin scanning.

The area of the screen available for scanning is limited to 256 by 256 pixels as discussed earlier and you won't be allowed to exceed this maximum.

When you have the rectangle at the right size and positioned over the desired area, press RETURN to start scanning. Pixels are reversed (EORed) in colour so that you can see the computer's progress. If the complexity of the image means that the available memory for storing points and line lengths is used up, the scanning will stop before the whole of the image is covered.

The total number of bytes used to store the points is displayed at the top of the screen. Press any key to see the image being replotted in the chosen output mode. If there wasn't enough memory to store all the points, the result will be a cropped image. The image will be drawn at the bottom left of the screen; you can change this when using the data with your own programs, which we'll discuss below.

Press any key and the data will be SPOOLed or SAVEd depending on your option earlier. If you chose just to "View" the image the program will end. Type RUN to restart to try the other scanning orientations etc.

Using LINEIT data in BASIC

If you opted to save a block of data then simply use the procedures PROChreplot(H%,Y%) in lines 1270-1350 of LineIt to plot horizontally scanned images, or PROCvreplot(X%,V%) in lines 1370-1450 as appropriate. Set the 'pts%' variable to &1100 or the address to which the data file was loaded, and E% to the value you at the top of the screen, the "Total Points". (H%,Y%) or (X%,V%) are the coordinates of the bottom left of the image in graphics units.

Program PHANB is an example of how to use the DATA statements as output by LineIt. Lines 270-370 contain the data points. PROCimg(X%,V%,C%) plots the image vertically in colour C% at (X%,V%). Lines 70-90 call PROCimg() three times, once to plot the PHANTASIALAND image in white at (0,0), then in red at (0,8) then in green at (0,4) giving a solid, three-dimensional look to the letters.

Let's look at PROCimg() in more detail:

   130 DEF PROCimg(X%,V%,C%)
   140 Y%=0:L%=0
   150 GCOL0,C%
   160 RESTORE
   170 READ E%
   180 FOR P%=0 TO E% STEP 2
   190 O%=Y%+L%
   200 READ Y%,L%
   210 X%=X%-(Y%<O%)*8
   220 MOVE X%,Y%*8+V%
   230 PLOT 1,0,L%*8
   240 NEXT
   250 ENDPROC

Line 150 sets the Graphics COLour, line 160 RESTOREs to the beginning of the DATA lines - necessary because the procedure is called more than once. E% contains the total number of data points. O% in line 190 is set the old coordinate plus line length; initially this must be zero - line 140 sets Y% and L% to 0 - so that the statement in line 210 evaluates to FALSE (0). The new coordinate will always be bigger than 0 so X%=X%-(Y% X%=X%-0*8 -> X%. On the other hand when the Y co-ordinate is smaller than the previous coordinate plus line length, the evaluation is TRUE (-1) so X%=X%-(Y% X%=X%-(-1)*8 -> X%=X%+8 and the next line will be plotted to the right.

If you are replotting in other modes, you must use the corresponding graphics units per pixel in the horizontal direction, that is to say, change the 8 in line 210 to 4 for Mode 1 or 4, and to 2 for Mode 0.

Line 220-230 plots the line double height. For a single height image change these lines to:

   220 MOVE X%,Y%*4+V%
   230 PLOT 1,0,L%*8
For horizontal images a similar but slightly different procedure is used. (H%,Y%) are the coordinates of the bottom left of the image, and C% is the colour as before. In this case the 8 in MOVE X%*8+H%,Y% must be substitued for 4 for plotting in Mode 1 and 4, or 2 for plotting in Mode 0:
   DEF PROCimg(H%,Y%,C%)
   X%=0:L%=0
   RESTORE
   READ E%
   FOR P%=0 TO E% STEP 2
   O%=X%+L%
   READ X%,L%
   Y%=Y%+(X%<O%)*4
   MOVE X%*8+H%,Y%
   PLOT 1,L%*8,0
   NEXT
   ENDPROC

CHARIT

This program works in a similar way to LineIt except that the image is converted into a series of ASCII character definitions. Again, this offers the advantage of being able to plot the image in any mode in any colour (or multiple colours), but works best for small images with lots of detail.

Enter the source mode, image filename, and scan colour as before. The "Start Char No" is the first CHR$ code, for example 128. The scannable area will be affected by how many characters are available for definition. Remeber this as it will be of significance later.

To SPOOL the VDU statements enter 1 in response to the next question, or type 2 to *SAVE characters as a block of memory, or type 3 just to view the image.

As before, the screen image will be loaded into the relevant mode and you use the cursor keys to select the area to be scanned. This doesn't have to be an exact number of character widths and lengths - if you set an area of, say, 60 by 32 pixels - 7.5 by 4 characters - the result will be 8 by 4 characters with the right hand halves of the characters on the right blanked out.

The extent to which you are allowed to enlarge the rectangle is affected by the start character number selected on the menu. 128 gives a total of 128 characters (from CHR$128 through to CHR$255) or 8192 square pixels, the maximum available. If you only need 32 characters, an initial CHR$ of 224 will be sufficient.

The total number of characters used is displayed - the number of characters across times number of characters down. Make a note of this for future reference. Press any key to watch the image being redrawn in the output mode.

Using CHARIT data in BASIC

If you are using 32 characters - one block - they can be *LOADed into page &C (on the BBC Model B) for a ready-made set of user-defined characters. If you need more than 32 characters you will have to 'explode' the character set by using line 190 of CharIt:

   ?&367=15:!&36B=&0C0B0A09

Briefly, this tells the computer that the data for characters 128-159, 160-191, 192-223, and 224-255 is held in RAM. The contents of &36B, &36C, &36D, and &36E are set to 9, &A, &B, and &C respectively - the pages at which the font definitions are stored. (Locations &36B-E are set to &C by default, which is why VDU128, 160, 192, or 224 prints the same shape.)

You will need to set up a loop to print the right characters at the right positions, for example:

   xsize%=8
   ysize%=4
   FOR Y%=0 TO ysize%-1
   FOR X%=0 TO xsize%-1
   VDU 31,10+X%,10+Y%,128+Y%*ysize%+X%
   NEXT
   NEXT

will plot a shape made up of 8x4 characters (=32 characters, one block which can fit into page &C) at text coordinates (10,10). Needless to say the printing of characters can also be done at the graphics cursor for 3D effects.

You can forsake clarity for compactness and rewrite the above as:

   FOR X%=0 TO 31:VDU 31,10+(X% AND 7),10+X% DIV 8,X%+128:NEXT

Program XALB is a demonstration running in Mode 4. PROCcharacters defines the characters used to make up "The Crystal Maze". Lines 40-50 set up the font flags in page three, although only three blocks (characters 128-211) are needed in this case. Lines 70-130 are a modifed version of the above.

As you will experience, LineIt can be used for large images but CharIt is useful for relatively small images. One way to improve CharIt is to remove the blank characters, which aren't required because CHR$32 (the space) can be used instead. This would save on the number of characters needed to store the image. Also, some characters in the image might duplicates of others, in which case the character in question needs only to be defined once and repeated as necessary when printing.

Christopher Dewhurst, EUG #64