1 /***********************************************************************
2 * *
3 * PS_LZWencode.c - output an image in PostScript format *
4 * (Lelpel-Ziv Welch encoding) *
5 * *
6 * Author: Evgeni Chernyaev (chernaev@mx.ihep.su) *
7 * *
8 * Copyright (C) 1993, 1994 by Evgeni Chernyaev. *
9 * *
10 * Permission to use, copy, modify, and distribute this software and *
11 * its documentation for non-commercial purpose is hereby granted *
12 * without fee, provided that the above copyright notice appear in all *
13 * copies and that both the copyright notice and this permission *
14 * notice appear in supporting documentation. *
15 * *
16 * This software is provided "as is" without express or implied *
17 * warranty. *
18 * *
19 ***********************************************************************/
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <time.h>
24
25 #ifdef __STDC__
26 #define ARGS(alist) alist
27 #else
28 #define ARGS(alist) ()
29 #endif
30
31 typedef unsigned char byte;
32
33 static int Nbyte;
34 static char s[80];
35 static void (*put_b) ARGS((byte));
36 #define put_string nc=strlen(s); for(i=0;i<nc;i++) (*put_b)(s[i]); Nbyte += nc
37
38
39 #define MAXWIDTH 4096
40 #define BLACK 1
41 #define WHITE 0
42
43 /***********************************************************************
44 * *
45 * Name: PutPreview Date: 02.11.93 *
46 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
47 * *
48 * Function: Output device independent B&W preview *
49 * *
50 * Input: Width - image width *
51 * Height - image height *
52 * R[] - red components *
53 * G[] - green components *
54 * B[] - blue components *
55 * ScLine[] - array for scan line (byte per pixel) *
56 * get_scline - user routine to read scan line: *
57 * get_scline(y, Width, ScLine) *
58 * *
59 ***********************************************************************/
PutPreview(Width,Height,R,G,B,ScLine,get_scline)60 static void PutPreview(Width, Height, R, G, B, ScLine, get_scline)
61 int Width, Height;
62 byte R[], G[], B[], ScLine[];
63 void (*get_scline) ARGS((int, int, byte *));
64 {
65 int i, k, nc, x, y;
66 int mask, hex, err, dp, dp1, dp2, ddd[MAXWIDTH];
67
68 static int FSgamma[256] = { /* Floyd-Steinberg gamma */
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8,
72 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
73 24, 26, 27, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 43, 44,
74 45, 47, 48, 50, 51, 53, 54, 56, 58, 59, 61, 62, 64, 66, 67, 69,
75 70, 72, 74, 76, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 95, 96,
76 98,100,102,104,105,107,109,111,113,114,116,118,120,122,124,125,
77 127,129,131,133,135,136,138,140,142,144,145,147,149,151,153,154,
78 156,158,160,162,163,165,167,169,170,172,174,175,177,179,181,182,
79 184,186,187,189,190,192,194,195,197,198,200,201,203,204,206,207,
80 209,210,212,213,215,216,217,219,220,221,223,224,225,226,228,229,
81 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
82 246,246,247,248,248,249,250,250,251,251,252,252,253,253,254,254,
83 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
84 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 };
85
86 k = (Width + 279) / 280; /* 70 HEX per line */
87 sprintf(s,"%%%%BeginPreview: %d %d 1 %d\n", Width, Height, k*Height);
88 put_string;
89 for (i=0; i<Width; i++)
90 ddd[i] = 0;
91
92 for (y=0; y<Height; y++) {
93 (*get_scline)(y, Width, ScLine);
94 nc = 0; mask = 128; hex = 0; dp1 = 0;
95 for (x=0; x<Width; x++) {
96 i = ScLine[x];
97 i = (11*R[i] + 16*G[i] + 5*B[i]) / 32;
98 dp = FSgamma[i] + dp1 + ddd[x]; /* Floyd-Steinberg dithering */
99 if (dp<128) { /* --- x 7/16 */
100 hex += BLACK*mask; err = dp; /* 3/16 5/16 1/16 */
101 }else{
102 hex += WHITE*mask; err = dp - 255;
103 }
104 dp1 = (err*7)/16;
105 if (x == 0) {
106 ddd[0] = (err*5)/16;
107 dp2 = err/16;
108 }else{
109 ddd[x-1] += (err*3)/16;
110 ddd[x] = dp2 + (err*5)/16;
111 dp2 = err/16;
112 }
113 mask /= 2;
114 if (mask == 0) {
115 if (nc == 0) {
116 sprintf(&s[nc],"%% "); nc = 2;
117 }
118 sprintf(&s[nc],"%02x",hex); nc += 2;
119 if (nc == 72) {
120 sprintf(&s[nc],"\n"); put_string;
121 nc = 0;
122 }
123 mask = 128; hex = 0;
124 }
125 }
126 if (mask == 128) {
127 if (nc != 0) {
128 sprintf(&s[nc],"\n"); put_string;
129 }
130 }else{
131 if (nc == 0) {
132 sprintf(&s[nc],"%% "); nc = 2;
133 }
134 sprintf(&s[nc],"%02x\n",hex); put_string;
135 }
136 }
137 sprintf(s,"%%%%EndPreview\n"); put_string;
138 }
139
140 /***********************************************************************
141 * *
142 * Name: ASCII85encode Date: 05.11.93 *
143 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
144 * *
145 * Function: ASCII85 encode and output byte buffer *
146 * *
147 * Input: k - number of bytes *
148 * Buf - byte buffer *
149 * *
150 ***********************************************************************/
ASCII85encode(k,Buf)151 static void ASCII85encode(k, Buf)
152 int k;
153 byte Buf[];
154 {
155 unsigned long Value;
156 int i,j, n, nc;
157
158 if (k == 0) return;
159 s[5] = '\0';
160 for (j=0; j<k; j+=4) {
161 Value = Buf[j]*256*256*256;
162 if (j+1 < k) Value += Buf[j+1]*256*256;
163 if (j+2 < k) Value += Buf[j+2]*256;
164 if (j+3 < k) Value += Buf[j+3];
165 for (n=4; n>=0; n--) {
166 s[n] = Value % 85 + 33;
167 Value /= 85;
168 }
169 if (k-j < 4) s[k-j+1] = '\0';
170 put_string;
171 }
172 sprintf(s,"\n");
173 put_string;
174 }
175
176 #define BITS 12 /* largest code size */
177 #define HSIZE 5003 /* hash table size */
178 #define SHIFT 4 /* shift for hashing */
179 #define CLEARCODE 256 /* Clear Code */
180 #define EOD 257 /* End Of Data code */
181 #define PIXS 170000 /* largest # of pixels */
182
183 /***********************************************************************
184 * *
185 * Name: PutCode Date: 05.11.93 *
186 * Author: E.Chernyaev (IHEP/Protvino) Revised: *
187 * *
188 * Function: Put out code (LZW encoding) *
189 * *
190 * Input: Code - code *
191 * CodeSize - codesize *
192 * *
193 ***********************************************************************/
PutCode(Code,CodeSize)194 static void PutCode(Code, CodeSize)
195 int Code, CodeSize;
196 {
197 static int k, PartA, PartB, SizeA, SizeB;
198 static int mask[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
199 0x001F, 0x003F, 0x007F, 0x00FF,
200 0x01FF, 0x03FF, 0x07FF, 0x0FFF };
201 static byte Accum[56];
202 if (Code == -1) {
203 k = 0;
204 PartA = 0;
205 SizeA = 0;
206 return;
207 }
208
209 PartB = Code;
210 SizeB = CodeSize;
211
212 while (SizeB >= 8) {
213 SizeB = SizeA + SizeB - 8;
214 Accum[k++] = PartA | (PartB >> SizeB);
215 if (k == 56) {
216 ASCII85encode(k,Accum);
217 k = 0;
218 }
219 PartB &= mask[SizeB];
220 SizeA = 0;
221 PartA = 0;
222 }
223
224 SizeA = SizeB;
225 PartA = PartB << (8-SizeB);
226 if (Code == EOD) {
227 if (SizeA != 0) Accum[k++] = PartA;
228 ASCII85encode(k, Accum);
229 }
230 }
231
232 /***********************************************************************
233 * *
234 * Name: EncodeData Date: 05.11.93 *
235 * Author: E.Chernyaev (IHEP/Protvino) Revised: 21.06.94 *
236 * 04.06.94 *
237 * Function: Lelpel-Ziv Welch encoding of an image *
238 * *
239 * Input: Width - image width *
240 * Height - image height *
241 * Ncol - number of colors *
242 * R[] - red components *
243 * G[] - green components *
244 * B[] - blue components *
245 * ScLine[] - array for scan line (byte per pixel) *
246 * get_scline - user routine to read scan line: *
247 * get_scline(y, Width, ScLine) *
248 * *
249 * Return: size of PS *
250 * *
251 ***********************************************************************/
EncodeData(Width,Height,Ncol,R,G,B,ScLine,get_scline)252 static void EncodeData(Width, Height, Ncol, R, G, B, ScLine, get_scline)
253 int Width, Height, Ncol;
254 byte R[], G[], B[], ScLine[];
255 void (*get_scline) ARGS((int, int, byte *));
256 {
257 int i, k, nc, x, y, disp, Code, K;
258 long CodeK, Npix;
259 char **q;
260 int FreeCode, CurCodeSize, CurMaxCode;
261
262 long HashTab [HSIZE]; /* hash table */
263 int CodeTab [HSIZE]; /* code table */
264
265 /* O U T P U T P A L E T T E */
266
267 for (k=0; k<Ncol; k++) {
268 sprintf(s,"%02x%02x%02x",R[k],G[k],B[k]); put_string;
269 if (k % 10 == 9) {
270 sprintf(s,"\n"); put_string;
271 }else{
272 sprintf(s," "); put_string;
273 }
274 }
275 for (k=Ncol; k<256; k++) {
276 sprintf(s,"000000"); put_string;
277 if (k % 10 == 9) {
278 sprintf(s,"\n"); put_string;
279 }else{
280 sprintf(s," "); put_string;
281 }
282 }
283 sprintf(s,"\n"); put_string;
284
285 /* L W Z C O M P R E S S I O N */
286
287 PutCode(-1, 0);
288 FreeCode = CLEARCODE + 2;
289 CurCodeSize = 9;
290 CurMaxCode = 511;
291 memset((char *) HashTab, -1, sizeof(HashTab));
292 PutCode(CLEARCODE, CurCodeSize); /* 1st - clear code */
293 Npix = 0;
294 for (y=0; y<Height; y++) {
295 (*get_scline)(y, Width, ScLine);
296 x = 0;
297 if (y == 0) Code = ScLine[x++];
298 while(x < Width) {
299 K = ScLine[x++]; /* next symbol */
300 Npix++;
301 CodeK = ((long) K << BITS) + Code; /* set full code */
302 k = (K << SHIFT) ^ Code; /* xor hashing */
303
304 if (HashTab[k] == CodeK) { /* full code found */
305 Code = CodeTab[k];
306 continue;
307 }
308 else if (HashTab[k] < 0 ) /* empty slot */
309 goto NOMATCH;
310
311 disp = HSIZE - k; /* secondary hash */
312 if (k == 0) disp = 1;
313
314 PROBE:
315 if ((k -= disp) < 0)
316 k += HSIZE;
317
318 if (HashTab[k] == CodeK) { /* full code found */
319 Code = CodeTab[k];
320 continue;
321 }
322
323 if (HashTab[k] > 0) /* try again */
324 goto PROBE;
325
326 NOMATCH: /* full code not found */
327 PutCode(Code, CurCodeSize);
328 Code = K;
329 if (FreeCode == CurMaxCode) {
330 CurCodeSize++;
331 CurMaxCode = CurMaxCode*2 + 1;
332 }
333
334 if (CurCodeSize <= BITS && Npix <= PIXS) {
335 CodeTab[k] = FreeCode++; /* code -> hashtable */
336 HashTab[k] = CodeK;
337 }else{
338 if (CurCodeSize > BITS) CurCodeSize = BITS;
339 PutCode(CLEARCODE, CurCodeSize);
340 memset((char *) HashTab, -1, sizeof(HashTab));
341 FreeCode = CLEARCODE + 2;
342 CurCodeSize = 9;
343 CurMaxCode = 511;
344 Npix = 0;
345 }
346 }
347 }
348 /* O U T P U T T H E R E S T */
349
350 PutCode(Code, CurCodeSize);
351 if (FreeCode == CurMaxCode && CurCodeSize != BITS)
352 CurCodeSize++;
353 PutCode(EOD, CurCodeSize);
354 sprintf(s,"~>\n"); put_string;
355 }
356
357 /***********************************************************************
358 * *
359 * Name: PS_LZWencode Date: 02.02.93 *
360 * Author: E.Chernyaev (IHEP/Protvino) Revised: 02.11.93 *
361 * *
362 * Function: Output image in PostScript format *
363 * (Lelpel-Ziv Welch encoding) *
364 * *
365 * Input: iwhat - 0 - PostScript (PS) *
366 * 1 - encapsulated PostScript (EPS) *
367 * 2 - encapsulated PostScript with preview (EPSI) *
368 * 10 - PostScript (Gray) (PS) *
369 * 11 - encapsulated PostScript (Gray) (EPS) *
370 * 12 - encapsulated PostScript with preview (EPSI) *
371 * Width - image width *
372 * Height - image height *
373 * Ncol - number of colors *
374 * R[] - red components *
375 * G[] - green components *
376 * B[] - blue components *
377 * ScLine[] - array for scan line (byte per pixel) *
378 * get_scline - user routine to read scan line: *
379 * get_scline(y, Width, ScLine) *
380 * pb - user routine for "put_byte": pb(b) *
381 * *
382 * Return: size of PS *
383 * *
384 ***********************************************************************/
PS_LZWencode(iwhat,Width,Height,Ncol,R,G,B,ScLine,get_scline,pb)385 long PS_LZWencode(iwhat, Width, Height, Ncol, R, G, B, ScLine, get_scline, pb)
386 int iwhat, Width, Height, Ncol;
387 byte R[], G[], B[], ScLine[];
388 void (*get_scline) ARGS((int, int, byte *)), (*pb) ARGS((byte));
389 {
390 extern char ProgName[];
391 extern char ProgVers[];
392 extern char FileName[];
393
394 int ifeps, ifgray, i, nc;
395 char **q;
396 time_t clock;
397
398 static char *HeaderPS[] = {
399 "%***********************************************************************",
400 "%* *",
401 "%* Function: Display a Lempel-Ziv Welch (LZW) encoded color image. *",
402 "%* This file is suitable for any kind of PostScript printer: *",
403 "%* Level I/II, color/grayscale, format A4/A3/... *",
404 "%* By default the image will be centered, rotated and scaled *",
405 "%* to fill the maximum space on a page. *",
406 "%* If you want to use this file as an Encapsulated PostScript*",
407 "%* file (for example inside a LaTeX document), then just *",
408 "%* uncomment line '/EPSneeded true def'. *",
409 "%* To optimize output on GrayScale printers you may uncomment*",
410 "%* line '/GRAYneeded true def'. *",
411 "%* *",
412 "%* Author: Evgeni CHERNYAEV (chernaev@mx.ihep.su) *",
413 "%* *",
414 "%***********************************************************************",
415 "gsave",
416 "userdict begin",
417 "%/EPSneeded true def",
418 NULL,
419 };
420 static char *HeaderEPS[] = {
421 "%***********************************************************************",
422 "%* *",
423 "%* Function: Display a Lempel-Ziv Welch (LZW) encoded color image. *",
424 "%* This is an Encapsulated PostScript file suitable for any *",
425 "% kind of PostScript printer: Level I/II, color/grayscale...*",
426 "%* To optimize output on GrayScale printers you may uncomment*",
427 "%* line '/GRAYneeded true def'. *",
428 "%* *",
429 "%* Author: Evgeni CHERNYAEV (chernaev@vxcern.cern.ch) *",
430 "%* *",
431 "%***********************************************************************",
432 "gsave",
433 "userdict begin",
434 "/EPSneeded true def",
435 NULL,
436 };
437 static char *HeaderCol[] = {
438 "%/GRAYneeded true def",
439 "end",
440 "%***********************************************************************",
441 "%* Image Description *",
442 "%***********************************************************************",
443 NULL,
444 };
445 static char *HeaderGray[] = {
446 "/GRAYneeded true def",
447 "end",
448 "%***********************************************************************",
449 "%* Image Description *",
450 "%***********************************************************************",
451 NULL,
452 };
453 static char *CommonPart[] = {
454 "/mm {2.835 mul} def",
455 "userdict /EPSneeded known {",
456 " /EPSneeded userdict /EPSneeded get def",
457 "}{",
458 " /EPSneeded false def",
459 "} ifelse",
460 "userdict /GRAYneeded known {",
461 " /GRAYneeded userdict /GRAYneeded get def",
462 "}{",
463 " /GRAYneeded false def",
464 "} ifelse",
465 "EPSneeded {",
466 " /IfRotate false def",
467 " /MarginX 0 def /MarginY 0 def",
468 " /Ymax rows def /Xmax colomns def /Ymin 0 def /Xmin 0 def",
469 "}{",
470 " /IfRotate colomns rows gt {true} {false} ifelse def",
471 " /MarginX 8 mm def /MarginY 18 mm def",
472 " 0 0 moveto clippath pathbbox",
473 " /Ymax exch def /Xmax exch def /Ymin exch def /Xmin exch def",
474 "} ifelse",
475 "/IfColor systemdict /colorimage known {true} {false} ifelse def",
476 "GRAYneeded {/IfColor false def} if",
477 "/IfLevel2 systemdict /filter known systemdict /setcolorspace known and",
478 " {true} {false} ifelse def",
479 "%***********************************************************************",
480 "% Procedures *",
481 "%***********************************************************************",
482 "/Table 4096 array def",
483 "/StrArray 10 array def",
484 "/InLine 70 string def",
485 "/BinCodes 112 string def",
486 "/CurBit 0 def /FreeCode 258 def /CurCodeSize 9 def /CurMask 511 def",
487 "/incr IfColor {3} {1} ifelse def",
488 "IfLevel2 not {/setcolorspace null def /filter null def} if",
489 "%***********************************************************************",
490 "/ReadLine { % Read Next Data Line (ASCII85 decode) *",
491 "%***********************************************************************",
492 " BinCodes 0 BinCodes 56 56 getinterval putinterval",
493 " currentfile InLine readline pop pop",
494 " 1 1 14 {",
495 " /i exch 1 sub def",
496 " /k i 5 mul def",
497 " /c1 InLine k get 33 sub 255 and def",
498 " /rest c1 1868977 mul",
499 " InLine k 1 add get 33 sub 255 and 614125 mul add",
500 " InLine k 2 add get 33 sub 255 and 7225 mul add",
501 " InLine k 3 add get 33 sub 255 and 85 mul add",
502 " InLine k 4 add get 33 sub 255 and add def",
503 " /k i 4 mul 56 add def",
504 " BinCodes k c1 3 mul rest 16777216 idiv add 255 and put",
505 " /rest rest 16777216 mod def",
506 " BinCodes k 1 add rest 65536 idiv put",
507 " BinCodes k 2 add rest 256 idiv 255 and put",
508 " BinCodes k 3 add rest 255 and put",
509 " } for",
510 "} bind def",
511 "%***********************************************************************",
512 "/ReadCode { % Read next code *",
513 "%***********************************************************************",
514 " /CurByte CurBit 8 idiv def",
515 " /CurCode",
516 " BinCodes CurByte get 8 bitshift",
517 " BinCodes CurByte 1 add get add 8 bitshift",
518 " BinCodes CurByte 2 add get add",
519 " CurCodeSize CurBit 7 and add 24 sub bitshift CurMask and def",
520 " /CurBit CurBit CurCodeSize add dup 448 ge {ReadLine 448 sub} if def",
521 "} bind def",
522 "%***********************************************************************",
523 "/DecodeCode { % Decode CurCode *",
524 "%***********************************************************************",
525 " ReadCode CurCode 256 eq {",
526 " /FreeCode 258 def /CurCodeSize 9 def /CurMask 511 def",
527 " /StrInd -1 def /Lrest 0 def ReadCode",
528 " }{",
529 " L Lrest gt {",
530 " /StrInd StrInd 1 add def /Lrest 65535 def",
531 " StrArray StrInd get null eq {StrArray StrInd 65535 string put} if",
532 " /CurStr StrArray StrInd get def",
533 " } if",
534 " Table FreeCode CurStr 65535 Lrest sub L getinterval",
535 " dup 0 Table OldCode get putinterval",
536 " dup L incr sub Table",
537 " CurCode FreeCode lt {CurCode} {OldCode} ifelse get",
538 " 0 incr getinterval putinterval put",
539 " /Lrest Lrest L sub def /FreeCode FreeCode 1 add def",
540 " FreeCode CurMask ge CurCodeSize 12 lt and {",
541 " /CurCodeSize CurCodeSize 1 add def",
542 " /CurMask CurMask 1 bitshift 1 add def",
543 " } if",
544 " } ifelse",
545 " /OldCode CurCode def",
546 " Table CurCode get dup length incr add /L exch def",
547 "} bind def",
548 "%***********************************************************************",
549 "/DisplayImage { % Display a LZW-encoded color image *",
550 "%***********************************************************************",
551 " /DelX Xmax Xmin sub MarginX 2 mul sub def",
552 " /DelY Ymax Ymin sub MarginY 2 mul sub def",
553 " /SizeX IfRotate {rows} {colomns} ifelse def",
554 " /SizeY IfRotate {colomns} {rows} ifelse def",
555 " /FactorX DelX SizeX div def /FactorY DelY SizeY div def",
556 " /Factor FactorX FactorY le {FactorX} {FactorY} ifelse def",
557 " /ScaleX SizeX Factor mul def /ScaleY SizeY Factor mul def",
558 " Xmin DelX ScaleX sub 2 div MarginX add add",
559 " Ymin DelY ScaleY sub 2 div MarginY add add translate",
560 " IfRotate {ScaleY ScaleX} {ScaleX ScaleY} ifelse scale",
561 " /Palette currentfile 768 string readhexstring pop def",
562 " currentfile InLine readline pop pop",
563 " IfColor not {",
564 " 0 1 255 {",
565 " Palette exch dup /i exch 3 mul def",
566 " Palette i 0 add get 0.299 mul",
567 " Palette i 1 add get 0.587 mul add",
568 " Palette i 2 add get 0.114 mul add cvi put",
569 " } for",
570 " /Palette Palette 0 256 getinterval def",
571 " } if",
572 " /Matr IfRotate",
573 " {[0 colomns rows 0 0 0]} {[colomns 0 0 rows neg 0 rows]} ifelse def",
574 " IfLevel2 {",
575 " [/Indexed IfColor {/DeviceRGB} {/DeviceGray} ifelse 255 Palette]",
576 " setcolorspace",
577 " /infile currentfile /ASCII85Decode filter /LZWDecode filter def",
578 " 8 dict",
579 " dup /ImageType 1 put",
580 " dup /Width colomns put",
581 " dup /Height rows put",
582 " dup /BitsPerComponent 8 put",
583 " dup /ImageMatrix Matr put",
584 " dup /Interpolate false put",
585 " dup /Decode [0 255] put",
586 " dup /DataSource infile put image",
587 " }{",
588 " 0 1 255 {",
589 " Table exch dup incr mul Palette exch incr getinterval put",
590 " } for",
591 " ReadLine ReadLine",
592 " colomns rows 8 Matr {DecodeCode}",
593 " IfColor {false 3 colorimage} {image} ifelse",
594 " } ifelse",
595 "} bind def",
596 "%***********************************************************************",
597 "%* Image decoding *",
598 "%***********************************************************************",
599 "DisplayImage",
600 NULL,
601 };
602
603 /* C H E C K P A R A M E T E R S */
604
605 if (Width <= 0 || Width > MAXWIDTH || Height <= 0 || Height > MAXWIDTH) {
606 fprintf(stderr,
607 "\n%s: incorrect image size: %d x %d\n", ProgName, Width, Height);
608 return 0;
609 }
610
611 if (Ncol <= 0 || Ncol > 256) {
612 fprintf(stderr,"\n%s: wrong number of colors: %d\n", ProgName, Ncol);
613 return 0;
614 }
615
616 /* I N I T I A L I S A T I O N */
617
618 if (iwhat < 10)
619 ifeps = iwhat;
620 else
621 ifeps = iwhat - 10;
622 put_b = pb;
623 Nbyte = 0;
624
625 /* O U T P U T H E A D E R */
626
627 sprintf(s,"%%!PS-Adobe-2.0 EPSF-2.0\n"); put_string;
628 sprintf(s,"%%%%Title: %s\n", FileName); put_string;
629 sprintf(s,"%%%%Creator: %s %s\n", ProgName, ProgVers); put_string;
630 sprintf(s,"%%%%CreationDate: %s",(time(&clock),ctime(&clock))); put_string;
631 sprintf(s,"%%%%BoundingBox: 0 0 %d %d\n", Width, Height); put_string;
632 sprintf(s,"%%%%EndComments\n"); put_string;
633
634 /* O U T P U T P R E V I E W */
635
636 if (ifeps == 2)
637 PutPreview(Width, Height, R, G, B, ScLine, get_scline);
638
639 /* O U T P U T P O S T S C R I P T P R O G R A M M */
640
641 if (ifeps == 0)
642 q = HeaderPS;
643 else
644 q = HeaderEPS;
645 for ( ; *q; q++) {
646 sprintf(s,"%s\n",*q); put_string;
647 }
648 if (iwhat < 10)
649 q = HeaderCol;
650 else
651 q = HeaderGray;
652 for ( ; *q; q++) {
653 sprintf(s,"%s\n",*q); put_string;
654 }
655
656 sprintf(s,"/colomns %d def\n",Width); put_string;
657 sprintf(s,"/rows %d def\n",Height); put_string;
658 for (q=CommonPart; *q; q++) {
659 sprintf(s,"%s\n",*q); put_string;
660 }
661
662 /* O U T P U T E N C O D E D D A T A */
663
664 EncodeData(Width, Height, Ncol, R, G, B, ScLine, get_scline);
665
666 sprintf(s,"showpage grestore\n"); put_string;
667 sprintf(s,"%%%%Trailer\n"); put_string;
668 return (Nbyte);
669 }
670