]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
f7faf1f5 | 2 | * "$Id: image-sgilib.c 4741 2005-10-02 04:25:52Z mike $" |
ef416fc2 | 3 | * |
4 | * SGI image file format library routines for the Common UNIX Printing | |
5 | * System (CUPS). | |
6 | * | |
7 | * Copyright 1993-2005 by Easy Software Products. | |
8 | * | |
9 | * These coded instructions, statements, and computer programs are the | |
10 | * property of Easy Software Products and are protected by Federal | |
11 | * copyright law. Distribution and use rights are outlined in the file | |
12 | * "LICENSE.txt" which should have been included with this file. If this | |
13 | * file is missing or damaged please contact Easy Software Products | |
14 | * at: | |
15 | * | |
16 | * Attn: CUPS Licensing Information | |
17 | * Easy Software Products | |
18 | * 44141 Airport View Drive, Suite 204 | |
19 | * Hollywood, Maryland 20636 USA | |
20 | * | |
21 | * Voice: (301) 373-9600 | |
22 | * EMail: cups-info@cups.org | |
23 | * WWW: http://www.cups.org | |
24 | * | |
25 | * This file is subject to the Apple OS-Developed Software exception. | |
26 | * | |
27 | * Contents: | |
28 | * | |
29 | * sgiClose() - Close an SGI image file. | |
30 | * sgiGetRow() - Get a row of image data from a file. | |
31 | * sgiOpen() - Open an SGI image file for reading or writing. | |
32 | * sgiOpenFile() - Open an SGI image file for reading or writing. | |
33 | * sgiPutRow() - Put a row of image data to a file. | |
34 | * getlong() - Get a 32-bit big-endian integer. | |
35 | * getshort() - Get a 16-bit big-endian integer. | |
36 | * putlong() - Put a 32-bit big-endian integer. | |
37 | * putshort() - Put a 16-bit big-endian integer. | |
38 | * read_rle8() - Read 8-bit RLE data. | |
39 | * read_rle16() - Read 16-bit RLE data. | |
40 | * write_rle8() - Write 8-bit RLE data. | |
41 | * write_rle16() - Write 16-bit RLE data. | |
42 | */ | |
43 | ||
44 | #include "image-sgi.h" | |
45 | ||
46 | ||
47 | /* | |
48 | * Local functions... | |
49 | */ | |
50 | ||
51 | static int getlong(FILE *); | |
52 | static int getshort(FILE *); | |
53 | static int putlong(long, FILE *); | |
54 | static int putshort(unsigned short, FILE *); | |
55 | static int read_rle8(FILE *, unsigned short *, int); | |
56 | static int read_rle16(FILE *, unsigned short *, int); | |
57 | static int write_rle8(FILE *, unsigned short *, int); | |
58 | static int write_rle16(FILE *, unsigned short *, int); | |
59 | ||
60 | ||
61 | /* | |
62 | * 'sgiClose()' - Close an SGI image file. | |
63 | */ | |
64 | ||
65 | int /* O - 0 on success, -1 on error */ | |
66 | sgiClose(sgi_t *sgip) /* I - SGI image */ | |
67 | { | |
68 | int i; /* Return status */ | |
69 | long *offset; /* Looping var for offset table */ | |
70 | ||
71 | ||
72 | if (sgip == NULL) | |
73 | return (-1); | |
74 | ||
75 | if (sgip->mode == SGI_WRITE && sgip->comp != SGI_COMP_NONE) | |
76 | { | |
77 | /* | |
78 | * Write the scanline offset table to the file... | |
79 | */ | |
80 | ||
81 | fseek(sgip->file, 512, SEEK_SET); | |
82 | ||
83 | for (i = sgip->ysize * sgip->zsize, offset = sgip->table[0]; | |
84 | i > 0; | |
85 | i --, offset ++) | |
86 | if (putlong(offset[0], sgip->file) < 0) | |
87 | return (-1); | |
88 | ||
89 | for (i = sgip->ysize * sgip->zsize, offset = sgip->length[0]; | |
90 | i > 0; | |
91 | i --, offset ++) | |
92 | if (putlong(offset[0], sgip->file) < 0) | |
93 | return (-1); | |
94 | } | |
95 | ||
96 | if (sgip->table != NULL) | |
97 | { | |
98 | free(sgip->table[0]); | |
99 | free(sgip->table); | |
100 | } | |
101 | ||
102 | if (sgip->length != NULL) | |
103 | { | |
104 | free(sgip->length[0]); | |
105 | free(sgip->length); | |
106 | } | |
107 | ||
108 | if (sgip->comp == SGI_COMP_ARLE) | |
109 | free(sgip->arle_row); | |
110 | ||
111 | i = fclose(sgip->file); | |
112 | free(sgip); | |
113 | ||
114 | return (i); | |
115 | } | |
116 | ||
117 | ||
118 | /* | |
119 | * 'sgiGetRow()' - Get a row of image data from a file. | |
120 | */ | |
121 | ||
122 | int /* O - 0 on success, -1 on error */ | |
123 | sgiGetRow(sgi_t *sgip, /* I - SGI image */ | |
124 | unsigned short *row, /* O - Row to read */ | |
125 | int y, /* I - Line to read */ | |
126 | int z) /* I - Channel to read */ | |
127 | { | |
128 | int x; /* X coordinate */ | |
129 | long offset; /* File offset */ | |
130 | ||
131 | ||
132 | if (sgip == NULL || | |
133 | row == NULL || | |
134 | y < 0 || y >= sgip->ysize || | |
135 | z < 0 || z >= sgip->zsize) | |
136 | return (-1); | |
137 | ||
138 | switch (sgip->comp) | |
139 | { | |
140 | case SGI_COMP_NONE : | |
141 | /* | |
142 | * Seek to the image row - optimize buffering by only seeking if | |
143 | * necessary... | |
144 | */ | |
145 | ||
146 | offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp; | |
147 | if (offset != ftell(sgip->file)) | |
148 | fseek(sgip->file, offset, SEEK_SET); | |
149 | ||
150 | if (sgip->bpp == 1) | |
151 | { | |
152 | for (x = sgip->xsize; x > 0; x --, row ++) | |
153 | *row = getc(sgip->file); | |
154 | } | |
155 | else | |
156 | { | |
157 | for (x = sgip->xsize; x > 0; x --, row ++) | |
158 | *row = getshort(sgip->file); | |
159 | } | |
160 | break; | |
161 | ||
162 | case SGI_COMP_RLE : | |
163 | offset = sgip->table[z][y]; | |
164 | if (offset != ftell(sgip->file)) | |
165 | fseek(sgip->file, offset, SEEK_SET); | |
166 | ||
167 | if (sgip->bpp == 1) | |
168 | return (read_rle8(sgip->file, row, sgip->xsize)); | |
169 | else | |
170 | return (read_rle16(sgip->file, row, sgip->xsize)); | |
171 | } | |
172 | ||
173 | return (0); | |
174 | } | |
175 | ||
176 | ||
177 | /* | |
178 | * 'sgiOpen()' - Open an SGI image file for reading or writing. | |
179 | */ | |
180 | ||
181 | sgi_t * /* O - New image */ | |
182 | sgiOpen(const char *filename, /* I - File to open */ | |
183 | int mode, /* I - Open mode (SGI_READ or SGI_WRITE) */ | |
184 | int comp, /* I - Type of compression */ | |
185 | int bpp, /* I - Bytes per pixel */ | |
186 | int xsize, /* I - Width of image in pixels */ | |
187 | int ysize, /* I - Height of image in pixels */ | |
188 | int zsize) /* I - Number of channels */ | |
189 | { | |
190 | sgi_t *sgip; /* New SGI image file */ | |
191 | FILE *file; /* Image file pointer */ | |
192 | ||
193 | ||
194 | if (mode == SGI_READ) | |
195 | file = fopen(filename, "rb"); | |
196 | else | |
197 | file = fopen(filename, "wb+"); | |
198 | ||
199 | if (file == NULL) | |
200 | return (NULL); | |
201 | ||
202 | if ((sgip = sgiOpenFile(file, mode, comp, bpp, xsize, ysize, zsize)) == NULL) | |
203 | fclose(file); | |
204 | ||
205 | return (sgip); | |
206 | } | |
207 | ||
208 | ||
209 | /* | |
210 | * 'sgiOpenFile()' - Open an SGI image file for reading or writing. | |
211 | */ | |
212 | ||
213 | sgi_t * /* O - New image */ | |
214 | sgiOpenFile(FILE *file, /* I - File to open */ | |
215 | int mode, /* I - Open mode (SGI_READ or SGI_WRITE) */ | |
216 | int comp, /* I - Type of compression */ | |
217 | int bpp, /* I - Bytes per pixel */ | |
218 | int xsize, /* I - Width of image in pixels */ | |
219 | int ysize, /* I - Height of image in pixels */ | |
220 | int zsize) /* I - Number of channels */ | |
221 | { | |
222 | int i, j; /* Looping var */ | |
223 | char name[80]; /* Name of file in image header */ | |
224 | short magic; /* Magic number */ | |
225 | sgi_t *sgip; /* New image pointer */ | |
226 | ||
227 | ||
228 | if ((sgip = calloc(sizeof(sgi_t), 1)) == NULL) | |
229 | return (NULL); | |
230 | ||
231 | sgip->file = file; | |
232 | ||
233 | switch (mode) | |
234 | { | |
235 | case SGI_READ : | |
236 | sgip->mode = SGI_READ; | |
237 | ||
238 | magic = getshort(sgip->file); | |
239 | if (magic != SGI_MAGIC) | |
240 | { | |
241 | free(sgip); | |
242 | return (NULL); | |
243 | } | |
244 | ||
245 | sgip->comp = getc(sgip->file); | |
246 | sgip->bpp = getc(sgip->file); | |
247 | getshort(sgip->file); /* Dimensions */ | |
248 | sgip->xsize = getshort(sgip->file); | |
249 | sgip->ysize = getshort(sgip->file); | |
250 | sgip->zsize = getshort(sgip->file); | |
251 | getlong(sgip->file); /* Minimum pixel */ | |
252 | getlong(sgip->file); /* Maximum pixel */ | |
253 | ||
254 | if (sgip->comp) | |
255 | { | |
256 | /* | |
257 | * This file is compressed; read the scanline tables... | |
258 | */ | |
259 | ||
260 | fseek(sgip->file, 512, SEEK_SET); | |
261 | ||
262 | sgip->table = calloc(sgip->zsize, sizeof(long *)); | |
263 | sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); | |
264 | for (i = 1; i < sgip->zsize; i ++) | |
265 | sgip->table[i] = sgip->table[0] + i * sgip->ysize; | |
266 | ||
267 | for (i = 0; i < sgip->zsize; i ++) | |
268 | for (j = 0; j < sgip->ysize; j ++) | |
269 | sgip->table[i][j] = getlong(sgip->file); | |
270 | } | |
271 | break; | |
272 | ||
273 | case SGI_WRITE : | |
274 | if (xsize < 1 || | |
275 | ysize < 1 || | |
276 | zsize < 1 || | |
277 | bpp < 1 || bpp > 2 || | |
278 | comp < SGI_COMP_NONE || comp > SGI_COMP_ARLE) | |
279 | { | |
280 | free(sgip); | |
281 | return (NULL); | |
282 | } | |
283 | ||
284 | sgip->mode = SGI_WRITE; | |
285 | ||
286 | putshort(SGI_MAGIC, sgip->file); | |
287 | putc((sgip->comp = comp) != 0, sgip->file); | |
288 | putc(sgip->bpp = bpp, sgip->file); | |
289 | putshort(3, sgip->file); /* Dimensions */ | |
290 | putshort(sgip->xsize = xsize, sgip->file); | |
291 | putshort(sgip->ysize = ysize, sgip->file); | |
292 | putshort(sgip->zsize = zsize, sgip->file); | |
293 | if (bpp == 1) | |
294 | { | |
295 | putlong(0, sgip->file); /* Minimum pixel */ | |
296 | putlong(255, sgip->file); /* Maximum pixel */ | |
297 | } | |
298 | else | |
299 | { | |
300 | putlong(-32768, sgip->file); /* Minimum pixel */ | |
301 | putlong(32767, sgip->file); /* Maximum pixel */ | |
302 | } | |
303 | putlong(0, sgip->file); /* Reserved */ | |
304 | ||
305 | memset(name, 0, sizeof(name)); | |
306 | fwrite(name, sizeof(name), 1, sgip->file); | |
307 | ||
308 | for (i = 0; i < 102; i ++) | |
309 | putlong(0, sgip->file); | |
310 | ||
311 | switch (comp) | |
312 | { | |
313 | case SGI_COMP_NONE : /* No compression */ | |
314 | /* | |
315 | * This file is uncompressed. To avoid problems with sparse files, | |
316 | * we need to write blank pixels for the entire image... | |
317 | */ | |
318 | ||
319 | if (bpp == 1) | |
320 | { | |
321 | for (i = xsize * ysize * zsize; i > 0; i --) | |
322 | putc(0, sgip->file); | |
323 | } | |
324 | else | |
325 | { | |
326 | for (i = xsize * ysize * zsize; i > 0; i --) | |
327 | putshort(0, sgip->file); | |
328 | } | |
329 | break; | |
330 | ||
331 | case SGI_COMP_ARLE : /* Aggressive RLE */ | |
332 | sgip->arle_row = calloc(xsize, sizeof(unsigned short)); | |
333 | sgip->arle_offset = 0; | |
334 | ||
335 | case SGI_COMP_RLE : /* Run-Length Encoding */ | |
336 | /* | |
337 | * This file is compressed; write the (blank) scanline tables... | |
338 | */ | |
339 | ||
340 | for (i = 2 * ysize * zsize; i > 0; i --) | |
341 | putlong(0, sgip->file); | |
342 | ||
343 | sgip->firstrow = ftell(sgip->file); | |
344 | sgip->nextrow = ftell(sgip->file); | |
345 | sgip->table = calloc(sgip->zsize, sizeof(long *)); | |
346 | sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); | |
347 | for (i = 1; i < sgip->zsize; i ++) | |
348 | sgip->table[i] = sgip->table[0] + i * sgip->ysize; | |
349 | sgip->length = calloc(sgip->zsize, sizeof(long *)); | |
350 | sgip->length[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long)); | |
351 | for (i = 1; i < sgip->zsize; i ++) | |
352 | sgip->length[i] = sgip->length[0] + i * sgip->ysize; | |
353 | break; | |
354 | } | |
355 | break; | |
356 | ||
357 | default : | |
358 | free(sgip); | |
359 | return (NULL); | |
360 | } | |
361 | ||
362 | return (sgip); | |
363 | } | |
364 | ||
365 | ||
366 | /* | |
367 | * 'sgiPutRow()' - Put a row of image data to a file. | |
368 | */ | |
369 | ||
370 | int /* O - 0 on success, -1 on error */ | |
371 | sgiPutRow(sgi_t *sgip, /* I - SGI image */ | |
372 | unsigned short *row, /* I - Row to write */ | |
373 | int y, /* I - Line to write */ | |
374 | int z) /* I - Channel to write */ | |
375 | { | |
376 | int x; /* X coordinate */ | |
377 | long offset; /* File offset */ | |
378 | ||
379 | ||
380 | if (sgip == NULL || | |
381 | row == NULL || | |
382 | y < 0 || y >= sgip->ysize || | |
383 | z < 0 || z >= sgip->zsize) | |
384 | return (-1); | |
385 | ||
386 | switch (sgip->comp) | |
387 | { | |
388 | case SGI_COMP_NONE : | |
389 | /* | |
390 | * Seek to the image row - optimize buffering by only seeking if | |
391 | * necessary... | |
392 | */ | |
393 | ||
394 | offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp; | |
395 | if (offset != ftell(sgip->file)) | |
396 | fseek(sgip->file, offset, SEEK_SET); | |
397 | ||
398 | if (sgip->bpp == 1) | |
399 | { | |
400 | for (x = sgip->xsize; x > 0; x --, row ++) | |
401 | putc(*row, sgip->file); | |
402 | } | |
403 | else | |
404 | { | |
405 | for (x = sgip->xsize; x > 0; x --, row ++) | |
406 | putshort(*row, sgip->file); | |
407 | } | |
408 | break; | |
409 | ||
410 | case SGI_COMP_ARLE : | |
411 | if (sgip->table[z][y] != 0) | |
412 | return (-1); | |
413 | ||
414 | /* | |
415 | * First check the last row written... | |
416 | */ | |
417 | ||
418 | if (sgip->arle_offset > 0) | |
419 | { | |
420 | for (x = 0; x < sgip->xsize; x ++) | |
421 | if (row[x] != sgip->arle_row[x]) | |
422 | break; | |
423 | ||
424 | if (x == sgip->xsize) | |
425 | { | |
426 | sgip->table[z][y] = sgip->arle_offset; | |
427 | sgip->length[z][y] = sgip->arle_length; | |
428 | return (0); | |
429 | } | |
430 | } | |
431 | ||
432 | /* | |
433 | * If that didn't match, search all the previous rows... | |
434 | */ | |
435 | ||
436 | fseek(sgip->file, sgip->firstrow, SEEK_SET); | |
437 | ||
438 | if (sgip->bpp == 1) | |
439 | { | |
440 | for (;;) | |
441 | { | |
442 | sgip->arle_offset = ftell(sgip->file); | |
443 | if ((sgip->arle_length = read_rle8(sgip->file, sgip->arle_row, sgip->xsize)) < 0) | |
444 | { | |
445 | x = 0; | |
446 | break; | |
447 | } | |
448 | ||
449 | if (memcmp(row, sgip->arle_row, sgip->xsize * sizeof(unsigned short)) == 0) | |
450 | { | |
451 | x = sgip->xsize; | |
452 | break; | |
453 | } | |
454 | } | |
455 | } | |
456 | else | |
457 | { | |
458 | for (;;) | |
459 | { | |
460 | sgip->arle_offset = ftell(sgip->file); | |
461 | if ((sgip->arle_length = read_rle16(sgip->file, sgip->arle_row, sgip->xsize)) < 0) | |
462 | { | |
463 | x = 0; | |
464 | break; | |
465 | } | |
466 | ||
467 | if (memcmp(row, sgip->arle_row, sgip->xsize * sizeof(unsigned short)) == 0) | |
468 | { | |
469 | x = sgip->xsize; | |
470 | break; | |
471 | } | |
472 | } | |
473 | } | |
474 | ||
475 | if (x == sgip->xsize) | |
476 | { | |
477 | sgip->table[z][y] = sgip->arle_offset; | |
478 | sgip->length[z][y] = sgip->arle_length; | |
479 | return (0); | |
480 | } | |
481 | else | |
482 | fseek(sgip->file, 0, SEEK_END); /* Clear EOF */ | |
483 | ||
484 | case SGI_COMP_RLE : | |
485 | if (sgip->table[z][y] != 0) | |
486 | return (-1); | |
487 | ||
488 | offset = sgip->table[z][y] = sgip->nextrow; | |
489 | ||
490 | if (offset != ftell(sgip->file)) | |
491 | fseek(sgip->file, offset, SEEK_SET); | |
492 | ||
493 | if (sgip->bpp == 1) | |
494 | x = write_rle8(sgip->file, row, sgip->xsize); | |
495 | else | |
496 | x = write_rle16(sgip->file, row, sgip->xsize); | |
497 | ||
498 | if (sgip->comp == SGI_COMP_ARLE) | |
499 | { | |
500 | sgip->arle_offset = offset; | |
501 | sgip->arle_length = x; | |
502 | memcpy(sgip->arle_row, row, sgip->xsize * sizeof(unsigned short)); | |
503 | } | |
504 | ||
505 | sgip->nextrow = ftell(sgip->file); | |
506 | sgip->length[z][y] = x; | |
507 | ||
508 | return (x); | |
509 | } | |
510 | ||
511 | return (0); | |
512 | } | |
513 | ||
514 | ||
515 | /* | |
516 | * 'getlong()' - Get a 32-bit big-endian integer. | |
517 | */ | |
518 | ||
519 | static int /* O - Long value */ | |
520 | getlong(FILE *fp) /* I - File to read from */ | |
521 | { | |
522 | unsigned char b[4]; /* Bytes from file */ | |
523 | ||
524 | ||
525 | fread(b, 4, 1, fp); | |
526 | return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); | |
527 | } | |
528 | ||
529 | ||
530 | /* | |
531 | * 'getshort()' - Get a 16-bit big-endian integer. | |
532 | */ | |
533 | ||
534 | static int /* O - Short value */ | |
535 | getshort(FILE *fp) /* I - File to read from */ | |
536 | { | |
537 | unsigned char b[2]; /* Bytes from file */ | |
538 | ||
539 | ||
540 | fread(b, 2, 1, fp); | |
541 | return ((b[0] << 8) | b[1]); | |
542 | } | |
543 | ||
544 | ||
545 | /* | |
546 | * 'putlong()' - Put a 32-bit big-endian integer. | |
547 | */ | |
548 | ||
549 | static int /* O - 0 on success, -1 on error */ | |
550 | putlong(long n, /* I - Long to write */ | |
551 | FILE *fp) /* I - File to write to */ | |
552 | { | |
553 | if (putc(n >> 24, fp) == EOF) | |
554 | return (EOF); | |
555 | if (putc(n >> 16, fp) == EOF) | |
556 | return (EOF); | |
557 | if (putc(n >> 8, fp) == EOF) | |
558 | return (EOF); | |
559 | if (putc(n, fp) == EOF) | |
560 | return (EOF); | |
561 | else | |
562 | return (0); | |
563 | } | |
564 | ||
565 | ||
566 | /* | |
567 | * 'putshort()' - Put a 16-bit big-endian integer. | |
568 | */ | |
569 | ||
570 | static int /* O - 0 on success, -1 on error */ | |
571 | putshort(unsigned short n, /* I - Short to write */ | |
572 | FILE *fp) /* I - File to write to */ | |
573 | { | |
574 | if (putc(n >> 8, fp) == EOF) | |
575 | return (EOF); | |
576 | if (putc(n, fp) == EOF) | |
577 | return (EOF); | |
578 | else | |
579 | return (0); | |
580 | } | |
581 | ||
582 | ||
583 | /* | |
584 | * 'read_rle8()' - Read 8-bit RLE data. | |
585 | */ | |
586 | ||
587 | static int /* O - Value on success, -1 on error */ | |
588 | read_rle8(FILE *fp, /* I - File to read from */ | |
589 | unsigned short *row, /* O - Data */ | |
590 | int xsize) /* I - Width of data in pixels */ | |
591 | { | |
592 | int i, /* Looping var */ | |
593 | ch, /* Current character */ | |
594 | count, /* RLE count */ | |
595 | length; /* Number of bytes read... */ | |
596 | ||
597 | ||
598 | length = 0; | |
599 | ||
600 | while (xsize > 0) | |
601 | { | |
602 | if ((ch = getc(fp)) == EOF) | |
603 | return (-1); | |
604 | length ++; | |
605 | ||
606 | count = ch & 127; | |
607 | if (count == 0) | |
608 | break; | |
609 | ||
610 | if (ch & 128) | |
611 | { | |
612 | for (i = 0; i < count; i ++, row ++, xsize --, length ++) | |
613 | *row = getc(fp); | |
614 | } | |
615 | else | |
616 | { | |
617 | ch = getc(fp); | |
618 | length ++; | |
619 | for (i = 0; i < count; i ++, row ++, xsize --) | |
620 | *row = ch; | |
621 | } | |
622 | } | |
623 | ||
624 | return (xsize > 0 ? -1 : length); | |
625 | } | |
626 | ||
627 | ||
628 | /* | |
629 | * 'read_rle16()' - Read 16-bit RLE data. | |
630 | */ | |
631 | ||
632 | static int /* O - Value on success, -1 on error */ | |
633 | read_rle16(FILE *fp, /* I - File to read from */ | |
634 | unsigned short *row, /* O - Data */ | |
635 | int xsize) /* I - Width of data in pixels */ | |
636 | { | |
637 | int i, /* Looping var */ | |
638 | ch, /* Current character */ | |
639 | count, /* RLE count */ | |
640 | length; /* Number of bytes read... */ | |
641 | ||
642 | ||
643 | length = 0; | |
644 | ||
645 | while (xsize > 0) | |
646 | { | |
647 | if ((ch = getshort(fp)) == EOF) | |
648 | return (-1); | |
649 | length ++; | |
650 | ||
651 | count = ch & 127; | |
652 | if (count == 0) | |
653 | break; | |
654 | ||
655 | if (ch & 128) | |
656 | { | |
657 | for (i = 0; i < count; i ++, row ++, xsize --, length ++) | |
658 | *row = getshort(fp); | |
659 | } | |
660 | else | |
661 | { | |
662 | ch = getshort(fp); | |
663 | length ++; | |
664 | for (i = 0; i < count; i ++, row ++, xsize --) | |
665 | *row = ch; | |
666 | } | |
667 | } | |
668 | ||
669 | return (xsize > 0 ? -1 : length * 2); | |
670 | } | |
671 | ||
672 | ||
673 | /* | |
674 | * 'write_rle8()' - Write 8-bit RLE data. | |
675 | */ | |
676 | ||
677 | static int /* O - Length on success, -1 on error */ | |
678 | write_rle8(FILE *fp, /* I - File to write to */ | |
679 | unsigned short *row, /* I - Data */ | |
680 | int xsize) /* I - Width of data in pixels */ | |
681 | { | |
682 | int length, /* Length in bytes */ | |
683 | count, /* Number of repeating pixels */ | |
684 | i, /* Looping var */ | |
685 | x; /* Current column */ | |
686 | unsigned short *start, /* Start of current sequence */ | |
687 | repeat; /* Repeated pixel */ | |
688 | ||
689 | ||
690 | for (x = xsize, length = 0; x > 0;) | |
691 | { | |
692 | start = row; | |
693 | row += 2; | |
694 | x -= 2; | |
695 | ||
696 | while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) | |
697 | { | |
698 | row ++; | |
699 | x --; | |
700 | } | |
701 | ||
702 | row -= 2; | |
703 | x += 2; | |
704 | ||
705 | count = row - start; | |
706 | while (count > 0) | |
707 | { | |
708 | i = count > 126 ? 126 : count; | |
709 | count -= i; | |
710 | ||
711 | if (putc(128 | i, fp) == EOF) | |
712 | return (-1); | |
713 | length ++; | |
714 | ||
715 | while (i > 0) | |
716 | { | |
717 | if (putc(*start, fp) == EOF) | |
718 | return (-1); | |
719 | start ++; | |
720 | i --; | |
721 | length ++; | |
722 | } | |
723 | } | |
724 | ||
725 | if (x <= 0) | |
726 | break; | |
727 | ||
728 | start = row; | |
729 | repeat = row[0]; | |
730 | ||
731 | row ++; | |
732 | x --; | |
733 | ||
734 | while (x > 0 && *row == repeat) | |
735 | { | |
736 | row ++; | |
737 | x --; | |
738 | } | |
739 | ||
740 | count = row - start; | |
741 | while (count > 0) | |
742 | { | |
743 | i = count > 126 ? 126 : count; | |
744 | count -= i; | |
745 | ||
746 | if (putc(i, fp) == EOF) | |
747 | return (-1); | |
748 | length ++; | |
749 | ||
750 | if (putc(repeat, fp) == EOF) | |
751 | return (-1); | |
752 | length ++; | |
753 | } | |
754 | } | |
755 | ||
756 | length ++; | |
757 | ||
758 | if (putc(0, fp) == EOF) | |
759 | return (-1); | |
760 | else | |
761 | return (length); | |
762 | } | |
763 | ||
764 | ||
765 | /* | |
766 | * 'write_rle16()' - Write 16-bit RLE data. | |
767 | */ | |
768 | ||
769 | static int /* O - Length in words */ | |
770 | write_rle16(FILE *fp, /* I - File to write to */ | |
771 | unsigned short *row, /* I - Data */ | |
772 | int xsize) /* I - Width of data in pixels */ | |
773 | { | |
774 | int length, /* Length in words */ | |
775 | count, /* Number of repeating pixels */ | |
776 | i, /* Looping var */ | |
777 | x; /* Current column */ | |
778 | unsigned short *start, /* Start of current sequence */ | |
779 | repeat; /* Repeated pixel */ | |
780 | ||
781 | ||
782 | for (x = xsize, length = 0; x > 0;) | |
783 | { | |
784 | start = row; | |
785 | row += 2; | |
786 | x -= 2; | |
787 | ||
788 | while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0])) | |
789 | { | |
790 | row ++; | |
791 | x --; | |
792 | } | |
793 | ||
794 | row -= 2; | |
795 | x += 2; | |
796 | ||
797 | count = row - start; | |
798 | while (count > 0) | |
799 | { | |
800 | i = count > 126 ? 126 : count; | |
801 | count -= i; | |
802 | ||
803 | if (putshort(128 | i, fp) == EOF) | |
804 | return (-1); | |
805 | length ++; | |
806 | ||
807 | while (i > 0) | |
808 | { | |
809 | if (putshort(*start, fp) == EOF) | |
810 | return (-1); | |
811 | start ++; | |
812 | i --; | |
813 | length ++; | |
814 | } | |
815 | } | |
816 | ||
817 | if (x <= 0) | |
818 | break; | |
819 | ||
820 | start = row; | |
821 | repeat = row[0]; | |
822 | ||
823 | row ++; | |
824 | x --; | |
825 | ||
826 | while (x > 0 && *row == repeat) | |
827 | { | |
828 | row ++; | |
829 | x --; | |
830 | } | |
831 | ||
832 | count = row - start; | |
833 | while (count > 0) | |
834 | { | |
835 | i = count > 126 ? 126 : count; | |
836 | count -= i; | |
837 | ||
838 | if (putshort(i, fp) == EOF) | |
839 | return (-1); | |
840 | length ++; | |
841 | ||
842 | if (putshort(repeat, fp) == EOF) | |
843 | return (-1); | |
844 | length ++; | |
845 | } | |
846 | } | |
847 | ||
848 | length ++; | |
849 | ||
850 | if (putshort(0, fp) == EOF) | |
851 | return (-1); | |
852 | else | |
853 | return (2 * length); | |
854 | } | |
855 | ||
856 | ||
857 | /* | |
f7faf1f5 | 858 | * End of "$Id: image-sgilib.c 4741 2005-10-02 04:25:52Z mike $". |
ef416fc2 | 859 | */ |