]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-sgilib.c
2 * "$Id: image-sgilib.c 4741 2005-10-02 04:25:52Z mike $"
4 * SGI image file format library routines for the Common UNIX Printing
7 * Copyright 1993-2005 by Easy Software Products.
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
16 * Attn: CUPS Licensing Information
17 * Easy Software Products
18 * 44141 Airport View Drive, Suite 204
19 * Hollywood, Maryland 20636 USA
21 * Voice: (301) 373-9600
22 * EMail: cups-info@cups.org
23 * WWW: http://www.cups.org
25 * This file is subject to the Apple OS-Developed Software exception.
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.
44 #include "image-sgi.h"
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);
62 * 'sgiClose()' - Close an SGI image file.
65 int /* O - 0 on success, -1 on error */
66 sgiClose(sgi_t
*sgip
) /* I - SGI image */
68 int i
; /* Return status */
69 long *offset
; /* Looping var for offset table */
75 if (sgip
->mode
== SGI_WRITE
&& sgip
->comp
!= SGI_COMP_NONE
)
78 * Write the scanline offset table to the file...
81 fseek(sgip
->file
, 512, SEEK_SET
);
83 for (i
= sgip
->ysize
* sgip
->zsize
, offset
= sgip
->table
[0];
86 if (putlong(offset
[0], sgip
->file
) < 0)
89 for (i
= sgip
->ysize
* sgip
->zsize
, offset
= sgip
->length
[0];
92 if (putlong(offset
[0], sgip
->file
) < 0)
96 if (sgip
->table
!= NULL
)
102 if (sgip
->length
!= NULL
)
104 free(sgip
->length
[0]);
108 if (sgip
->comp
== SGI_COMP_ARLE
)
109 free(sgip
->arle_row
);
111 i
= fclose(sgip
->file
);
119 * 'sgiGetRow()' - Get a row of image data from a file.
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 */
128 int x
; /* X coordinate */
129 long offset
; /* File offset */
134 y
< 0 || y
>= sgip
->ysize
||
135 z
< 0 || z
>= sgip
->zsize
)
142 * Seek to the image row - optimize buffering by only seeking if
146 offset
= 512 + (y
+ z
* sgip
->ysize
) * sgip
->xsize
* sgip
->bpp
;
147 if (offset
!= ftell(sgip
->file
))
148 fseek(sgip
->file
, offset
, SEEK_SET
);
152 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
153 *row
= getc(sgip
->file
);
157 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
158 *row
= getshort(sgip
->file
);
163 offset
= sgip
->table
[z
][y
];
164 if (offset
!= ftell(sgip
->file
))
165 fseek(sgip
->file
, offset
, SEEK_SET
);
168 return (read_rle8(sgip
->file
, row
, sgip
->xsize
));
170 return (read_rle16(sgip
->file
, row
, sgip
->xsize
));
178 * 'sgiOpen()' - Open an SGI image file for reading or writing.
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 */
190 sgi_t
*sgip
; /* New SGI image file */
191 FILE *file
; /* Image file pointer */
194 if (mode
== SGI_READ
)
195 file
= fopen(filename
, "rb");
197 file
= fopen(filename
, "wb+");
202 if ((sgip
= sgiOpenFile(file
, mode
, comp
, bpp
, xsize
, ysize
, zsize
)) == NULL
)
210 * 'sgiOpenFile()' - Open an SGI image file for reading or writing.
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 */
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 */
228 if ((sgip
= calloc(sizeof(sgi_t
), 1)) == NULL
)
236 sgip
->mode
= SGI_READ
;
238 magic
= getshort(sgip
->file
);
239 if (magic
!= SGI_MAGIC
)
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 */
257 * This file is compressed; read the scanline tables...
260 fseek(sgip
->file
, 512, SEEK_SET
);
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
;
267 for (i
= 0; i
< sgip
->zsize
; i
++)
268 for (j
= 0; j
< sgip
->ysize
; j
++)
269 sgip
->table
[i
][j
] = getlong(sgip
->file
);
277 bpp
< 1 || bpp
> 2 ||
278 comp
< SGI_COMP_NONE
|| comp
> SGI_COMP_ARLE
)
284 sgip
->mode
= SGI_WRITE
;
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
);
295 putlong(0, sgip
->file
); /* Minimum pixel */
296 putlong(255, sgip
->file
); /* Maximum pixel */
300 putlong(-32768, sgip
->file
); /* Minimum pixel */
301 putlong(32767, sgip
->file
); /* Maximum pixel */
303 putlong(0, sgip
->file
); /* Reserved */
305 memset(name
, 0, sizeof(name
));
306 fwrite(name
, sizeof(name
), 1, sgip
->file
);
308 for (i
= 0; i
< 102; i
++)
309 putlong(0, sgip
->file
);
313 case SGI_COMP_NONE
: /* No compression */
315 * This file is uncompressed. To avoid problems with sparse files,
316 * we need to write blank pixels for the entire image...
321 for (i
= xsize
* ysize
* zsize
; i
> 0; i
--)
326 for (i
= xsize
* ysize
* zsize
; i
> 0; i
--)
327 putshort(0, sgip
->file
);
331 case SGI_COMP_ARLE
: /* Aggressive RLE */
332 sgip
->arle_row
= calloc(xsize
, sizeof(unsigned short));
333 sgip
->arle_offset
= 0;
335 case SGI_COMP_RLE
: /* Run-Length Encoding */
337 * This file is compressed; write the (blank) scanline tables...
340 for (i
= 2 * ysize
* zsize
; i
> 0; i
--)
341 putlong(0, sgip
->file
);
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
;
367 * 'sgiPutRow()' - Put a row of image data to a file.
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 */
376 int x
; /* X coordinate */
377 long offset
; /* File offset */
382 y
< 0 || y
>= sgip
->ysize
||
383 z
< 0 || z
>= sgip
->zsize
)
390 * Seek to the image row - optimize buffering by only seeking if
394 offset
= 512 + (y
+ z
* sgip
->ysize
) * sgip
->xsize
* sgip
->bpp
;
395 if (offset
!= ftell(sgip
->file
))
396 fseek(sgip
->file
, offset
, SEEK_SET
);
400 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
401 putc(*row
, sgip
->file
);
405 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
406 putshort(*row
, sgip
->file
);
411 if (sgip
->table
[z
][y
] != 0)
415 * First check the last row written...
418 if (sgip
->arle_offset
> 0)
420 for (x
= 0; x
< sgip
->xsize
; x
++)
421 if (row
[x
] != sgip
->arle_row
[x
])
424 if (x
== sgip
->xsize
)
426 sgip
->table
[z
][y
] = sgip
->arle_offset
;
427 sgip
->length
[z
][y
] = sgip
->arle_length
;
433 * If that didn't match, search all the previous rows...
436 fseek(sgip
->file
, sgip
->firstrow
, SEEK_SET
);
442 sgip
->arle_offset
= ftell(sgip
->file
);
443 if ((sgip
->arle_length
= read_rle8(sgip
->file
, sgip
->arle_row
, sgip
->xsize
)) < 0)
449 if (memcmp(row
, sgip
->arle_row
, sgip
->xsize
* sizeof(unsigned short)) == 0)
460 sgip
->arle_offset
= ftell(sgip
->file
);
461 if ((sgip
->arle_length
= read_rle16(sgip
->file
, sgip
->arle_row
, sgip
->xsize
)) < 0)
467 if (memcmp(row
, sgip
->arle_row
, sgip
->xsize
* sizeof(unsigned short)) == 0)
475 if (x
== sgip
->xsize
)
477 sgip
->table
[z
][y
] = sgip
->arle_offset
;
478 sgip
->length
[z
][y
] = sgip
->arle_length
;
482 fseek(sgip
->file
, 0, SEEK_END
); /* Clear EOF */
485 if (sgip
->table
[z
][y
] != 0)
488 offset
= sgip
->table
[z
][y
] = sgip
->nextrow
;
490 if (offset
!= ftell(sgip
->file
))
491 fseek(sgip
->file
, offset
, SEEK_SET
);
494 x
= write_rle8(sgip
->file
, row
, sgip
->xsize
);
496 x
= write_rle16(sgip
->file
, row
, sgip
->xsize
);
498 if (sgip
->comp
== SGI_COMP_ARLE
)
500 sgip
->arle_offset
= offset
;
501 sgip
->arle_length
= x
;
502 memcpy(sgip
->arle_row
, row
, sgip
->xsize
* sizeof(unsigned short));
505 sgip
->nextrow
= ftell(sgip
->file
);
506 sgip
->length
[z
][y
] = x
;
516 * 'getlong()' - Get a 32-bit big-endian integer.
519 static int /* O - Long value */
520 getlong(FILE *fp
) /* I - File to read from */
522 unsigned char b
[4]; /* Bytes from file */
526 return ((b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | b
[3]);
531 * 'getshort()' - Get a 16-bit big-endian integer.
534 static int /* O - Short value */
535 getshort(FILE *fp
) /* I - File to read from */
537 unsigned char b
[2]; /* Bytes from file */
541 return ((b
[0] << 8) | b
[1]);
546 * 'putlong()' - Put a 32-bit big-endian integer.
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 */
553 if (putc(n
>> 24, fp
) == EOF
)
555 if (putc(n
>> 16, fp
) == EOF
)
557 if (putc(n
>> 8, fp
) == EOF
)
559 if (putc(n
, fp
) == EOF
)
567 * 'putshort()' - Put a 16-bit big-endian integer.
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 */
574 if (putc(n
>> 8, fp
) == EOF
)
576 if (putc(n
, fp
) == EOF
)
584 * 'read_rle8()' - Read 8-bit RLE data.
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 */
592 int i
, /* Looping var */
593 ch
, /* Current character */
594 count
, /* RLE count */
595 length
; /* Number of bytes read... */
602 if ((ch
= getc(fp
)) == EOF
)
612 for (i
= 0; i
< count
; i
++, row
++, xsize
--, length
++)
619 for (i
= 0; i
< count
; i
++, row
++, xsize
--)
624 return (xsize
> 0 ? -1 : length
);
629 * 'read_rle16()' - Read 16-bit RLE data.
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 */
637 int i
, /* Looping var */
638 ch
, /* Current character */
639 count
, /* RLE count */
640 length
; /* Number of bytes read... */
647 if ((ch
= getshort(fp
)) == EOF
)
657 for (i
= 0; i
< count
; i
++, row
++, xsize
--, length
++)
664 for (i
= 0; i
< count
; i
++, row
++, xsize
--)
669 return (xsize
> 0 ? -1 : length
* 2);
674 * 'write_rle8()' - Write 8-bit RLE data.
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 */
682 int length
, /* Length in bytes */
683 count
, /* Number of repeating pixels */
685 x
; /* Current column */
686 unsigned short *start
, /* Start of current sequence */
687 repeat
; /* Repeated pixel */
690 for (x
= xsize
, length
= 0; x
> 0;)
696 while (x
> 0 && (row
[-2] != row
[-1] || row
[-1] != row
[0]))
708 i
= count
> 126 ? 126 : count
;
711 if (putc(128 | i
, fp
) == EOF
)
717 if (putc(*start
, fp
) == EOF
)
734 while (x
> 0 && *row
== repeat
)
743 i
= count
> 126 ? 126 : count
;
746 if (putc(i
, fp
) == EOF
)
750 if (putc(repeat
, fp
) == EOF
)
758 if (putc(0, fp
) == EOF
)
766 * 'write_rle16()' - Write 16-bit RLE data.
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 */
774 int length
, /* Length in words */
775 count
, /* Number of repeating pixels */
777 x
; /* Current column */
778 unsigned short *start
, /* Start of current sequence */
779 repeat
; /* Repeated pixel */
782 for (x
= xsize
, length
= 0; x
> 0;)
788 while (x
> 0 && (row
[-2] != row
[-1] || row
[-1] != row
[0]))
800 i
= count
> 126 ? 126 : count
;
803 if (putshort(128 | i
, fp
) == EOF
)
809 if (putshort(*start
, fp
) == EOF
)
826 while (x
> 0 && *row
== repeat
)
835 i
= count
> 126 ? 126 : count
;
838 if (putshort(i
, fp
) == EOF
)
842 if (putshort(repeat
, fp
) == EOF
)
850 if (putshort(0, fp
) == EOF
)
858 * End of "$Id: image-sgilib.c 4741 2005-10-02 04:25:52Z mike $".