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