summaryrefslogtreecommitdiff
path: root/support/bm2ltx/pcx_fmt.doc
blob: 09e3c516f37ecc1b299f31e8c5d5fc33a8a4b3f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
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
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
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
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941


Ian Ashdown
byHeart Software
620 Ballantree Road
West Vancouver, B.C.
Canada V7S 1W3

Issue 1: 91/02/12
Issue 2: 91/03/27
Issue 3: 91/08/08
Issue 4: 91/08/11











                               PCX Graphics

                                    by 

                               Ian Ashdown
                             byHeart Software

Looking to add monochrome or full-color bit-mapped graphics to your 
application programs?  If so, you might consider the PCX graphics file 
format.  Originally developed in 1982 by ZSoft Corporation for their PC 
Paintbrush (R) products, it has become a de facto industry standard for 
storing and transferring bit-mapped images on MS-DOS machines.  It can 
support displays of any resolution using palettes of up to 256 
simultaneous colors, and is very simple to implement.  Furthermore, it's 
not limited to MS-DOS and OS/2-based machines; the PCX format is 
applicable to any environment supporting bit-mapped graphics. 

Today, more commercial programs support ZSoft's PCX format than any 
other, including Aldus-Microsoft's Tag Image File Format (TIFF).  
However, unlike TIFF with its publicly-available technical 
specifications, the PCX file format has never been completely documented.  
When ZSoft first created PC Paintbrush, the only video displays they had 
to contend with were two monochrome adapters (Hercules and Tecmar) and 
the IBM Color Graphics Adapter (CGA).  They have since quietly modified 
and extended their format on several occasions to support EGA, VGA and 
SuperVGA displays.  Documentation is scarce, incomplete and sometimes 
contradictory.  There's a small booklet available from ZSoft that 
describes the current version (with several omissions), a sample Pascal 
program from their CompuServe forum (GO WINAPB), a few magazine articles, 
and chapters in a few books (see the references at the end of this 
article). 

Personally, I think it's about time to remedy this situation.  The 
following is a complete set of technical specifications for the current 
version of PCX.  All of the information has been derived from printed 
information provided by ZSoft and conversations with their Technical 
Services department.  This is it, folks!  We now have formal (if not 
exactly official) specifications to work with when including the PCX 
graphics file format in our application programs. 

My original plan was to include sample C source code for reading and 
writing PCX image files.  However, both this article and the source code 
grew to the extent that one had to go.  If you don't want to develop your 
own PCX file handling routines from scratch, PCX_LIB is available through 
the CUG Library as CUG Volume #???.  It includes fully commented C source 
code for reading and writing PCX image files, complete with software 
drivers for Hercules, CGA, EGA, and VGA display adapters.



















                                                                    p. 1

PCX Specifications 

The PCX graphics file format (Version 5) is designed to store monochrome 
and color bit-mapped images of any resolution with palettes of up to 256 
simultaneous colors.  It was originally designed for MS-DOS 
microcomputers, but is adaptable to other bit-mapped graphic 
environments.  A simple but effective byte-oriented, run-length encoding 
scheme is used to compress the image data.

There are two or three sections to a PCX graphics file - a 128-byte 
header, the encoded image data (which can be of any length) and an 
optional 256-color palette (see Figure 1).  This palette is appended to 
the file only if the image contains more than 16 colors. 














































                                                                    p. 2

1.  PCX File Header

The file header describes the graphical environment in which the image is 
to be displayed.  The information contained in the header is somewhat 
device-dependent in that the PCX file format implicitly assumes the 
presence of a standard IBM PC-compatible display adapter.  Furthermore, 
the specific type and video mode of the adapter needed to display the 
image correctly cannot be uniquely determined from the file header 
information.  It is in general the user's responsibility to ensure that 
the correct video mode has been selected before displaying a PCX image. 

The file header structure is shown in Figure 2.  A complete description 
of each structure member is as follows: 

1.1   PCX Flag

A constant value (0x0a) that signifies a PCX image file. 

1.2   Version

Indicates the PCX file format version. It can be one of five values: 

    0 - Version 2.5 of PC Paintbrush.
    2 - Version 2.8 (with palette information).
    3 - Version 2.8 (without palette information).
    4 - PC Paintbrush for Windows (not 3.0).
    5 - Version 3.0 and greater of PC Paintbrush and Paintbrush Plus, 
        including Publisher's Paintbrush. 

Most commercial programs supporting the PCX file format conform to 
Version 5.  See Section 3, "Color Palettes", for further information. 

1.3   Encoding (1)

A constant value (0x01) that indicates run-length encoding was used to 
encode and compress the image data. 

1.4   Bits per Pixel

The number of bits per pixel per color plane (typically 1, 2, 4 or 8). 

1.5   Window

A structure with the following members: 

    Name    Bytes    Description

    xul       2      Upper left corner horizontal position
    yul       2      Upper left corner vertical position
    xlr       2      Lower right corner horizontal position
    ylr       2      Lower right corner vertical position

These members describe the position and size of the image within the 
display, and are measured in pixels (starting with zero). 





                                                                    p. 3

1.6   HDPI (2)

"Horizontal dots per inch".  The value represents the horizontal 
resolution of the device used to create the image. 

1.7   VDPI (2)

"Vertical dots per inch".  The value represents the vertical resolution 
of the device used to create the image. 

1.8   Color Map

The color palette to be used when displaying an image with 16 or fewer 
colors.  See Section 3, "Color Palettes", for further information. 

1.9   Reserved

This member was used to indicate the appropriate MS-DOS video mode in 
previous PCX file format versions.  It is ignored in Version 5, but
should be set to zero.

1.10  NPlanes

The number of color planes used to display the image (typically 1 or 4).  
See Section 3, "Color Palettes", for further information. 

1.11  Bytes per Line

The number of bytes required for a buffer when decoding one color plane 
scan line.  This value should be an even number (for compatibility with 
some existing commercial programs).  See Section 2, "Image Encoding and 
Decoding", for further information. 

1.12  Palette Info (3)

A bit-mapped variable indicating how to interpret the color palette.  
Only the lowest two bits are  significant; the others are ignored.  It 
can have one of two possible values: 

    0x01 - color or black & white
    0x02 - grayscale

If the variable is set to 0x02 (grayscale), the color palette must be set 
to shades of gray. 

1.13  HScreen Size (4)

Horizontal screen size in pixels.

1.14  VScreen Size (4)

Vertical screen size in pixels.

1.15  Filler

Blank space to fill out 128-byte header.  All bytes within this member  
should be set to zero. 


                                                                    p. 4

Notes

1. ZSoft has reserved the right to change the encoding scheme for better 
   image compression performance in future versions. 

2. Horizontal and vertical resolution for video display adapters is 
   defined as the total number of displayed pixels for the current video 
   mode.  For scanners, it is defined in terms of dots per inch.  (These 
   values are provided for information only.  They are not required for 
   encoding or decoding PCX image files.) 

3. The "palette info" member of the file header was used in previous 
   versions of the PCX file format to indicate whether the palette 
   represented a color or grayscale palette.  If it was set to 0x02 (as a 
   bitmap - the upper 6 bits could be set at random), the file decoding 
   functions could assume a default grayscale palette if necessary.  
   However, the palette already had a true (and possibly nonlinear) 
   grayscale, so the "palette info" member was never really used by 
   ZSoft.  The current PC Paintbrush IV and IV Plus products simply 
   ignore it. 

4. The "HScreen Size" and "VScreen Size" members were added to Version 5 
   of the PCX format to support PC Paintbrush IV Version 1.02 and IV Plus 
   Version 1.0.  Since earlier Version 5 PCX files may contain 
   uninitialized data in place of these members, ZSoft specifically 
   recommends that they not be used to determine the appropriate video 
   mode for displaying the files.
































                                                                    p. 5

2.  Image Encoding and Decoding 

The PCX graphics file format considers an image to be a contiguous 
sequence (block) of eight-bit bytes representing a bit-mapped raster 
display.  A simple byte-oriented, run-length encoding (RLE) scheme is
used to compress the display data.  When the display is represented by
more than one color plane (such as color images on EGA displays), each
scan line is stored sequentially by color plane. 

The run-length encoding scheme uses a byte pair consisting of a "count" 
byte and a following "data" byte to represent sequences of display bytes 
with the same value.  A count byte is uniquely identified by having its 
two most significant bits set; its six least significant bits are used to 
represent the count value (1 to 63).  The following data byte is the 
value that is repeated in the display data the number of times indicated 
by the count value. 

Any display data byte which is not part of a sequence of bytes of the 
same value and which does not have its two most significant bits set is 
stored as itself in the encoded image data.  Single display data bytes 
with a value of 0xc0 or greater are encoded with a count value of one. 

2.1.  Decoding

Decoding display data from encoded image data is done on a line-by-line 
basis.  The pixel dimensions of the displayed image are calculated as: 

    horz_size = Window.xlr - Window.xul + 1

and

    vert_size = Window.ylr - Window.yul + 1

The number of bytes required to buffer one complete scan line for all 
color planes in sequence is: 

    buffer_size = NPlanes * Bytes per Line

Since there are always an integral number of bytes in the buffer, there 
may be unused data at the end of each color plane scan line if the number 
of bits per pixel is other than eight.  This unused data should be masked 
off when transferring the line buffer contents to the video display 
adapter memory. 

In theory, each color plane scan line may contain an even or odd number 
of bytes.  However, some application programs expect an even number of 
bytes.  ZSoft ensures that their products create PCX files with an even 
number of bytes per color plane scan line, and recommends that other 
programs do the same for compatibility.  Of course, decoding functions 
should be able to read files with either an even or odd number of bytes 
per color plane scan line. 

Decoding begins with the first scan line and proceeds by examining each 
byte of the encoded image data.  If the two most significant bits of the 
byte are set, the lower six bits indicate how many times the next byte is 




                                                                    p. 6

Decoding begins with the first scan line and proceeds by examining each 
byte of the encoded image data.  If the two most significant bits of the 
byte are set, the lower six bits indicate how many times the next byte is 
to be duplicated in the line buffer.  If these two bits are not set, the 
byte itself is copied (once) to the line buffer.  A count is kept of the 
number of bytes in the line buffer.  The current scan line is complete 
when its value equals "buffer_size". 

If the display contains more than one color plane, each plane is decoded 
in sequence.  The order in which they are decoded is device-dependent.  
For instance, the Enhanced Graphics Adapter has four color planes ordered 
as blue, green, red and intensity.  The beginning of each color plane 
scan line within the line buffer is given by: 

    offset = plane_number * Bytes per Line

where "plane_number" is a number between 0 and NPlanes - 1. 

A decoding break occurs at the end of each scan line.  That is, an 
encoding byte pair can only represent a contiguous sequence of bytes 
within the current scan line.  However, this is not necessarily true for 
color planes.  An encoding byte pair may represent a contiguous sequence 
of identical bytes that extends across two color planes for one display 
image scan line. 

Decoding continues until all scan lines (as indicated by "vert_size") 
have been decoded.  Some older versions of PC Paintbrush padded the image 
with extra (uninitialized) scan lines so that all blocks of scan lines (8 
or 16 lines) read from the file were the same size.  The image data was 
read until end-of-file was returned.  ZSoft no longer uses this 
technique, since it conflicts with the appended color palette (see 
Subsection 3.3, "VGA 256-Color Palettes").  The extra data read could 
also overrun the user's image buffer. 

A sample C function to decode a complete image scan line (all color planes)
from a PCX file is shown in Figure 3. 

2.2.  Encoding

Encoding display image data is also done on a line-by-line basis, 
following the order of scan lines stored in the display adapter's memory 
buffer.  The current scan line is encoded for each color plane on a per-
byte basis.  As noted above, ZSoft recommends that all color plane scan 
lines be padded if necessary to ensure they contain an even number of 
bytes. 

ZSoft also recommends that the data used to pad the last one or two bytes 
of a scan line represent white data.  Apparently, some application 
programs display this data when printing or faxing the files.

A sample C function to encode a single monochrome or color image scan 
line for a PCX file is shown in Figure 4.







                                                                    p. 7

3.  Color Palettes 

The PCX file format supports color palettes of up to 16 colors in the 
file header.  Larger palettes (up to a maximum of 256 colors) are stored 
in an optional color palette that is appended to the encoded image data 
portion of the file. 

The file header color palette has two different formats, both designed 
for IBM PC-compatible machines.  A device-specific palette is used for 
Color Graphics Adapters (CGA),  and a standard R-G-B palette is used for 
Enhanced Graphics Adapters (EGA), Multicolor Graphics Adapters (MCGA), 
Video Graphics Adapters (VGA) and extended Video Graphics Adapters 
(SuperVGA). 

ZSoft's PC Paintbrush products no longer support the CGA color palette.  
The following information is provided only for compatibility with older 
PCX files. 

3.1.  CGA Color Palettes

The PCX format supports eight possible CGA color palettes for video modes 
4 (320x200 4-color graphics) and 5 (320x200 monochrome graphics, color 
burst off).  Each palette consists of a background color and three 
foreground colors (or shades of grey).  The background can be one of 16 
colors, the value for which is stored in the first byte of the PCX file 
header Color Map member.  Only the upper four bits are significant; the 
value must be right-shifted by four bits (or divided by 16) to determine 
the appropriate CGA hardware palette register value. 

The foreground color palette is specified by the fourth byte of the Color 
Map, which has the following structure: 

    Name                Bit    Description

    Color Burst Enable   7     0 - color
                               1 - monochrome
    Palette              6     0 - yellow
                               1 - white
    Intensity            5     0 - dim
                               1 - bright

The lower five bits are ignored. 

Most published descriptions of the ROM BIOS call "Set CGA Palette" 
(Interrupt 16, Function 11) document only two palettes, obtainable by 
setting register BL to 0x00 or 0x01.  This is equivalent to the "Palette" 
bit above.  However, the palette intensity (equivalent to the "Intensity" 
bit above) can be selected using bit 4 of the BL register (0 = dim, 1 = 
bright). 

The original CGA display adapter was designed for use with NTSC composite 
video monitors and color televisions.  The "color burst" is a periodic 
burst of a 3.58 MHz signal superimposed on the composite video signal to 
synchronize the phase of the monitor's internal 3.58 MHz oscillator.  
(Without synchronization, the picture has drifting color bars.)  The 
presence or absence of the burst determines whether the image is 
displayed in color or monochrome. 


                                                                    p. 8

The "Color Burst Enable" bit above actually indicates whether the MS-DOS 
video mode is to be 4 (color) or 5 (monochrome).  However, the color 
burst signal has no meaning for RGB monitors.  Video mode 5 will produce 
only two distinct color palettes on CGA displays adapters with RGB 
monitors, and three distinct palettes on EGA, VGA and SuperVGA display 
adapters emulating a CGA display. 

Under video mode 6 (640 x 200 2-color graphics), the first byte of the
CGA color palette specifies the foreground color (i.e. - the color of
the displayed pixels).

3.2.  EGA/VGA 16-Color Palettes

The 16-color palette for EGA, MCGA, VGA and SuperVGA displays is an array 
of 16 elements, each a structure with the following members: 

    Name    Bytes    Description

    Red       1      Red intensity
    Green     1      Green intensity
    Blue      1      Blue intensity

All color map entries are stored as unsigned bytes with values ranging 
between 0 and 255.  Where display adapters support fewer intensity 
levels, the value of each color map entry is interpreted by dividing its 
value by 256/n, where n is the number of allowable intensity levels 
(typically 2, 4 or 16). 

3.3.  VGA 256-Color Palettes

The 256-color palette for MCGA, VGA and SuperVGA displays is an array of 
256 elements, each a structure with the same members as the EGA/VGA 16-
color palette, which is appended to the encoded image data portion of the 
file (see Figure 1).  It is always preceded by a constant byte flag with
the value 0x0c (12 decimal). 

Only Version 5 PCX-format files support 256-color palettes, and then only 
when the image has more than 16 colors.  ZSoft recommends the following 
technique to determine if a 256-color palette is present: first verify 
that the file version number is 5, then count back 769 bytes from the end 
of the file.  If the value of this byte is not 0x0c, the optional 256-
color palette is not present and the EGA/VGA 16-color file header palette 
should be used. 

It is possible that a Version 5 PCX-format file with a valid file header 
palette can have the value 0x0c in the 769th byte from the end of the 
encoded image data.  The above technique would then falsely indicate the
presence of an appended 256-color palette.  To avoid this problem, it is 
necessary to first decode the image and note the file position where the 
encoded image data section ends before counting back 769 bytes from the 
end of the file.  If the supposed 256-color palette flag is located in 
the image data section, then the file header palette should be used 
instead.






                                                                    p. 9

3.4.  24-Bit Color 

Future versions of ZSoft's Publisher's Paintbrush will support up to 16.7 
million simultaneous colors.  The PCX file format will be based on three 
color planes (red, green and blue), with 8 bits per pixel per plane.  
There will be no color palette, since the color of each pixel will be 
fully specified by the encoded image data. 

3.5.  Disabling the Palette 

It is occasionally necessary to disable the color palette of a PCX file 
in order to correctly display the image.  In other words, the current 
(default) setting of the display adapter's palette registers are used.  
This can be done by changing the PCX file version number from '5' to '3' 
(i.e. - PC Paintbrush Version 2.8 without palette information).  The file 
decoding functions must then check the file version number and ignore the 
color palette if it is set to '3'.






































                                                                    p. 10

4.  Other Environments 

While the PCX file format was designed for MS-DOS machines, it is 
nevertheless possible to display PCX images on other machines.  It will 
generally be necessary to map the image representation (i.e. - window 
dimensions, number of color planes, bits per pixel per plane, and the 
color palette) to the capabilities of the display hardware. 

It is also necessary to remember that all information in a PCX-format 
file is stored as either 8-bit bytes or 16-bit words.  Words are stored 
in the big-endian format characteristic of 80x86-based machines.  That 
is, the eight least significant bits (lower byte) are stored first, 
followed by the eight most significant bits (upper byte).  If PCX-format 
files are transferred to little-endian machines (such as those based on 
680x0 and Z8000 processors), the order of bytes within each word will 
have to be reversed before they can be interpreted.  (This applies to the 
file header only, since the encoded image data and optional 256-color 
palette are stored as bytes.)









































                                                                    p. 11

References 

Azer, S. [1988].  "Working With PCX Files", Microcornucopia, No. 42 
(July-August), p. 42.

Lindley, C.A. [1990].  Practical Image Processing in C, John Wiley & Sons 
Inc., New York, N.Y.

Luze, M. [1991].  "Printing PCX Files", C Gazette, Vol. 5:2 (Winter 1990 -
1991), pp. 11-22.

Phoenix Technologies Ltd. [1989].  System BIOS for IBM PC/XT/AT Computers 
and Compatibles, Addison-Wesley, Reading, MA.

Quirk, K. [1989].  "Translating PCX Files", Dr. Dobb's Journal, Vol. 14:8 
(August), pp. 30-36, 105-108.

Rimmer, S. [1990].  Bit-Mapped Graphics, Windcrest Books, Blue Ridge 
Summit, PA.

ZSoft Corporation [1988].  PCX Technical Reference Manual Revision 4,
ZSoft Corporation, Marietta, GA.





































                                                                    p. 12

Figures

+--------------------------------------------+
|    File Header (128 bytes)                 |
+--------------------------------------------+
|    Encoded Image Data (variable length)    |
+--------------------------------------------+
|    Optional Color Palette (769 bytes)      |
+--------------------------------------------+

Figure 1 - Basic PCX File Format


Name           Bytes  Description 

PCX Flag         1    Constant flag
Version          1    PCX version number
Encoding         1    Run-length encoding flag
Bits per Pixel   1    Number of bits per pixel per plane
Window           8    Window dimensions
HDPI             2    Horizontal image resolution
VDPI             2    Vertical image resolution
Color Map       48    Hardware R-G-B color palette
Reserved         1    (Used to contain video mode)
NPlanes          1    Number of color planes
Bytes per Line   2    Number of bytes per scan line
Palette Info     2    Palette interpretation
HScreen Size     2    Horizontal screen size
VScreen Size     2    Vertical screen size
Filler          54    Initialized filler bytes

Figure 2 - PCX File Header Structure


/* Read an encoded scan line (all color planes) from a          */
/* PCX-format image file and write the decoded data to a scan   */
/* line buffer                                                  */

void pcx_read_line
(
  unsigned char *linep, /* PCX scan line buffer pointer         */
  FILE *fp,             /* PCX image file pointer               */
  int bpline            /* # bytes per line (all color planes)  */
)
{
  int data;         /* Image data byte                          */
  int count;        /* Image data byte repeat count             */
  int offset = 0;   /* Scan line buffer offset                  */

  while (offset < bpline)   /* Decode current scan line         */
  {
    data = getc(fp);        /* Get next byte                    */

    /* If top two bits of byte are set, lower six bits show how */
    /* many times to duplicate next byte                        */




                                                                    p. 13

    if ((data & 0xc0) == 0xc0)
    {
      count = data & 0x3f;          /* Mask off repeat count    */
      data = getc(fp);              /* Get next byte            */
      memset(linep, data, count);   /* Duplicate byte           */
      linep += count;
      offset += count;
    }
    else
    {
      *linep++ = (unsigned char) data;  /* Copy byte            */
      offset++;
    }
  }
}

Figure 3 - Decode PCX Image File Scan Line Function


/* Encode a scan line and write it to a PCX file (the line is   */
/* assumed to contain the color plane scan lines in sequence,   */
/* with padding for an even number of bytes and trailing white  */
/* data for each line as appropriate)                           */

void pcx_write_line
(
  unsigned char *linep, /* Scan line buffer pointer             */
  int length,           /* Scan line buffer length (in bytes)   */
  FILE *fp              /* PCX file pointer                     */
)
{
  int curr_data;        /* Current data byte                    */
  int prev_data;        /* Previous data byte                   */
  int data_count;       /* Data repeat count                    */
  int line_count;       /* Scan line byte count                 */

  prev_data = *linep++; /* Initialize the previous data byte    */
  data_count = 1;
  line_count = 1;

  while (line_count < length)   /* Encode scan line             */
  {
    curr_data = *linep++;       /* Get the current data byte    */
    line_count++;               /* Increment line byte count    */

    if (curr_data == prev_data) /* Repeating data bytes ?       */
    {
      data_count++;             /* Increment data repeat count  */

      if (data_count == 0x3f)   /* Max allowable repeat count ? */
      {
        pcx_encode(prev_data, data_count, fp);  /* Encode data  */
        data_count = 0;
      }
    }




                                                                    p. 14

    else    /* End of repeating data bytes                      */
    {
      if (data_count > 0)
        pcx_encode(prev_data, data_count, fp);  /* Encode data  */

      prev_data = curr_data;    /* Current data byte now prev   */
      data_count = 1;
    }
  }

  if (data_count > 0)           /* Any remaining data ?         */
  {
    pcx_encode(prev_data, data_count, fp);      /* Encode data  */
  }
}


/* Write an encoded byte pair (or single byte) to a file        */

void pcx_encode
(
  int data,     /* Data byte                                    */
  int count,    /* Data byte repeat count                       */
  FILE *fp      /* PCX file pointer                             */
)
{
  if (((data & 0xc0) == 0xc0) || count > 1)
  {
    putc(0xc0 | count, fp);     /* Write count byte             */
  }

  putc(data, fp);       /* Write data byte                      */
}

Figure 4 - Encode Image Scan Line Functions
























                                                                    p. 15