1 2 DESIGN OF THE UTAH RLE FORMAT 3 4 Spencer W. Thomas 5 6 University of Utah, Department of Computer Science 7 8 9 10 11 12 13 14 15 ABSTRACT 16 17 The Utah RLE (Run Length Encoded) format is designed to provide an 18 efficient, device independent means of storing multi-level raster 19 images. Images of arbitrary size and depth can be saved. The design 20 of the format is presented, followed by descriptions of the library 21 routines used to create and read RLE format files. 22 231. Introduction 24 The Utah RLE (Run Length Encoded) format is designed to provide an efficient, 25device independent means of storing multi-level raster images. It is not 26designed for binary (bitmap) images. It is built on several basic concepts. 27The central concept is that of a channel. A channel corresponds to a single 28color, thus there are normally a red channel, a green channel, and a blue 29channel. Up to 255 color channels are available for use; one channel is 30reserved for "alpha" data. Although the format supports arbitrarily deep 31channels, the current implementation is restricted to 8 bits per channel. 32 33 Image data is stored in an RLE file in a scanline form, with the data for 34each channel of the scanline grouped together. Runs of identical pixel values 35are compressed into a count and a value. However, sequences of differing 36pixels are also stored efficiently (not as a sequence of single pixel runs). 37 38 The file header contains a large amount of information about the image, 39including its size, the number of channels saved, whether it has an alpha 40channel, an optional color map, and comments. The comments may be used to add 41arbitrary extra information to the saved image. 42 43 A subroutine interface has been written to allow programs to read and write 44files in the RLE format. Two interfaces are available, one that completely 45interprets the RLE file and returns scanline pixel data, and one that returns a 46list of "raw" run and pixel data. The second is more efficient, but more 47difficult to use, the first is easy to use, but slower. 48 49 The Utah RLE format has been used to save images from many sources, and to 50display saved images on many different displays and from many different 51computers. 52 532. Description of RLE Format 54 All data in the RLE file is treated as a byte stream. Where quantities 55larger than 8 bits occur, they are written in PDP-11 byte order (low order byte 56first). 57 58 The RLE file consists of two parts, a header followed by scanline data. The 59header contains general information about the image, while the scanline data is 60a stream of operations describing the image itself. 61 62 63 642.1. The Header 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 Figure 2-1: RLE file header 90 91 The header has a fixed part and a variable part. A diagram of the header is 92shown in Figure 2-1. The magic number identifies the file as an RLE file. 93Following this are the coordinates of the lower left corner of the image and 94the size of the image in the X and Y directions. Images are defined in a first 95quadrant coordinate system (origin at the lower left, X increasing to the 96right, Y increasing up.) Thus, the image is enclosed in the rectangle 97 98 [xpos,xpos+xsize-1]X[ypos,ypos+ysize-1]. 99 100The position and size are 16 bit integer quantities; images up to 32K square 101may be saved (the sizes should not be negative). 102 103 A flags byte follows. There are currently four flags defined: 104 105 ClearFirst If this flag is set, the image rectangle should first be cleared 106 to the background color (q.v.) before reading the scanline data. 107 108 NoBackground If this flag is set, no background color is supplied, and the 109 ClearFirst flag should be ignored. 110 111 Alpha This flag indicates the presence of an "alpha" channel. The 112 alpha channel is used by image compositing software to correctly 113 blend anti-aliased edges. It is stored as channel -1 (255). 114 115 Comments If this flag is set, comments are present in the variable part 116 of the header, immediately following the color map. 117 118 The next byte is treated as an unsigned 8 bit value, and indicates the number 119of color channels that were saved. It may have any value from 0 to 254 120(channel 255 is reserved for alpha values). 121 122 The pixelbits byte gives the number of bits in each pixel. The only value 123currently supported by the software is 8 (in fact, this byte is currently 124ignored when reading RLE files). Pixel sizes taking more than one byte will be 125packed low order byte first. 126 127 The next two bytes describe the size and shape of the color map. Ncmap is 128the number of color channels in the color map. It need not be identical to 129ncolors, but interpretation of values of ncmap different from 0, 1, or ncolors 130may be ambiguous, unless ncolors is 1. If ncmap is zero, no color map is 131saved. Cmaplen is the log base 2 of the length of each channel of the color 132map. Thus, a value for cmaplen of 8 indicates a color map with 256 entries per 133channel. 134 135 Immediately following the fixed header is the variable part of the file 136header. It starts with the background color. The background color has ncolors 137entries; if necessary, it is filled out to an odd number of bytes with a filler 138byte on the end (since the fixed header is an odd number bytes long, this 139returns to a 16 bit boundary). 140 141 Following the background color is the color map, if present. Color map 142values are stored as 16 bit quantities, left justified in the word. Software 143interpreting the color map must apply a shift appropriate to the application or 144to the hardware being used. This convention permits use of the color map 145without knowing the original output precision. The channels of the map are 146stored in increasing numerical order (starting with channel 0), with the 147entries of each channel stored also in increasing order (starting with entry 1480). The color map entries for each channel are stored contiguously. 149 150 Comments, if present, follow the color map. A 16 bit quantity giving the 151length of the comment block comes first. If the length is odd, a filler byte 152will be present at the end, restoring the 16 bit alignment (but this byte is 153not part of the comments). The comment block contains any number of 154null-terminated text strings. These strings will conventionally be of the form 155"name=value", allowing for easy retrieval of specific information. However, 156there is no restriction that a given name appear only once, and a comment may 157contain an arbitrary string. The intent of the comment block is to allow 158information to be attached to the file that is not specifically provided for in 159the RLE format. 160 161 162 1632.2. The Scanline Data 164 The scanline data consists of a sequence of operations, such as Run, 165SetChannel, and Pixels, describing the actual image. An image is stored 166starting at the lower left corner and proceeding upwards in order of increasing 167scanline number. Each operation and its associated data takes up an even 168number of bytes, so that all operations begin on a 16 bit boundary. This makes 169the implementation more efficient on many architectures. 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 Figure 2-2: RLE file operand formats 186 187 Each operation is identified by an 8 bit opcode, and may have one or more 188operands. Single operand operations fit into a single 16 bit word if the 189operand value is less than 256. So that operand values are not limited to the 190range 0..255, each operation has a long variant, in which the byte following 191the opcode is ignored and the following word is taken as a 16 bit quantity. 192The long variant of an opcode is indicated by setting the bit 0x40 in the 193opcode (this allows for 64 opcodes, of which 6 have been used so far.) The two 194single operand formats are shown pictorially in Figure 2-2. 195 196 The individual operations will now be discussed in detail. The descriptions 197are phrased in terms of the actions necessary to interpret the file. Three 198indices are necessary: the current channel, the scanline number, and the pixel 199index. The current channel is the channel to which data operations apply. The 200scanline number is just the Y position of the scanline in the image. The pixel 201index is the X position of the pixel within the scanline. The operations are: 202 203 SkipLines Increment the scanline number by the operand value. This 204 operation terminates the current scanline. The pixel index 205 should be reset to the xpos value from the header. 206 207 SetColor Set the current channel to the operand value. This operation 208 does not have a long variant. Note that an operand value of 255 209 will be interpreted as a -1, indicating the alpha channel. All 210 other operand values are positive. The pixel index is reset to 211 the xpos value. 212 213 SkipPixels Skip over pixels in the current scanline. Increment pixel index 214 by the operand value. Pixels skipped will be left in the 215 background color. 216 217 PixelData Following this opcode is a sequence of pixel values. The length 218 of the sequence is given by the operand value. If the length of 219 the sequence is odd, a filler byte is appended. Pixel values 220 are inserted into the scanline in increasing X order. The pixel 221 index is incremented by the sequence length. 222 223 Run This is the only two operand opcode. The first operand is the 224 length (N) of the run. The second operand is the pixel value, 225 followed by a filler byte if necessary(E.g., a 16 bit pixel 226 value would not need a filler byte.). The next N pixels in the 227 scanline are set to the given pixel value. The pixel index is 228 incremented by N, to point to the pixel following the run. 229 230 EOF This opcode has no operand, and indicates the end of the RLE 231 file. It is provided so that RLE files may be concatenated 232 together and still be correctly interpreted. It is not 233 required, a physical end of file will also indicate the end of 234 the RLE data. 235 236 237 2382.3. Subroutine Interface 239 Two similar subroutine interfaces are provided for reading and writing files 240in the RLE format. Both read or write a scanline worth of data at a time. A 241simple "row" interface communicates in terms of arrays of pixel values. It is 242simple to use, but slower than the "raw" interface, which uses a list of 243"opcode" values as its communication medium. 244 245 In both cases, the interface must be initialized by calling a setup function. 246The two types of calls may be interleaved; for example, in a rendering program, 247the background could be written using the "raw" interface, while scanlines 248containing image data could be converted with the "row" interface. The package 249allows multiple RLE streams to be open simultaneously, as is necessary for use 250in a compositing tool, for example. All data relevant to a particular RLE 251stream is contained in a "globals" structure. 252 253 The globals structure echoes the format of the RLE header. The fields are 254described below: 255 256 dispatch The RLE creation routines are capable of writing various types 257 of output files in addition to RLE. This value is an index into 258 a dispatch table. This value is initialized by sv_setup. 259 260 ncolors The number of color channels in the output file. Up to this 261 many color channels will be saved, depending on the values in 262 the channel bitmap (see below). 263 264 bg_color A pointer to an array of ncolors integers containing the 265 background color. 266 267 alpha If this is non-zero, an alpha channel will be saved. The 268 presence or absence of an alpha channel has no effect on the 269 value in ncolors. 270 271 background Indicates how to treat background pixels. It has the following 272 values: 273 274 0 Save all pixels, the background color is ignored. 275 276 1 Save only non-background pixels, but don't set the "clear 277 screen" bit. This indicates "overlay" mode, a cheap form 278 of compositing (but see note below about this.) 279 280 2 Save only non-background pixels, clear the screen to the 281 background color before restoring the image. 282 283 xmin, xmax, ymin, ymax 284 Inclusive bounds of the image region being saved. 285 286 ncmap Number of channels of color map to be saved. The color map will 287 not be saved if this is 0. 288 289 cmaplen Log base 2 of the number of entries in each channel of the color 290 map. 291 292 cmap Pointer to an array containing the color map. The map is saved 293 in "channel major" order. Each entry in the map is a 16 bit 294 value with the color value left justified in the word. If this 295 pointer is NULL, no color map will be saved. 296 297 comments Pointer to an array of pointers to strings. The array is 298 terminated by a NULL pointer (like argv or envp). If this 299 pointer is NULL or if the first pointer it points to is NULL, 300 comments will not be saved. 301 302 fd File (FILE *) pointer to be used for writing or reading the RLE 303 file. 304 305 bits A bitmap containing 256 bits. A channel will be saved (or 306 retrieved) only if the corresponding bit is set in the bitmap. 307 The alpha channel corresponds to bit 255. The bitmap allows an 308 application to easily ignore color channel data that is 309 irrelevant to it. 310 311 The globals structure also contains private data for use by the RLE reading 312and writing routines; data that must be maintained between calls, but that 313applies to each stream separately. 314 315 316 3172.4. Writing RLE files 318 To create a run-length encoded file, one first initializes a globals 319structure with the relevant information about the image, including the output 320file descriptor. The output file should be open and empty. Then one calls 321sv_setup: 322 323 sv_setup( RUN_DISPATCH, &globals ); 324 325This writes the file header and initializes the private portions of the global 326data structure for use by the RLE file writing routines. 327 328 The image data must be available or expressible in a scanline order (with the 329origin at the bottom of the screen). After each scanline is computed, it is 330written to the output file by calling one of sv_putrow or sv_putraw. If a 331vertical interval of the image has no data, it may be skipped by calling 332sv_skiprow: 333 334 /* Skip nrow scanlines */ 335 sv_skiprow( &globals, nrow ); 336 337 If the image data for a scanline is available as an array of pixel values, 338sv_putrow should be used to write the data to the output file. As an example, 339let us assume that we have a 512 pixel long scanline, with three color channels 340and no alpha data. We could call sv_putrow as follows: 341 342 rle_pixel scandata[3][512], *rows[3]; 343 int i; 344 345 for ( i = 0; i < 3; i++ ) 346 rows[i] = scandata[i]; 347 sv_putrow( rows, 512, &globals ); 348 349Note that sv_putrow is passed an array of pointers to vectors of pixels. This 350makes it easy to pass arbitrarily many, and to specify values of rowlen 351different from the size of (e.g.) the scandata array. 352 353 The first element of each row of pixels is the pixel at the xmin location in 354the scanline. Therefore, when saving only part of an image, one must be 355careful to set the rows pointers to point to the correct pixel in the scanline. 356 357 If an alpha channel is specified to be saved, things get a little more 358complex. Here is the same example, but now with an alpha channel being saved. 359 360 rle_pixel scandata[3][512], 361 alpha[512], *rows[4]; 362 int i; 363 364 rows[0] = alpha; 365 for ( i = 0; i < 3; i++ ) 366 rows[i+1] = scandata[i]; 367 sv_putrow( rows+1, 512, &globals ); 368 369The sv_putrow routine expects to find the pointer to the alpha channel at the 370-1 position in the rows array. Thus, we pass a pointer to rows[1] and put the 371pointer to the alpha channel in rows[0]. 372 373 Finally, after all scanlines have been written, we call sv_puteof to write an 374EOF opcode into the file. This is not strictly necessary, since a physical end 375of file also indicates the end of the RLE data, but it is a good idea. 376 377 Here is a skeleton of an application that uses sv_putrow to save an image is 378shown in Figure 2-3. This example uses the default values supplied in the 379globals variable sv_globals, modifying it to indicate the presence of an alpha 380channel. 381 382 Using sv_putraw is more complicated, as it takes arrays of rle_op structures 383instead of just pixels. If the data is already available in something close to 384this form, however, sv_putraw will run much more quickly than sv_putrow. An 385rle_op is a structure with the following contents: 386 387 opcode The type of data. One of ByteData or RunData. 388 389 xloc The X location within the scanline at which this data begins. 390 391 length The length of the data. This is either the number of pixels 392 that are the same color, for a run, or the number of pixels 393 provided as byte data. 394 395 pixels A pointer to an array of pixel values. This field is used only 396 for the ByteData opcode. 397 398 run_val The pixel value for a RunData opcode. 399 400 Since there is no guarantee that the different color channels will require 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 #include <svfb_global.h> 502 503 main() 504 { 505 rle_pixel scanline[3][512], alpha[512], *rows[4]; 506 int y, i; 507 508 /* Most of the default values in sv_globals are ok */ 509 /* We do have an alpha channel, though */ 510 sv_globals.sv_alpha = 1; 511 SV_SET_BIT( sv_globals, SV_ALPHA ); 512 513 rows[0] = alpha; 514 for ( i = 0; i < 3; i++ ) 515 rows[i+1] = scanline[i]; 516 517 sv_setup( RUN_DISPATCH, &sv_globals ); 518 519 /* Create output for 512 x 480 (default size) display */ 520 for ( y = 0; y < 480; y++ ) 521 { 522 mk_scanline( y, scanline, alpha ); 523 sv_putrow( rows, 512, &sv_globals ); 524 } 525 sv_puteof( &sv_globals ); 526 } 527 528 Figure 2-3: Example of use of sv_putrow 529 530the same set of rle_ops to describe their data, a separate count must be 531provided for each channel. Here is a sample call to sv_putraw: 532 533 int nraw[3]; /* Length of each row */ 534 rle_op *rows[3];/* Data pointers */ 535 sv_putraw( rows, nraw, &globals ); 536 537A more complete example of the use of sv_putraw will be given in connection 538with the description of rle_getraw, below. 539 540 Calls to sv_putrow and sv_putraw may be freely intermixed, as required by the 541application. 542 543 544 5452.5. Reading RLE Files 546 Reading an RLE file is much like writing one. An initial call to a setup 547routine reads the file header and fills in the globals structure. Then, a 548scanline at a time is read by calling rle_getrow or rle_getraw. 549 550 The calling program is responsible for opening the input file. A call to 551rle_get_setup will then read the header information and fill in the supplied 552globals structure. The return code from rle_get_setup indicates a variety of 553errors, such as the input file not being an RLE file, or encountering an EOF 554while reading the header. 555 556 Each time rle_getrow is called, it fills in the supplied scanline buffer with 557one scanline of image data and returns the Y position of the scanline (which 558will be one greater than the previous time it was called). Depending on the 559setting of the background flag, the scanline buffer may or may not be cleared 560to the background color on each call. If it is not (background is 0 or 1), and 561if the caller does not clear the buffer between scanlines, then a "smearing" 562effect will be seen, if some pixels from previous scanlines are not overwritten 563by pixels on the current scanline. Note that if background is 0, then no 564background color was supplied, and setting background to 2 to try to get 565automatic buffer clearing will usually cause a segmentation fault when 566rle_getrow tries to get the background color through the bg_color pointer. 567 568 Figure 2-4 shows an example of the use of rle_getrow. Note the dynamic 569allocation of scanline storage space, and compensation for presence of an alpha 570channel. A subroutine, rle_row_alloc, is available that performs the storage 571allocation automatically. It is described below. If the alpha channel were 572irrelevant, the macro SV_CLR_BIT could be used to inhibit reading it, and no 573storage space would be needed for it. 574 575 The function rle_getraw is the inverse of sv_putraw. When called, it fills 576in the supplied buffer with raw data for a single scanline. It returns the 577 15 578scanline y position, or 2 to indicate end of file. It is assumed that no 579 15 580image will have more than 2 -1 scanlines. A complete program (except for 581error checking) that reads an RLE file from standard input and produces a 582negative image on standard output is shown in Figure 2-5. 583 584 The functions rle_row_alloc and rle_raw_alloc simplify allocation of buffer 585space for use by the rle routines. Both use a supplied globals structure to 586determine how many and which channels need buffer space, as well as the size of 587the buffer for each scanline. The returned buffer pointers will be adjusted 588for the presence of an alpha channel, if it is present. Buffer space for pixel 589or rle_op data will be allocate only for those channels that have bits set in 590the channel bitmap. The buffer space may be freed by calling rle_row_free or 591rle_raw_free, respectively. 592 5933. Comments, issues, and directions 594 Some comments on the file format and current subroutine implementation: 595 596 - The background color for the alpha channel is always 0. 597 598 - All channels must have the same number of bits. This could be a 599 problem when saving, e.g., Z values, or if more than 8 bits of 600 precision were desired for the alpha channel. 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 /* An example of using rle_getrow */ 702 /* Scanline pointer */ 703 rle_pixel ** scan; 704 int i; 705 706 /* Read the RLE file from stdin */ 707 rle_get_setup( &globals ); 708 709 /* Allocate enough space for scanline data, including alpha channel */ 710 /* (Should check for non-zero return, indicating a malloc error) */ 711 rle_row_alloc( &globals, &scan ); 712 713 /* Read scanline data */ 714 while ( (y = rle_getrow( &globals, stdin, scan ) <= globals.sv_ymax ) 715 /* Use the scanline data */; 716 717 718 Figure 2-4: Example of rle_getrow use. 719 720 721 #include <stdio.h> 722 #include <svfb_global.h> 723 #include <rle_getraw.h> 724 725 main() 726 { 727 struct sv_globals in_glob, out_glob; 728 rle_op ** scan; 729 int * nraw, i, j, c, y, newy; 730 731 in_glob.svfb_fd = stdin; 732 rle_get_setup( &in_glob ); 733 /* Copy setup information from input to output file */ 734 out_glob = in_glob; 735 out_glob.svfb_fd = stdout; 736 737 /* Get storage for calling rle_getraw */ 738 rle_raw_alloc( &in_glob, &scan, &nraw ); 739 740 /* Negate background color! */ 741 if ( in_glob.sv_background ) 742 for ( i = 0; i < in_glob.sv_ncolors; i++ ) 743 out_glob.sv_bg_color[i] = 255 - out_glob.sv_bg_color[i]; 744 745 /* Init output file */ 746 sv_setup( RUN_DISPATCH, &out_glob ); 747 748 y = in_glob.sv_ymin; 749 while ( (newy = rle_getraw( &in_glob, scan, nraw )) != 32768 ) { 750 /* If > one line skipped in input, do same in output */ 751 if ( newy - y > 1 ) 752 sv_skiprow( &out_glob, newy - y ); 753 y = newy; 754 /* Map all color channels */ 755 for ( c = 0; c < out_glob.sv_ncolors; c++ ) 756 for ( i = 0; i < nraw[c]; i++ ) 757 switch( scan[c][i].opcode ) { 758 case RRunDataOp: 759 scan[c][i].u.run_val = 255 - scan[c][i].u.run_val; 760 break; 761 case RByteDataOp: 762 for ( j = 0; j < scan[c][i].length; j++ ) 763 scan[c][i].u.pixels[j] = 764 255 - scan[c][i].u.pixels[j]; 765 break; 766 } 767 sv_putraw( scan, nraw, &out_glob ); 768 /* Free raw data */ 769 rle_freeraw( &in_glob, scan, nraw ); 770 } 771 sv_puteof( &out_glob ); 772 773 /* Free storage */ 774 rle_raw_free( &in_glob, scan, nraw ); 775 } 776 777 778 Figure 2-5: Program to produce a negative of an image 779 780 - Pixels are skipped (by sv_putrow) only if all channel values of the 781 pixel are equal to the corresponding background color values. 782 783 - The current Implementation of sv_putrow skips pixels only if at least 784 2 adjacent pixels are equal to the background. The SkipPixels 785 operation is intended for efficiency, not to provide cheap 786 compositing. 787 788 - Nothing forces the image data to lie within the bounds declared in 789 the header. However, rle_getrow will not write outside these bounds, 790 to prevent core dumps. No such protection is provided by rle_getraw. 791 792 - Images saved in RLE are usually about 1/3 their original size (for an 793 "average" image). Highly complex images may end up slightly larger 794 than they would have been if saved by the trivial method. 795 796 We have not yet decided how pixels with other than 8 bits should be packed 797into the file. To keep the file size down, one would like to pack ByteData as 798tightly as possible. However, for interpretation speed, it would probably be 799better to save one value in each (pixelbits+7)/8 bytes. 800 801 Some proposed enhancements include: 802 803 - A "ramp" opcode. This specifies that pixel values should be linearly 804 ramped between two values for a given number of pixels in the 805 scanline. This opcode would be difficult to generate from an image, 806 but if an application knew it was generating a ramp, it could produce 807 significant file size savings (e.g. in Gouraud shaded images). 808 809 - Opcodes indicating that the current scanline is identical to the 810 previous, or that it differs only slightly (presumably followed by 811 standard opcodes indicating the difference). Detection of identical 812 scanlines is easy, deciding that a scanline differs slightly enough 813 to warrant a differential description could be difficult. In images 814 with large areas with little change, this could produce size 815 savings(This suggestion was inspired by a description of the RLE 816 format used at Ohio State University.) 817 818 The subroutine library is still missing some useful functions. Some proposed 819additions are: 820 821 - Conversion from "raw" to "row" format, and back. One could then view 822 sv_putrow as being a "raw" to "row" conversion followed by a call to 823 sv_putraw, and rle_getrow as a call to rle_getraw followed by "row" 824 to "raw" conversion. 825 826 - A function to merge several channels of "raw" data into a single 827 channel. For example, this would take separate red, green, and blue 828 channels and combine them into a single RGB channel. This would be 829 useful for RLE interpretation on devices that do not easily support 830 the separate channel paradigm, while preserving the efficiency of the 831 "raw" interface. It could also be used to increase the efficiency of 832 a compositing program. 833 834 The Utah RLE format has developed and matured over a period of about six 835years, and has proven to be versatile and useful for a wide variety of 836applications that require image transmittal and storage. It provides a 837compact, efficiently interpreted image storage capability. We expect to see 838continued development of capabilities and utility, but expect very little 839change in the basic format. 840 8414. Acknowledgments 842 This work was supported in part by the National Science Foundation 843(DCR-8203692 and DCR-8121750), the Defense Advanced Research Projects Agency 844(DAAK11-84-K-0017), the Army Research Office (DAAG29-81-K-0111), and the Office 845of Naval Research (N00014-82-K-0351). All opinions, findings, conclusions or 846recommendations expressed in this document are those of the authors and do not 847necessarily reflect the views of the sponsoring agencies. 848 849 Table of Contents 8501. Introduction 0 8512. Description of RLE Format 0 852 2.1. The Header 0 853 2.2. The Scanline Data 0 854 2.3. Subroutine Interface 1 855 2.4. Writing RLE files 1 856 2.5. Reading RLE Files 2 8573. Comments, issues, and directions 2 8584. Acknowledgments 5 859 860 List of Figures 861Figure 2-1: RLE file header 0 862Figure 2-2: RLE file operand formats 0 863Figure 2-3: Example of use of sv_putrow 2 864Figure 2-4: Example of rle_getrow use. 3 865Figure 2-5: Program to produce a negative of an image 4 866