#include #ifdef __STDC__ #define ARGS(alist) alist #else #define ARGS(alist) () #endif #define put_byte(A) (*put_b)((byte)(A)); Nbyte++ typedef unsigned char byte; static long Nbyte; static void (*put_b) ARGS((byte)); static void put_scline ARGS((byte *, int)); static void put_word ARGS((int)); /*********************************************************************** * * * Name: PCXencode Date: 18.11.92 * * Author: E.Chernyaev (IHEP/Protvino) Revised: * * * * Function: PCX compression of the image * * * * Input: Width - image width (must be >= 8) * * Height - image height (must be >= 8) * * Ncol - number of colors * * R[] - red components * * G[] - green components * * B[] - blue components * * ScLine[] - array for scan line (byte per pixel) * * get_scline - user routine to read scan line: * * get_scline(y, Width, ScLine) * * pb - user routine for "put_byte": pb(b) * * * * Return: size of PCX * * * ***********************************************************************/ long PCXencode(Width, Height, Ncol, R, G, B, ScLine, get_scline, pb) int Width, Height, Ncol; byte R[], G[], B[], ScLine[]; void (*get_scline) ARGS((int, int, byte *)), (*pb) ARGS((byte)); { int i, n; /* C H E C K P A R A M E T E R S */ if (Width <= 0 || Width > 4096 || Height <= 0 || Height > 4096) { fprintf(stderr, "\nPCXencode: incorrect image size: %d x %d\n", Width, Height); return 0; } if (Ncol <= 0 || Ncol > 256) { fprintf(stderr,"\nPCXencode: wrong number of colors: %d\n", Ncol); return 0; } /* I N I T I A L I S A T I O N */ put_b = pb; Nbyte = 0; /* W R I T E H E A D E R */ put_byte(0x0a); /* PCX magic number */ put_byte(0x05); /* PC Paintbrush version */ put_byte(0x01); /* PCX run length encoding */ put_byte(8); /* bits per pixel */ put_word(0); /* image left */ put_word(0); /* image top */ put_word(Width-1); /* image right */ put_word(Height-1); /* image bottom */ put_word(Width); /* horizontal resolution */ put_word(Height); /* vertical resolution */ n = (Ncol < 16) ? Ncol : 16; /* dummy color palette */ for (i = 0; i < n; ++i) { put_byte(R[i]); put_byte(G[i]); put_byte(B[i]); } for (; i < 16; ++i) { put_byte(255); put_byte(255); put_byte(255); } put_byte(0); /* reserved byte */ put_byte(1); /* number of color planes */ put_word(Width); /* number of bytes per scanline */ put_word(1); /* pallette info */ for (i = 0; i < 58; ++i) { /* fill to end of header */ put_byte(0); } /* W R I T E I M A G E */ for (i = 0; i < Height; i++) { (*get_scline)(i, Width, ScLine); put_scline(ScLine, Width); } /* W R I T E P A L E T T E */ put_byte(0x0c); /* magic for 256 colors */ for (i = 0; i < Ncol; ++i) { put_byte(R[i]); put_byte(G[i]); put_byte(B[i]); } for (; i < 256; ++i) { put_byte(255); put_byte(255); put_byte(255); } return Nbyte; } static void put_scline(buf, size) byte *buf; int size; { byte *ptr, *end; int current, previous, count; ptr = buf; end = ptr + size; previous = *ptr++; count = 1; /* R U N L E N G T H E N C O D I N G */ while (ptr < end) { current = *ptr++; if (current == previous && count < 63) { count++; continue; } if (count > 1 || (previous & 0xc0) == 0xc0) { count |= 0xc0; put_byte(count); } put_byte(previous); previous = current; count = 1; } if (count > 1 || (previous & 0xc0) == 0xc0) { count |= 0xc0; put_byte(count); } put_byte(previous); } static void put_word(i) int i; { put_byte(i & 0xff); put_byte((i>>8) & 0xff); }